aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Linus Torvalds <torvalds@linux-foundation.org>2012-11-11 13:20:32 +0100
committerGravatar Dirk Hohndel <dirk@hohndel.org>2012-11-11 14:44:10 +0100
commit01e8984d7d3b6da1196766b3b411151a5a7a5053 (patch)
treeecea8ec90dcf28b23ec45fad582ded34fbdedc3c
parentfe4f13f184ffb97ee4b6dbd4138a9d8ae3aabd14 (diff)
downloadsubsurface-01e8984d7d3b6da1196766b3b411151a5a7a5053.tar.gz
Create tool-tip with depth/pressure for the whole profile area
This extends on our current tooltip logic (which shows events when you mouse over them) to show tooltips for the whole profile area. If you mouse over an event, that is still shown in the tooltip, but even in the absense of events, the tooltip will be active, and mousing over the profile area will show the time, depth and pressure. This can certainly be improved upon further, but even in this form it is useful. Fixes #9 Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
-rw-r--r--display.h6
-rw-r--r--gtk-gui.c48
-rw-r--r--print.c6
-rw-r--r--profile.c43
4 files changed, 84 insertions, 19 deletions
diff --git a/display.h b/display.h
index 880a8b7be..6eea822aa 100644
--- a/display.h
+++ b/display.h
@@ -21,16 +21,20 @@ extern void do_print(void);
struct graphics_context {
int printer;
cairo_t *cr;
+ cairo_rectangle_t drawing_area;
double maxx, maxy;
double leftx, rightx;
double topy, bottomy;
+ unsigned int maxtime;
+ void *plot_info;
};
typedef enum { SC_SCREEN, SC_PRINT } scale_mode_t;
-extern void plot(struct graphics_context *gc, cairo_rectangle_t *drawing_area, struct dive *dive, scale_mode_t scale);
+extern void plot(struct graphics_context *gc, struct dive *dive, scale_mode_t scale);
extern void init_profile_background(struct graphics_context *gc);
extern void attach_tooltip(int x, int y, int w, int h, const char *text);
+extern void get_plot_details(struct graphics_context *gc, int time, char *buf, size_t bufsize);
struct options {
enum { PRETTY, TABLE, ONEPERPAGE } type;
diff --git a/gtk-gui.c b/gtk-gui.c
index 025cd1e45..ea335749c 100644
--- a/gtk-gui.c
+++ b/gtk-gui.c
@@ -1300,21 +1300,44 @@ void attach_tooltip(int x, int y, int w, int h, const char *text)
(_r.y <= _y) && (_r.y + _r.height >= _y))
static gboolean profile_tooltip (GtkWidget *widget, gint x, gint y,
- gboolean keyboard_mode, GtkTooltip *tooltip, gpointer user_data)
+ gboolean keyboard_mode, GtkTooltip *tooltip, struct graphics_context *gc)
{
int i;
- cairo_rectangle_t *drawing_area = user_data;
+ cairo_rectangle_t *drawing_area = &gc->drawing_area;
gint tx = x - drawing_area->x; /* get transformed coordinates */
gint ty = y - drawing_area->y;
+ gint width, height, time = -1;
+ char buffer[80], plot[80];
+ const char *event = "";
+
+ if (tx < 0 || ty < 0)
+ return FALSE;
+
+ width = drawing_area->width - 2*drawing_area->x;
+ height = drawing_area->height - 2*drawing_area->y;
+ if (width <= 0 || height <= 0)
+ return FALSE;
+
+ if (tx > width || ty > height)
+ return FALSE;
+
+ time = (tx * gc->maxtime) / width;
/* are we over an event marker ? */
for (i = 0; i < tooltips; i++) {
if (INSIDE_RECT(tooltip_rects[i].rect, tx, ty)) {
- gtk_tooltip_set_text(tooltip,tooltip_rects[i].text);
- return TRUE; /* show tooltip */
+ event = tooltip_rects[i].text;
+ break;
}
}
- return FALSE; /* don't show tooltip */
+ get_plot_details(gc, time, plot, sizeof(plot));
+
+ snprintf(buffer, sizeof(buffer), " %d:%02d%c%s%c%s", time / 60, time % 60,
+ *plot ? '\n' : ' ', plot,
+ *event ? '\n' : ' ', event);
+ gtk_tooltip_set_text(tooltip, buffer);
+ return TRUE;
+
}
static int zoom_x = -1, zoom_y = -1;
@@ -1322,19 +1345,18 @@ static int zoom_x = -1, zoom_y = -1;
static gboolean expose_event(GtkWidget *widget, GdkEventExpose *event, gpointer data)
{
struct dive *dive = current_dive;
- struct graphics_context gc = { .printer = 0 };
- static cairo_rectangle_t drawing_area;
+ static struct graphics_context gc = { .printer = 0 };
/* the drawing area gives TOTAL width * height - x,y is used as the topx/topy offset
* so effective drawing area is width-2x * height-2y */
- drawing_area.width = widget->allocation.width;
- drawing_area.height = widget->allocation.height;
- drawing_area.x = MIN(50,drawing_area.width / 20.0);
- drawing_area.y = MIN(50,drawing_area.height / 20.0);
+ gc.drawing_area.width = widget->allocation.width;
+ gc.drawing_area.height = widget->allocation.height;
+ gc.drawing_area.x = MIN(50,gc.drawing_area.width / 20.0);
+ gc.drawing_area.y = MIN(50,gc.drawing_area.height / 20.0);
gc.cr = gdk_cairo_create(widget->window);
g_object_set(widget, "has-tooltip", TRUE, NULL);
- g_signal_connect(widget, "query-tooltip", G_CALLBACK(profile_tooltip), &drawing_area);
+ g_signal_connect(widget, "query-tooltip", G_CALLBACK(profile_tooltip), &gc);
init_profile_background(&gc);
cairo_paint(gc.cr);
@@ -1349,7 +1371,7 @@ static gboolean expose_event(GtkWidget *widget, GdkEventExpose *event, gpointer
tooltip_rects = NULL;
}
tooltips = 0;
- plot(&gc, &drawing_area, dive, SC_SCREEN);
+ plot(&gc, dive, SC_SCREEN);
}
cairo_destroy(gc.cr);
diff --git a/print.c b/print.c
index 62317c15e..9ce367508 100644
--- a/print.c
+++ b/print.c
@@ -300,13 +300,13 @@ static void show_dive_table(struct dive *dive, cairo_t *cr, double w,
static void show_dive_profile(struct dive *dive, cairo_t *cr, double w,
double h)
{
- cairo_rectangle_t drawing_area = { w/20.0, h/20.0, w, h};
struct graphics_context gc = {
.printer = 1,
- .cr = cr
+ .cr = cr,
+ .drawing_area = { w/20.0, h/20.0, w, h},
};
cairo_save(cr);
- plot(&gc, &drawing_area, dive, SC_PRINT);
+ plot(&gc, dive, SC_PRINT);
cairo_restore(cr);
}
diff --git a/profile.c b/profile.c
index 065934746..c8ce440d6 100644
--- a/profile.c
+++ b/profile.c
@@ -900,6 +900,8 @@ static void plot_depth_profile(struct graphics_context *gc, struct plot_info *pi
maxtime = get_maxtime(pi);
maxdepth = get_maxdepth(pi);
+ gc->maxtime = maxtime;
+
/* Time markers: at most every 10 seconds, but no more than 12 markers.
* We start out with 10 seconds and increment up to 30 minutes,
* depending on the dive time.
@@ -1908,11 +1910,12 @@ static void plot_set_scale(scale_mode_t scale)
}
}
-void plot(struct graphics_context *gc, cairo_rectangle_t *drawing_area, struct dive *dive, scale_mode_t scale)
+void plot(struct graphics_context *gc, struct dive *dive, scale_mode_t scale)
{
struct plot_info *pi;
static struct sample fake[4];
struct sample *sample = dive->sample;
+ cairo_rectangle_t *drawing_area = &gc->drawing_area;
int nr = dive->samples;
plot_set_scale(scale);
@@ -1994,5 +1997,41 @@ void plot(struct graphics_context *gc, cairo_rectangle_t *drawing_area, struct d
plot_depth_scale(gc, pi);
- free(pi);
+ if (gc->printer) {
+ free(pi);
+ } else {
+ free(gc->plot_info);
+ gc->plot_info = pi;
+ }
+}
+
+static void plot_string(struct plot_data *entry, char *buf, size_t bufsize)
+{
+ int depth_decimals, pressure;
+ const char *depth_unit, *pressure_unit;
+ double depth;
+
+ depth = get_depth_units(entry->depth, &depth_decimals, &depth_unit);
+ pressure = get_pressure_units(GET_PRESSURE(entry), &pressure_unit);
+
+ snprintf(buf, bufsize, "%.*f %s\n%d %s",
+ depth_decimals, depth, depth_unit,
+ pressure, pressure_unit);
+}
+
+void get_plot_details(struct graphics_context *gc, int time, char *buf, size_t bufsize)
+{
+ struct plot_info *pi = gc->plot_info;
+
+ *buf = 0;
+ if (pi) {
+ int i;
+ for (i = 0; i < pi->nr; i++) {
+ struct plot_data *entry = pi->entry + i;
+ if (entry->sec >= time) {
+ plot_string(entry, buf, bufsize);
+ break;
+ }
+ }
+ }
}