]> git.tdb.fi Git - ext/subsurface.git/blob - info.c
Stop plotting the gas / consumption information into the profile
[ext/subsurface.git] / info.c
1 #include <stdio.h>
2 #include <string.h>
3 #include <stdlib.h>
4 #include <time.h>
5
6 #include "dive.h"
7 #include "display.h"
8 #include "divelist.h"
9
10 static GtkWidget *info_frame;
11 static GtkWidget *depth, *duration, *temperature, *airconsumption;
12 static GtkEntry *location, *buddy, *divemaster;
13 static GtkTextBuffer *notes;
14 static int location_changed = 1, notes_changed = 1;
15 static int divemaster_changed = 1, buddy_changed = 1;
16
17 #define EMPTY_AIRCONSUMPTION " \n "
18 #define AIRCON_WIDTH 20
19
20 static const char *weekday(int wday)
21 {
22         static const char wday_array[7][4] = {
23                 "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
24         };
25         return wday_array[wday];
26 }
27
28 static char *get_text(GtkTextBuffer *buffer)
29 {
30         GtkTextIter start;
31         GtkTextIter end;
32
33         gtk_text_buffer_get_start_iter(buffer, &start);
34         gtk_text_buffer_get_end_iter(buffer, &end);
35         return gtk_text_buffer_get_text(buffer, &start, &end, FALSE);
36 }
37
38 void update_air_info(char *buffer)
39 {
40         char markup[120];
41         
42         if (! buffer)
43                 buffer = EMPTY_AIRCONSUMPTION;
44         snprintf(markup, sizeof(markup), "<span font=\"8\">%s</span>",buffer);
45         gtk_label_set_markup(GTK_LABEL(airconsumption), markup);
46 }
47
48 /*
49  * Return air usage (in liters).
50  */
51 static double calculate_airuse(struct dive *dive)
52 {
53         double airuse = 0;
54         int i;
55
56         for (i = 0; i < MAX_CYLINDERS; i++) {
57                 cylinder_t *cyl = dive->cylinder + i;
58                 int size = cyl->type.size.mliter;
59                 double kilo_atm;
60
61                 if (!size)
62                         continue;
63
64                 kilo_atm = (cyl->start.mbar - cyl->end.mbar) / 1013250.0;
65
66                 /* Liters of air at 1 atm == milliliters at 1k atm*/
67                 airuse += kilo_atm * size;
68         }
69         return airuse;
70 }
71
72 static void update_air_info_frame(struct dive *dive)
73 {
74         const double liters_per_cuft = 28.317;
75         const char *unit, *format, *desc;
76         double airuse;
77         char buffer1[80];
78         char buffer2[80];
79         int len;
80
81         airuse = calculate_airuse(dive);
82         if (!airuse) {
83                 update_air_info(NULL);
84                 return;
85         }
86         switch (output_units.volume) {
87         case LITER:
88                 unit = "l";
89                 format = "vol: %4.0f %s";
90                 break;
91         case CUFT:
92                 unit = "cuft";
93                 format = "vol: %4.2f %s";
94                 airuse /= liters_per_cuft;
95                 break;
96         }
97         len = snprintf(buffer1, sizeof(buffer1), format, airuse, unit);
98         if (dive->duration.seconds) {
99                 double pressure = 1 + (dive->meandepth.mm / 10000.0);
100                 double sac = airuse / pressure * 60 / dive->duration.seconds;
101                 snprintf(buffer1+len, sizeof(buffer1)-len, 
102                                 "\nSAC: %4.2f %s/min", sac, unit);
103         }
104         len = 0;
105         desc = dive->cylinder[0].type.description;
106         if (desc || dive->cylinder[0].gasmix.o2.permille) {
107                 int o2 = dive->cylinder[0].gasmix.o2.permille / 10;
108                 if (!desc)
109                         desc = "";
110                 if (!o2)
111                         o2 = 21;
112                 len = snprintf(buffer2, sizeof(buffer2), "%s (%d%%): used ", desc, o2);
113         }
114         snprintf(buffer2+len, sizeof(buffer2)-len, buffer1); 
115         update_air_info(buffer2);
116 }
117
118 void flush_dive_info_changes(struct dive *dive)
119 {
120         if (!dive)
121                 return;
122
123         if (location_changed) {
124                 g_free(dive->location);
125                 dive->location = gtk_editable_get_chars(GTK_EDITABLE(location), 0, -1);
126         }
127
128         if (divemaster_changed) {
129                 g_free(dive->divemaster);
130                 dive->divemaster = gtk_editable_get_chars(GTK_EDITABLE(divemaster), 0, -1);
131         }
132
133         if (buddy_changed) {
134                 g_free(dive->buddy);
135                 dive->buddy = gtk_editable_get_chars(GTK_EDITABLE(buddy), 0, -1);
136         }
137
138         if (notes_changed) {
139                 g_free(dive->notes);
140                 dive->notes = get_text(notes);
141         }
142 }
143
144 void show_dive_info(struct dive *dive)
145 {
146         struct tm *tm;
147         char buffer[80];
148         char *text;
149
150         if (!dive) {
151                 gtk_label_set_text(GTK_LABEL(depth), "");
152                 gtk_label_set_text(GTK_LABEL(duration), "");
153                 gtk_label_set_text(GTK_LABEL(airconsumption), EMPTY_AIRCONSUMPTION);
154                 gtk_label_set_width_chars(GTK_LABEL(airconsumption), AIRCON_WIDTH);
155                 return;
156         }
157         /* dive number and location (or lacking that, the date) go in the window title */
158         tm = gmtime(&dive->when);
159         text = dive->location;
160         if (!text)
161                 text = "";
162         if (*text) {
163                 snprintf(buffer, sizeof(buffer), "Dive #%d - %s", dive->number, text);
164         } else {
165                 snprintf(buffer, sizeof(buffer), "Dive #%d - %s %02d/%02d/%04d at %d:%02d",
166                         dive->number,
167                         weekday(tm->tm_wday),
168                         tm->tm_mon+1, tm->tm_mday,
169                         tm->tm_year+1900,
170                         tm->tm_hour, tm->tm_min);
171         }
172         text = buffer;
173         if (!dive->number)
174                 text += 10;     /* Skip the "Dive #0 - " part */
175         gtk_window_set_title(GTK_WINDOW(main_window), text);
176
177         /* the date goes in the frame label */
178         snprintf(buffer, sizeof(buffer), "%s %02d/%02d/%04d at %d:%02d",
179                 weekday(tm->tm_wday),
180                 tm->tm_mon+1, tm->tm_mday,
181                 tm->tm_year+1900,
182                 tm->tm_hour, tm->tm_min);
183         gtk_frame_set_label(GTK_FRAME(info_frame), buffer);
184
185
186         switch (output_units.length) {
187         case METERS:
188                 snprintf(buffer, sizeof(buffer),
189                         "%.1f m",
190                         dive->maxdepth.mm / 1000.0);
191                 break;
192         case FEET:
193                 snprintf(buffer, sizeof(buffer),
194                         "%d ft",
195                         to_feet(dive->maxdepth));
196                 break;
197         }
198         gtk_label_set_text(GTK_LABEL(depth), buffer);
199
200         snprintf(buffer, sizeof(buffer),
201                 "%d min",
202                 dive->duration.seconds / 60);
203         gtk_label_set_text(GTK_LABEL(duration), buffer);
204
205         *buffer = 0;
206         if (dive->watertemp.mkelvin) {
207                 switch (output_units.temperature) {
208                 case CELSIUS:
209                         snprintf(buffer, sizeof(buffer),
210                                 "%d C",
211                                 to_C(dive->watertemp));
212                         break;
213                 case FAHRENHEIT:
214                         snprintf(buffer, sizeof(buffer),
215                                 "%d F",
216                                 to_F(dive->watertemp));
217                         break;
218                 case KELVIN:
219                         snprintf(buffer, sizeof(buffer),
220                                 "%d K",
221                                 to_K(dive->watertemp));
222                         break;
223                 }
224         }
225         gtk_label_set_text(GTK_LABEL(temperature), buffer);
226
227         text = dive->location ? : "";
228         gtk_entry_set_text(location, text);
229
230         text = dive->divemaster ? : "";
231         gtk_entry_set_text(divemaster, text);
232
233         text = dive->buddy ? : "";
234         gtk_entry_set_text(buddy, text);
235
236         text = dive->notes ? : "";
237         gtk_text_buffer_set_text(notes, text, -1);
238
239         update_air_info_frame(dive);
240 }
241
242 static GtkWidget *info_label(GtkWidget *box, const char *str, GtkJustification jtype)
243 {
244         GtkWidget *label = gtk_label_new(str);
245         gtk_label_set_justify(GTK_LABEL(label), jtype);
246         gtk_box_pack_start(GTK_BOX(box), label, TRUE, TRUE, 0);
247         return label;
248 }
249
250 GtkWidget *dive_info_frame(void)
251 {
252         GtkWidget *frame;
253         GtkWidget *hbox;
254         GtkWidget *vbox;
255
256         frame = gtk_frame_new("Dive info");
257         info_frame = frame;
258         gtk_widget_show(frame);
259
260         vbox = gtk_vbox_new(FALSE, 6);
261         gtk_container_set_border_width(GTK_CONTAINER(vbox), 3);
262         gtk_container_add(GTK_CONTAINER(frame), vbox);
263
264         hbox = gtk_hbox_new(FALSE, 16);
265         gtk_container_set_border_width(GTK_CONTAINER(hbox), 3);
266         gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, TRUE, 0);
267
268         depth = info_label(hbox, "depth", GTK_JUSTIFY_RIGHT);
269         duration = info_label(hbox, "duration", GTK_JUSTIFY_RIGHT);
270         temperature = info_label(hbox, "temperature", GTK_JUSTIFY_RIGHT);
271         airconsumption = info_label(hbox, "air", GTK_JUSTIFY_RIGHT);
272         gtk_misc_set_alignment(GTK_MISC(airconsumption), 1.0, 0.5);
273         gtk_label_set_width_chars(GTK_LABEL(airconsumption), AIRCON_WIDTH);
274
275         return frame;
276 }
277
278 static GtkEntry *text_entry(GtkWidget *box, const char *label)
279 {
280         GtkWidget *entry;
281         GtkWidget *frame = gtk_frame_new(label);
282
283         gtk_box_pack_start(GTK_BOX(box), frame, FALSE, TRUE, 0);
284
285         entry = gtk_entry_new();
286         gtk_container_add(GTK_CONTAINER(frame), entry);
287
288         return GTK_ENTRY(entry);
289 }
290
291 static GtkTextBuffer *text_view(GtkWidget *box, const char *label)
292 {
293         GtkWidget *view, *vbox;
294         GtkTextBuffer *buffer;
295         GtkWidget *frame = gtk_frame_new(label);
296
297         gtk_box_pack_start(GTK_BOX(box), frame, TRUE, TRUE, 0);
298         box = gtk_hbox_new(FALSE, 3);
299         gtk_container_add(GTK_CONTAINER(frame), box);
300         vbox = gtk_vbox_new(FALSE, 3);
301         gtk_container_add(GTK_CONTAINER(box), vbox);
302
303         GtkWidget* scrolled_window = gtk_scrolled_window_new(0, 0);
304         gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
305         gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled_window), GTK_SHADOW_IN);
306         gtk_widget_show(scrolled_window);
307
308         view = gtk_text_view_new();
309         gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(view), GTK_WRAP_WORD);
310         gtk_container_add(GTK_CONTAINER(scrolled_window), view);
311
312         buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
313
314         gtk_box_pack_start(GTK_BOX(vbox), scrolled_window, TRUE, TRUE, 0);
315         return buffer;
316 }
317
318 GtkWidget *extended_dive_info_widget(void)
319 {
320         GtkWidget *vbox, *hbox;
321         vbox = gtk_vbox_new(FALSE, 6);
322
323         gtk_container_set_border_width(GTK_CONTAINER(vbox), 6);
324         location = text_entry(vbox, "Location");
325
326         hbox = gtk_hbox_new(FALSE, 3);
327         gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, TRUE, 0);
328
329         divemaster = text_entry(hbox, "Divemaster");
330         buddy = text_entry(hbox, "Buddy");
331
332         notes = text_view(vbox, "Notes");
333
334         /* Add extended info here: name, description, yadda yadda */
335         show_dive_info(current_dive);
336         return vbox;
337 }