Ottie: Add ottie-editor
This commit is contained in:
@@ -682,6 +682,7 @@ subdir('gsk')
|
||||
subdir('ottie')
|
||||
subdir('gtk')
|
||||
subdir('ottie/tools')
|
||||
subdir('ottie/editor')
|
||||
subdir('modules')
|
||||
if get_option('demos')
|
||||
subdir('demos')
|
||||
|
||||
28
ottie/editor/main.c
Normal file
28
ottie/editor/main.c
Normal file
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright © 2020 Benjamin Otte
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <ottie-editor-application.h>
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
return g_application_run (G_APPLICATION (ottie_editor_application_new ()), argc, argv);
|
||||
}
|
||||
31
ottie/editor/meson.build
Normal file
31
ottie/editor/meson.build
Normal file
@@ -0,0 +1,31 @@
|
||||
ottie_editor_sources = [
|
||||
'main.c',
|
||||
'ottie-editor-application.c',
|
||||
'ottie-editor-window.c',
|
||||
]
|
||||
|
||||
ottie_editor_resources = gnome.compile_resources('ottie_editor_resources',
|
||||
'ottie-editor.gresource.xml',
|
||||
source_dir: '.',
|
||||
)
|
||||
|
||||
executable('ottie-editor',
|
||||
sources: [ottie_editor_sources, ottie_editor_resources],
|
||||
dependencies: [libgtk_css_dep, libgdk_dep, libgsk_dep, libgtk_static_dep, libottie_dep],
|
||||
include_directories: confinc,
|
||||
c_args: [
|
||||
'-DGTK_COMPILATION',
|
||||
'-DG_LOG_DOMAIN="OttieEditor"',
|
||||
] + common_cflags,
|
||||
gui_app: true,
|
||||
link_with: [libgtk_static, libgtk_css, libgdk, libgsk, libottie],
|
||||
link_args: common_ldflags,
|
||||
install: false,
|
||||
)
|
||||
|
||||
# icons, don't install them until we decide to install ottie-editor
|
||||
#icontheme_dir = join_paths(gtk_datadir, 'icons/hicolor')
|
||||
|
||||
#foreach size: ['scalable', 'symbolic']
|
||||
# install_subdir('data/' + size, install_dir: icontheme_dir)
|
||||
#endforeach
|
||||
215
ottie/editor/ottie-editor-application.c
Normal file
215
ottie/editor/ottie-editor-application.c
Normal file
@@ -0,0 +1,215 @@
|
||||
/*
|
||||
* Copyright © 2020 Benjamin Otte
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "ottie-editor-application.h"
|
||||
|
||||
#include "ottie-editor-window.h"
|
||||
|
||||
struct _OttieEditorApplication
|
||||
{
|
||||
GtkApplication parent;
|
||||
};
|
||||
|
||||
struct _OttieEditorApplicationClass
|
||||
{
|
||||
GtkApplicationClass parent_class;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE(OttieEditorApplication, ottie_editor_application, GTK_TYPE_APPLICATION);
|
||||
|
||||
static void
|
||||
ottie_editor_application_init (OttieEditorApplication *app)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
activate_about (GSimpleAction *action,
|
||||
GVariant *parameter,
|
||||
gpointer user_data)
|
||||
{
|
||||
GtkApplication *app = user_data;
|
||||
char *version;
|
||||
GString *s;
|
||||
char *os_name;
|
||||
char *os_version;
|
||||
GtkWidget *dialog;
|
||||
|
||||
os_name = g_get_os_info (G_OS_INFO_KEY_NAME);
|
||||
os_version = g_get_os_info (G_OS_INFO_KEY_VERSION_ID);
|
||||
s = g_string_new ("");
|
||||
if (os_name && os_version)
|
||||
g_string_append_printf (s, "OS\t%s %s\n\n", os_name, os_version);
|
||||
|
||||
g_string_append (s, "System libraries\n");
|
||||
g_string_append_printf (s, "\tGLib\t%d.%d.%d\n",
|
||||
glib_major_version,
|
||||
glib_minor_version,
|
||||
glib_micro_version);
|
||||
g_string_append_printf (s, "\tPango\t%s\n",
|
||||
pango_version_string ());
|
||||
g_string_append_printf (s, "\tGTK\t%d.%d.%d\n",
|
||||
gtk_get_major_version (),
|
||||
gtk_get_minor_version (),
|
||||
gtk_get_micro_version ());
|
||||
|
||||
version = g_strdup_printf ("%s\nRunning against GTK %d.%d.%d",
|
||||
PACKAGE_VERSION,
|
||||
gtk_get_major_version (),
|
||||
gtk_get_minor_version (),
|
||||
gtk_get_micro_version ());
|
||||
|
||||
dialog = g_object_new (GTK_TYPE_ABOUT_DIALOG,
|
||||
"transient-for", gtk_application_get_active_window (app),
|
||||
"program-name", "GTK Node Editor",
|
||||
"version", version,
|
||||
"copyright", "© 2019—2020 The GTK Team",
|
||||
"license-type", GTK_LICENSE_LGPL_2_1,
|
||||
"website", "http://www.gtk.org",
|
||||
"comments", "Program to test GTK rendering",
|
||||
"authors", (const char *[]){ "Benjamin Otte", "Timm Bäder", NULL},
|
||||
"logo-icon-name", "org.gtk.gtk4.OttieEditor.Devel",
|
||||
"title", "About GTK Node Editor",
|
||||
"system-information", s->str,
|
||||
NULL);
|
||||
gtk_about_dialog_add_credit_section (GTK_ABOUT_DIALOG (dialog),
|
||||
"Artwork by", (const char *[]) { "Jakub Steiner", NULL });
|
||||
|
||||
gtk_window_present (GTK_WINDOW (dialog));
|
||||
|
||||
g_string_free (s, TRUE);
|
||||
g_free (version);
|
||||
g_free (os_name);
|
||||
g_free (os_version);
|
||||
}
|
||||
|
||||
static void
|
||||
activate_quit (GSimpleAction *action,
|
||||
GVariant *parameter,
|
||||
gpointer data)
|
||||
{
|
||||
g_application_quit (G_APPLICATION (data));
|
||||
}
|
||||
|
||||
static void
|
||||
activate_inspector (GSimpleAction *action,
|
||||
GVariant *parameter,
|
||||
gpointer user_data)
|
||||
{
|
||||
gtk_window_set_interactive_debugging (TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
activate_help (GSimpleAction *action,
|
||||
GVariant *parameter,
|
||||
gpointer user_data)
|
||||
{
|
||||
GtkBuilder *builder;
|
||||
GtkWidget *window;
|
||||
GtkTextBuffer *buffer;
|
||||
GBytes *bytes;
|
||||
const char *text;
|
||||
gsize len;
|
||||
|
||||
builder = gtk_builder_new ();
|
||||
gtk_builder_add_from_resource (builder, "/org/gtk/gtk4/node-editor/help-window.ui", NULL);
|
||||
window = GTK_WIDGET (gtk_builder_get_object (builder, "window"));
|
||||
buffer = GTK_TEXT_BUFFER (gtk_builder_get_object (builder, "buffer"));
|
||||
|
||||
bytes = g_resources_lookup_data ("/org/gtk/gtk4/node-editor/node-format.md",
|
||||
G_RESOURCE_LOOKUP_FLAGS_NONE,
|
||||
NULL);
|
||||
text = g_bytes_get_data (bytes, &len);
|
||||
gtk_text_buffer_set_text (buffer, text, len);
|
||||
g_bytes_unref (bytes);
|
||||
|
||||
gtk_window_present (GTK_WINDOW (window));
|
||||
g_object_unref (builder);
|
||||
}
|
||||
|
||||
static GActionEntry app_entries[] =
|
||||
{
|
||||
{ "about", activate_about, NULL, NULL, NULL },
|
||||
{ "quit", activate_quit, NULL, NULL, NULL },
|
||||
{ "inspector", activate_inspector, NULL, NULL, NULL },
|
||||
{ "help", activate_help, NULL, NULL, NULL },
|
||||
};
|
||||
|
||||
static void
|
||||
ottie_editor_application_startup (GApplication *app)
|
||||
{
|
||||
const char *help_accels[2] = { "F1", NULL };
|
||||
const char *quit_accels[2] = { "<Ctrl>Q", NULL };
|
||||
const char *open_accels[2] = { "<Ctrl>O", NULL };
|
||||
|
||||
G_APPLICATION_CLASS (ottie_editor_application_parent_class)->startup (app);
|
||||
|
||||
g_action_map_add_action_entries (G_ACTION_MAP (app),
|
||||
app_entries, G_N_ELEMENTS (app_entries),
|
||||
app);
|
||||
gtk_application_set_accels_for_action (GTK_APPLICATION (app), "app.help", help_accels);
|
||||
gtk_application_set_accels_for_action (GTK_APPLICATION (app), "app.quit", quit_accels);
|
||||
gtk_application_set_accels_for_action (GTK_APPLICATION (app), "win.open", open_accels);
|
||||
}
|
||||
|
||||
static void
|
||||
ottie_editor_application_activate (GApplication *app)
|
||||
{
|
||||
OttieEditorWindow *win;
|
||||
|
||||
win = ottie_editor_window_new (OTTIE_EDITOR_APPLICATION (app));
|
||||
gtk_window_present (GTK_WINDOW (win));
|
||||
}
|
||||
|
||||
static void
|
||||
ottie_editor_application_open (GApplication *app,
|
||||
GFile **files,
|
||||
int n_files,
|
||||
const char *hint)
|
||||
{
|
||||
OttieEditorWindow *win;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < n_files; i++)
|
||||
{
|
||||
win = ottie_editor_window_new (OTTIE_EDITOR_APPLICATION (app));
|
||||
ottie_editor_window_load (win, files[i]);
|
||||
gtk_window_present (GTK_WINDOW (win));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ottie_editor_application_class_init (OttieEditorApplicationClass *class)
|
||||
{
|
||||
GApplicationClass *application_class = G_APPLICATION_CLASS (class);
|
||||
|
||||
application_class->startup = ottie_editor_application_startup;
|
||||
application_class->activate = ottie_editor_application_activate;
|
||||
application_class->open = ottie_editor_application_open;
|
||||
}
|
||||
|
||||
OttieEditorApplication *
|
||||
ottie_editor_application_new (void)
|
||||
{
|
||||
return g_object_new (OTTIE_EDITOR_APPLICATION_TYPE,
|
||||
"application-id", "org.gtk.gtk4.OttieEditor",
|
||||
"flags", G_APPLICATION_HANDLES_OPEN,
|
||||
NULL);
|
||||
}
|
||||
38
ottie/editor/ottie-editor-application.h
Normal file
38
ottie/editor/ottie-editor-application.h
Normal file
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright © 2020 Benjamin Otte
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#ifndef __OTTIE_EDITOR_APPLICATION_H__
|
||||
#define __OTTIE_EDITOR_APPLICATION_H__
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
|
||||
#define OTTIE_EDITOR_APPLICATION_TYPE (ottie_editor_application_get_type ())
|
||||
#define OTTIE_EDITOR_APPLICATION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), OTTIE_EDITOR_APPLICATION_TYPE, OttieEditorApplication))
|
||||
|
||||
|
||||
typedef struct _OttieEditorApplication OttieEditorApplication;
|
||||
typedef struct _OttieEditorApplicationClass OttieEditorApplicationClass;
|
||||
|
||||
|
||||
GType ottie_editor_application_get_type (void);
|
||||
OttieEditorApplication *ottie_editor_application_new (void);
|
||||
|
||||
|
||||
#endif /* __OTTIE_EDITOR_APPLICATION_H__ */
|
||||
431
ottie/editor/ottie-editor-window.c
Normal file
431
ottie/editor/ottie-editor-window.c
Normal file
@@ -0,0 +1,431 @@
|
||||
/*
|
||||
* Copyright © 2020 Benjamin Otte
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "ottie-editor-window.h"
|
||||
|
||||
#include "ottie/ottiecreationprivate.h"
|
||||
#include "ottie/ottiecompositionlayerprivate.h"
|
||||
#include "ottie/ottiegroupshapeprivate.h"
|
||||
#include "ottie/ottieshapelayerprivate.h"
|
||||
#include "ottie/ottiepaintable.h"
|
||||
|
||||
struct _OttieEditorWindow
|
||||
{
|
||||
GtkApplicationWindow parent;
|
||||
|
||||
GFileMonitor *file_monitor;
|
||||
|
||||
OttieCreation *creation;
|
||||
OttiePaintable *paintable;
|
||||
|
||||
GtkWidget *picture;
|
||||
GtkWidget *listview;
|
||||
};
|
||||
|
||||
struct _OttieEditorWindowClass
|
||||
{
|
||||
GtkApplicationWindowClass parent_class;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE(OttieEditorWindow, ottie_editor_window, GTK_TYPE_APPLICATION_WINDOW);
|
||||
|
||||
static gboolean
|
||||
load_file_contents (OttieEditorWindow *self,
|
||||
GFile *file)
|
||||
{
|
||||
GBytes *bytes;
|
||||
|
||||
bytes = g_file_load_bytes (file, NULL, NULL, NULL);
|
||||
if (bytes == NULL)
|
||||
return FALSE;
|
||||
|
||||
if (!g_utf8_validate (g_bytes_get_data (bytes, NULL), g_bytes_get_size (bytes), NULL))
|
||||
{
|
||||
g_bytes_unref (bytes);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
ottie_creation_load_bytes (self->creation, bytes);
|
||||
#if 0
|
||||
gtk_text_buffer_set_text (self->text_buffer,
|
||||
g_bytes_get_data (bytes, NULL),
|
||||
g_bytes_get_size (bytes));
|
||||
#endif
|
||||
|
||||
g_bytes_unref (bytes);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
file_changed_cb (GFileMonitor *monitor,
|
||||
GFile *file,
|
||||
GFile *other_file,
|
||||
GFileMonitorEvent event_type,
|
||||
gpointer user_data)
|
||||
{
|
||||
OttieEditorWindow *self = user_data;
|
||||
|
||||
if (event_type == G_FILE_MONITOR_EVENT_CHANGED)
|
||||
load_file_contents (self, file);
|
||||
}
|
||||
|
||||
void
|
||||
ottie_editor_window_load (OttieEditorWindow *self,
|
||||
GFile *file)
|
||||
{
|
||||
GError *error = NULL;
|
||||
|
||||
if (!load_file_contents (self, file))
|
||||
return;
|
||||
|
||||
g_clear_object (&self->file_monitor);
|
||||
self->file_monitor = g_file_monitor_file (file, G_FILE_MONITOR_NONE, NULL, &error);
|
||||
|
||||
if (error)
|
||||
{
|
||||
g_warning ("couldn't monitor file: %s", error->message);
|
||||
g_error_free (error);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_signal_connect (self->file_monitor, "changed", G_CALLBACK (file_changed_cb), self);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
open_response_cb (GtkWidget *dialog,
|
||||
int response,
|
||||
OttieEditorWindow *self)
|
||||
{
|
||||
gtk_widget_hide (dialog);
|
||||
|
||||
if (response == GTK_RESPONSE_ACCEPT)
|
||||
{
|
||||
GFile *file;
|
||||
|
||||
file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (dialog));
|
||||
ottie_editor_window_load (self, file);
|
||||
g_object_unref (file);
|
||||
}
|
||||
|
||||
gtk_window_destroy (GTK_WINDOW (dialog));
|
||||
}
|
||||
|
||||
static void
|
||||
show_open_filechooser (OttieEditorWindow *self)
|
||||
{
|
||||
GtkWidget *dialog;
|
||||
|
||||
dialog = gtk_file_chooser_dialog_new ("Open lottie file",
|
||||
GTK_WINDOW (self),
|
||||
GTK_FILE_CHOOSER_ACTION_OPEN,
|
||||
"_Cancel", GTK_RESPONSE_CANCEL,
|
||||
"_Load", GTK_RESPONSE_ACCEPT,
|
||||
NULL);
|
||||
|
||||
gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_ACCEPT);
|
||||
gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
|
||||
|
||||
GFile *cwd = g_file_new_for_path (".");
|
||||
gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), cwd, NULL);
|
||||
g_object_unref (cwd);
|
||||
|
||||
g_signal_connect (dialog, "response", G_CALLBACK (open_response_cb), self);
|
||||
gtk_widget_show (dialog);
|
||||
}
|
||||
|
||||
static void
|
||||
open_cb (GtkWidget *button,
|
||||
OttieEditorWindow *self)
|
||||
{
|
||||
show_open_filechooser (self);
|
||||
}
|
||||
|
||||
static void
|
||||
save_response_cb (GtkWidget *dialog,
|
||||
int response,
|
||||
OttieEditorWindow *self)
|
||||
{
|
||||
gtk_widget_hide (dialog);
|
||||
|
||||
if (response == GTK_RESPONSE_ACCEPT)
|
||||
{
|
||||
#if 0
|
||||
GFile *file;
|
||||
char *text;
|
||||
#endif
|
||||
GError *error = NULL;
|
||||
|
||||
#if 0
|
||||
text = get_current_text (self->text_buffer);
|
||||
|
||||
file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (dialog));
|
||||
g_file_replace_contents (file, text, strlen (text),
|
||||
NULL, FALSE,
|
||||
G_FILE_CREATE_NONE,
|
||||
NULL,
|
||||
NULL,
|
||||
&error);
|
||||
#endif
|
||||
|
||||
if (error != NULL)
|
||||
{
|
||||
GtkWidget *message_dialog;
|
||||
|
||||
message_dialog = gtk_message_dialog_new (GTK_WINDOW (gtk_widget_get_root (GTK_WIDGET (self))),
|
||||
GTK_DIALOG_MODAL|GTK_DIALOG_DESTROY_WITH_PARENT,
|
||||
GTK_MESSAGE_INFO,
|
||||
GTK_BUTTONS_OK,
|
||||
"Saving failed");
|
||||
gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (message_dialog),
|
||||
"%s", error->message);
|
||||
g_signal_connect (message_dialog, "response", G_CALLBACK (gtk_window_destroy), NULL);
|
||||
gtk_widget_show (message_dialog);
|
||||
g_error_free (error);
|
||||
}
|
||||
|
||||
#if 0
|
||||
g_free (text);
|
||||
g_object_unref (file);
|
||||
#endif
|
||||
}
|
||||
|
||||
gtk_window_destroy (GTK_WINDOW (dialog));
|
||||
}
|
||||
|
||||
static void
|
||||
save_cb (GtkWidget *button,
|
||||
OttieEditorWindow *self)
|
||||
{
|
||||
GtkWidget *dialog;
|
||||
|
||||
dialog = gtk_file_chooser_dialog_new ("Save file",
|
||||
GTK_WINDOW (gtk_widget_get_root (GTK_WIDGET (button))),
|
||||
GTK_FILE_CHOOSER_ACTION_SAVE,
|
||||
"_Cancel", GTK_RESPONSE_CANCEL,
|
||||
"_Save", GTK_RESPONSE_ACCEPT,
|
||||
NULL);
|
||||
|
||||
gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_ACCEPT);
|
||||
gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
|
||||
|
||||
GFile *cwd = g_file_new_for_path (".");
|
||||
gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), cwd, NULL);
|
||||
g_object_unref (cwd);
|
||||
|
||||
g_signal_connect (dialog, "response", G_CALLBACK (save_response_cb), self);
|
||||
gtk_widget_show (dialog);
|
||||
}
|
||||
|
||||
static GdkTexture *
|
||||
create_texture (OttieEditorWindow *self)
|
||||
{
|
||||
GtkSnapshot *snapshot;
|
||||
GskRenderer *renderer;
|
||||
GskRenderNode *node;
|
||||
GdkTexture *texture;
|
||||
int width, height;
|
||||
|
||||
width = gdk_paintable_get_intrinsic_width (GDK_PAINTABLE (self->paintable));
|
||||
height = gdk_paintable_get_intrinsic_height (GDK_PAINTABLE (self->paintable));
|
||||
|
||||
if (width <= 0 || height <= 0)
|
||||
return NULL;
|
||||
snapshot = gtk_snapshot_new ();
|
||||
gdk_paintable_snapshot (GDK_PAINTABLE (self->paintable), snapshot, width, height);
|
||||
node = gtk_snapshot_free_to_node (snapshot);
|
||||
if (node == NULL)
|
||||
return NULL;
|
||||
|
||||
renderer = gtk_native_get_renderer (gtk_widget_get_native (GTK_WIDGET (self)));
|
||||
texture = gsk_renderer_render_texture (renderer, node, NULL);
|
||||
gsk_render_node_unref (node);
|
||||
|
||||
return texture;
|
||||
}
|
||||
|
||||
static void
|
||||
export_image_response_cb (GtkWidget *dialog,
|
||||
int response,
|
||||
GdkTexture *texture)
|
||||
{
|
||||
gtk_widget_hide (dialog);
|
||||
|
||||
if (response == GTK_RESPONSE_ACCEPT)
|
||||
{
|
||||
GFile *file;
|
||||
|
||||
file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (dialog));
|
||||
if (!gdk_texture_save_to_png (texture, g_file_peek_path (file)))
|
||||
{
|
||||
GtkWidget *message_dialog;
|
||||
|
||||
message_dialog = gtk_message_dialog_new (GTK_WINDOW (gtk_window_get_transient_for (GTK_WINDOW (dialog))),
|
||||
GTK_DIALOG_MODAL|GTK_DIALOG_DESTROY_WITH_PARENT,
|
||||
GTK_MESSAGE_INFO,
|
||||
GTK_BUTTONS_OK,
|
||||
"Exporting to image failed");
|
||||
g_signal_connect (message_dialog, "response", G_CALLBACK (gtk_window_destroy), NULL);
|
||||
gtk_widget_show (message_dialog);
|
||||
}
|
||||
|
||||
g_object_unref (file);
|
||||
}
|
||||
|
||||
gtk_window_destroy (GTK_WINDOW (dialog));
|
||||
g_object_unref (texture);
|
||||
}
|
||||
|
||||
static void
|
||||
export_image_cb (GtkWidget *button,
|
||||
OttieEditorWindow *self)
|
||||
{
|
||||
GdkTexture *texture;
|
||||
GtkWidget *dialog;
|
||||
|
||||
texture = create_texture (self);
|
||||
if (texture == NULL)
|
||||
return;
|
||||
|
||||
dialog = gtk_file_chooser_dialog_new ("",
|
||||
GTK_WINDOW (gtk_widget_get_root (GTK_WIDGET (button))),
|
||||
GTK_FILE_CHOOSER_ACTION_SAVE,
|
||||
"_Cancel", GTK_RESPONSE_CANCEL,
|
||||
"_Save", GTK_RESPONSE_ACCEPT,
|
||||
NULL);
|
||||
|
||||
gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_ACCEPT);
|
||||
gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
|
||||
g_signal_connect (dialog, "response", G_CALLBACK (export_image_response_cb), texture);
|
||||
gtk_widget_show (dialog);
|
||||
}
|
||||
|
||||
static GListModel *
|
||||
create_object_children (gpointer item,
|
||||
gpointer user_data)
|
||||
{
|
||||
if (OTTIE_IS_COMPOSITION_LAYER (item))
|
||||
{
|
||||
return G_LIST_MODEL (g_object_ref (ottie_composition_layer_get_composition (item)));
|
||||
}
|
||||
else if (OTTIE_IS_SHAPE_LAYER (item))
|
||||
{
|
||||
return G_LIST_MODEL (g_object_ref (ottie_shape_layer_get_shape (item)));
|
||||
}
|
||||
else if (OTTIE_IS_GROUP_SHAPE (item))
|
||||
{
|
||||
return g_object_ref (item);
|
||||
}
|
||||
else
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
notify_prepared_cb (OttieCreation *creation,
|
||||
GParamSpec *pspec,
|
||||
OttieEditorWindow *self)
|
||||
{
|
||||
GtkTreeListModel *treemodel;
|
||||
GtkSingleSelection *selection;
|
||||
|
||||
if (ottie_creation_is_prepared (creation))
|
||||
{
|
||||
treemodel = gtk_tree_list_model_new (G_LIST_MODEL (ottie_creation_get_composition (self->creation)),
|
||||
FALSE,
|
||||
TRUE,
|
||||
create_object_children,
|
||||
NULL,
|
||||
NULL);
|
||||
selection = gtk_single_selection_new (G_LIST_MODEL (treemodel));
|
||||
gtk_list_view_set_model (GTK_LIST_VIEW (self->listview), GTK_SELECTION_MODEL (selection));
|
||||
g_object_unref (selection);
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_list_view_set_model (GTK_LIST_VIEW (self->listview), NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ottie_editor_window_finalize (GObject *object)
|
||||
{
|
||||
//OttieEditorWindow *self = OTTIE_EDITOR_WINDOW (object);
|
||||
|
||||
G_OBJECT_CLASS (ottie_editor_window_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
ottie_editor_window_class_init (OttieEditorWindowClass *class)
|
||||
{
|
||||
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (class);
|
||||
|
||||
object_class->finalize = ottie_editor_window_finalize;
|
||||
|
||||
g_type_ensure (OTTIE_TYPE_CREATION);
|
||||
g_type_ensure (OTTIE_TYPE_PAINTABLE);
|
||||
|
||||
gtk_widget_class_set_template_from_resource (widget_class,
|
||||
"/org/gtk/gtk4/ottie-editor/ottie-editor-window.ui");
|
||||
|
||||
gtk_widget_class_bind_template_child (widget_class, OttieEditorWindow, creation);
|
||||
gtk_widget_class_bind_template_child (widget_class, OttieEditorWindow, paintable);
|
||||
gtk_widget_class_bind_template_child (widget_class, OttieEditorWindow, picture);
|
||||
gtk_widget_class_bind_template_child (widget_class, OttieEditorWindow, listview);
|
||||
|
||||
gtk_widget_class_bind_template_callback (widget_class, open_cb);
|
||||
gtk_widget_class_bind_template_callback (widget_class, save_cb);
|
||||
gtk_widget_class_bind_template_callback (widget_class, export_image_cb);
|
||||
gtk_widget_class_bind_template_callback (widget_class, notify_prepared_cb);
|
||||
}
|
||||
|
||||
static void
|
||||
window_open (GSimpleAction *action,
|
||||
GVariant *parameter,
|
||||
gpointer user_data)
|
||||
{
|
||||
OttieEditorWindow *self = user_data;
|
||||
|
||||
show_open_filechooser (self);
|
||||
}
|
||||
|
||||
static GActionEntry win_entries[] = {
|
||||
{ "open", window_open, NULL, NULL, NULL },
|
||||
};
|
||||
|
||||
static void
|
||||
ottie_editor_window_init (OttieEditorWindow *self)
|
||||
{
|
||||
gtk_widget_init_template (GTK_WIDGET (self));
|
||||
|
||||
g_action_map_add_action_entries (G_ACTION_MAP (self), win_entries, G_N_ELEMENTS (win_entries), self);
|
||||
}
|
||||
|
||||
OttieEditorWindow *
|
||||
ottie_editor_window_new (OttieEditorApplication *application)
|
||||
{
|
||||
return g_object_new (OTTIE_EDITOR_WINDOW_TYPE,
|
||||
"application", application,
|
||||
NULL);
|
||||
}
|
||||
42
ottie/editor/ottie-editor-window.h
Normal file
42
ottie/editor/ottie-editor-window.h
Normal file
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright © 2020 Benjamin Otte
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#ifndef __OTTIE_EDITOR_WINDOW_H__
|
||||
#define __OTTIE_EDITOR_WINDOW_H__
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "ottie-editor-application.h"
|
||||
|
||||
#define OTTIE_EDITOR_WINDOW_TYPE (ottie_editor_window_get_type ())
|
||||
#define OTTIE_EDITOR_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), OTTIE_EDITOR_WINDOW_TYPE, OttieEditorWindow))
|
||||
|
||||
|
||||
typedef struct _OttieEditorWindow OttieEditorWindow;
|
||||
typedef struct _OttieEditorWindowClass OttieEditorWindowClass;
|
||||
|
||||
|
||||
GType ottie_editor_window_get_type (void);
|
||||
|
||||
OttieEditorWindow * ottie_editor_window_new (OttieEditorApplication *application);
|
||||
|
||||
void ottie_editor_window_load (OttieEditorWindow *self,
|
||||
GFile *file);
|
||||
|
||||
#endif /* __OTTIE_EDITOR_WINDOW_H__ */
|
||||
133
ottie/editor/ottie-editor-window.ui
Normal file
133
ottie/editor/ottie-editor-window.ui
Normal file
@@ -0,0 +1,133 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<menu id="gear_menu">
|
||||
<section>
|
||||
<item>
|
||||
<attribute name="label" translatable="yes">_Help</attribute>
|
||||
<attribute name="action">app.help</attribute>
|
||||
</item>
|
||||
<item>
|
||||
<attribute name="label" translatable="yes">_Inspector</attribute>
|
||||
<attribute name="action">app.inspector</attribute>
|
||||
</item>
|
||||
<item>
|
||||
<attribute name="label" translatable="yes">_About Ottie Editor</attribute>
|
||||
<attribute name="action">app.about</attribute>
|
||||
</item>
|
||||
</section>
|
||||
</menu>
|
||||
|
||||
<object class="OttieCreation" id="creation">
|
||||
<signal name="notify::prepared" handler="notify_prepared_cb"/>
|
||||
</object>
|
||||
|
||||
<object class="OttiePaintable" id="paintable">
|
||||
<property name="creation">creation</property>
|
||||
</object>
|
||||
|
||||
<template class="OttieEditorWindow" parent="GtkApplicationWindow">
|
||||
<property name="title" translatable="yes">Ottie Editor</property>
|
||||
<property name="default-width">1024</property>
|
||||
<property name="default-height">768</property>
|
||||
<child type="titlebar">
|
||||
<object class="GtkHeaderBar" id="header">
|
||||
<child type="start">
|
||||
<object class="GtkButton">
|
||||
<property name="icon-name">document-open-symbolic</property>
|
||||
<property name="tooltip-text">Open file</property>
|
||||
<signal name="clicked" handler="open_cb"/>
|
||||
</object>
|
||||
</child>
|
||||
<child type="start">
|
||||
<object class="GtkButton">
|
||||
<property name="icon-name">document-save-symbolic</property>
|
||||
<property name="tooltip-text">Save</property>
|
||||
<signal name="clicked" handler="save_cb"/>
|
||||
</object>
|
||||
</child>
|
||||
<child type="start">
|
||||
<object class="GtkButton">
|
||||
<property name="icon-name">insert-image-symbolic</property>
|
||||
<property name="tooltip-text">Export to image</property>
|
||||
<signal name="clicked" handler="export_image_cb"/>
|
||||
</object>
|
||||
</child>
|
||||
<child type="end">
|
||||
<object class="GtkMenuButton" id="gear_menu_button">
|
||||
<property name="valign">center</property>
|
||||
<property name="menu-model">gear_menu</property>
|
||||
<property name="icon-name">open-menu-symbolic</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkPaned">
|
||||
<property name="shrink-end-child">false</property>
|
||||
<property name="position">400</property>
|
||||
<child>
|
||||
<object class="GtkScrolledWindow">
|
||||
<property name="hexpand">1</property>
|
||||
<property name="vexpand">1</property>
|
||||
<child>
|
||||
<object class="GtkListView" id="listview">
|
||||
<property name="factory">
|
||||
<object class="GtkBuilderListItemFactory">
|
||||
<property name="bytes"><![CDATA[
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<template class="GtkListItem">
|
||||
<property name="child">
|
||||
<object class="GtkTreeExpander" id="expander">
|
||||
<binding name="list-row">
|
||||
<lookup name="item">GtkListItem</lookup>
|
||||
</binding>
|
||||
<property name="child">
|
||||
<object class="GtkLabel">
|
||||
<property name="xalign">0</property>
|
||||
<binding name="label">
|
||||
<lookup name="name" type="OttieObject">
|
||||
<lookup name="item">expander</lookup>
|
||||
</lookup>
|
||||
</binding>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
</property>
|
||||
</template>
|
||||
</interface>
|
||||
]]></property>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<child>
|
||||
<object class="GtkScrolledWindow">
|
||||
<property name="hexpand">1</property>
|
||||
<property name="vexpand">1</property>
|
||||
<property name="min-content-height">100</property>
|
||||
<property name="min-content-width">100</property>
|
||||
<child>
|
||||
<object class="GtkViewport">
|
||||
<child>
|
||||
<object class="GtkPicture" id="picture">
|
||||
<property name="can-shrink">0</property>
|
||||
<property name="paintable">paintable</property>
|
||||
<property name="halign">center</property>
|
||||
<property name="valign">center</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</template>
|
||||
</interface>
|
||||
6
ottie/editor/ottie-editor.gresource.xml
Normal file
6
ottie/editor/ottie-editor.gresource.xml
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<gresources>
|
||||
<gresource prefix="/org/gtk/gtk4/ottie-editor">
|
||||
<file preprocess="xml-stripblanks">ottie-editor-window.ui</file>
|
||||
</gresource>
|
||||
</gresources>
|
||||
Reference in New Issue
Block a user