static void gfilter_dialog(GFilterArgs *args, GwyContainer *data, GwyDataField *dfield, GwyDataField *mfield, gint id, GQuark mquark) { GtkWidget *dialog, *table, *vbox, *hbox, *scwin, *hbox2, *label; GtkTreeView *treeview; GtkTreeSelection *selection; GFilterControls controls; gint response, row, i; GwySIUnit *siunit; GwyPixmapLayer *layer; controls.args = args; controls.mask = mfield; controls.in_init = TRUE; controls.computed = FALSE; siunit = gwy_si_unit_new(NULL); for (i = 0; i < NQUANTITIES; i++) { controls.vf[i] = gwy_si_unit_get_format_with_digits(siunit, GWY_SI_UNIT_FORMAT_VFMARKUP, 1.0, 4, NULL); } g_object_unref(siunit); dialog = gtk_dialog_new_with_buttons(_("Filter Grains"), NULL, 0, NULL); gtk_dialog_add_action_widget(GTK_DIALOG(dialog), gwy_stock_like_button_new(_("_Update"), GTK_STOCK_EXECUTE), RESPONSE_PREVIEW); gtk_dialog_add_button(GTK_DIALOG(dialog), GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL); gtk_dialog_add_button(GTK_DIALOG(dialog), GTK_STOCK_OK, GTK_RESPONSE_OK); gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_OK); gtk_dialog_set_response_sensitive(GTK_DIALOG(dialog), RESPONSE_PREVIEW, !args->update); gwy_help_add_to_proc_dialog(GTK_DIALOG(dialog), GWY_HELP_DEFAULT); controls.dialog = dialog; hbox = gtk_hbox_new(FALSE, 2); gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), hbox, TRUE, TRUE, 4); vbox = gtk_vbox_new(FALSE, 4); gtk_box_pack_start(GTK_BOX(hbox), vbox, FALSE, FALSE, 4); controls.mydata = gwy_container_new(); gwy_container_set_object_by_name(controls.mydata, "/0/data", dfield); mfield = gwy_data_field_duplicate(mfield); gwy_container_set_object_by_name(controls.mydata, "/0/mask", mfield); g_object_unref(mfield); gwy_app_sync_data_items(data, controls.mydata, id, 0, FALSE, GWY_DATA_ITEM_PALETTE, GWY_DATA_ITEM_MASK_COLOR, GWY_DATA_ITEM_RANGE, GWY_DATA_ITEM_REAL_SQUARE, 0); controls.view = gwy_data_view_new(controls.mydata); layer = gwy_layer_basic_new(); g_object_set(layer, "data-key", "/0/data", "gradient-key", "/0/base/palette", "range-type-key", "/0/base/range-type", "min-max-key", "/0/base", NULL); gwy_data_view_set_data_prefix(GWY_DATA_VIEW(controls.view), "/0/data"); gwy_data_view_set_base_layer(GWY_DATA_VIEW(controls.view), layer); layer = gwy_layer_mask_new(); gwy_pixmap_layer_set_data_key(layer, "/0/mask"); gwy_layer_mask_set_color_key(GWY_LAYER_MASK(layer), "/0/mask"); gwy_data_view_set_alpha_layer(GWY_DATA_VIEW(controls.view), layer); gwy_set_data_preview_size(GWY_DATA_VIEW(controls.view), PREVIEW_SIZE); gtk_box_pack_start(GTK_BOX(vbox), controls.view, FALSE, FALSE, 0); controls.update = gtk_check_button_new_with_mnemonic(_("I_nstant updates")); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(controls.update), args->update); gtk_box_pack_start(GTK_BOX(vbox), controls.update, FALSE, FALSE, 0); g_signal_connect_swapped(controls.update, "toggled", G_CALLBACK(update_changed), &controls); hbox2 = gtk_hbox_new(FALSE, 6); gtk_box_pack_start(GTK_BOX(vbox), hbox2, FALSE, FALSE, 0); label = gtk_label_new_with_mnemonic(_("_Mask color:")); gtk_box_pack_start(GTK_BOX(hbox2), label, FALSE, FALSE, 0); controls.color_button = gwy_color_button_new(); gwy_color_button_set_use_alpha(GWY_COLOR_BUTTON(controls.color_button), TRUE); load_mask_color(controls.color_button, gwy_data_view_get_data(GWY_DATA_VIEW(controls.view))); gtk_label_set_mnemonic_widget(GTK_LABEL(label), controls.color_button); gtk_box_pack_start(GTK_BOX(hbox2), controls.color_button, FALSE, FALSE, 0); g_signal_connect(controls.color_button, "clicked", G_CALLBACK(mask_color_changed), &controls); table = gtk_table_new(10, 4, FALSE); gtk_table_set_row_spacings(GTK_TABLE(table), 2); gtk_table_set_col_spacings(GTK_TABLE(table), 6); gtk_container_set_border_width(GTK_CONTAINER(table), 4); gtk_box_pack_start(GTK_BOX(hbox), table, TRUE, TRUE, 4); controls.table = table; row = 0; scwin = gtk_scrolled_window_new(NULL, NULL); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scwin), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); gtk_table_attach(GTK_TABLE(table), scwin, 0, 4, row, row+1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); controls.values = gwy_grain_value_tree_view_new(FALSE, "name", "symbol_markup", NULL); treeview = GTK_TREE_VIEW(controls.values); gtk_widget_set_size_request(scwin, -1, 120); gtk_tree_view_set_headers_visible(treeview, FALSE); selection = gtk_tree_view_get_selection(treeview); gtk_tree_selection_set_mode(selection, GTK_SELECTION_BROWSE); gwy_grain_value_tree_view_set_same_units(treeview, args->units_equal); gwy_grain_value_tree_view_set_expanded_groups(treeview, args->expanded); gtk_container_add(GTK_CONTAINER(scwin), controls.values); row++; hbox2 = gtk_hbox_new(FALSE, 0); for (i = 0; i < NQUANTITIES; i++) { gchar buf[2]; buf[0] = 'A' + i; buf[1] = '\0'; controls.set_as[i] = gtk_button_new_with_label(buf); gtk_box_pack_start(GTK_BOX(hbox2), controls.set_as[i], FALSE, FALSE, 0); g_object_set_data(G_OBJECT(controls.set_as[i]), "id", GUINT_TO_POINTER(i)); g_signal_connect_swapped(controls.set_as[i], "clicked", G_CALLBACK(set_as_clicked), &controls); } gwy_table_attach_hscale(table, row++, _("Set selected as:"), NULL, GTK_OBJECT(hbox2), GWY_HSCALE_WIDGET_NO_EXPAND); controls.logical_op = gwy_enum_combo_box_newl(G_CALLBACK(logical_op_changed), &controls, args->logical, "A", GRAIN_LOGICAL_A, "A ∧ B", GRAIN_LOGICAL_A_AND_B, "A ∨ B", GRAIN_LOGICAL_A_OR_B, "A ∧ B ∧ C", GRAIN_LOGICAL_A_AND_B_AND_C, "A ∨ B ∨ C", GRAIN_LOGICAL_A_OR_B_OR_C, "(A ∧ B) ∨ C", GRAIN_LOGICAL_A_AND_B_OR_C, "(A ∨ B) ∧ C", GRAIN_LOGICAL_A_OR_B_AND_C, NULL); gwy_table_attach_hscale(table, row++, _("Keep grains satisfying:"), NULL, GTK_OBJECT(controls.logical_op), GWY_HSCALE_WIDGET); for (i = 0; i < NQUANTITIES; i++) { gtk_table_set_row_spacing(GTK_TABLE(table), row-1, 8); controls.header[i] = gtk_label_new(NULL); gtk_misc_set_alignment(GTK_MISC(controls.header[i]), 0.0, 0.5); gtk_table_attach(GTK_TABLE(table), controls.header[i], 0, 4, row, row+1, GTK_FILL, 0, 0, 0); row++; /* The values are set properly later. */ controls.lower_label[i] = gtk_label_new(_("Lower threshold:")); gtk_misc_set_alignment(GTK_MISC(controls.lower_label[i]), 0.0, 0.5); gtk_table_attach(GTK_TABLE(table), controls.lower_label[i], 0, 1, row, row+1, GTK_FILL, 0, 0, 0); controls.lower[i] = gtk_adjustment_new(0.0, 0.0, 0.0, 1.0, 10.0, 0.0); g_object_set_data(G_OBJECT(controls.lower[i]), "id", GUINT_TO_POINTER(i)); g_signal_connect_swapped(controls.lower[i], "value-changed", G_CALLBACK(threshold_changed), &controls); controls.lower_scale[i] = gtk_hscale_new(GTK_ADJUSTMENT(controls.lower[i])); gtk_scale_set_draw_value(GTK_SCALE(controls.lower_scale[i]), FALSE); gtk_widget_set_size_request(controls.lower_scale[i], GWY_HSCALE_WIDTH, -1); gtk_table_attach(GTK_TABLE(table), controls.lower_scale[i], 1, 2, row, row+1, GTK_EXPAND | GTK_FILL, 0, 0, 0); controls.lower_entry[i] = gtk_entry_new(); gtk_entry_set_width_chars(GTK_ENTRY(controls.lower_entry[i]), 8); gtk_table_attach(GTK_TABLE(table), controls.lower_entry[i], 2, 3, row, row+1, GTK_FILL, 0, 0, 0); gwy_widget_set_activate_on_unfocus(controls.lower_entry[i], TRUE); g_object_set_data(G_OBJECT(controls.lower_entry[i]), "id", GUINT_TO_POINTER(i)); g_signal_connect_swapped(controls.lower_entry[i], "activate", G_CALLBACK(threshold_activated), &controls); controls.lower_units[i] = gtk_label_new(NULL); gtk_misc_set_alignment(GTK_MISC(controls.lower_units[i]), 0.0, 0.5); gtk_table_attach(GTK_TABLE(table), controls.lower_units[i], 3, 4, row, row+1, GTK_FILL, 0, 0, 0); row++; controls.upper_label[i] = gtk_label_new(_("Upper threshold:")); gtk_misc_set_alignment(GTK_MISC(controls.upper_label[i]), 0.0, 0.5); gtk_table_attach(GTK_TABLE(table), controls.upper_label[i], 0, 1, row, row+1, GTK_FILL, 0, 0, 0); controls.upper[i] = gtk_adjustment_new(0.0, 0.0, 0.0, 1.0, 10.0, 0.0); g_object_set_data(G_OBJECT(controls.upper[i]), "id", GUINT_TO_POINTER(i | IS_UPPER)); g_signal_connect_swapped(controls.upper[i], "value-changed", G_CALLBACK(threshold_changed), &controls); controls.upper_scale[i] = gtk_hscale_new(GTK_ADJUSTMENT(controls.upper[i])); gtk_scale_set_draw_value(GTK_SCALE(controls.upper_scale[i]), FALSE); gtk_widget_set_size_request(controls.upper_scale[i], GWY_HSCALE_WIDTH, -1); gtk_table_attach(GTK_TABLE(table), controls.upper_scale[i], 1, 2, row, row+1, GTK_EXPAND | GTK_FILL, 0, 0, 0); controls.upper_entry[i] = gtk_entry_new(); gtk_entry_set_width_chars(GTK_ENTRY(controls.upper_entry[i]), 8); gtk_table_attach(GTK_TABLE(table), controls.upper_entry[i], 2, 3, row, row+1, GTK_FILL, 0, 0, 0); gwy_widget_set_activate_on_unfocus(controls.upper_entry[i], TRUE); g_object_set_data(G_OBJECT(controls.upper_entry[i]), "id", GUINT_TO_POINTER(i | IS_UPPER)); g_signal_connect_swapped(controls.upper_entry[i], "activate", G_CALLBACK(threshold_activated), &controls); controls.upper_units[i] = gtk_label_new(NULL); gtk_misc_set_alignment(GTK_MISC(controls.upper_units[i]), 0.0, 0.5); gtk_table_attach(GTK_TABLE(table), controls.upper_units[i], 3, 4, row, row+1, GTK_FILL, 0, 0, 0); row++; } for (i = 0; i < NQUANTITIES; i++) { GwyInventory *inventory; GwyGrainValue *gvalue; inventory = gwy_grain_values(); gvalue = gwy_inventory_get_item(inventory, args->ranges[i].quantity); set_up_quantity(&controls, gvalue, i); } logical_op_changed(GTK_COMBO_BOX(controls.logical_op), &controls); /* finished initializing, allow instant updates */ controls.in_init = FALSE; gfilter_invalidate(&controls); gtk_widget_show_all(dialog); do { response = gtk_dialog_run(GTK_DIALOG(dialog)); switch (response) { case GTK_RESPONSE_CANCEL: case GTK_RESPONSE_DELETE_EVENT: args->expanded = gwy_grain_value_tree_view_get_expanded_groups (GTK_TREE_VIEW(controls.values)); for (i = 0; i < NQUANTITIES; i++) gwy_si_unit_value_format_free(controls.vf[i]); gtk_widget_destroy(dialog); case GTK_RESPONSE_NONE: g_object_unref(controls.mydata); gfilter_save_args(gwy_app_settings_get(), args); return; break; case GTK_RESPONSE_OK: break; case RESPONSE_PREVIEW: preview(&controls); break; default: g_assert_not_reached(); break; } } while (response != GTK_RESPONSE_OK); for (i = 0; i < NQUANTITIES; i++) gwy_si_unit_value_format_free(controls.vf[i]); args->expanded = gwy_grain_value_tree_view_get_expanded_groups (GTK_TREE_VIEW(controls.values)); gwy_app_sync_data_items(controls.mydata, data, 0, id, FALSE, GWY_DATA_ITEM_MASK_COLOR, 0); gtk_widget_destroy(dialog); gfilter_save_args(gwy_app_settings_get(), args); if (controls.computed) { mfield = gwy_container_get_object_by_name(controls.mydata, "/0/mask"); gwy_app_undo_qcheckpointv(data, 1, &mquark); gwy_container_set_object(data, mquark, mfield); g_object_unref(controls.mydata); } else { g_object_unref(controls.mydata); run_noninteractive(args, data, controls.mask, mquark); } gwy_app_channel_log_add_proc(data, id, id); }
static void fit_dialog(FitArgs *args) { GtkWidget *label, *dialog, *hbox, *hbox2, *table, *align, *expander, *scroll; GtkTable *table2; GwyGraphModel *gmodel; GwyGraphCurveModel *cmodel; GwyGraphArea *area; GwySelection *selection; GwySIUnit *siunit; FitControls controls; gint response, row; GString *report; gdouble xmin, xmax; controls.args = args; controls.in_update = TRUE; controls.param = g_array_new(FALSE, TRUE, sizeof(FitParamControl)); gmodel = gwy_graph_get_model(GWY_GRAPH(args->parent_graph)); gwy_graph_model_get_x_range(gmodel, &xmin, &xmax); g_object_get(gmodel, "si-unit-x", &siunit, NULL); args->abscissa_vf = gwy_si_unit_get_format_with_digits(siunit, GWY_SI_UNIT_FORMAT_VFMARKUP, MAX(fabs(xmin), fabs(xmax)), 4, NULL); g_object_unref(siunit); dialog = gtk_dialog_new_with_buttons(_("Fit FD Curve"), NULL, 0, NULL); controls.dialog = dialog; gtk_dialog_add_action_widget(GTK_DIALOG(dialog), gwy_stock_like_button_new(gwy_sgettext("verb|_Fit"), GTK_STOCK_EXECUTE), RESPONSE_FIT); gtk_dialog_add_button(GTK_DIALOG(dialog), gwy_sgettext("verb|_Estimate"), RESPONSE_ESTIMATE); gtk_dialog_add_button(GTK_DIALOG(dialog), _("_Plot Inits"), RESPONSE_PLOT); gtk_dialog_add_button(GTK_DIALOG(dialog), GTK_STOCK_SAVE, RESPONSE_SAVE); gtk_dialog_add_button(GTK_DIALOG(dialog), GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL); gtk_dialog_add_button(GTK_DIALOG(dialog), GTK_STOCK_OK, GTK_RESPONSE_OK); gwy_help_add_to_graph_dialog(GTK_DIALOG(dialog), GWY_HELP_DEFAULT); gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_OK); hbox = gtk_hbox_new(FALSE, 2); gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), hbox, TRUE, TRUE, 0); /* Graph */ args->graph_model = gwy_graph_model_new_alike(gmodel); controls.graph = gwy_graph_new(args->graph_model); g_object_unref(args->graph_model); gtk_widget_set_size_request(controls.graph, 400, 300); gwy_graph_enable_user_input(GWY_GRAPH(controls.graph), FALSE); gtk_box_pack_start(GTK_BOX(hbox), controls.graph, TRUE, TRUE, 0); gwy_graph_set_status(GWY_GRAPH(controls.graph), GWY_GRAPH_STATUS_XSEL); area = GWY_GRAPH_AREA(gwy_graph_get_area(GWY_GRAPH(controls.graph))); selection = gwy_graph_area_get_selection(area, GWY_GRAPH_STATUS_XSEL); gwy_selection_set_max_objects(selection, 1); g_signal_connect(selection, "changed", G_CALLBACK(graph_selected), &controls); gwy_graph_model_add_curve(controls.args->graph_model, gwy_graph_model_get_curve(gmodel, args->curve)); args->fitfunc = NULL; /* Controls */ align = gtk_alignment_new(0.0, 0.0, 0.0, 0.0); gtk_box_pack_start(GTK_BOX(hbox), align, FALSE, FALSE, 0); g_signal_connect(align, "size-request", G_CALLBACK(grow_width), NULL); table = gtk_table_new(7, 2, FALSE); gtk_table_set_row_spacings(GTK_TABLE(table), 2); gtk_table_set_col_spacings(GTK_TABLE(table), 6); gtk_box_pack_start(GTK_BOX(hbox), table, FALSE, FALSE, 0); gtk_container_set_border_width(GTK_CONTAINER(table), 4); row = 0; /* Curve to fit */ label = gtk_label_new_with_mnemonic(_("_Graph curve:")); gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5); gtk_table_attach(GTK_TABLE(table), label, 0, 1, row, row+1, GTK_FILL, 0, 0, 0); controls.curve = curve_selector_new(gmodel, G_CALLBACK(curve_changed), &controls, args->curve); gtk_label_set_mnemonic_widget(GTK_LABEL(label), controls.curve); gtk_table_attach(GTK_TABLE(table), controls.curve, 1, 2, row, row+1, GTK_EXPAND | GTK_FILL, 0, 0, 0); row++; /* Fitted function */ label = gtk_label_new_with_mnemonic(_("F_unction:")); gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5); gtk_table_attach(GTK_TABLE(table), label, 0, 1, row, row+1, GTK_FILL, 0, 0, 0); controls.function = function_selector_new(G_CALLBACK(function_changed), &controls, args->function_type); gtk_label_set_mnemonic_widget(GTK_LABEL(label), controls.function); gtk_table_attach(GTK_TABLE(table), controls.function, 1, 2, row, row+1, GTK_EXPAND | GTK_FILL, 0, 0, 0); row++; controls.formula = gtk_label_new("f(x) ="); gtk_misc_set_alignment(GTK_MISC(controls.formula), 0.0, 0.5); gtk_label_set_selectable(GTK_LABEL(controls.formula), TRUE); scroll = gtk_scrolled_window_new(NULL, NULL); gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scroll), controls.formula); gtk_table_attach(GTK_TABLE(table), scroll, 0, 2, row, row+1, GTK_FILL, 0, 0, 8); row++; /* Parameters sought */ controls.param_table = gtk_table_new(1, 10, FALSE); table2 = GTK_TABLE(controls.param_table); gtk_table_set_row_spacing(table2, 0, 2); gtk_table_set_col_spacings(table2, 2); gtk_table_set_col_spacing(table2, 0, 6); gtk_table_set_col_spacing(table2, 4, 6); gtk_table_set_col_spacing(table2, 5, 6); gtk_table_set_col_spacing(table2, 7, 6); gtk_table_set_col_spacing(table2, 8, 6); gtk_table_attach(GTK_TABLE(table), GTK_WIDGET(table2), 0, 2, row, row+1, GTK_FILL, 0, 0, 0); gtk_table_set_row_spacing(GTK_TABLE(table), row, 8); row++; gtk_table_attach(table2, gwy_label_new_header(_("Fix")), 0, 1, 0, 1, GTK_FILL, 0, 0, 0); gtk_table_attach(table2, gwy_label_new_header(_("Parameter")), 1, 5, 0, 1, GTK_FILL, 0, 0, 0); gtk_table_attach(table2, gwy_label_new_header(_("Error")), 6, 8, 0, 1, GTK_FILL, 0, 0, 0); gtk_table_attach(table2, gwy_label_new_header(_("Initial")), 9, 10, 0, 1, GTK_FILL, 0, 0, 0); /* Make space for 4 parameters */ #if 0 for (i = 0; i < 4; i++) fit_param_row_create(&controls, i, table2, i+1); #endif /* Chi^2 */ label = gtk_label_new(NULL); gtk_label_set_markup(GTK_LABEL(label), _("χ<sup>2</sup> result:")); gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5); gtk_table_attach(GTK_TABLE(table), label, 0, 1, row, row+1, GTK_FILL, 0, 0, 0); controls.chisq = gtk_label_new(NULL); gtk_misc_set_alignment(GTK_MISC(controls.chisq), 0.0, 0.5); gtk_table_attach(GTK_TABLE(table), controls.chisq, 1, 2, row, row+1, GTK_EXPAND | GTK_FILL, 0, 0, 0); gtk_table_set_row_spacing(GTK_TABLE(table), row, 8); row++; /* Correlation matrix */ expander = gtk_expander_new(NULL); gtk_expander_set_label_widget(GTK_EXPANDER(expander), gwy_label_new_header(_("Correlation Matrix"))); gtk_table_attach(GTK_TABLE(table), expander, 0, 2, row, row+1, GTK_FILL, 0, 0, 0); gtk_table_set_row_spacing(GTK_TABLE(table), row, 8); row++; align = gtk_alignment_new(0.0, 0.5, 0.0, 0.0); gtk_container_add(GTK_CONTAINER(expander), align); row++; controls.covar = g_array_new(FALSE, TRUE, sizeof(GtkWidget*)); controls.covar_table = gtk_table_new(1, 1, TRUE); table2 = GTK_TABLE(controls.covar_table); gtk_table_set_col_spacings(table2, 6); gtk_table_set_row_spacings(table2, 2); gtk_container_add(GTK_CONTAINER(align), GTK_WIDGET(table2)); /* Fit area */ hbox2 = gtk_hbox_new(FALSE, 6); gtk_table_attach(GTK_TABLE(table), hbox2, 0, 2, row, row+1, GTK_FILL, 0, 0, 0); row++; label = gtk_label_new(_("Range:")); gtk_box_pack_start(GTK_BOX(hbox2), label, FALSE, FALSE, 0); controls.from = gtk_entry_new(); g_object_set_data(G_OBJECT(controls.from), "id", (gpointer)"from"); gtk_entry_set_width_chars(GTK_ENTRY(controls.from), 8); gtk_box_pack_start(GTK_BOX(hbox2), controls.from, FALSE, FALSE, 0); g_signal_connect(controls.from, "activate", G_CALLBACK(range_changed), &controls); gwy_widget_set_activate_on_unfocus(controls.from, TRUE); label = gtk_label_new(gwy_sgettext("range|to")); gtk_box_pack_start(GTK_BOX(hbox2), label, FALSE, FALSE, 0); controls.to = gtk_entry_new(); g_object_set_data(G_OBJECT(controls.to), "id", (gpointer)"to"); gtk_entry_set_width_chars(GTK_ENTRY(controls.to), 8); gtk_box_pack_start(GTK_BOX(hbox2), controls.to, FALSE, FALSE, 0); g_signal_connect(controls.to, "activate", G_CALLBACK(range_changed), &controls); gwy_widget_set_activate_on_unfocus(controls.to, TRUE); label = gtk_label_new(NULL); gtk_label_set_markup(GTK_LABEL(label), args->abscissa_vf->units); gtk_box_pack_start(GTK_BOX(hbox2), label, FALSE, FALSE, 0); /* Auto-update */ hbox2 = gtk_hbox_new(FALSE, 6); gtk_table_attach(GTK_TABLE(table), hbox2, 0, 2, row, row+1, GTK_FILL, 0, 0, 0); row++; label = gtk_label_new(_("Instant:")); gtk_box_pack_start(GTK_BOX(hbox2), label, FALSE, FALSE, 0); controls.auto_estimate = gtk_check_button_new_with_mnemonic(_("e_stimate")); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(controls.auto_estimate), args->auto_estimate); gtk_box_pack_start(GTK_BOX(hbox2), controls.auto_estimate, FALSE, FALSE, 0); g_signal_connect(controls.auto_estimate, "toggled", G_CALLBACK(auto_estimate_changed), &controls); controls.auto_plot = gtk_check_button_new_with_mnemonic(_("p_lot")); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(controls.auto_plot), args->auto_plot); gtk_box_pack_start(GTK_BOX(hbox2), controls.auto_plot, FALSE, FALSE, 0); g_signal_connect(controls.auto_plot, "toggled", G_CALLBACK(auto_plot_changed), &controls); function_changed(GTK_COMBO_BOX(controls.function), &controls); graph_selected(selection, -1, &controls); controls.in_update = FALSE; gtk_widget_show_all(dialog); do { response = gtk_dialog_run(GTK_DIALOG(dialog)); fit_fetch_entry(&controls); switch (response) { case GTK_RESPONSE_CANCEL: case GTK_RESPONSE_DELETE_EVENT: gtk_widget_destroy(dialog); fit_controls_free(&controls); return; break; case GTK_RESPONSE_OK: if (args->is_estimated) { cmodel = gwy_graph_model_get_curve(args->graph_model, 1); gwy_graph_model_add_curve(gmodel, cmodel); } gtk_widget_destroy(dialog); break; case RESPONSE_SAVE: report = create_fit_report(args); gwy_save_auxiliary_data(_("Save Fit Report"), GTK_WINDOW(dialog), -1, report->str); g_string_free(report, TRUE); break; case RESPONSE_ESTIMATE: fit_estimate(&controls); break; case RESPONSE_PLOT: fit_set_state(&controls, FALSE, TRUE); fit_plot_curve(args); break; case RESPONSE_FIT: fit_do(&controls); break; default: g_assert_not_reached(); break; } } while (response != GTK_RESPONSE_OK); fit_controls_free(&controls); }
static void fit_param_row_create(FitControls *controls, gint i, GtkTable *table, gint row) { FitParamControl *cntrl; cntrl = &g_array_index(controls->param, FitParamControl, i); /* Fix */ cntrl->fix = gtk_check_button_new(); gtk_table_attach(table, cntrl->fix, 0, 1, row, row+1, 0, 0, 0, 0); g_object_set_data(G_OBJECT(cntrl->fix), "id", GINT_TO_POINTER(i + 1)); gtk_widget_show(cntrl->fix); g_signal_connect(cntrl->fix, "toggled", G_CALLBACK(fix_changed), controls); /* Name */ cntrl->name = gtk_label_new(NULL); gtk_misc_set_alignment(GTK_MISC(cntrl->name), 1.0, 0.5); gtk_table_attach(table, cntrl->name, 1, 2, row, row+1, GTK_FILL, 0, 0, 0); gtk_widget_show(cntrl->name); /* Equals */ cntrl->equals = gtk_label_new("="); gtk_table_attach(table, cntrl->equals, 2, 3, row, row+1, 0, 0, 0, 0); gtk_widget_show(cntrl->equals); /* Value */ cntrl->value = gtk_label_new(NULL); gtk_misc_set_alignment(GTK_MISC(cntrl->value), 1.0, 0.5); gtk_table_attach(table, cntrl->value, 3, 4, row, row+1, GTK_FILL, 0, 0, 0); gtk_widget_show(cntrl->value); cntrl->value_unit = gtk_label_new(NULL); gtk_misc_set_alignment(GTK_MISC(cntrl->value_unit), 0.0, 0.5); gtk_table_attach(table, cntrl->value_unit, 4, 5, row, row+1, GTK_FILL, 0, 0, 0); gtk_widget_show(cntrl->value_unit); /* Plus-minus */ cntrl->pm = gtk_label_new("±"); gtk_table_attach(table, cntrl->pm, 5, 6, row, row+1, 0, 0, 0, 0); gtk_widget_show(cntrl->pm); /* Error */ cntrl->error = gtk_label_new(NULL); gtk_misc_set_alignment(GTK_MISC(cntrl->error), 1.0, 0.5); gtk_table_attach(table, cntrl->error, 6, 7, row, row+1, GTK_FILL, 0, 0, 0); gtk_widget_show(cntrl->error); cntrl->error_unit = gtk_label_new(NULL); gtk_misc_set_alignment(GTK_MISC(cntrl->error_unit), 0.0, 0.5); gtk_table_attach(table, cntrl->error_unit, 7, 8, row, row+1, GTK_FILL, 0, 0, 0); gtk_widget_show(cntrl->error_unit); /* Copy */ cntrl->copy = gtk_button_new_with_label("→"); gtk_button_set_relief(GTK_BUTTON(cntrl->copy), GTK_RELIEF_NONE); gtk_table_attach(table, cntrl->copy, 8, 9, row, row+1, 0, 0, 0, 0); g_object_set_data(G_OBJECT(cntrl->copy), "id", GINT_TO_POINTER(i + 1)); gtk_widget_show(cntrl->copy); g_signal_connect(cntrl->copy, "clicked", G_CALLBACK(copy_param), controls); /* Initial */ cntrl->init = gtk_entry_new(); gtk_entry_set_width_chars(GTK_ENTRY(cntrl->init), 12); gtk_table_attach(table, cntrl->init, 9, 10, row, row+1, GTK_EXPAND | GTK_FILL, 0, 0, 0); g_object_set_data(G_OBJECT(cntrl->init), "id", GINT_TO_POINTER(i + 1)); gtk_widget_show(cntrl->init); g_signal_connect(cntrl->init, "activate", G_CALLBACK(param_initial_activate), controls); gwy_widget_set_activate_on_unfocus(cntrl->init, TRUE); }
static gboolean tilt_dialog(TiltArgs *args, GwyDataField *dfield) { enum { RESPONSE_RESET = 1 }; GtkWidget *dialog, *spin, *table, *label; GwySIUnit *unit; gchar *unitstr; TiltControls controls; gboolean units_equal; gint row, response; unit = gwy_si_unit_new(NULL); units_equal = gwy_si_unit_equal(gwy_data_field_get_si_unit_z(dfield), gwy_data_field_get_si_unit_xy(dfield)); gwy_si_unit_divide(gwy_data_field_get_si_unit_z(dfield), gwy_data_field_get_si_unit_xy(dfield), unit); unitstr = gwy_si_unit_get_string(unit, GWY_SI_UNIT_FORMAT_VFMARKUP); g_object_unref(unit); dialog = gtk_dialog_new_with_buttons(_("Tilt"), NULL, 0, _("_Reset"), RESPONSE_RESET, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OK, GTK_RESPONSE_OK, NULL); gtk_dialog_set_has_separator(GTK_DIALOG(dialog), FALSE); gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_OK); controls.args = args; controls.in_update = TRUE; table = gtk_table_new(5 + (units_equal ? 1 : 0), 3, FALSE); gtk_table_set_row_spacings(GTK_TABLE(table), 2); gtk_table_set_col_spacings(GTK_TABLE(table), 6); gtk_container_set_border_width(GTK_CONTAINER(table), 4); gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), table); row = 0; /* Slopes */ label = gwy_label_new_header(_("Slopes")); gtk_table_attach(GTK_TABLE(table), label, 0, 3, row, row+1, GTK_EXPAND | GTK_FILL, 0, 0, 0); row++; controls.dx = gtk_adjustment_new(args->dx, -100, 100, 1e-4, 1e-2, 0); spin = gwy_table_attach_hscale(table, row, _("_X:"), unitstr, controls.dx, GWY_HSCALE_NO_SCALE); gwy_widget_set_activate_on_unfocus(spin, TRUE); gtk_spin_button_set_digits(GTK_SPIN_BUTTON(spin), 6); g_signal_connect(controls.dx, "value-changed", G_CALLBACK(tilt_dx_changed), &controls); row++; controls.dy = gtk_adjustment_new(args->dy, -100, 100, 1e-4, 1e-2, 0); spin = gwy_table_attach_hscale(table, row, _("_Y:"), unitstr, controls.dy, GWY_HSCALE_NO_SCALE); gwy_widget_set_activate_on_unfocus(spin, TRUE); gtk_spin_button_set_digits(GTK_SPIN_BUTTON(spin), 6); g_signal_connect(controls.dy, "value-changed", G_CALLBACK(tilt_dy_changed), &controls); gtk_table_set_row_spacing(GTK_TABLE(table), row, 8); row++; /* Angles (adjustment values will be calculated later) */ label = gwy_label_new_header(_("Angles")); gtk_table_attach(GTK_TABLE(table), label, 0, 3, row, row+1, GTK_EXPAND | GTK_FILL, 0, 0, 0); row++; if (units_equal) { controls.theta = gtk_adjustment_new(0, 0, 89.6, 1e-2, 1.0, 0); spin = gwy_table_attach_hscale(table, row, _("θ:"), _("deg"), controls.theta, GWY_HSCALE_NO_SCALE); gwy_widget_set_activate_on_unfocus(spin, TRUE); gtk_spin_button_set_digits(GTK_SPIN_BUTTON(spin), 4); g_signal_connect_swapped(controls.theta, "value-changed", G_CALLBACK(tilt_angle_changed), &controls); row++; } else controls.theta = gtk_adjustment_new(0, 0, 90.0, 1e-2, 1.0, 0); controls.phi = gtk_adjustment_new(0, -180, 180, 1e-2, 1.0, 0); spin = gwy_table_attach_hscale(table, row, _("φ:"), _("deg"), controls.phi, GWY_HSCALE_NO_SCALE); gwy_widget_set_activate_on_unfocus(spin, TRUE); gtk_spin_button_set_digits(GTK_SPIN_BUTTON(spin), 4); g_signal_connect_swapped(controls.phi, "value-changed", G_CALLBACK(tilt_angle_changed), &controls); row++; controls.in_update = FALSE; tilt_deriv_to_angles(&controls); gtk_widget_show_all(dialog); do { response = gtk_dialog_run(GTK_DIALOG(dialog)); switch (response) { case GTK_RESPONSE_CANCEL: case GTK_RESPONSE_DELETE_EVENT: gtk_widget_destroy(dialog); case GTK_RESPONSE_NONE: return FALSE; break; case GTK_RESPONSE_OK: break; case RESPONSE_RESET: dialog_reset(&controls); break; default: g_assert_not_reached(); break; } } while (response != GTK_RESPONSE_OK); gtk_widget_destroy(dialog); return TRUE; }