diff options
author | Dirk Hohndel <dirk@hohndel.org> | 2013-02-17 00:52:04 -0800 |
---|---|---|
committer | Dirk Hohndel <dirk@hohndel.org> | 2013-02-17 00:52:04 -0800 |
commit | 07c5cb882f55b735db6afa7efbee7240032e6d78 (patch) | |
tree | afe3a78ac44fd1f1e31b034a4104eaff3a514d5c | |
parent | f0ff972d91a6b765ab3cfa20c92a5c7191c421cf (diff) | |
download | subsurface-07c5cb882f55b735db6afa7efbee7240032e6d78.tar.gz |
Print: implement dynamic pagination of the table layout
Instead of a fixed number of dives per page we are now using the paginate
callback to dynamically figure out how many pages we need and which dive to
start each page with.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
-rw-r--r-- | print.c | 95 |
1 files changed, 67 insertions, 28 deletions
@@ -13,6 +13,10 @@ #define FONT_LARGE (FONT_NORMAL * 1.2) static double rel_width[] = { 0.333, 1.166, 0.5, 0.5, 1.0, 1.0, 1.8 }; +static int last_page_paginated, last_dive_paginated; +/* dynamically growing array of the first dive to be printed on each + * page in table mode */ +static int *first_dive; static struct options print_options; @@ -504,7 +508,7 @@ static void show_table_header(cairo_t *cr, PangoLayout *layout, double w) } static int show_table_cell(int i, cairo_t *cr, PangoLayout *layout, double colwidth, int height_count, - char *buffer, int len, double *curwidth, double y) + char *buffer, int len, double *curwidth, double y, gboolean paginate) { PangoRectangle logic_ext; double inner_colwidth = 0.95 * colwidth; @@ -512,7 +516,8 @@ static int show_table_cell(int i, cairo_t *cr, PangoLayout *layout, double colwi pango_layout_set_width(layout, inner_colwidth * rel_width[i]); pango_layout_set_text(layout, buffer, len); pango_layout_set_justify(layout, 0); - pango_cairo_show_layout(cr, layout); + if (!paginate) + pango_cairo_show_layout(cr, layout); *curwidth += colwidth * rel_width[i]; pango_layout_get_extents(layout, NULL, &logic_ext); if (logic_ext.height > height_count) @@ -520,7 +525,7 @@ static int show_table_cell(int i, cairo_t *cr, PangoLayout *layout, double colwi return height_count; } -static int show_dive_table(struct dive *dive, cairo_t *cr, PangoLayout *layout, double w, double dy) +static int show_dive_table(struct dive *dive, cairo_t *cr, PangoLayout *layout, double w, double dy, gboolean paginate) { double depth; const char *unit; @@ -539,7 +544,7 @@ static int show_dive_table(struct dive *dive, cairo_t *cr, PangoLayout *layout, len = 0; if (dive->number) len = snprintf(buffer, sizeof(buffer), "#%d", dive->number); - height_count = show_table_cell(0, cr, layout, colwidth, height_count, buffer, len, &curwidth, dy); + height_count = show_table_cell(0, cr, layout, colwidth, height_count, buffer, len, &curwidth, dy, paginate); // Col 2: Date # (1 + 1/6 of the regular width) utc_mkdate(dive->when, &tm); @@ -551,27 +556,27 @@ static int show_dive_table(struct dive *dive, cairo_t *cr, PangoLayout *layout, tm.tm_mday, tm.tm_year + 1900, tm.tm_hour, tm.tm_min ); - height_count = show_table_cell(1, cr, layout, colwidth, height_count, buffer, len, &curwidth, dy); + height_count = show_table_cell(1, cr, layout, colwidth, height_count, buffer, len, &curwidth, dy, paginate); // Col 3: Depth (1/2 width) depth = get_depth_units(dive->maxdepth.mm, &decimals, &unit); len = snprintf(buffer, sizeof(buffer), "%.*f %s", decimals, depth, unit); - height_count = show_table_cell(2, cr, layout, colwidth, height_count, buffer, len, &curwidth, dy); + height_count = show_table_cell(2, cr, layout, colwidth, height_count, buffer, len, &curwidth, dy, paginate); // Col 4: Duration (1/2 width) len = snprintf(buffer, sizeof(buffer), _("%d min"),(dive->duration.seconds + 59) / 60); - height_count = show_table_cell(3, cr, layout, colwidth, height_count, buffer, len, &curwidth, dy); + height_count = show_table_cell(3, cr, layout, colwidth, height_count, buffer, len, &curwidth, dy, paginate); // Col 5: Master - height_count = show_table_cell(4, cr, layout, colwidth, height_count, dive->divemaster ? : "", -1, &curwidth, dy); + height_count = show_table_cell(4, cr, layout, colwidth, height_count, dive->divemaster ? : "", -1, &curwidth, dy, paginate); // Col 6: Buddy - height_count = show_table_cell(5, cr, layout, colwidth, height_count, dive->buddy ? : "", -1, &curwidth, dy); + height_count = show_table_cell(5, cr, layout, colwidth, height_count, dive->buddy ? : "", -1, &curwidth, dy, paginate); // Col 7: Location - height_count = show_table_cell(6, cr, layout, colwidth, height_count, dive->location ? : "", -1, &curwidth, dy); + height_count = show_table_cell(6, cr, layout, colwidth, height_count, dive->location ? : "", -1, &curwidth, dy, paginate); /* Return the biggest column height, will be used to plot the frame and * and translate the next row */ @@ -731,28 +736,33 @@ static void draw_page(GtkPrintOperation *operation, pango_font_description_free(font); } -static void draw_table(GtkPrintOperation *operation, - GtkPrintContext *context, - gint page_nr, - gpointer user_data) +static void draw_table(GtkPrintOperation *operation, GtkPrintContext *context, gint page_nr, gpointer user_data) { int i, nr, maxwidth, maxheight; - int n_dive_per_page = 35; cairo_t *cr; - double w, h, max_ext, delta_y; + double w, h, max_ext, delta_y, y; struct dive *dive; PangoFontDescription *font; PangoLayout *layout; PangoRectangle logic_ext; + gboolean paginate = TRUE; + if (user_data) { + paginate = FALSE; + } else { + first_dive = realloc(first_dive, (page_nr + 1) * sizeof(int)); + first_dive[page_nr] = last_dive_paginated + 1; + } + nr = first_dive[page_nr]; cr = gtk_print_context_get_cairo_context(context); font = pango_font_description_from_string("Sans"); cairo_save(cr); w = gtk_print_context_get_width(context); - h = gtk_print_context_get_height(context)/(n_dive_per_page+1); + h = gtk_print_context_get_height(context); maxwidth = w * PANGO_SCALE; - maxheight = h * PANGO_SCALE * 0.9; + /* let's limit the height so we can fit at least 35 dives */ + maxheight = h * PANGO_SCALE * 0.9 / 35; layout = pango_cairo_create_layout(cr); pango_layout_set_height(layout, maxheight); @@ -763,9 +773,9 @@ static void draw_table(GtkPrintOperation *operation, /* We actually want to scale the text and the lines now */ cairo_scale(cr, 0.5, 0.5); - nr = page_nr*n_dive_per_page; pango_layout_get_extents(layout, NULL, &logic_ext); - cairo_translate (cr, w/10, 2 * logic_ext.height / (double) PANGO_SCALE); + cairo_translate (cr, w/10, 2.0 * logic_ext.height / PANGO_SCALE); + y = 2.0 * logic_ext.height / PANGO_SCALE; show_table_header(cr, layout, w*2); set_font(layout, font, FONT_NORMAL*1.2, PANGO_ALIGN_LEFT); /* We wanted the header ellipsized but not the data */ @@ -774,19 +784,25 @@ static void draw_table(GtkPrintOperation *operation, /* Get the height for an only line but move two down */ pango_layout_get_extents(layout, NULL, &logic_ext); delta_y = logic_ext.height; - cairo_translate (cr, 0, 2 * delta_y / (double) PANGO_SCALE); - - for (i = 0; i < n_dive_per_page; i++) { + cairo_translate (cr, 0, 2.0 * delta_y / PANGO_SCALE); + y += 2.0 * delta_y / PANGO_SCALE; + for (i = 0; i < dive_table.nr - nr; i++) { dive = get_dive_for_printing(nr+i); if (!dive) - return; + break; /* Write the dive data and get the max. height of the row */ - max_ext = show_dive_table(dive, cr, layout, w*2, delta_y / 4 / PANGO_SCALE); + max_ext = show_dive_table(dive, cr, layout, w*2, delta_y / 4 / PANGO_SCALE, paginate); /* Draw a frame for each row */ - print_table_frame (cr, -0.05, 0, w, (max_ext + delta_y / 2) / PANGO_SCALE); + if (user_data) + print_table_frame (cr, -0.05, 0, w, (max_ext + delta_y / 2) / PANGO_SCALE); /* and move down by the max. height of it */ cairo_translate (cr, 0, (max_ext + delta_y / 2) / PANGO_SCALE); + y += (max_ext + delta_y / 2) / PANGO_SCALE; + if (y > 1.9 * h) + break; } + if (paginate) + last_dive_paginated += i + 1; cairo_restore (cr); pango_font_description_free(font); g_object_unref (layout); @@ -817,7 +833,8 @@ static void begin_print(GtkPrintOperation *operation, gpointer user_data) } else if (print_options.type == TWOPERPAGE) { dives_per_page = 2; } else { - dives_per_page = 35; + /* set it to one page - gets update during pagination */ + dives_per_page = dives; } pages = (dives + dives_per_page - 1) / dives_per_page; gtk_print_operation_set_n_pages(operation, pages); @@ -896,6 +913,24 @@ static GtkWidget *print_dialog(GtkPrintOperation *operation, gpointer user_data) return vbox; } +static gboolean paginate(GtkPrintOperation *operation, GtkPrintContext *context, gpointer user_data) +{ + draw_table(operation, context, last_page_paginated++, NULL); + if (last_dive_paginated >= dive_table.nr) { + return TRUE; + } else { + gtk_print_operation_set_n_pages(operation, last_page_paginated + 1); + return FALSE; + } +} +static void end_print(GtkPrintOperation *operation, GtkPrintContext *context, gpointer user_data) +{ + if (first_dive) { + free(first_dive); + first_dive = 0; + } +} + static void print_dialog_apply(GtkPrintOperation *operation, GtkWidget *widget, gpointer user_data) { Print_params *print_params = g_slice_new(Print_params); @@ -914,7 +949,11 @@ static void print_dialog_apply(GtkPrintOperation *operation, GtkWidget *widget, print_params->rotation = 1; g_signal_connect(operation, "draw_page", G_CALLBACK(draw_page), print_params); } else { - g_signal_connect(operation, "draw_page", G_CALLBACK(draw_table), NULL); + g_signal_connect(operation, "draw_page", G_CALLBACK(draw_table), print_params); + g_signal_connect(operation, "paginate", G_CALLBACK(paginate), NULL); + g_signal_connect(operation, "end_print", G_CALLBACK(end_print), NULL); + last_page_paginated = 0; + last_dive_paginated = -1; } } } |