]> git.tdb.fi Git - ext/subsurface.git/blob - profile.c
Add location note to the top bar too.
[ext/subsurface.git] / profile.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <time.h>
4
5 #include "dive.h"
6 #include "display.h"
7
8 int selected_dive = 0;
9
10 #define ROUND_UP(x,y) ((((x)+(y)-1)/(y))*(y))
11
12 /*
13  * When showing dive profiles, we scale things to the
14  * current dive. However, we don't scale past less than
15  * 30 minutes or 90 ft, just so that small dives show
16  * up as such.
17  */
18 static int round_seconds_up(int seconds)
19 {
20         return MAX(30*60, ROUND_UP(seconds, 60*10));
21 }
22
23 static int round_feet_up(int feet)
24 {
25         return MAX(90, ROUND_UP(feet+5, 15));
26 }
27
28 /* Scale to 0,0 -> maxx,maxy */
29 #define SCALE(x,y) (x)*maxx/scalex+topx,(y)*maxy/scaley+topy
30
31 static void plot(cairo_t *cr, int w, int h, struct dive *dive, int samples, struct sample *sample)
32 {
33         int i;
34         double topx, topy, maxx, maxy;
35         double scalex, scaley;
36         int maxtime, maxdepth;
37         int begins, sec, depth;
38
39         topx = w / 20.0;
40         topy = h / 20.0;
41         maxx = (w - 2*topx);
42         maxy = (h - 2*topy);
43
44         cairo_set_line_width(cr, 2);
45
46         /* Get plot scaling limits */
47         maxtime = round_seconds_up(dive->duration.seconds);
48         maxdepth = round_feet_up(to_feet(dive->maxdepth));
49
50         /* Depth markers: every 15 ft */
51         scalex = 1.0;
52         scaley = maxdepth;
53         cairo_set_source_rgba(cr, 1, 1, 1, 0.5);
54         for (i = 15; i < maxdepth; i += 15) {
55                 cairo_move_to(cr, SCALE(0, i));
56                 cairo_line_to(cr, SCALE(1, i));
57         }
58
59         /* Time markers: every 5 min */
60         scalex = maxtime;
61         scaley = 1.0;
62         for (i = 5*60; i < maxtime; i += 5*60) {
63                 cairo_move_to(cr, SCALE(i, 0));
64                 cairo_line_to(cr, SCALE(i, 1));
65         }
66         cairo_stroke(cr);
67
68         scaley = maxdepth;
69
70         /* Depth profile */
71         cairo_set_source_rgba(cr, 1, 0.2, 0.2, 0.80);
72         begins = sample->time.seconds;
73         cairo_move_to(cr, SCALE(sample->time.seconds, to_feet(sample->depth)));
74         for (i = 1; i < dive->samples; i++) {
75                 sample++;
76                 sec = sample->time.seconds;
77                 depth = to_feet(sample->depth);
78                 cairo_line_to(cr, SCALE(sec, depth));
79         }
80         scaley = 1.0;
81         cairo_line_to(cr, SCALE(sec, 0));
82         cairo_line_to(cr, SCALE(begins, 0));
83         cairo_close_path(cr);
84         cairo_set_source_rgba(cr, 1, 0.2, 0.2, 0.20);
85         cairo_fill_preserve(cr);
86         cairo_set_source_rgba(cr, 1, 0.2, 0.2, 0.80);
87         cairo_stroke(cr);
88
89         /* Bounding box last */
90         scalex = scaley = 1.0;
91         cairo_set_source_rgb(cr, 1, 1, 1);
92         cairo_move_to(cr, SCALE(0,0));
93         cairo_line_to(cr, SCALE(0,1));
94         cairo_line_to(cr, SCALE(1,1));
95         cairo_line_to(cr, SCALE(1,0));
96         cairo_close_path(cr);
97         cairo_stroke(cr);
98
99 }
100
101 static gboolean expose_event(GtkWidget *widget, GdkEventExpose *event, gpointer data)
102 {
103         struct dive *dive = current_dive;
104         cairo_t *cr;
105         int w,h;
106
107         w = widget->allocation.width;
108         h = widget->allocation.height;
109
110         cr = gdk_cairo_create(widget->window);
111         cairo_set_source_rgb(cr, 0, 0, 0);
112         cairo_paint(cr);
113
114         if (dive && dive->samples)
115                 plot(cr, w, h, dive, dive->samples, dive->sample);
116
117         cairo_destroy(cr);
118
119         return FALSE;
120 }
121
122 GtkWidget *dive_profile_frame(void)
123 {
124         GtkWidget *frame;
125         GtkWidget *da;
126
127         frame = gtk_frame_new("Dive profile");
128         gtk_widget_show(frame);
129         da = gtk_drawing_area_new();
130         gtk_widget_set_size_request(da, 450, 350);
131         g_signal_connect(da, "expose_event", G_CALLBACK(expose_event), NULL);
132         gtk_container_add(GTK_CONTAINER(frame), da);
133
134         return frame;
135 }