2021-11-23 22:03:45 +01:00
|
|
|
#include <math.h>
|
|
|
|
|
2021-11-15 22:26:20 +01:00
|
|
|
#include <gtk/gtk.h>
|
2021-11-16 23:14:05 +01:00
|
|
|
#include <gdk/gdk.h>
|
2021-11-15 22:26:20 +01:00
|
|
|
|
|
|
|
#include <openmg/chapter.h>
|
|
|
|
#include <openmg/view/chapter_view.h>
|
|
|
|
#include <openmg/view/picture.h>
|
|
|
|
#include <openmg/util/gobject_utility_extensions.h>
|
|
|
|
#include <openmg/util/string.h>
|
|
|
|
#include <openmg/backend/readmng.h>
|
|
|
|
|
|
|
|
static void
|
|
|
|
fire_zoom (GtkGestureZoom *zoom,
|
|
|
|
gdouble scale,
|
|
|
|
gpointer user_data);
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
guint current_page;
|
|
|
|
GListModel *pages;
|
|
|
|
GtkPicture *current_picture;
|
2021-11-17 23:34:46 +01:00
|
|
|
AdwLeaflet *views_leaflet;
|
|
|
|
GtkScrolledWindow *zoomable_picture_container;
|
2021-11-23 22:03:45 +01:00
|
|
|
double zoom;
|
2021-11-15 22:26:20 +01:00
|
|
|
} ChapterVisorData;
|
2021-11-16 23:14:05 +01:00
|
|
|
|
2021-11-17 23:34:46 +01:00
|
|
|
static void
|
|
|
|
set_image_zoomable_picture_container (ChapterVisorData *chapter_visor_data);
|
|
|
|
static void
|
|
|
|
set_zoomable_picture_container_properties (
|
2021-11-23 20:37:23 +01:00
|
|
|
GtkScrolledWindow *zoomable_picture_container,
|
|
|
|
ChapterVisorData *chapter_visor_data);
|
2021-11-17 23:34:46 +01:00
|
|
|
static void
|
|
|
|
append_chapter_view_leaflet (AdwLeaflet *views_leaflet,
|
|
|
|
GtkBox *chapter_view_container);
|
|
|
|
static void
|
|
|
|
add_controls_overlay (GtkOverlay *overlay, ChapterVisorData *chapter_visor_data);
|
|
|
|
static void
|
|
|
|
go_prev (GtkButton *prev,
|
|
|
|
gpointer user_data);
|
|
|
|
static void
|
|
|
|
go_next (GtkButton *next,
|
|
|
|
gpointer user_data);
|
2021-11-23 22:03:45 +01:00
|
|
|
static void
|
|
|
|
set_image_dimensions (GtkWidget *picture,
|
2021-11-23 22:18:03 +01:00
|
|
|
ChapterVisorData *chapter_visor_data,
|
|
|
|
gdouble scale);
|
|
|
|
static void
|
|
|
|
zoom_end (GtkGesture *zoom,
|
|
|
|
GdkEventSequence *sequence,
|
|
|
|
gpointer user_data);
|
|
|
|
|
2021-11-16 23:14:05 +01:00
|
|
|
static void
|
|
|
|
image_page_show (GtkWidget *picture, gpointer user_data) {
|
2021-11-23 22:03:45 +01:00
|
|
|
ChapterVisorData *chapter_visor_data = (ChapterVisorData *) user_data;
|
|
|
|
|
|
|
|
chapter_visor_data->zoom = 1;
|
2021-11-23 22:18:03 +01:00
|
|
|
set_image_dimensions (picture, chapter_visor_data, 1);
|
2021-11-23 22:03:45 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
set_image_dimensions (GtkWidget *picture,
|
2021-11-23 22:18:03 +01:00
|
|
|
ChapterVisorData *chapter_visor_data,
|
|
|
|
gdouble scale) {
|
2021-11-16 23:14:05 +01:00
|
|
|
double final_width = 0;
|
|
|
|
double final_height = 0;
|
2021-11-23 22:03:45 +01:00
|
|
|
GdkPaintable *paintable = gtk_picture_get_paintable (GTK_PICTURE (picture));
|
|
|
|
GtkWidget *views_leaflet = GTK_WIDGET (chapter_visor_data->views_leaflet);
|
2021-11-23 22:22:06 +01:00
|
|
|
gdouble scale_factor = log (scale) / 20 + log (chapter_visor_data->zoom);
|
2021-11-23 22:18:03 +01:00
|
|
|
chapter_visor_data->zoom = pow (M_E, scale_factor);
|
2021-11-16 23:14:05 +01:00
|
|
|
guint width = gtk_widget_get_allocated_width
|
2021-11-23 22:03:45 +01:00
|
|
|
(views_leaflet) * chapter_visor_data->zoom;
|
2021-11-16 23:14:05 +01:00
|
|
|
gdk_paintable_compute_concrete_size (
|
2021-11-23 22:03:45 +01:00
|
|
|
paintable,
|
|
|
|
width,
|
|
|
|
0,
|
|
|
|
gdk_paintable_get_intrinsic_width (paintable),
|
|
|
|
gdk_paintable_get_intrinsic_height (paintable),
|
|
|
|
&final_width,
|
|
|
|
&final_height
|
|
|
|
);
|
|
|
|
g_object_set_property_int (G_OBJECT (picture),
|
|
|
|
"width-request", (int) final_width);
|
|
|
|
g_object_set_property_int (G_OBJECT (picture),
|
|
|
|
"height-request", (int) final_height);
|
2021-11-16 23:14:05 +01:00
|
|
|
g_object_set_property_int (G_OBJECT (picture),
|
|
|
|
"width-request", (int) final_width);
|
|
|
|
g_object_set_property_int (G_OBJECT (picture),
|
|
|
|
"height-request", (int) final_height);
|
|
|
|
}
|
|
|
|
|
2021-11-15 22:26:20 +01:00
|
|
|
void
|
|
|
|
setup_chapter_view (MgMangaChapter *chapter, AdwLeaflet *views_leaflet) {
|
|
|
|
MgBackendReadmng *readmng = mg_backend_readmng_new ();
|
|
|
|
GtkBox *chapter_view_container = GTK_BOX (gtk_box_new (GTK_ORIENTATION_VERTICAL, 0));
|
|
|
|
GtkScrolledWindow *zoomable_picture_container = GTK_SCROLLED_WINDOW (gtk_scrolled_window_new ());
|
2021-11-17 23:34:46 +01:00
|
|
|
GtkOverlay *overlay = GTK_OVERLAY (gtk_overlay_new ());
|
2021-11-15 22:26:20 +01:00
|
|
|
GListModel *pages = mg_backend_readmng_get_chapter_images (readmng, chapter);
|
|
|
|
ChapterVisorData *chapter_visor_data = g_malloc (sizeof *chapter_visor_data);
|
2021-11-17 23:34:46 +01:00
|
|
|
chapter_visor_data->current_page = 0;
|
|
|
|
chapter_visor_data->pages = pages;
|
|
|
|
chapter_visor_data->views_leaflet = views_leaflet;
|
|
|
|
chapter_visor_data->zoomable_picture_container = zoomable_picture_container;
|
2021-11-23 20:37:23 +01:00
|
|
|
set_zoomable_picture_container_properties (zoomable_picture_container,
|
|
|
|
chapter_visor_data);
|
2021-11-17 23:34:46 +01:00
|
|
|
set_image_zoomable_picture_container (chapter_visor_data);
|
|
|
|
|
|
|
|
gtk_overlay_set_child (overlay, GTK_WIDGET (zoomable_picture_container));
|
|
|
|
add_controls_overlay (overlay, chapter_visor_data);
|
|
|
|
gtk_box_append (chapter_view_container, GTK_WIDGET (overlay));
|
|
|
|
append_chapter_view_leaflet (views_leaflet, chapter_view_container);
|
2021-11-22 01:02:00 +01:00
|
|
|
|
|
|
|
g_clear_object (&readmng);
|
2021-11-17 23:34:46 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
add_controls_overlay (GtkOverlay *overlay, ChapterVisorData *chapter_visor_data) {
|
2021-11-16 23:14:05 +01:00
|
|
|
GtkButton *next_button = GTK_BUTTON (gtk_button_new_from_icon_name
|
|
|
|
("go-next-symbolic"));
|
|
|
|
GtkButton *previous_button = GTK_BUTTON (gtk_button_new_from_icon_name
|
|
|
|
("go-previous-symbolic"));
|
2021-11-17 23:34:46 +01:00
|
|
|
g_signal_connect (G_OBJECT (next_button), "clicked", G_CALLBACK (go_next), chapter_visor_data);
|
|
|
|
g_signal_connect (G_OBJECT (previous_button), "clicked", G_CALLBACK (go_prev), chapter_visor_data);
|
|
|
|
gtk_widget_set_valign (GTK_WIDGET (next_button), GTK_ALIGN_CENTER);
|
|
|
|
gtk_widget_set_halign (GTK_WIDGET (next_button), GTK_ALIGN_END);
|
|
|
|
gtk_widget_set_valign (GTK_WIDGET (previous_button), GTK_ALIGN_CENTER);
|
|
|
|
gtk_widget_set_halign (GTK_WIDGET (previous_button), GTK_ALIGN_START);
|
|
|
|
gtk_overlay_add_overlay (overlay, GTK_WIDGET (next_button));
|
|
|
|
gtk_overlay_add_overlay (overlay, GTK_WIDGET (previous_button));
|
|
|
|
}
|
|
|
|
static void
|
|
|
|
go_next (GtkButton *next,
|
|
|
|
gpointer user_data) {
|
|
|
|
ChapterVisorData *chapter_visor_data = (ChapterVisorData *) user_data;
|
|
|
|
GListModel *pages = chapter_visor_data->pages;
|
|
|
|
if (chapter_visor_data->current_page < g_list_model_get_n_items (pages) -1) {
|
|
|
|
chapter_visor_data->current_page = chapter_visor_data->current_page + 1;
|
|
|
|
set_image_zoomable_picture_container (chapter_visor_data);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
static void
|
|
|
|
go_prev (GtkButton *prev,
|
|
|
|
gpointer user_data) {
|
|
|
|
ChapterVisorData *chapter_visor_data = (ChapterVisorData *) user_data;
|
|
|
|
if (chapter_visor_data->current_page > 0) {
|
|
|
|
chapter_visor_data->current_page = chapter_visor_data->current_page - 1;
|
|
|
|
set_image_zoomable_picture_container (chapter_visor_data);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
set_image_zoomable_picture_container (ChapterVisorData *chapter_visor_data) {
|
|
|
|
GtkScrolledWindow *zoomable_picture_container = chapter_visor_data->zoomable_picture_container;
|
|
|
|
MgUtilString *string_util = mg_util_string_new ();
|
|
|
|
GtkPicture *current_picture;
|
|
|
|
GListModel *pages = chapter_visor_data->pages;
|
|
|
|
guint current_page = chapter_visor_data->current_page;
|
2021-11-15 22:26:20 +01:00
|
|
|
const char *url_image_not_owned =
|
2021-11-16 23:14:05 +01:00
|
|
|
gtk_string_list_get_string (GTK_STRING_LIST
|
2021-11-17 23:34:46 +01:00
|
|
|
(pages), current_page);
|
2021-11-15 22:26:20 +01:00
|
|
|
char *url_image = mg_util_string_alloc_string (string_util, strlen (url_image_not_owned));
|
|
|
|
mg_util_string_copy_substring (string_util,
|
|
|
|
url_image_not_owned, url_image,
|
|
|
|
strlen(url_image_not_owned) + 1, 0,
|
|
|
|
strlen (url_image_not_owned));
|
2021-11-16 23:14:05 +01:00
|
|
|
|
2021-11-15 22:26:20 +01:00
|
|
|
current_picture = create_picture_from_url
|
2021-11-22 22:31:05 +01:00
|
|
|
(url_image, 0);
|
2021-11-17 23:34:46 +01:00
|
|
|
chapter_visor_data->current_picture = current_picture;
|
2021-11-16 23:14:05 +01:00
|
|
|
g_signal_connect (G_OBJECT (current_picture), "map",
|
2021-11-23 22:03:45 +01:00
|
|
|
G_CALLBACK (image_page_show), chapter_visor_data);
|
2021-11-15 22:26:20 +01:00
|
|
|
gtk_scrolled_window_set_child (zoomable_picture_container, GTK_WIDGET (current_picture));
|
2021-11-22 01:02:00 +01:00
|
|
|
|
|
|
|
g_free (url_image);
|
|
|
|
g_clear_object (&string_util);
|
2021-11-17 23:34:46 +01:00
|
|
|
}
|
2021-11-15 22:26:20 +01:00
|
|
|
|
2021-11-17 23:34:46 +01:00
|
|
|
static void
|
|
|
|
set_zoomable_picture_container_properties (
|
2021-11-23 20:37:23 +01:00
|
|
|
GtkScrolledWindow *zoomable_picture_container,
|
|
|
|
ChapterVisorData *chapter_visor_data) {
|
2021-11-17 23:34:46 +01:00
|
|
|
GtkGesture *zoom_controller = gtk_gesture_zoom_new ();
|
|
|
|
g_object_set_property_int (G_OBJECT (zoomable_picture_container), "hexpand", 1);
|
|
|
|
g_object_set_property_int (G_OBJECT (zoomable_picture_container), "vexpand", 1);
|
2021-11-15 22:26:20 +01:00
|
|
|
gtk_widget_add_controller (GTK_WIDGET (zoomable_picture_container),
|
|
|
|
GTK_EVENT_CONTROLLER (zoom_controller));
|
2021-11-23 20:37:23 +01:00
|
|
|
g_signal_connect (G_OBJECT (zoom_controller), "scale-changed", G_CALLBACK (fire_zoom), chapter_visor_data);
|
2021-11-23 22:18:03 +01:00
|
|
|
g_signal_connect (G_OBJECT (zoom_controller), "end", G_CALLBACK (zoom_end), chapter_visor_data);
|
2021-11-17 23:34:46 +01:00
|
|
|
}
|
|
|
|
|
2021-11-15 22:26:20 +01:00
|
|
|
|
2021-11-17 23:34:46 +01:00
|
|
|
static void
|
|
|
|
append_chapter_view_leaflet (AdwLeaflet *views_leaflet,
|
|
|
|
GtkBox *chapter_view_container) {
|
2021-11-16 23:14:05 +01:00
|
|
|
GtkWidget *widget = adw_leaflet_get_adjacent_child
|
|
|
|
(views_leaflet, ADW_NAVIGATION_DIRECTION_FORWARD);
|
|
|
|
for (;widget;widget = adw_leaflet_get_adjacent_child
|
|
|
|
(views_leaflet, ADW_NAVIGATION_DIRECTION_FORWARD)) {
|
|
|
|
adw_leaflet_remove (views_leaflet, widget);
|
|
|
|
}
|
2021-11-15 22:26:20 +01:00
|
|
|
adw_leaflet_append (views_leaflet, GTK_WIDGET (chapter_view_container));
|
|
|
|
adw_leaflet_navigate (views_leaflet, ADW_NAVIGATION_DIRECTION_FORWARD);
|
2021-11-17 23:34:46 +01:00
|
|
|
|
2021-11-15 22:26:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
fire_zoom (GtkGestureZoom *zoom,
|
|
|
|
gdouble scale,
|
|
|
|
gpointer user_data) {
|
2021-11-23 22:03:45 +01:00
|
|
|
ChapterVisorData *chapter_visor_data = (ChapterVisorData *) user_data;
|
2021-11-23 22:18:03 +01:00
|
|
|
set_image_dimensions (GTK_WIDGET (chapter_visor_data->current_picture),
|
|
|
|
chapter_visor_data, scale);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
zoom_end (GtkGesture *zoom,
|
|
|
|
GdkEventSequence *sequence,
|
|
|
|
gpointer user_data) {
|
|
|
|
ChapterVisorData *chapter_visor_data = (ChapterVisorData *) user_data;
|
|
|
|
gdouble scale = gtk_gesture_zoom_get_scale_delta
|
|
|
|
(GTK_GESTURE_ZOOM (zoom));
|
2021-11-23 22:22:06 +01:00
|
|
|
gdouble scale_factor = log (scale) / 20 + log (chapter_visor_data->zoom);
|
2021-11-23 22:03:45 +01:00
|
|
|
chapter_visor_data->zoom = pow (M_E, scale_factor);
|
2021-11-15 22:26:20 +01:00
|
|
|
}
|