From 189da15810deabd739d7c11c6e95fea55739fe60 Mon Sep 17 00:00:00 2001 From: Thomas White Date: Sat, 1 Aug 2020 15:13:49 +0200 Subject: Initial import from archive --- src/model-editor.c | 831 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 831 insertions(+) create mode 100644 src/model-editor.c (limited to 'src/model-editor.c') diff --git a/src/model-editor.c b/src/model-editor.c new file mode 100644 index 0000000..3146b5d --- /dev/null +++ b/src/model-editor.c @@ -0,0 +1,831 @@ +/* + * model-editor.c + * + * GUI for editing atomic models + * + * (c) 2006-2007 Thomas White + * + * synth2d - Two-Dimensional Crystallographic Fourier Synthesis + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include + +#include "displaywindow.h" +#include "data.h" +#include "elements.h" +#include "main.h" +#include "statistics.h" +#include "refine.h" +#include "model.h" +#include "gtk-symmetry.h" + +enum { + MODEL_ATOMS_COLUMN_ACTIVE, + MODEL_ATOMS_COLUMN_REFINE, + MODEL_ATOMS_COLUMN_ELEMENT, + MODEL_ATOMS_COLUMN_X, + MODEL_ATOMS_COLUMN_Y, + MODEL_ATOMS_COLUMN_Z, /* Atomic coordinates */ + MODEL_ATOMS_COLUMN_B, /* Debye-Waller */ + MODEL_ATOMS_COLUMN_OCC, /* Occupancy */ + MODEL_ATOMS_COLUMNS +}; + +static gint model_save_response(GtkWidget *dialog, gint response, gpointer data) { + + if ( response == GTK_RESPONSE_ACCEPT ) { + + char *filename; + + filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)); + model_save(filename, model_get_current()); + g_free(filename); + + } + + gtk_widget_destroy(dialog); + + return 0; + +} + +gint model_save_open(GtkWidget *widget, gpointer data) { + + GtkWidget *dialog; + + dialog = gtk_file_chooser_dialog_new("Save Atomic Model", GTK_WINDOW(displaywindow_gtkwindow()), GTK_FILE_CHOOSER_ACTION_SAVE, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, NULL); + #if HAVE_GTK_TEN + gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(dialog), TRUE); + #endif /* HAVE_GTK_TEN */ + gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), "synth2d-model.xyz"); + + g_signal_connect(G_OBJECT(dialog), "response", G_CALLBACK(model_save_response), NULL); + + gtk_widget_show_all(dialog); + + return 0; + +} + +static gint model_load_response(GtkWidget *dialog, gint response, gpointer data) { + + if ( response == GTK_RESPONSE_ACCEPT ) { + + char *filename; + + filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)); + model_load_as_current(filename); + displaywindow_forceview(DWV_MODEL); + g_free(filename); + + } + + gtk_widget_destroy(dialog); + + return 0; + +} + +gint model_load_open(GtkWidget *widget, gpointer data) { + + GtkWidget *dialog; + + dialog = gtk_file_chooser_dialog_new("Load Atomic Model", GTK_WINDOW(displaywindow_gtkwindow()), GTK_FILE_CHOOSER_ACTION_OPEN, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL); + + g_signal_connect(G_OBJECT(dialog), "response", G_CALLBACK(model_load_response), NULL); + + gtk_widget_show_all(dialog); + + return 0; + +} + +/* Not all model updates should trigger an update of the display and R-factor + * (e.g. changing a refinement flag) */ +static void model_editor_put_model_noupdate(ModelEditor *editor) { + + GtkTreeIter iter; + gboolean ival; + + editor->model->n_atoms = 0; + ival = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(editor->list_store), &iter); + while ( ival ) { + + double x, y, z, B, occ; + gboolean refine, active; + gchar *tmp; + + gtk_tree_model_get(GTK_TREE_MODEL(editor->list_store), &iter, MODEL_ATOMS_COLUMN_X, &x, MODEL_ATOMS_COLUMN_Y, &y, MODEL_ATOMS_COLUMN_Z, &z, + MODEL_ATOMS_COLUMN_ELEMENT, &tmp, + MODEL_ATOMS_COLUMN_B, &B, MODEL_ATOMS_COLUMN_OCC, &occ, + MODEL_ATOMS_COLUMN_ACTIVE, &active, MODEL_ATOMS_COLUMN_REFINE, &refine, -1); + + editor->model->atoms[editor->model->n_atoms].x = x; + editor->model->atoms[editor->model->n_atoms].y = y; + editor->model->atoms[editor->model->n_atoms].z = z; + editor->model->atoms[editor->model->n_atoms].B = B; + editor->model->atoms[editor->model->n_atoms].occ = occ; + editor->model->atoms[editor->model->n_atoms].active = active; + editor->model->atoms[editor->model->n_atoms].refine = refine; + editor->model->atoms[editor->model->n_atoms].ref = elements_lookup(tmp); + editor->model->n_atoms++; + + ival = gtk_tree_model_iter_next(GTK_TREE_MODEL(editor->list_store), &iter); + + } + +} + +/* Transfer model from an editor to its corresponding model */ +static void model_editor_put_model(ModelEditor *editor) { + model_editor_put_model_noupdate(editor); + model_notify_update_editor(editor->model); +} + +/* Transfer model->editor */ +void model_editor_get_model(ModelEditor *editor) { + + size_t i; + char tmp[32]; + + gtk_list_store_clear(GTK_LIST_STORE(editor->list_store)); + for ( i=0; imodel->n_atoms; i++ ) { + + double x, y, z, B, occ; + gboolean refine, active; + GtkTreeIter iter; + + x = editor->model->atoms[i].x; + y = editor->model->atoms[i].y; + z = editor->model->atoms[i].z; + B = editor->model->atoms[i].B; + occ = editor->model->atoms[i].occ; + active = editor->model->atoms[i].active; + refine = editor->model->atoms[i].refine; + + gtk_list_store_append(GTK_LIST_STORE(editor->list_store), &iter); + gtk_list_store_set(editor->list_store, &iter, MODEL_ATOMS_COLUMN_X, x, MODEL_ATOMS_COLUMN_Y, y, MODEL_ATOMS_COLUMN_Z, z, + MODEL_ATOMS_COLUMN_ELEMENT, elements[editor->model->atoms[i].ref].element_name, + MODEL_ATOMS_COLUMN_B, B, MODEL_ATOMS_COLUMN_OCC, occ, + MODEL_ATOMS_COLUMN_ACTIVE, active, MODEL_ATOMS_COLUMN_REFINE, refine, -1); + + }; + + snprintf(tmp, 31, "%.2f", editor->model->thickness); + gtk_entry_set_text(GTK_ENTRY(editor->thickness), tmp); + gtk_symmetry_set_symmetry(GTK_SYMMETRY(editor->symmetry), editor->model->sym); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(editor->point_atoms), editor->model->point_atoms); + + +} + +static gint model_editor_symmetry_changed(GtkWidget *thickness, ModelEditor *editor) { + + editor->model->sym = gtk_symmetry_get_symmetry(GTK_SYMMETRY(editor->symmetry)); + model_notify_update_editor(editor->model); + + return 0; + +} + +static gint model_editor_thickness_edited(GtkWidget *thickness, ModelEditor *editor) { + + const char *str; + float tf; + double t; + char tmp[32]; + + str = gtk_entry_get_text(GTK_ENTRY(thickness)); + sscanf(str, "%f", &tf); t = tf; + editor->model->thickness = t; + + snprintf(tmp, 31, "%.2f", editor->model->thickness); + gtk_entry_set_text(GTK_ENTRY(thickness), tmp); + + model_notify_update_editor(editor->model); + + return 0; + +} + +void model_editor_unlock(ModelEditor *editor) { + + gtk_widget_set_sensitive(editor->add_button, TRUE); + gtk_widget_set_sensitive(editor->model_atoms_tree, TRUE); + +} + +void model_editor_lock(ModelEditor *editor) { + + gtk_widget_set_sensitive(editor->add_button, FALSE); + gtk_widget_set_sensitive(editor->model_atoms_tree, FALSE); + gtk_tree_selection_unselect_all(gtk_tree_view_get_selection(GTK_TREE_VIEW(editor->model_atoms_tree))); + +} + +static gint model_atoms_delete_atom(GtkWidget *widget, ModelEditor *editor) { + + GtkTreePath *path; + GtkTreeViewColumn *column; + GtkTreeIter iter; + + gtk_tree_view_get_cursor(GTK_TREE_VIEW(editor->model_atoms_tree), &path, &column); + gtk_tree_model_get_iter(GTK_TREE_MODEL(editor->list_store), &iter, path); + gtk_list_store_remove(GTK_LIST_STORE(editor->list_store), &iter); + model_editor_put_model(editor); + + return 0; + +} + +static gint model_atoms_add_atom(GtkWidget *widget, ModelEditor *editor) { + + GtkTreeIter iter; + unsigned int number; + + number = gtk_combo_box_get_active(GTK_COMBO_BOX(editor->atom_define)); + gtk_list_store_append(GTK_LIST_STORE(editor->list_store), &iter); + gtk_list_store_set(GTK_LIST_STORE(editor->list_store), &iter, + MODEL_ATOMS_COLUMN_ELEMENT, elements[number].element_name, + MODEL_ATOMS_COLUMN_ACTIVE, TRUE, MODEL_ATOMS_COLUMN_REFINE, TRUE, + MODEL_ATOMS_COLUMN_B, 0.0005, + MODEL_ATOMS_COLUMN_OCC, 1.0, -1); + model_editor_put_model(editor); + + return 0; + +} + +static gint model_atoms_selection_changed(GtkTreeSelection *selection, ModelEditor *editor) { + + GtkTreePath *path; + GtkTreeViewColumn *column; + GtkTreeIter iter; + double x, y, z, B, occ; + char tmp[32]; + + gtk_widget_set_sensitive(editor->delete_button, gtk_tree_selection_get_selected(selection, NULL, NULL)); + gtk_widget_set_sensitive(editor->position_table, gtk_tree_selection_get_selected(selection, NULL, NULL)); + + if ( !gtk_tree_selection_get_selected(selection, NULL, NULL) ) return 0; + + gtk_tree_view_get_cursor(GTK_TREE_VIEW(editor->model_atoms_tree), &path, &column); + gtk_tree_model_get_iter(GTK_TREE_MODEL(editor->list_store), &iter, path); + gtk_tree_model_get(GTK_TREE_MODEL(editor->list_store), &iter, MODEL_ATOMS_COLUMN_X, &x, + MODEL_ATOMS_COLUMN_Y, &y, MODEL_ATOMS_COLUMN_Z, &z, + MODEL_ATOMS_COLUMN_B, &B, MODEL_ATOMS_COLUMN_OCC, &occ, -1); + + /* Set the scales, but don't trigger a callback */ + editor->scale_lock++; + gtk_range_set_value(GTK_RANGE(editor->x_scale), x); + gtk_range_set_value(GTK_RANGE(editor->y_scale), y); + gtk_range_set_value(GTK_RANGE(editor->z_scale), z); + gtk_range_set_value(GTK_RANGE(editor->b_scale), B); + gtk_range_set_value(GTK_RANGE(editor->occ_scale), occ); + editor->scale_lock--; + + snprintf(tmp, 31, "%f", x); gtk_entry_set_text(GTK_ENTRY(editor->x_edit), tmp); + snprintf(tmp, 31, "%f", y); gtk_entry_set_text(GTK_ENTRY(editor->y_edit), tmp); + snprintf(tmp, 31, "%f", z); gtk_entry_set_text(GTK_ENTRY(editor->z_edit), tmp); + snprintf(tmp, 31, "%f", B); gtk_entry_set_text(GTK_ENTRY(editor->b_edit), tmp); + snprintf(tmp, 31, "%f", occ); gtk_entry_set_text(GTK_ENTRY(editor->occ_edit), tmp); + + return 0; + +} + +static gint model_atoms_active_toggled(GtkCellRendererToggle *cell, gchar *path_string, ModelEditor *editor) { + + GtkTreeIter iter; + gboolean active; + + gtk_tree_model_get_iter_from_string(GTK_TREE_MODEL(editor->list_store), &iter, path_string); + + gtk_tree_model_get(GTK_TREE_MODEL(editor->list_store), &iter, MODEL_ATOMS_COLUMN_ACTIVE, &active, -1); + active = !active; + gtk_list_store_set(GTK_LIST_STORE(editor->list_store), &iter, MODEL_ATOMS_COLUMN_ACTIVE, active, -1); + + model_editor_put_model(editor); + + return 0; + +} + +static gint model_atoms_refine_toggled(GtkCellRendererToggle *cell, gchar *path_string, ModelEditor *editor) { + + GtkTreeIter iter; + gboolean refine; + + gtk_tree_model_get_iter_from_string(GTK_TREE_MODEL(editor->list_store), &iter, path_string); + + gtk_tree_model_get(GTK_TREE_MODEL(editor->list_store), &iter, MODEL_ATOMS_COLUMN_REFINE, &refine, -1); + refine = !refine; + gtk_list_store_set(GTK_LIST_STORE(editor->list_store), &iter, MODEL_ATOMS_COLUMN_REFINE, refine, -1); + + model_editor_put_model_noupdate(editor); + + return 0; + +} + +static gint model_editor_x_edit(GtkWidget *x_edit, ModelEditor *editor) { + + const char *str; + float xf; + double x; + GtkTreePath *path; + GtkTreeViewColumn *column; + GtkTreeIter iter; + + str = gtk_entry_get_text(GTK_ENTRY(x_edit)); + sscanf(str, "%f", &xf); x = xf; + + gtk_tree_view_get_cursor(GTK_TREE_VIEW(editor->model_atoms_tree), &path, &column); + gtk_tree_model_get_iter(GTK_TREE_MODEL(editor->list_store), &iter, path); + gtk_list_store_set(GTK_LIST_STORE(editor->list_store), &iter, MODEL_ATOMS_COLUMN_X, x, -1); + + /* This triggers an x_scale callback which updates the model */ + gtk_range_set_value(GTK_RANGE(editor->x_scale), x); + + return 0; + +} + +static gint model_editor_y_edit(GtkWidget *y_edit, ModelEditor *editor) { + + const char *str; + float yf; + double y; + GtkTreePath *path; + GtkTreeViewColumn *column; + GtkTreeIter iter; + + str = gtk_entry_get_text(GTK_ENTRY(y_edit)); + sscanf(str, "%f", &yf); y = yf; + + gtk_tree_view_get_cursor(GTK_TREE_VIEW(editor->model_atoms_tree), &path, &column); + gtk_tree_model_get_iter(GTK_TREE_MODEL(editor->list_store), &iter, path); + gtk_list_store_set(GTK_LIST_STORE(editor->list_store), &iter, MODEL_ATOMS_COLUMN_Y, y, -1); + + /* This triggers a y_scale callback which updates the model */ + gtk_range_set_value(GTK_RANGE(editor->y_scale), y); + + return 0; + +} + +static gint model_editor_z_edit(GtkWidget *z_edit, ModelEditor *editor) { + + const char *str; + float zf; + double z; + GtkTreePath *path; + GtkTreeViewColumn *column; + GtkTreeIter iter; + + str = gtk_entry_get_text(GTK_ENTRY(z_edit)); + sscanf(str, "%f", &zf); z = zf; + + gtk_tree_view_get_cursor(GTK_TREE_VIEW(editor->model_atoms_tree), &path, &column); + gtk_tree_model_get_iter(GTK_TREE_MODEL(editor->list_store), &iter, path); + gtk_list_store_set(GTK_LIST_STORE(editor->list_store), &iter, MODEL_ATOMS_COLUMN_Z, z, -1); + + /* This triggers a z_scale callback which updates the model */ + gtk_range_set_value(GTK_RANGE(editor->z_scale), z); + + return 0; + +} + +static gint model_editor_b_edit(GtkWidget *b_edit, ModelEditor *editor) { + + const char *str; + float bf; + double b; + GtkTreePath *path; + GtkTreeViewColumn *column; + GtkTreeIter iter; + + str = gtk_entry_get_text(GTK_ENTRY(b_edit)); + sscanf(str, "%f", &bf); b = bf; + + gtk_tree_view_get_cursor(GTK_TREE_VIEW(editor->model_atoms_tree), &path, &column); + gtk_tree_model_get_iter(GTK_TREE_MODEL(editor->list_store), &iter, path); + gtk_list_store_set(GTK_LIST_STORE(editor->list_store), &iter, MODEL_ATOMS_COLUMN_B, b, -1); + + /* This triggers a b_scale callback which updates the model */ + gtk_range_set_value(GTK_RANGE(editor->b_scale), b); + + return 0; + +} + +static gint model_editor_occ_edit(GtkWidget *occ_edit, ModelEditor *editor) { + + const char *str; + float occf; + double occ; + GtkTreePath *path; + GtkTreeViewColumn *column; + GtkTreeIter iter; + + str = gtk_entry_get_text(GTK_ENTRY(occ_edit)); + sscanf(str, "%f", &occf); occ = occf; + + gtk_tree_view_get_cursor(GTK_TREE_VIEW(editor->model_atoms_tree), &path, &column); + gtk_tree_model_get_iter(GTK_TREE_MODEL(editor->list_store), &iter, path); + gtk_list_store_set(GTK_LIST_STORE(editor->list_store), &iter, MODEL_ATOMS_COLUMN_OCC, occ, -1); + + /* This triggers an occ_scale callback which updates the model */ + gtk_range_set_value(GTK_RANGE(editor->occ_scale), occ); + + return 0; + +} + +static gint model_editor_x_scale(GtkWidget *x_scale, ModelEditor *editor) { + + GtkTreePath *path; + GtkTreeViewColumn *column; + GtkTreeIter iter; + double x; + char tmp[32]; + + if ( editor->scale_lock > 0 ) return 0; + + x = gtk_range_get_value(GTK_RANGE(x_scale)); + + gtk_tree_view_get_cursor(GTK_TREE_VIEW(editor->model_atoms_tree), &path, &column); + gtk_tree_model_get_iter(GTK_TREE_MODEL(editor->list_store), &iter, path); + gtk_list_store_set(GTK_LIST_STORE(editor->list_store), &iter, MODEL_ATOMS_COLUMN_X, x, -1); + + snprintf(tmp, 31, "%f", x); gtk_entry_set_text(GTK_ENTRY(editor->x_edit), tmp); + + model_editor_put_model(editor); + + return 0; + +} + +static gint model_editor_y_scale(GtkWidget *y_scale, ModelEditor *editor) { + + GtkTreePath *path; + GtkTreeViewColumn *column; + GtkTreeIter iter; + double y; + char tmp[32]; + + if ( editor->scale_lock > 0 ) return 0; + + y = gtk_range_get_value(GTK_RANGE(y_scale)); + + gtk_tree_view_get_cursor(GTK_TREE_VIEW(editor->model_atoms_tree), &path, &column); + gtk_tree_model_get_iter(GTK_TREE_MODEL(editor->list_store), &iter, path); + gtk_list_store_set(GTK_LIST_STORE(editor->list_store), &iter, MODEL_ATOMS_COLUMN_Y, y, -1); + + snprintf(tmp, 31, "%f", y); gtk_entry_set_text(GTK_ENTRY(editor->y_edit), tmp); + + model_editor_put_model(editor); + + return 0; + +} + +static gint model_editor_z_scale(GtkWidget *z_scale, ModelEditor *editor) { + + GtkTreePath *path; + GtkTreeViewColumn *column; + GtkTreeIter iter; + double z; + char tmp[32]; + + if ( editor->scale_lock > 0 ) return 0; + + z = gtk_range_get_value(GTK_RANGE(z_scale)); + + gtk_tree_view_get_cursor(GTK_TREE_VIEW(editor->model_atoms_tree), &path, &column); + gtk_tree_model_get_iter(GTK_TREE_MODEL(editor->list_store), &iter, path); + gtk_list_store_set(GTK_LIST_STORE(editor->list_store), &iter, MODEL_ATOMS_COLUMN_Z, z, -1); + + snprintf(tmp, 31, "%f", z); gtk_entry_set_text(GTK_ENTRY(editor->z_edit), tmp); + + model_editor_put_model(editor); + + return 0; + +} + +static gint model_editor_b_scale(GtkWidget *b_scale, ModelEditor *editor) { + + GtkTreePath *path; + GtkTreeViewColumn *column; + GtkTreeIter iter; + double b; + char tmp[32]; + + if ( editor->scale_lock > 0 ) return 0; + + b = gtk_range_get_value(GTK_RANGE(b_scale)); + + gtk_tree_view_get_cursor(GTK_TREE_VIEW(editor->model_atoms_tree), &path, &column); + gtk_tree_model_get_iter(GTK_TREE_MODEL(editor->list_store), &iter, path); + gtk_list_store_set(GTK_LIST_STORE(editor->list_store), &iter, MODEL_ATOMS_COLUMN_B, b, -1); + + snprintf(tmp, 31, "%f", b); gtk_entry_set_text(GTK_ENTRY(editor->b_edit), tmp); + + model_editor_put_model(editor); + + return 0; + +} + +static gint model_editor_occ_scale(GtkWidget *occ_scale, ModelEditor *editor) { + + GtkTreePath *path; + GtkTreeViewColumn *column; + GtkTreeIter iter; + double occ; + char tmp[32]; + + if ( editor->scale_lock > 0 ) return 0; + + occ = gtk_range_get_value(GTK_RANGE(occ_scale)); + + gtk_tree_view_get_cursor(GTK_TREE_VIEW(editor->model_atoms_tree), &path, &column); + gtk_tree_model_get_iter(GTK_TREE_MODEL(editor->list_store), &iter, path); + gtk_list_store_set(GTK_LIST_STORE(editor->list_store), &iter, MODEL_ATOMS_COLUMN_OCC, occ, -1); + + snprintf(tmp, 31, "%f", occ); gtk_entry_set_text(GTK_ENTRY(editor->occ_edit), tmp); + + model_editor_put_model(editor); + + return 0; + +} + +static gint model_editor_pointatoms_toggled(GtkWidget *point_atoms, ModelEditor *editor) { + + editor->model->point_atoms = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(point_atoms)); + model_editor_put_model(editor); + + return 0; + +} + +static gint model_editor_close(GtkWidget *widget, gint response, ModelEditor *editor) { + + /* Bye bye */ + editor->model->editor = NULL; + gtk_widget_destroy(editor->window); + free(editor); + + return 0; + +} + +static void model_editor_do_list(GtkWidget *vbox, ModelEditor *editor) { + + GtkTreeViewColumn *column; + GtkCellRenderer *renderer; + GtkCellRenderer *togglerenderer_active; + GtkCellRenderer *togglerenderer_refine; + + GtkWidget *scrolledwindow; + GtkWidget *add_button; + GtkWidget *button_box; + + unsigned int i = 0; + + editor->list_store = gtk_list_store_new(MODEL_ATOMS_COLUMNS, G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, G_TYPE_STRING, G_TYPE_DOUBLE, + G_TYPE_DOUBLE, G_TYPE_DOUBLE, G_TYPE_DOUBLE, G_TYPE_DOUBLE); + model_editor_get_model(editor); + editor->model_atoms_tree = gtk_tree_view_new_with_model(GTK_TREE_MODEL(editor->list_store)); + + renderer = gtk_cell_renderer_text_new(); + togglerenderer_active = gtk_cell_renderer_toggle_new(); + togglerenderer_refine = gtk_cell_renderer_toggle_new(); + + column = gtk_tree_view_column_new_with_attributes("On", togglerenderer_active, "active", MODEL_ATOMS_COLUMN_ACTIVE, NULL); + gtk_tree_view_append_column(GTK_TREE_VIEW(editor->model_atoms_tree), column); + g_signal_connect(G_OBJECT(togglerenderer_active), "toggled", G_CALLBACK(model_atoms_active_toggled), editor); + + column = gtk_tree_view_column_new_with_attributes("R?", togglerenderer_refine, "active", MODEL_ATOMS_COLUMN_REFINE, NULL); + gtk_tree_view_append_column(GTK_TREE_VIEW(editor->model_atoms_tree), column); + g_signal_connect(G_OBJECT(togglerenderer_refine), "toggled", G_CALLBACK(model_atoms_refine_toggled), editor); + + column = gtk_tree_view_column_new_with_attributes("Element", renderer, "text", MODEL_ATOMS_COLUMN_ELEMENT, NULL); + gtk_tree_view_column_set_min_width(GTK_TREE_VIEW_COLUMN(column), 100); + gtk_tree_view_append_column(GTK_TREE_VIEW(editor->model_atoms_tree), column); + + column = gtk_tree_view_column_new_with_attributes("x", renderer, "text", MODEL_ATOMS_COLUMN_X, NULL); + gtk_tree_view_column_set_min_width(GTK_TREE_VIEW_COLUMN(column), 70); + gtk_tree_view_append_column(GTK_TREE_VIEW(editor->model_atoms_tree), column); + + column = gtk_tree_view_column_new_with_attributes("y", renderer, "text", MODEL_ATOMS_COLUMN_Y, NULL); + gtk_tree_view_column_set_min_width(GTK_TREE_VIEW_COLUMN(column), 70); + gtk_tree_view_append_column(GTK_TREE_VIEW(editor->model_atoms_tree), column); + + column = gtk_tree_view_column_new_with_attributes("z", renderer, "text", MODEL_ATOMS_COLUMN_Z, NULL); + gtk_tree_view_column_set_min_width(GTK_TREE_VIEW_COLUMN(column), 70); + gtk_tree_view_append_column(GTK_TREE_VIEW(editor->model_atoms_tree), column); + + column = gtk_tree_view_column_new_with_attributes("B", renderer, "text", MODEL_ATOMS_COLUMN_B, NULL); + gtk_tree_view_column_set_min_width(GTK_TREE_VIEW_COLUMN(column), 70); + gtk_tree_view_append_column(GTK_TREE_VIEW(editor->model_atoms_tree), column); + + column = gtk_tree_view_column_new_with_attributes("Occupancy", renderer, "text", MODEL_ATOMS_COLUMN_OCC, NULL); + gtk_tree_view_column_set_min_width(GTK_TREE_VIEW_COLUMN(column), 70); + gtk_tree_view_append_column(GTK_TREE_VIEW(editor->model_atoms_tree), column); + + scrolledwindow = gtk_scrolled_window_new(gtk_tree_view_get_hadjustment(GTK_TREE_VIEW(editor->model_atoms_tree)), + gtk_tree_view_get_vadjustment(GTK_TREE_VIEW(editor->model_atoms_tree))); + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolledwindow), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + gtk_container_add(GTK_CONTAINER(scrolledwindow), GTK_WIDGET(editor->model_atoms_tree)); + + gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(scrolledwindow), TRUE, TRUE, 5); + + button_box = gtk_hbox_new(FALSE, 0); + gtk_box_pack_start(GTK_BOX(vbox), button_box, FALSE, FALSE, 5); + + add_button = gtk_button_new_from_stock(GTK_STOCK_ADD); + gtk_box_pack_end(GTK_BOX(button_box), add_button, FALSE, FALSE, 5); + + editor->atom_define = gtk_combo_box_new_text(); + while ( elements[i].z > 0 ) { + gtk_combo_box_append_text(GTK_COMBO_BOX(editor->atom_define), elements[i].element_name); + i++; + } + gtk_combo_box_set_active(GTK_COMBO_BOX(editor->atom_define), 0); + gtk_box_pack_end(GTK_BOX(button_box), GTK_WIDGET(editor->atom_define), FALSE, FALSE, 5); + g_signal_connect(G_OBJECT(add_button), "clicked", G_CALLBACK(model_atoms_add_atom), editor); + + editor->delete_button = gtk_button_new_from_stock(GTK_STOCK_DELETE); + gtk_box_pack_end(GTK_BOX(button_box), editor->delete_button, FALSE, FALSE, 5); + g_signal_connect(G_OBJECT(editor->delete_button), "clicked", G_CALLBACK(model_atoms_delete_atom), editor); + + g_signal_connect(G_OBJECT(gtk_tree_view_get_selection(GTK_TREE_VIEW(editor->model_atoms_tree))), "changed", + G_CALLBACK(model_atoms_selection_changed), editor); + gtk_widget_set_sensitive(editor->delete_button, + gtk_tree_selection_get_selected(gtk_tree_view_get_selection(GTK_TREE_VIEW(editor->model_atoms_tree)), NULL, NULL)); + + editor->add_button = add_button; + +} + +/* Open the model editor for a given model */ +ModelEditor *model_editor_open(AtomicModel *model) { + + ModelEditor *editor; + + GtkWidget *vbox; + GtkWidget *hbox; + GtkWidget *x_scale_label; + GtkWidget *y_scale_label; + GtkWidget *z_scale_label; + GtkWidget *b_scale_label; + GtkWidget *occ_scale_label; + GtkWidget *top_hbox; + GtkWidget *label; + + /* Don't proceed if an editor is already open for this model */ + if ( model->editor ) return model->editor; + editor = malloc(sizeof(ModelEditor)); + editor->model = model; + editor->scale_lock = 0; + + editor->window = gtk_dialog_new_with_buttons("Edit Atomic Model", GTK_WINDOW(displaywindow_gtkwindow()), + GTK_DIALOG_DESTROY_WITH_PARENT, GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE, NULL); + gtk_window_set_default_size(GTK_WINDOW(editor->window), 550, 600); + + vbox = gtk_vbox_new(FALSE, 0); + hbox = gtk_hbox_new(FALSE, 0); + gtk_box_pack_start(GTK_BOX(GTK_DIALOG(editor->window)->vbox), GTK_WIDGET(hbox), TRUE, TRUE, 7); + gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(vbox), TRUE, TRUE, 5); + + top_hbox = gtk_hbox_new(FALSE, 0); + label = gtk_label_new("Thickness: "); + gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5); + gtk_box_pack_start(GTK_BOX(top_hbox), GTK_WIDGET(label), TRUE, TRUE, 5); + editor->thickness = gtk_entry_new(); + gtk_entry_set_alignment(GTK_ENTRY(editor->thickness), 1); + gtk_entry_set_max_length(GTK_ENTRY(editor->thickness), 10); + gtk_entry_set_width_chars(GTK_ENTRY(editor->thickness), 8); + gtk_box_pack_start(GTK_BOX(top_hbox), GTK_WIDGET(editor->thickness), TRUE, TRUE, 5); + label = gtk_label_new(" nm"); + gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); + gtk_box_pack_start(GTK_BOX(top_hbox), GTK_WIDGET(label), TRUE, TRUE, 5); + g_signal_connect(G_OBJECT(editor->thickness), "activate", G_CALLBACK(model_editor_thickness_edited), editor); + gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(top_hbox), FALSE, FALSE, 2); + + editor->point_atoms = gtk_check_button_new_with_label("Point atoms"); + g_signal_connect(G_OBJECT(editor->point_atoms), "toggled", G_CALLBACK(model_editor_pointatoms_toggled), editor); + gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(editor->point_atoms), FALSE, TRUE, 2); + + editor->symmetry = gtk_symmetry_new(2, 2, FALSE); + gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(editor->symmetry), FALSE, FALSE, 2); + g_signal_connect(G_OBJECT(editor->symmetry), "changed", G_CALLBACK(model_editor_symmetry_changed), editor); + + /* Add the list of atoms and Add/Remove widgets */ + model_editor_do_list(vbox, editor); + + /* Add the atomic coordinate editor */ + editor->position_table = gtk_table_new(5, 3, FALSE); + gtk_table_set_homogeneous(GTK_TABLE(editor->position_table), FALSE); + gtk_table_set_row_spacings(GTK_TABLE(editor->position_table), 2); + gtk_table_set_col_spacings(GTK_TABLE(editor->position_table), 5); + gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(editor->position_table), FALSE, FALSE, 5); + + editor->x_scale = gtk_hscale_new_with_range(0, 1, 0.05); + gtk_scale_set_draw_value(GTK_SCALE(editor->x_scale), FALSE); + //gtk_range_set_update_policy(GTK_RANGE(editor->x_scale), GTK_UPDATE_DELAYED); + g_signal_connect(G_OBJECT(editor->x_scale), "value-changed", G_CALLBACK(model_editor_x_scale), editor); + gtk_table_attach(GTK_TABLE(editor->position_table), GTK_WIDGET(editor->x_scale), 2, 3, 1, 2, GTK_EXPAND | GTK_FILL, GTK_SHRINK, 2, 2); + x_scale_label = gtk_label_new("x"); + gtk_misc_set_alignment(GTK_MISC(x_scale_label), 1.0, 0.5); + gtk_table_attach(GTK_TABLE(editor->position_table), GTK_WIDGET(x_scale_label), 1, 2, 1, 2, GTK_SHRINK | GTK_FILL, GTK_SHRINK, 2, 2); + editor->x_edit = gtk_entry_new(); + gtk_entry_set_max_length(GTK_ENTRY(editor->x_edit), 10); + gtk_entry_set_width_chars(GTK_ENTRY(editor->x_edit), 8); + g_signal_connect(G_OBJECT(editor->x_edit), "activate", G_CALLBACK(model_editor_x_edit), editor); + gtk_table_attach(GTK_TABLE(editor->position_table), GTK_WIDGET(editor->x_edit), 3, 4, 1, 2, GTK_SHRINK, GTK_SHRINK, 2, 2); + + editor->y_scale = gtk_hscale_new_with_range(0, 1, 0.05); + gtk_scale_set_draw_value(GTK_SCALE(editor->y_scale), FALSE); + g_signal_connect(G_OBJECT(editor->y_scale), "value-changed", G_CALLBACK(model_editor_y_scale), editor); + //gtk_range_set_update_policy(GTK_RANGE(editor->y_scale), GTK_UPDATE_DELAYED); + gtk_table_attach(GTK_TABLE(editor->position_table), GTK_WIDGET(editor->y_scale), 2, 3, 2, 3, GTK_EXPAND | GTK_FILL, GTK_SHRINK, 2, 2); + y_scale_label = gtk_label_new("y"); + gtk_misc_set_alignment(GTK_MISC(y_scale_label), 1.0, 0.5); + gtk_table_attach(GTK_TABLE(editor->position_table), GTK_WIDGET(y_scale_label), 1, 2, 2, 3, GTK_SHRINK | GTK_FILL, GTK_SHRINK, 2, 2); + editor->y_edit = gtk_entry_new(); + gtk_entry_set_max_length(GTK_ENTRY(editor->y_edit), 10); + gtk_entry_set_width_chars(GTK_ENTRY(editor->y_edit), 8); + g_signal_connect(G_OBJECT(editor->y_edit), "activate", G_CALLBACK(model_editor_y_edit), editor); + gtk_table_attach(GTK_TABLE(editor->position_table), GTK_WIDGET(editor->y_edit), 3, 4, 2, 3, GTK_SHRINK, GTK_SHRINK, 2, 2); + + editor->z_scale = gtk_hscale_new_with_range(0, 1, 0.05); + gtk_scale_set_draw_value(GTK_SCALE(editor->z_scale), FALSE); + g_signal_connect(G_OBJECT(editor->z_scale), "value-changed", G_CALLBACK(model_editor_z_scale), editor); + //gtk_range_set_update_policy(GTK_RANGE(editor->z_scale), GTK_UPDATE_DELAYED); + gtk_table_attach(GTK_TABLE(editor->position_table), GTK_WIDGET(editor->z_scale), 2, 3, 3, 4, GTK_EXPAND | GTK_FILL, GTK_SHRINK, 2, 2); + z_scale_label = gtk_label_new("z"); + gtk_misc_set_alignment(GTK_MISC(z_scale_label), 1.0, 0.5); + gtk_table_attach(GTK_TABLE(editor->position_table), GTK_WIDGET(z_scale_label), 1, 2, 3, 4, GTK_SHRINK | GTK_FILL, GTK_SHRINK, 2, 2); + editor->z_edit = gtk_entry_new(); + gtk_entry_set_max_length(GTK_ENTRY(editor->z_edit), 10); + gtk_entry_set_width_chars(GTK_ENTRY(editor->z_edit), 8); + g_signal_connect(G_OBJECT(editor->z_edit), "activate", G_CALLBACK(model_editor_z_edit), editor); + gtk_table_attach(GTK_TABLE(editor->position_table), GTK_WIDGET(editor->z_edit), 3, 4, 3, 4, GTK_SHRINK, GTK_SHRINK, 2, 2); + + editor->b_scale = gtk_hscale_new_with_range(0, 0.001, 0.00001); + gtk_scale_set_draw_value(GTK_SCALE(editor->b_scale), FALSE); + g_signal_connect(G_OBJECT(editor->b_scale), "value-changed", G_CALLBACK(model_editor_b_scale), editor); + //gtk_range_set_update_policy(GTK_RANGE(editor->b_scale), GTK_UPDATE_DELAYED); + gtk_table_attach(GTK_TABLE(editor->position_table), GTK_WIDGET(editor->b_scale), 2, 3, 4, 5, GTK_EXPAND | GTK_FILL, GTK_SHRINK, 2, 2); + b_scale_label = gtk_label_new("B"); + gtk_misc_set_alignment(GTK_MISC(b_scale_label), 1.0, 0.5); + gtk_table_attach(GTK_TABLE(editor->position_table), GTK_WIDGET(b_scale_label), 1, 2, 4, 5, GTK_SHRINK | GTK_FILL, GTK_SHRINK, 2, 2); + editor->b_edit = gtk_entry_new(); + gtk_entry_set_max_length(GTK_ENTRY(editor->b_edit), 10); + gtk_entry_set_width_chars(GTK_ENTRY(editor->b_edit), 8); + g_signal_connect(G_OBJECT(editor->b_edit), "activate", G_CALLBACK(model_editor_b_edit), editor); + gtk_table_attach(GTK_TABLE(editor->position_table), GTK_WIDGET(editor->b_edit), 3, 4, 4, 5, GTK_SHRINK, GTK_SHRINK, 2, 2); + + editor->occ_scale = gtk_hscale_new_with_range(0, 1, 0.05); + gtk_scale_set_draw_value(GTK_SCALE(editor->occ_scale), FALSE); + g_signal_connect(G_OBJECT(editor->occ_scale), "value-changed", G_CALLBACK(model_editor_occ_scale), editor); + //gtk_range_set_update_policy(GTK_RANGE(editor->occ_scale), GTK_UPDATE_DELAYED); + gtk_table_attach(GTK_TABLE(editor->position_table), GTK_WIDGET(editor->occ_scale), 2, 3, 5, 6, GTK_EXPAND | GTK_FILL, GTK_SHRINK, 2, 2); + occ_scale_label = gtk_label_new("Occ"); + gtk_misc_set_alignment(GTK_MISC(occ_scale_label), 1.0, 0.5); + gtk_table_attach(GTK_TABLE(editor->position_table), GTK_WIDGET(occ_scale_label), 1, 2, 5, 6, GTK_SHRINK | GTK_FILL, GTK_SHRINK, 2, 2); + editor->occ_edit = gtk_entry_new(); + gtk_entry_set_max_length(GTK_ENTRY(editor->occ_edit), 10); + gtk_entry_set_width_chars(GTK_ENTRY(editor->occ_edit), 8); + g_signal_connect(G_OBJECT(editor->occ_edit), "activate", G_CALLBACK(model_editor_occ_edit), editor); + gtk_table_attach(GTK_TABLE(editor->position_table), GTK_WIDGET(editor->occ_edit), 3, 4, 5, 6, GTK_SHRINK, GTK_SHRINK, 2, 2); + + g_signal_connect(G_OBJECT(editor->window), "response", G_CALLBACK(model_editor_close), editor); + + gtk_widget_set_sensitive(editor->delete_button, FALSE); + gtk_widget_set_sensitive(editor->position_table, FALSE); + /* If the model is locked, disable things appropriately from the start */ + if ( editor->model->lock_count > 0 ) model_editor_lock(editor); + + gtk_widget_show_all(editor->window); + + return editor; + +} + -- cgit v1.2.3