diff options
author | Dirk Hohndel <dirk@hohndel.org> | 2012-11-10 17:58:42 +0100 |
---|---|---|
committer | Dirk Hohndel <dirk@hohndel.org> | 2012-11-10 17:58:42 +0100 |
commit | 836bbad7a6c87c00fd99a14117f0d7b5fc8f9d7a (patch) | |
tree | d3477eeac2fc61eec0d7883298a0ba50bc006e47 | |
parent | 3d8c1e50fcc2c7e2ab43e8d09bf00e0610d69eaa (diff) | |
download | subsurface-836bbad7a6c87c00fd99a14117f0d7b5fc8f9d7a.tar.gz |
Add threshold feature for partial pressure graphs
The tec diving preference pane now allows us to set a partial pressure
threshold for each of the three gases. When the partial pressure surpasses
that value, the graph becomes red.
Fixes #12
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
-rw-r--r-- | display-gtk.h | 9 | ||||
-rw-r--r-- | gtk-gui.c | 103 | ||||
-rw-r--r-- | profile.c | 65 |
3 files changed, 141 insertions, 36 deletions
diff --git a/display-gtk.h b/display-gtk.h index 22ff9d626..d709696a6 100644 --- a/display-gtk.h +++ b/display-gtk.h @@ -25,12 +25,15 @@ typedef struct { gboolean po2; gboolean pn2; gboolean phe; -} enabled_graphs_t; + double po2_threshold; + double pn2_threshold; + double phe_threshold; +} partial_pressure_graphs_t; extern visible_cols_t visible_cols; -extern enabled_graphs_t enabled_graphs; +extern partial_pressure_graphs_t partial_pressure_graphs; -#define GRAPHS_ENABLED (enabled_graphs.po2 || enabled_graphs.pn2 || enabled_graphs.phe) +#define GRAPHS_ENABLED (partial_pressure_graphs.po2 || partial_pressure_graphs.pn2 || partial_pressure_graphs.phe) typedef enum { PREF_BOOL, @@ -37,7 +37,7 @@ struct units output_units; static GtkWidget *dive_profile; visible_cols_t visible_cols = {TRUE, FALSE, }; -enabled_graphs_t enabled_graphs = { FALSE, }; +partial_pressure_graphs_t partial_pressure_graphs = { FALSE, FALSE, FALSE, 1.6, 4.0, 10.0}; static const char *default_dive_computer_vendor; static const char *default_dive_computer_product; @@ -490,10 +490,13 @@ UNITCALLBACK(set_fahrenheit, temperature, FAHRENHEIT) UNITCALLBACK(set_kg, weight, KG) UNITCALLBACK(set_lbs, weight, LBS) -#define OPTIONCALLBACK(name, option) \ -static void name(GtkWidget *w, gpointer data) \ -{ \ - option = GTK_TOGGLE_BUTTON(w)->active; \ +#define OPTIONCALLBACK(name, option) \ +static void name(GtkWidget *w, gpointer data) \ +{ \ + GtkWidget **entry = data; \ + option = GTK_TOGGLE_BUTTON(w)->active; \ + if (entry) \ + gtk_widget_set_sensitive(*entry, option);\ } OPTIONCALLBACK(otu_toggle, visible_cols.otu) @@ -504,9 +507,9 @@ OPTIONCALLBACK(totalweight_toggle, visible_cols.totalweight) OPTIONCALLBACK(suit_toggle, visible_cols.suit) OPTIONCALLBACK(cylinder_toggle, visible_cols.cylinder) OPTIONCALLBACK(autogroup_toggle, autogroup) -OPTIONCALLBACK(po2_toggle, enabled_graphs.po2) -OPTIONCALLBACK(pn2_toggle, enabled_graphs.pn2) -OPTIONCALLBACK(phe_toggle, enabled_graphs.phe) +OPTIONCALLBACK(po2_toggle, partial_pressure_graphs.po2) +OPTIONCALLBACK(pn2_toggle, partial_pressure_graphs.pn2) +OPTIONCALLBACK(phe_toggle, partial_pressure_graphs.phe) static void event_toggle(GtkWidget *w, gpointer _data) { @@ -569,7 +572,9 @@ static void preferences_dialog(GtkWidget *w, gpointer data) { int result; GtkWidget *dialog, *notebook, *font, *frame, *box, *vbox, *button, *xmlfile_button; + GtkWidget *entry_po2, *entry_pn2, *entry_phe; const char *current_default, *new_default; + char threshold_text[10]; menu_units = output_units; @@ -701,27 +706,63 @@ static void preferences_dialog(GtkWidget *w, gpointer data) frame = gtk_frame_new(_("Show Partial Pressure Graphs in Profile")); gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 5); + vbox = gtk_vbox_new(FALSE, 6); + gtk_container_add(GTK_CONTAINER(frame), vbox); box = gtk_hbox_new(FALSE, 6); - gtk_container_add(GTK_CONTAINER(frame), box); + gtk_container_add(GTK_CONTAINER(vbox), box); button = gtk_check_button_new_with_label(_("pO" UTF8_SUBSCRIPT_2)); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), enabled_graphs.po2); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), partial_pressure_graphs.po2); gtk_box_pack_start(GTK_BOX(box), button, FALSE, FALSE, 6); - g_signal_connect(G_OBJECT(button), "toggled", G_CALLBACK(po2_toggle), NULL); + g_signal_connect(G_OBJECT(button), "toggled", G_CALLBACK(po2_toggle), &entry_po2); + + frame = gtk_frame_new(_("pO" UTF8_SUBSCRIPT_2 " threshold")); + gtk_box_pack_start(GTK_BOX(box), frame, FALSE, FALSE, 6); + entry_po2 = gtk_entry_new(); + gtk_entry_set_max_length(GTK_ENTRY(entry_po2), 4); + snprintf(threshold_text, sizeof(threshold_text), "%.1f", partial_pressure_graphs.po2_threshold); + gtk_entry_set_text(GTK_ENTRY(entry_po2), threshold_text); + gtk_widget_set_sensitive(entry_po2, partial_pressure_graphs.po2); + gtk_container_add(GTK_CONTAINER(frame), entry_po2); + + box = gtk_hbox_new(FALSE, 6); + gtk_container_add(GTK_CONTAINER(vbox), box); button = gtk_check_button_new_with_label(_("pN" UTF8_SUBSCRIPT_2)); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), enabled_graphs.pn2); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), partial_pressure_graphs.pn2); gtk_box_pack_start(GTK_BOX(box), button, FALSE, FALSE, 6); - g_signal_connect(G_OBJECT(button), "toggled", G_CALLBACK(pn2_toggle), NULL); + g_signal_connect(G_OBJECT(button), "toggled", G_CALLBACK(pn2_toggle), &entry_pn2); + + frame = gtk_frame_new(_("pN" UTF8_SUBSCRIPT_2 " threshold")); + gtk_box_pack_start(GTK_BOX(box), frame, FALSE, FALSE, 6); + entry_pn2 = gtk_entry_new(); + gtk_entry_set_max_length(GTK_ENTRY(entry_pn2), 4); + snprintf(threshold_text, sizeof(threshold_text), "%.1f", partial_pressure_graphs.pn2_threshold); + gtk_entry_set_text(GTK_ENTRY(entry_pn2), threshold_text); + gtk_widget_set_sensitive(entry_pn2, partial_pressure_graphs.pn2); + gtk_container_add(GTK_CONTAINER(frame), entry_pn2); + + box = gtk_hbox_new(FALSE, 6); + gtk_container_add(GTK_CONTAINER(vbox), box); button = gtk_check_button_new_with_label(_("pHe")); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), enabled_graphs.phe); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), partial_pressure_graphs.phe); gtk_box_pack_start(GTK_BOX(box), button, FALSE, FALSE, 6); - g_signal_connect(G_OBJECT(button), "toggled", G_CALLBACK(phe_toggle), NULL); + g_signal_connect(G_OBJECT(button), "toggled", G_CALLBACK(phe_toggle), &entry_phe); + + frame = gtk_frame_new(_("pHe threshold")); + gtk_box_pack_start(GTK_BOX(box), frame, FALSE, FALSE, 6); + entry_phe = gtk_entry_new(); + gtk_entry_set_max_length(GTK_ENTRY(entry_phe), 4); + snprintf(threshold_text, sizeof(threshold_text), "%.1f", partial_pressure_graphs.phe_threshold); + gtk_entry_set_text(GTK_ENTRY(entry_phe), threshold_text); + gtk_widget_set_sensitive(entry_phe, partial_pressure_graphs.phe); + gtk_container_add(GTK_CONTAINER(frame), entry_phe); gtk_widget_show_all(dialog); result = gtk_dialog_run(GTK_DIALOG(dialog)); if (result == GTK_RESPONSE_ACCEPT) { + const char *po2_threshold_text, *pn2_threshold_text, *phe_threshold_text; /* Make sure to flush any modified old dive data with old units */ update_dive(NULL); @@ -729,7 +770,12 @@ static void preferences_dialog(GtkWidget *w, gpointer data) free((void *)divelist_font); divelist_font = strdup(gtk_font_button_get_font_name(GTK_FONT_BUTTON(font))); set_divelist_font(divelist_font); - + po2_threshold_text = gtk_entry_get_text(GTK_ENTRY(entry_po2)); + sscanf(po2_threshold_text, "%lf", &partial_pressure_graphs.po2_threshold); + pn2_threshold_text = gtk_entry_get_text(GTK_ENTRY(entry_pn2)); + sscanf(pn2_threshold_text, "%lf", &partial_pressure_graphs.pn2_threshold); + phe_threshold_text = gtk_entry_get_text(GTK_ENTRY(entry_phe)); + sscanf(phe_threshold_text, "%lf", &partial_pressure_graphs.phe_threshold); output_units = menu_units; update_dive_list_units(); repaint_dive(); @@ -752,9 +798,12 @@ static void preferences_dialog(GtkWidget *w, gpointer data) subsurface_set_conf("divelist_font", PREF_STRING, divelist_font); subsurface_set_conf("autogroup", PREF_BOOL, BOOL_TO_PTR(autogroup)); - subsurface_set_conf("po2graph", PREF_BOOL, BOOL_TO_PTR(enabled_graphs.po2)); - subsurface_set_conf("pn2graph", PREF_BOOL, BOOL_TO_PTR(enabled_graphs.pn2)); - subsurface_set_conf("phegraph", PREF_BOOL, BOOL_TO_PTR(enabled_graphs.phe)); + subsurface_set_conf("po2graph", PREF_BOOL, BOOL_TO_PTR(partial_pressure_graphs.po2)); + subsurface_set_conf("pn2graph", PREF_BOOL, BOOL_TO_PTR(partial_pressure_graphs.pn2)); + subsurface_set_conf("phegraph", PREF_BOOL, BOOL_TO_PTR(partial_pressure_graphs.phe)); + subsurface_set_conf("po2threshold", PREF_STRING, po2_threshold_text); + subsurface_set_conf("pn2threshold", PREF_STRING, pn2_threshold_text); + subsurface_set_conf("phethreshold", PREF_STRING, phe_threshold_text); new_default = strdup(gtk_button_get_label(GTK_BUTTON(xmlfile_button))); @@ -1103,10 +1152,18 @@ void init_ui(int *argcp, char ***argvp) visible_cols.otu = PTR_TO_BOOL(subsurface_get_conf("OTU", PREF_BOOL)); visible_cols.sac = PTR_TO_BOOL(subsurface_get_conf("SAC", PREF_BOOL)); - enabled_graphs.po2 = PTR_TO_BOOL(subsurface_get_conf("po2graph", PREF_BOOL)); - enabled_graphs.pn2 = PTR_TO_BOOL(subsurface_get_conf("pn2graph", PREF_BOOL)); - enabled_graphs.phe = PTR_TO_BOOL(subsurface_get_conf("phegraph", PREF_BOOL)); - + partial_pressure_graphs.po2 = PTR_TO_BOOL(subsurface_get_conf("po2graph", PREF_BOOL)); + partial_pressure_graphs.pn2 = PTR_TO_BOOL(subsurface_get_conf("pn2graph", PREF_BOOL)); + partial_pressure_graphs.phe = PTR_TO_BOOL(subsurface_get_conf("phegraph", PREF_BOOL)); + conf_value = subsurface_get_conf("po2threshold", PREF_STRING); + if (conf_value) + sscanf(conf_value, "%lf", &partial_pressure_graphs.po2_threshold); + conf_value = subsurface_get_conf("pn2threshold", PREF_STRING); + if (conf_value) + sscanf(conf_value, "%lf", &partial_pressure_graphs.pn2_threshold); + conf_value = subsurface_get_conf("phethreshold", PREF_STRING); + if (conf_value) + sscanf(conf_value, "%lf", &partial_pressure_graphs.phe_threshold); divelist_font = subsurface_get_conf("divelist_font", PREF_STRING); autogroup = PTR_TO_BOOL(subsurface_get_conf("autogroup", PREF_BOOL)); default_filename = subsurface_get_conf("default_filename", PREF_STRING); @@ -74,7 +74,7 @@ typedef enum { VELO_STABLE, VELO_SLOW, VELO_MODERATE, VELO_FAST, VELO_CRAZY, /* gas colors */ - PO2, PN2, PHE, + PO2, PO2_ALERT, PN2, PN2_ALERT, PHE, PHE_ALERT, /* Other colors */ TEXT_BACKGROUND, ALERT_BG, ALERT_FG, EVENTS, SAMPLE_DEEP, SAMPLE_SHALLOW, @@ -109,8 +109,11 @@ static const color_t profile_color[] = { [VELO_CRAZY] = {{RED1, BLACK1_LOW_TRANS}}, [PO2] = {{APPLE1, APPLE1_MED_TRANS}}, + [PO2_ALERT] = {{RED1, APPLE1_MED_TRANS}}, [PN2] = {{BLACK1_LOW_TRANS, BLACK1_LOW_TRANS}}, + [PN2_ALERT] = {{RED1, BLACK1_LOW_TRANS}}, [PHE] = {{PEANUT, PEANUT_MED_TRANS}}, + [PHE_ALERT] = {{RED1, PEANUT_MED_TRANS}}, [TEXT_BACKGROUND] = {{CONCRETE1_LOWER_TRANS, WHITE1}}, [ALERT_BG] = {{BROOM1_LOWER_TRANS, BLACK1_LOW_TRANS}}, @@ -776,15 +779,15 @@ static void plot_pp_text(struct graphics_context *gc, struct plot_info *pi) setup_pp_limits(gc, pi); - if (enabled_graphs.po2) { + if (partial_pressure_graphs.po2) { maxpp = plot_single_gas_pp_text(gc, pi, po2_value, 0.4, PO2); } - if (enabled_graphs.pn2) { + if (partial_pressure_graphs.pn2) { m = plot_single_gas_pp_text(gc, pi, pn2_value, 0.6, PN2); if (m > maxpp) maxpp = m; } - if (enabled_graphs.phe) { + if (partial_pressure_graphs.phe) { m = plot_single_gas_pp_text(gc, pi, phe_value, 0.4, PHE); if (m > maxpp) maxpp = m; @@ -807,36 +810,78 @@ static void plot_pp_gas_profile(struct graphics_context *gc, struct plot_info *p setup_pp_limits(gc, pi); - if (enabled_graphs.po2) { + if (partial_pressure_graphs.po2) { set_source_rgba(gc, PO2); + entry = pi->entry; + move_to(gc, entry->sec, entry->po2); + for (i = 1; i < pi->nr; i++) { + entry++; + if (entry->po2 < partial_pressure_graphs.po2_threshold) + line_to(gc, entry->sec, entry->po2); + else + move_to(gc, entry->sec, entry->po2); + } + cairo_stroke(gc->cr); + set_source_rgba(gc, PO2_ALERT); entry = pi->entry; move_to(gc, entry->sec, entry->po2); for (i = 1; i < pi->nr; i++) { entry++; - line_to(gc, entry->sec, entry->po2); + if (entry->po2 >= partial_pressure_graphs.po2_threshold) + line_to(gc, entry->sec, entry->po2); + else + move_to(gc, entry->sec, entry->po2); } cairo_stroke(gc->cr); } - if (enabled_graphs.pn2) { + if (partial_pressure_graphs.pn2) { set_source_rgba(gc, PN2); + entry = pi->entry; + move_to(gc, entry->sec, entry->pn2); + for (i = 1; i < pi->nr; i++) { + entry++; + if (entry->pn2 < partial_pressure_graphs.pn2_threshold) + line_to(gc, entry->sec, entry->pn2); + else + move_to(gc, entry->sec, entry->pn2); + } + cairo_stroke(gc->cr); + set_source_rgba(gc, PN2_ALERT); entry = pi->entry; move_to(gc, entry->sec, entry->pn2); for (i = 1; i < pi->nr; i++) { entry++; - line_to(gc, entry->sec, entry->pn2); + if (entry->pn2 >= partial_pressure_graphs.pn2_threshold) + line_to(gc, entry->sec, entry->pn2); + else + move_to(gc, entry->sec, entry->pn2); } cairo_stroke(gc->cr); } - if (enabled_graphs.phe) { + if (partial_pressure_graphs.phe) { set_source_rgba(gc, PHE); + entry = pi->entry; + move_to(gc, entry->sec, entry->phe); + for (i = 1; i < pi->nr; i++) { + entry++; + if (entry->phe < partial_pressure_graphs.phe_threshold) + line_to(gc, entry->sec, entry->phe); + else + move_to(gc, entry->sec, entry->phe); + } + cairo_stroke(gc->cr); + set_source_rgba(gc, PHE_ALERT); entry = pi->entry; move_to(gc, entry->sec, entry->phe); for (i = 1; i < pi->nr; i++) { entry++; - line_to(gc, entry->sec, entry->phe); + if (entry->phe >= partial_pressure_graphs.phe_threshold) + line_to(gc, entry->sec, entry->phe); + else + move_to(gc, entry->sec, entry->phe); } cairo_stroke(gc->cr); } |