aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Dirk Hohndel <dirk@hohndel.org>2013-02-17 00:52:04 -0800
committerGravatar Dirk Hohndel <dirk@hohndel.org>2013-02-17 00:52:04 -0800
commit07c5cb882f55b735db6afa7efbee7240032e6d78 (patch)
treeafe3a78ac44fd1f1e31b034a4104eaff3a514d5c
parentf0ff972d91a6b765ab3cfa20c92a5c7191c421cf (diff)
downloadsubsurface-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.c95
1 files changed, 67 insertions, 28 deletions
diff --git a/print.c b/print.c
index d9e9bc884..2ccab9b4d 100644
--- a/print.c
+++ b/print.c
@@ -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;
}
}
}