[libgepub/widget-pagination] Pagination "almost" working with column-width css
- From: Daniel Garcia Moreno <danigm src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [libgepub/widget-pagination] Pagination "almost" working with column-width css
- Date: Fri, 19 May 2017 11:21:00 +0000 (UTC)
commit cf878df4c3ef7e27245c0c778fada5634a1b51bb
Author: Daniel GarcĂa Moreno <danigm wadobo com>
Date: Fri May 19 13:18:18 2017 +0200
Pagination "almost" working with column-width css
libgepub/gepub-widget.c | 354 ++++++++++++++++++++++++++++++++++-------------
libgepub/gepub-widget.h | 17 ++-
tests/test-gepub.c | 40 +++---
3 files changed, 285 insertions(+), 126 deletions(-)
---
diff --git a/libgepub/gepub-widget.c b/libgepub/gepub-widget.c
index f4ef9d0..5f52814 100644
--- a/libgepub/gepub-widget.c
+++ b/libgepub/gepub-widget.c
@@ -28,8 +28,10 @@ struct _GepubWidget {
GepubDoc *doc;
gboolean paginate;
- gint page;
- gint chapter_pages;
+ gint chapter_length; // real chapter length
+ gint chapter_pos; // position in the chapter, a percentage based on chapter_length
+ gint length;
+ gint init_chapter_pos;
};
struct _GepubWidgetClass {
@@ -40,8 +42,9 @@ enum {
PROP_0,
PROP_DOC,
PROP_PAGINATE,
- PROP_PAGE,
- PROP_NPAGES,
+ PROP_CHAPTER,
+ PROP_N_CHAPTERS,
+ PROP_CHAPTER_POS,
NUM_PROPS
};
@@ -50,6 +53,30 @@ static GParamSpec *properties[NUM_PROPS] = { NULL, };
G_DEFINE_TYPE (GepubWidget, gepub_widget, WEBKIT_TYPE_WEB_VIEW)
static void
+scroll_to_chapter_pos (GepubWidget *widget) {
+ gchar *script = g_strdup_printf("document.querySelector('body').scrollTo(%d, 0)", widget->chapter_pos);
+ webkit_web_view_run_javascript (WEBKIT_WEB_VIEW (widget), script, NULL, NULL, NULL);
+ g_free(script);
+}
+
+static void
+adjust_chapter_pos (GepubWidget *widget)
+{
+ // integer division to make a page start
+ gint page = widget->chapter_pos / widget->length;
+ gint next = page + 1;
+ gint d1 = widget->chapter_pos - (widget->length * page);
+ gint d2 = (widget->length * next) - widget->chapter_pos;
+
+ if (d1 < d2) {
+ widget->chapter_pos = widget->length * page;
+ } else {
+ widget->chapter_pos = widget->length * next;
+ }
+ scroll_to_chapter_pos (widget);
+}
+
+static void
pagination_initialize_finished (GObject *object,
GAsyncResult *result,
gpointer user_data)
@@ -73,8 +100,20 @@ pagination_initialize_finished (GObject *object,
double n;
n = JSValueToNumber (context, value, NULL);
- widget->chapter_pages = (int)n;
- g_object_notify_by_pspec (G_OBJECT (widget), properties[PROP_NPAGES]);
+ widget->chapter_length = (int)n;
+
+ if (widget->init_chapter_pos) {
+ widget->chapter_pos = widget->init_chapter_pos * widget->chapter_length / 100;
+ if (widget->chapter_pos > (widget->chapter_length - widget->length)) {
+ widget->chapter_pos = (widget->chapter_length - widget->length);
+ }
+ widget->init_chapter_pos = 0;
+ }
+
+ if (widget->chapter_pos) {
+ adjust_chapter_pos (widget);
+ }
+
} else {
g_warning ("Error running javascript: unexpected return value");
}
@@ -82,50 +121,67 @@ pagination_initialize_finished (GObject *object,
}
static void
-paginate_cb (WebKitWebView *web_view,
+get_length_finished (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ WebKitJavascriptResult *js_result;
+ JSValueRef value;
+ JSGlobalContextRef context;
+ GError *error = NULL;
+ GepubWidget *widget = GEPUB_WIDGET (user_data);
+
+ js_result = webkit_web_view_run_javascript_finish (WEBKIT_WEB_VIEW (object), result, &error);
+ if (!js_result) {
+ g_warning ("Error running javascript: %s", error->message);
+ g_error_free (error);
+ return;
+ }
+
+ context = webkit_javascript_result_get_global_context (js_result);
+ value = webkit_javascript_result_get_value (js_result);
+ if (JSValueIsNumber (context, value)) {
+ double n;
+
+ n = JSValueToNumber (context, value, NULL);
+ widget->length = (int)n;
+ } else {
+ g_warning ("Error running javascript: unexpected return value");
+ }
+ webkit_javascript_result_unref (js_result);
+}
+
+static void
+reload_length_cb (GtkWidget *widget,
+ GdkRectangle *allocation,
+ gpointer user_data)
+{
+ GepubWidget *gwidget = GEPUB_WIDGET (widget);
+ WebKitWebView *web_view = WEBKIT_WEB_VIEW (widget);
+
+ webkit_web_view_run_javascript (web_view,
+ "window.innerWidth",
+ NULL, get_length_finished, (gpointer)widget);
+
+ if (gwidget->paginate) {
+ webkit_web_view_run_javascript (web_view,
+ "document.querySelector('body').setAttribute('style', 'overflow: hidden; column-gap: 0px;');"
+ "document.querySelector('body').style.columnWidth = window.innerWidth+'px';"
+ "document.querySelector('body').style.height = window.innerHeight+'px';"
+ "document.querySelector('body').scrollWidth",
+ NULL, pagination_initialize_finished, (gpointer)widget);
+ }
+}
+
+static void
+docready_cb (WebKitWebView *web_view,
WebKitLoadEvent load_event,
gpointer user_data)
{
-
GepubWidget *widget = GEPUB_WIDGET (web_view);
if (load_event == WEBKIT_LOAD_FINISHED) {
- const gchar *script = "function initialize() { "
- "var d = document.querySelector('body');"
- "var ourH = window.innerHeight - 40; "
- "var ourW = window.innerWidth - 20; "
- "var fullH = d.offsetHeight; "
- "var pageCount = Math.floor(fullH/ourH)+1;"
- "var newW = pageCount * ourW; "
- "d.style.height = ourH+'px';"
- "d.style.width = newW+'px';"
- "d.style.WebkitColumnCount = pageCount;"
- "d.style.WebkitColumnGap = '20px';"
- "d.style.overflow = 'hidden';"
- "window.currentPage = 0; "
- "return pageCount;"
- "};"
- "function next() { "
- "var ourW = window.innerWidth - 10; "
- "window.currentPage += 1; "
- "window.scroll(ourW * window.currentPage, 0); "
- "};"
- "function prev() { "
- "var ourW = window.innerWidth - 10; "
- "window.currentPage -= 1; "
- "window.scroll(ourW * window.currentPage, 0); "
- "};"
- "function nth(index) { "
- "var ourW = window.innerWidth - 10; "
- "window.currentPage = index; "
- "window.scroll(ourW * window.currentPage, 0); "
- "};"
- "initialize();";
-
- if (widget->paginate) {
- webkit_web_view_run_javascript (web_view, "document.querySelector('body').style.margin =
'20px';", NULL, NULL, NULL);
- webkit_web_view_run_javascript (web_view, script, NULL, pagination_initialize_finished,
(gpointer)widget);
- }
+ reload_length_cb (GTK_WIDGET (widget), NULL, NULL);
}
}
@@ -177,8 +233,11 @@ gepub_widget_set_property (GObject *object,
case PROP_PAGINATE:
gepub_widget_set_pagination (widget, g_value_get_boolean (value));
break;
- case PROP_PAGE:
- gepub_widget_set_page (widget, g_value_get_int (value));
+ case PROP_CHAPTER:
+ gepub_doc_set_page (widget->doc, g_value_get_int (value));
+ break;
+ case PROP_CHAPTER_POS:
+ gepub_widget_set_pos (widget, g_value_get_float (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -201,11 +260,14 @@ gepub_widget_get_property (GObject *object,
case PROP_PAGINATE:
g_value_set_boolean (value, widget->paginate);
break;
- case PROP_PAGE:
- g_value_set_int (value, gepub_widget_get_page (widget));
+ case PROP_CHAPTER:
+ g_value_set_int (value, gepub_doc_get_page (widget->doc));
break;
- case PROP_NPAGES:
- g_value_set_int (value, gepub_widget_get_n_pages (widget));
+ case PROP_N_CHAPTERS:
+ g_value_set_int (value, gepub_doc_get_n_pages (widget->doc));
+ break;
+ case PROP_CHAPTER_POS:
+ g_value_set_float (value, gepub_widget_get_pos (widget));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -226,6 +288,11 @@ gepub_widget_finalize (GObject *object)
static void
gepub_widget_init (GepubWidget *widget)
{
+ widget->chapter_length = 0;
+ widget->paginate = FALSE;
+ widget->chapter_pos = 0;
+ widget->length = 0;
+ widget->init_chapter_pos = 0;
}
static void
@@ -238,7 +305,8 @@ gepub_widget_constructed (GObject *object)
ctx = webkit_web_view_get_context (WEBKIT_WEB_VIEW (widget));
webkit_web_context_register_uri_scheme (ctx, "epub", resource_callback, widget, NULL);
- g_signal_connect (widget, "load-changed", G_CALLBACK (paginate_cb), NULL);
+ g_signal_connect (widget, "load-changed", G_CALLBACK (docready_cb), NULL);
+ g_signal_connect (widget, "size-allocate", G_CALLBACK (reload_length_cb), NULL);
}
static void
@@ -266,20 +334,27 @@ gepub_widget_class_init (GepubWidgetClass *klass)
FALSE,
G_PARAM_READWRITE);
- properties[PROP_PAGE] =
- g_param_spec_int ("page",
- "Current page",
- "Current page in the chapter",
+ properties[PROP_CHAPTER] =
+ g_param_spec_int ("chapter",
+ "Current chapter",
+ "Current chapter in the doc",
-1, G_MAXINT, 0,
G_PARAM_READWRITE);
- properties[PROP_NPAGES] =
- g_param_spec_int ("chapter_pages",
- "Current chapter pages",
- "Current chapter number of pages",
+ properties[PROP_N_CHAPTERS] =
+ g_param_spec_int ("nchapters",
+ "Number of chapters in the doc",
+ "Number of chapters in the doc",
-1, G_MAXINT, 0,
G_PARAM_READABLE);
+ properties[PROP_CHAPTER_POS] =
+ g_param_spec_float ("chapter_pos",
+ "Current position in chapter",
+ "Current position in chapter",
+ 0, 100, 0,
+ G_PARAM_READWRITE);
+
g_object_class_install_properties (object_class, NUM_PROPS, properties);
}
@@ -314,6 +389,10 @@ reload_current_chapter (GepubWidget *widget)
{
GBytes *current;
+ widget->chapter_length = 0;
+ widget->chapter_pos = 0;
+ widget->length = 0;
+
current = gepub_doc_get_current_with_epub_uris (widget->doc);
webkit_web_view_load_bytes (WEBKIT_WEB_VIEW (widget),
current,
@@ -372,82 +451,161 @@ gepub_widget_set_pagination (GepubWidget *widget,
}
/**
- * gepub_widget_page_next:
+ * gepub_widget_get_n_chapters:
* @widget: a #GepubWidget
*
- * Change the page to the next
+ * Returns: the number of chapters in the document
*/
-void
-gepub_widget_page_next (GepubWidget *widget)
+gint
+gepub_widget_get_n_chapters (GepubWidget *widget)
{
- if (widget->page >= widget->chapter_pages)
- return;
+ g_return_val_if_fail (GEPUB_IS_DOC (widget->doc), 0);
+ return gepub_doc_get_n_pages (widget->doc);
+}
- webkit_web_view_run_javascript (WEBKIT_WEB_VIEW (widget), "next();", NULL, NULL, NULL);
- widget->page += 1;
+/**
+ * gepub_widget_get_chapter:
+ * @widget: a #GepubWidget
+ *
+ * Returns: the current chapter in the document
+ */
+gint
+gepub_widget_get_chapter (GepubWidget *widget)
+{
+ g_return_val_if_fail (GEPUB_IS_DOC (widget->doc), 0);
+ return gepub_doc_get_page (widget->doc);
}
/**
- * gepub_widget_page_prev:
+ * gepub_widget_get_chapter_length:
* @widget: a #GepubWidget
*
- * Change the page to the prev
+ * Returns: the current chapter length
+ */
+gint
+gepub_widget_get_chapter_length (GepubWidget *widget)
+{
+ g_return_val_if_fail (GEPUB_IS_DOC (widget->doc), 0);
+ return widget->chapter_length;
+}
+
+/**
+ * gepub_widget_set_chapter:
+ * @widget: a #GepubWidget
+ *
+ * Sets the current chapter in the doc
*/
void
-gepub_widget_page_prev (GepubWidget *widget)
+gepub_widget_set_chapter (GepubWidget *widget,
+ gint index)
{
- if (widget->page <= 0)
- return;
+ g_return_if_fail (GEPUB_IS_DOC (widget->doc));
+ return gepub_doc_set_page (widget->doc, index);
+}
- webkit_web_view_run_javascript (WEBKIT_WEB_VIEW (widget), "prev();", NULL, NULL, NULL);
- widget->page -= 1;
+/**
+ * gepub_widget_chapter_next:
+ * @widget: a #GepubWidget
+ *
+ * Returns: TRUE on success, FALSE if there's no next chapter
+ */
+gboolean
+gepub_widget_chapter_next (GepubWidget *widget)
+{
+ g_return_val_if_fail (GEPUB_IS_DOC (widget->doc), FALSE);
+ return gepub_doc_go_next (widget->doc);
+}
+
+/**
+ * gepub_widget_chapter_prev:
+ * @widget: a #GepubWidget
+ *
+ * Returns: TRUE on success, FALSE if there's no prev chapter
+ */
+gboolean
+gepub_widget_chapter_prev (GepubWidget *widget)
+{
+ g_return_val_if_fail (GEPUB_IS_DOC (widget->doc), FALSE);
+ return gepub_doc_go_prev (widget->doc);
}
/**
- * gepub_widget_get_n_pages:
+ * gepub_widget_page_next:
* @widget: a #GepubWidget
*
- * Returns: the number of pages in the chapter
+ * Returns: TRUE on success, FALSE if there's no next page
*/
-int
-gepub_widget_get_n_pages (GepubWidget *widget)
+gboolean
+gepub_widget_page_next (GepubWidget *widget)
{
- return widget->chapter_pages;
+ g_return_val_if_fail (GEPUB_IS_DOC (widget->doc), FALSE);
+ widget->chapter_pos = widget->chapter_pos + widget->length;
+
+ if (widget->chapter_pos > (widget->chapter_length - widget->length)) {
+ widget->chapter_pos = (widget->chapter_length - widget->length);
+ return gepub_doc_go_next (widget->doc);
+ }
+
+ scroll_to_chapter_pos (widget);
+
+ g_object_notify_by_pspec (G_OBJECT (widget), properties[PROP_CHAPTER_POS]);
+ return TRUE;
}
/**
- * gepub_widget_get_page:
+ * gepub_widget_page_prev:
* @widget: a #GepubWidget
*
- * Returns: the current page in the chapter
+ * Returns: TRUE on success, FALSE if there's no next page
*/
-int
-gepub_widget_get_page (GepubWidget *widget)
+gboolean
+gepub_widget_page_prev (GepubWidget *widget)
{
- return widget->page;
+ g_return_val_if_fail (GEPUB_IS_DOC (widget->doc), FALSE);
+ widget->chapter_pos = widget->chapter_pos - widget->length;
+
+ if (widget->chapter_pos < 0) {
+ widget->init_chapter_pos = 100;
+ return gepub_doc_go_prev (widget->doc);
+ }
+
+ scroll_to_chapter_pos (widget);
+
+ g_object_notify_by_pspec (G_OBJECT (widget), properties[PROP_CHAPTER_POS]);
+ return TRUE;
}
/**
- * gepub_widget_set_page:
+ * gepub_widget_get_pos:
* @widget: a #GepubWidget
- * @index: the new page index
*
- * Sets the widget current page to @index.
+ * Returns: the current position in the chapter
*/
-void
-gepub_widget_set_page (GepubWidget *widget, gint index)
+gfloat
+gepub_widget_get_pos (GepubWidget *widget)
{
- gchar *script;
+ g_return_val_if_fail (GEPUB_IS_DOC (widget->doc), 0);
- if (index >= widget->chapter_pages)
- return;
+ if (!widget->chapter_length) {
+ return 0;
+ }
- if (index < 0)
- return;
+ return widget->chapter_pos * 100 / (float)(widget->chapter_length);
+}
- script = g_strdup_printf ("nth(%d);", index);
- webkit_web_view_run_javascript (WEBKIT_WEB_VIEW (widget), script, NULL, NULL, NULL);
- widget->page = index;
+/**
+ * gepub_widget_set_pos:
+ * @widget: a #GepubWidget
+ *
+ * Sets the current position in the chapter
+ */
+void
+gepub_widget_set_pos (GepubWidget *widget,
+ gfloat index)
+{
+ g_return_if_fail (GEPUB_IS_DOC (widget->doc));
+ widget->chapter_pos = index * widget->chapter_length / 100;
+ adjust_chapter_pos (widget);
- g_free (script);
+ g_object_notify_by_pspec (G_OBJECT (widget), properties[PROP_CHAPTER_POS]);
}
diff --git a/libgepub/gepub-widget.h b/libgepub/gepub-widget.h
index d825bd1..67ed53a 100644
--- a/libgepub/gepub-widget.h
+++ b/libgepub/gepub-widget.h
@@ -47,13 +47,20 @@ void gepub_widget_set_doc (GepubWidget *wid
GepubDoc *doc);
void gepub_widget_set_pagination (GepubWidget *widget, gboolean p);
-void gepub_widget_page_next (GepubWidget *widget);
-void gepub_widget_page_prev (GepubWidget *widget);
-gint gepub_widget_get_n_pages (GepubWidget *widget);
-gint gepub_widget_get_page (GepubWidget *widget);
-void gepub_widget_set_page (GepubWidget *widget,
+gint gepub_widget_get_n_chapters (GepubWidget *widget);
+gint gepub_widget_get_chapter (GepubWidget *widget);
+gint gepub_widget_get_chapter_length (GepubWidget *widget);
+void gepub_widget_set_chapter (GepubWidget *widget,
gint index);
+gboolean gepub_widget_chapter_next (GepubWidget *widget);
+gboolean gepub_widget_chapter_prev (GepubWidget *widget);
+
+gfloat gepub_widget_get_pos (GepubWidget *widget);
+void gepub_widget_set_pos (GepubWidget *widget,
+ gfloat index);
+gboolean gepub_widget_page_next (GepubWidget *widget);
+gboolean gepub_widget_page_prev (GepubWidget *widget);
G_END_DECLS
diff --git a/tests/test-gepub.c b/tests/test-gepub.c
index ace6893..8f6864b 100644
--- a/tests/test-gepub.c
+++ b/tests/test-gepub.c
@@ -23,7 +23,7 @@ GtkWidget *PAGE_LABEL;
static void
reload_current_chapter (GepubWidget *widget)
{
- gchar *txt = g_strdup_printf ("%d", gepub_widget_get_n_pages (widget));
+ gchar *txt = g_strdup_printf ("%02.2f", gepub_widget_get_pos (widget));
gtk_label_set_text (GTK_LABEL (PAGE_LABEL), txt);
g_free (txt);
}
@@ -87,24 +87,13 @@ button_pressed (GtkButton *button, GepubWidget *widget)
} else if (!strcmp (gtk_button_get_label (button), "paginated")) {
gboolean b = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button));
gepub_widget_set_pagination (widget, b);
+ } else if (!strcmp (gtk_button_get_label (button), "< page")) {
+ gepub_widget_page_prev (widget);
+ } else if (!strcmp (gtk_button_get_label (button), "page >")) {
+ gepub_widget_page_next (widget);
}
update_text (doc);
- print_replaced_text (doc);
-}
-
-void
-spin_changed (GtkSpinButton *button, GepubWidget *widget)
-{
- gint value = gtk_spin_button_get_value_as_int (button);
- gint npages = gepub_widget_get_n_pages (widget);
-
- printf ("PAGE VALUE: %d - %d\n", value, npages);
- if (value >= gepub_widget_get_n_pages (widget)) {
- gtk_spin_button_set_value (button, npages);
- return;
- }
-
- gepub_widget_set_page (widget, value);
+ //print_replaced_text (doc);
}
void
@@ -273,7 +262,8 @@ main (int argc, char **argv)
GtkWidget *b_next;
GtkWidget *b_prev;
- GtkWidget *spin_button;
+ GtkWidget *p_next;
+ GtkWidget *p_prev;
GtkWidget *paginate;
@@ -290,7 +280,7 @@ main (int argc, char **argv)
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
g_signal_connect (window, "destroy", (GCallback)gtk_main_quit, NULL);
- gtk_widget_set_size_request (GTK_WIDGET (window), 800, 500);
+ gtk_widget_set_size_request (GTK_WIDGET (window), 1200, 800);
vpaned = gtk_paned_new (GTK_ORIENTATION_HORIZONTAL);
gtk_container_add (GTK_CONTAINER (window), vpaned);
@@ -322,8 +312,10 @@ main (int argc, char **argv)
b_next = gtk_button_new_with_label ("chapter >");
g_signal_connect (b_next, "clicked", (GCallback)button_pressed, GEPUB_WIDGET (widget));
- spin_button = gtk_spin_button_new_with_range (0, G_MAXINT, 1);
- g_signal_connect (spin_button, "value-changed", (GCallback)spin_changed, GEPUB_WIDGET (widget));
+ p_prev = gtk_button_new_with_label ("< page");
+ g_signal_connect (p_prev, "clicked", (GCallback)button_pressed, GEPUB_WIDGET (widget));
+ p_next = gtk_button_new_with_label ("page >");
+ g_signal_connect (p_next, "clicked", (GCallback)button_pressed, GEPUB_WIDGET (widget));
PAGE_LABEL = gtk_label_new ("0");
@@ -336,7 +328,9 @@ main (int argc, char **argv)
gtk_container_add (GTK_CONTAINER (hbox), b_prev);
gtk_container_add (GTK_CONTAINER (hbox), b_next);
- gtk_container_add (GTK_CONTAINER (hbox), spin_button);
+ gtk_container_add (GTK_CONTAINER (hbox), p_prev);
+ gtk_container_add (GTK_CONTAINER (hbox), p_next);
+
gtk_container_add (GTK_CONTAINER (hbox), PAGE_LABEL);
gtk_container_add (GTK_CONTAINER (hbox), paginate);
@@ -349,7 +343,7 @@ main (int argc, char **argv)
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled), GTK_POLICY_AUTOMATIC,
GTK_POLICY_AUTOMATIC);
gtk_box_pack_start (GTK_BOX (vbox), scrolled, TRUE, TRUE, 5);
- gtk_widget_set_size_request (GTK_WIDGET (vbox), 400, 500);
+ gtk_widget_set_size_request (GTK_WIDGET (vbox), 600, 500);
gtk_paned_add1 (GTK_PANED (vpaned), vbox);
gtk_paned_add2 (GTK_PANED (vpaned), widget);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]