/* SciGraphica - Scientific graphics and data manipulation * Copyright (C) 2001 Adrian E. Feiguin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include #include "sg_layer_control.h" #include "sg.h" #include "sg_dialogs.h" #include "sg_stock.h" #include "../pixmaps/pixmaps.h" #define LABEL_LEN 1000 typedef struct { gint type; gpointer data; void (* action) (gpointer object); gchar *path; } SGnodedata; static GtkWidget *layer_control_dialog = NULL; static GtkWidget *dialog; static GtkWidget *paned; static GtkWidget *swindow; static GtkWidget *main_frame; static GtkWidget *label; static GtkWidget *tree; static GtkWidget *window = NULL; static GdkPixmap *layer_pixmap; static GdkPixmap *plot2d_pixmap; static GdkPixmap *plot3d_pixmap; static GdkPixmap *polar_pixmap; static GdkBitmap *layer_mask; static GdkBitmap *plot2d_mask; static GdkBitmap *plot3d_mask; static GdkBitmap *polar_mask; static GList *nodes; static void (* update_function) (GtkWidget *widget); static gboolean mw_destroy (GtkWidget *widget); static void build_tree (SGplot *plot); static void expand_tree (gchar *path); static void open_dialog (GtkCTree *tree, GtkCTreeNode *node, gint column); void sg_layer_control_destroy() { if (layer_control_dialog) mw_destroy(window); } static gboolean mw_destroy(GtkWidget *widget) { GList *list; GtkCTreeNode *node; SGnodedata *data; sg_dialog_kill(widget); gtk_widget_destroy(widget); list = nodes; while(list){ node = (GtkCTreeNode *) list->data; data = (SGnodedata *)gtk_ctree_node_get_row_data(GTK_CTREE(tree), node); g_free(data->path); g_free(data); nodes = g_list_remove_link(nodes, list); g_list_free_1(list); list = nodes; } layer_control_dialog = NULL; return FALSE; } static void clear_paned(GtkWidget *widget, gpointer data) { if(GTK_BIN(main_frame)->child != NULL) gtk_widget_destroy(GTK_BIN(main_frame)->child); } static void destroy_dialog(GtkWidget *widget, gpointer data) { clear_paned(NULL, NULL); gtk_widget_destroy(GTK_WIDGET(data)); } static void button_press_apply(GtkWidget *widget, gpointer data) { sg_project_changed(TRUE); if(update_function) update_function(dialog); } static void button_press_ok(GtkWidget *widget, gpointer data) { button_press_apply(widget, data); destroy_dialog(widget, data); } void sg_layer_control_refresh(gchar *path) { GList *list; GtkCTreeNode *node; SGnodedata *data; if(!layer_control_dialog) return; list = nodes; while(list){ node = (GtkCTreeNode *) list->data; data = (SGnodedata *)gtk_ctree_node_get_row_data(GTK_CTREE(tree), node); g_free(data->path); g_free(data); nodes = g_list_remove_link(nodes, list); g_list_free_1(list); list = nodes; } gtk_container_remove(GTK_CONTAINER(swindow), tree); tree = gtk_ctree_new(1, 0); gtk_clist_set_row_height (GTK_CLIST (tree), 19); gtk_clist_set_column_auto_resize(GTK_CLIST(tree),0,TRUE); gtk_clist_set_selection_mode(GTK_CLIST(tree),GTK_SELECTION_SINGLE); gtk_ctree_set_line_style(GTK_CTREE(tree),GTK_CTREE_LINES_DOTTED); gtk_container_add(GTK_CONTAINER(swindow), tree); list = plots; while(list){ SGplot *plot; plot = (SGplot *) list->data; build_tree(plot); list = list->next; } /* connect signals */ gtk_signal_connect(GTK_OBJECT(tree), "tree_select_row", (GtkSignalFunc)open_dialog, NULL); expand_tree(path); gtk_widget_show(tree); } static void new_dataset_dialog(gpointer p_layer) { GtkWidget *frame; clear_paned(NULL, NULL); update_function = sg_data_dialog_update_plot; dialog = sg_data_dialog_new((SGlayer*)p_layer); frame = gtk_frame_new(NULL); gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_OUT); gtk_container_add(GTK_CONTAINER(main_frame), frame); gtk_container_add(GTK_CONTAINER(frame), dialog); gtk_widget_show_all(frame); gtk_label_set_text(GTK_LABEL(label), "Add/remove datasets"); } static void new_planes_dialog(gpointer p_layer) { clear_paned(NULL, NULL); update_function = sg_planes_dialog_update_plot; dialog = sg_planes_dialog_new((SGlayer *)p_layer); gtk_container_add(GTK_CONTAINER(main_frame), dialog); gtk_widget_show_all(dialog); gtk_label_set_text(GTK_LABEL(label), "Edit planes properties"); } static void new_axis_dialog(gpointer p_layer) { clear_paned(NULL, NULL); update_function = sg_axis_dialog_update_plot; dialog = sg_axis_dialog_new((SGlayer *)p_layer); gtk_container_add(GTK_CONTAINER(main_frame), dialog); gtk_widget_show_all(dialog); gtk_label_set_text(GTK_LABEL(label), "Edit axes properties"); } static void new_title_dialog(gpointer p_layer) { clear_paned(NULL, NULL); update_function = sg_title_dialog_update_plot; dialog = sg_title_dialog_new((SGlayer *)p_layer); gtk_container_add(GTK_CONTAINER(main_frame), dialog); gtk_widget_show_all(dialog); gtk_label_set_text(GTK_LABEL(label), "Edit titles properties"); } static void new_grids_dialog(gpointer p_layer) { GtkWidget *frame; clear_paned(NULL, NULL); update_function = sg_grids_dialog_update_plot; dialog = sg_grids_dialog_new((SGlayer *)p_layer); frame = gtk_frame_new(NULL); gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_OUT); gtk_container_add(GTK_CONTAINER(main_frame), frame); gtk_container_add(GTK_CONTAINER(frame), dialog); gtk_widget_show_all(frame); gtk_label_set_text(GTK_LABEL(label), "Edit grids properties"); } static void new_legends_dialog(gpointer p_layer) { GtkWidget *frame; clear_paned(NULL, NULL); update_function = sg_legends_dialog_update_plot; dialog = sg_legends_dialog_new((SGlayer *)p_layer); frame = gtk_frame_new(NULL); gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_OUT); gtk_container_add(GTK_CONTAINER(main_frame), frame); gtk_container_add(GTK_CONTAINER(frame), dialog); gtk_widget_show_all(frame); gtk_label_set_text(GTK_LABEL(label), "Edit legends properties"); } static void new_labels_dialog(gpointer p_layer) { clear_paned(NULL, NULL); update_function = sg_labels_dialog_update_plot; dialog = sg_labels_dialog_new((SGlayer *)p_layer); gtk_container_add(GTK_CONTAINER(main_frame), dialog); gtk_widget_show_all(main_frame); gtk_label_set_text(GTK_LABEL(label), "Edit labels properties"); } static void new_frame_dialog(gpointer p_layer) { GtkWidget *frame; clear_paned(NULL, NULL); update_function = sg_frame_dialog_update_plot; dialog = sg_frame_dialog_new((SGlayer *)p_layer); frame = gtk_frame_new(NULL); gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_OUT); gtk_container_add(GTK_CONTAINER(main_frame), frame); gtk_container_add(GTK_CONTAINER(frame), dialog); gtk_widget_show_all(frame); gtk_label_set_text(GTK_LABEL(label), "Edit frame properties"); } static void new_page_dialog(gpointer p_plot) { GtkWidget *frame; clear_paned(NULL, NULL); update_function = sg_page_dialog_update_plot; dialog = sg_page_dialog_new((SGplot *)p_plot); frame = gtk_frame_new(NULL); gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_OUT); gtk_container_add(GTK_CONTAINER(main_frame), frame); gtk_container_add(GTK_CONTAINER(frame), dialog); gtk_widget_show_all(frame); gtk_label_set_text(GTK_LABEL(label), "Edit page properties"); } static void new_style_dialog(gpointer p_layer) { GtkWidget *frame; clear_paned(NULL, NULL); if(!((SGlayer *)p_layer)->datasets){ dialog = gtk_label_new("This layer contains no datasets"); update_function = NULL; } else { update_function = sg_style_dialog_update_plot; dialog = sg_style_dialog_new((SGlayer *)p_layer); } frame = gtk_frame_new(NULL); gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_OUT); gtk_container_add(GTK_CONTAINER(main_frame), frame); gtk_container_add(GTK_CONTAINER(frame), dialog); gtk_widget_show_all(frame); gtk_label_set_text(GTK_LABEL(label), "Edit dataset properties"); } static void new_layer_dialog(gpointer p_layer) { GtkWidget *frame; clear_paned(NULL, NULL); update_function = sg_layer_dialog_update_plot; dialog = sg_layer_dialog_new((SGlayer *)p_layer); frame = gtk_frame_new(NULL); gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_OUT); gtk_container_add(GTK_CONTAINER(main_frame), frame); gtk_container_add(GTK_CONTAINER(frame), dialog); gtk_widget_show_all(frame); gtk_label_set_text(GTK_LABEL(label), "Edit layer properties"); } static void open_dialog(GtkCTree *tree, GtkCTreeNode *node, gint column) { SGnodedata *nodedata; gpointer data; data = gtk_ctree_node_get_row_data(tree, node); if(data == NULL) return; nodedata = (SGnodedata *)data; if(nodedata->action == NULL) return; nodedata->action(nodedata->data); } SGnodedata * sg_node_data_new(gint type, gpointer data, void (*action)(gpointer), gchar *path) { SGnodedata *node; node = g_new(SGnodedata, 1); node->type = type; node->data = data; node->action = action; node->path = g_strdup(path); return node; } static void build_tree(SGplot *plot) { GtkCTreeNode *root_item, *item, *subitem, *subsubitem; GList *list; gchar *title[1]; gchar *subtitle[1]; gchar label[1000]; gint n = 0; gchar path[1000]; gchar *text[20] = {"Legends", "Axes", "Titles", "Ticks Labels", "Frame", "Grids", "Datasets", "Properties", "Planes",}; title[0] = plot->name; root_item = gtk_ctree_insert_node(GTK_CTREE(tree), NULL, NULL, &title[0], 4, layer_pixmap, layer_mask, layer_pixmap, layer_mask, FALSE, FALSE); gtk_ctree_node_set_row_data(GTK_CTREE(tree), root_item, sg_node_data_new(1, plot, new_page_dialog, plot->name)); nodes = g_list_append(nodes, root_item); list = plot->layers; while(list){ SGlayer *layer; layer = (SGlayer *)list->data; g_snprintf(label, LABEL_LEN, "%s:%i",title[0],++n); subtitle[0] = g_strdup(label); switch(layer->type){ case SG_LAYER_2D: item = gtk_ctree_insert_node(GTK_CTREE(tree), root_item, NULL, &subtitle[0], 4, plot2d_pixmap, plot2d_mask, plot2d_pixmap, plot2d_mask, FALSE, FALSE); break; case SG_LAYER_3D: item = gtk_ctree_insert_node(GTK_CTREE(tree), root_item, NULL, &subtitle[0], 4, plot3d_pixmap, plot3d_mask, plot3d_pixmap, plot3d_mask, FALSE, FALSE); break; case SG_LAYER_POLAR: item = gtk_ctree_insert_node(GTK_CTREE(tree), root_item, NULL, &subtitle[0], 4, polar_pixmap, polar_mask, polar_pixmap, polar_mask, FALSE, FALSE); break; } gtk_ctree_node_set_row_data(GTK_CTREE(tree), item, sg_node_data_new(2, list->data, new_layer_dialog, label)); nodes = g_list_append(nodes, item); g_free(subtitle[0]); g_snprintf(path, LABEL_LEN, "%s:%s",label, "frame"); subitem = gtk_ctree_insert_node(GTK_CTREE(tree), item, NULL, &text[4], 4, NULL, NULL, NULL, NULL, FALSE, FALSE); gtk_ctree_node_set_row_data(GTK_CTREE(tree), subitem, sg_node_data_new(2, list->data, new_frame_dialog, path)); nodes = g_list_append(nodes, subitem); if(layer->type == SG_LAYER_3D){ g_snprintf(path, LABEL_LEN, "%s:%s",label, "planes"); subitem = gtk_ctree_insert_node(GTK_CTREE(tree), item, NULL, &text[8], 4, NULL, NULL, NULL, NULL, FALSE, FALSE); gtk_ctree_node_set_row_data(GTK_CTREE(tree), subitem, sg_node_data_new(2, list->data, new_planes_dialog, path)); nodes = g_list_append(nodes, subitem); } g_snprintf(path, LABEL_LEN, "%s:%s",label, "grids"); subitem = gtk_ctree_insert_node(GTK_CTREE(tree), item, NULL, &text[5], 4, NULL, NULL, NULL, NULL, FALSE, FALSE); gtk_ctree_node_set_row_data(GTK_CTREE(tree), subitem, sg_node_data_new(2, list->data, new_grids_dialog, path)); nodes = g_list_append(nodes, subitem); g_snprintf(path, LABEL_LEN, "%s:%s",label, "legends"); subitem = gtk_ctree_insert_node(GTK_CTREE(tree), item, NULL, &text[0], 4, NULL, NULL, NULL, NULL, FALSE, FALSE); gtk_ctree_node_set_row_data(GTK_CTREE(tree), subitem, sg_node_data_new(2, list->data, new_legends_dialog, path)); nodes = g_list_append(nodes, subitem); g_snprintf(path, LABEL_LEN, "%s:%s",label, "axis"); subitem = gtk_ctree_insert_node(GTK_CTREE(tree), item, NULL, &text[1], 4, NULL, NULL, NULL, NULL, FALSE, FALSE); gtk_ctree_node_set_row_data(GTK_CTREE(tree), subitem, sg_node_data_new(2, list->data, new_axis_dialog, path)); nodes = g_list_append(nodes, subitem); g_snprintf(path, LABEL_LEN, "%s:%s",label, "axis:title"); subsubitem = gtk_ctree_insert_node(GTK_CTREE(tree), subitem, NULL, &text[2], 4, NULL, NULL, NULL, NULL, FALSE, FALSE); gtk_ctree_node_set_row_data(GTK_CTREE(tree), subsubitem, sg_node_data_new(2, list->data, new_title_dialog, path)); nodes = g_list_append(nodes, subsubitem); g_snprintf(path, LABEL_LEN, "%s:%s",label, "axis:labels"); subsubitem = gtk_ctree_insert_node(GTK_CTREE(tree), subitem, NULL, &text[3], 4, NULL, NULL, NULL, NULL, FALSE, FALSE); gtk_ctree_node_set_row_data(GTK_CTREE(tree), subsubitem, sg_node_data_new(2, list->data, new_labels_dialog, path)); nodes = g_list_append(nodes, subsubitem); g_snprintf(path, LABEL_LEN, "%s:%s",label, "dataset"); subitem = gtk_ctree_insert_node(GTK_CTREE(tree), item, NULL, &text[6], 4, NULL, NULL, NULL, NULL, FALSE, FALSE); gtk_ctree_node_set_row_data(GTK_CTREE(tree), subitem, sg_node_data_new(2, list->data, new_dataset_dialog, path)); nodes = g_list_append(nodes, subitem); g_snprintf(path, LABEL_LEN, "%s:%s",label, "dataset:style"); subsubitem = gtk_ctree_insert_node(GTK_CTREE(tree), subitem, NULL, &text[7], 4, NULL, NULL, NULL, NULL, FALSE, FALSE); gtk_ctree_node_set_row_data(GTK_CTREE(tree), subsubitem, sg_node_data_new(2, list->data, new_style_dialog, path)); nodes = g_list_append(nodes, subsubitem); list = list->next; } } static GtkCTreeNode * find_node_by_path(gchar *path) { GList *list; gchar *node_path; GtkCTreeNode *node; SGnodedata *data; node_path = NULL; list = nodes; while(list){ node = (GtkCTreeNode *) list->data; data = (SGnodedata *)gtk_ctree_node_get_row_data(GTK_CTREE(tree), node); node_path = data->path; if(strcmp(node_path, path) == 0) return node; list = list->next; } return NULL; } static void expand_tree(gchar *path) { GtkCTreeNode *node; gchar *c; gchar sub_node[1000]; gint nlen; if(path == NULL) return; node = NULL; c = path; nlen = 0; while(*c != '\0' && *c != '\n' && c != NULL){ if(*c == ':'){ node = find_node_by_path(sub_node); if(node) gtk_ctree_expand(GTK_CTREE(tree), node); } nlen++; sub_node[nlen-1] = *c; sub_node[nlen]='\0'; c++; } node = find_node_by_path(sub_node); if(node) { gtk_ctree_expand(GTK_CTREE(tree), node); gtk_ctree_select(GTK_CTREE(tree), node); } } void sg_layer_control (gchar *path) { GtkWidget *main_box; GtkWidget *frame; GtkWidget *action_area; GtkWidget *right_box; GtkWidget *right_sub_box; GtkWidget *ok_button, *apply_button, *cancel_button; GList *list; SGplot *plot; if(layer_control_dialog){ gdk_window_raise(layer_control_dialog->window); return; } nodes = NULL; layer_control_dialog = window = gtk_window_new (GTK_WINDOW_TOPLEVEL); gtk_container_set_border_width(GTK_CONTAINER(window), 2); gtk_window_set_policy(GTK_WINDOW(window), FALSE, TRUE, FALSE); gtk_window_set_title (GTK_WINDOW(window),"Layer Control"); sg_dialog_new(window); /* Create widgets */ main_box = gtk_vbox_new(FALSE, 5); gtk_container_add (GTK_CONTAINER (window), main_box); paned = gtk_hpaned_new(); gtk_paned_set_gutter_size (GTK_PANED(paned), 10); gtk_paned_set_position (GTK_PANED(paned), 150); gtk_box_pack_start (GTK_BOX(main_box), paned, TRUE, TRUE, 0); swindow = gtk_scrolled_window_new(NULL, NULL); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(swindow), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); gtk_widget_set_usize(swindow, 200, 120); gtk_paned_pack1(GTK_PANED(paned), swindow, FALSE, FALSE); tree = gtk_ctree_new(1, 0); gtk_clist_set_row_height (GTK_CLIST (tree), 19); gtk_clist_set_column_auto_resize(GTK_CLIST(tree),0,TRUE); gtk_clist_set_selection_mode(GTK_CLIST(tree),GTK_SELECTION_SINGLE); gtk_ctree_set_line_style(GTK_CTREE(tree),GTK_CTREE_LINES_DOTTED); gtk_container_add(GTK_CONTAINER(swindow), tree); layer_pixmap = gdk_pixmap_colormap_create_from_xpm_d(NULL, gdk_colormap_get_system(), &layer_mask, NULL, layer_xpm); plot2d_pixmap = gdk_pixmap_colormap_create_from_xpm_d(NULL, gdk_colormap_get_system(), &plot2d_mask, NULL, _2d_small_xpm); plot3d_pixmap = gdk_pixmap_colormap_create_from_xpm_d(NULL, gdk_colormap_get_system(), &plot3d_mask, NULL, _3d_small_xpm); polar_pixmap = gdk_pixmap_colormap_create_from_xpm_d(NULL, gdk_colormap_get_system(), &polar_mask, NULL, polar_small_xpm); list = plots; while(list){ plot = (SGplot *) list->data; build_tree(plot); list = list->next; } /***************************************************/ right_box = gtk_vbox_new(FALSE, 5); gtk_paned_pack2(GTK_PANED(paned), right_box, FALSE, FALSE); /* Action area */ action_area = gtk_hbutton_box_new (); gtk_button_box_set_layout(GTK_BUTTON_BOX(action_area), GTK_BUTTONBOX_END); gtk_button_box_set_spacing(GTK_BUTTON_BOX(action_area), 5); gtk_box_pack_end (GTK_BOX (right_box), action_area, FALSE, FALSE, 0); gtk_widget_show (action_area); ok_button = sg_stock_button(GNOME_STOCK_BUTTON_OK); gtk_box_pack_start (GTK_BOX (action_area), ok_button, FALSE, FALSE, 0); /* GTK_WIDGET_SET_FLAGS (ok_button, GTK_CAN_DEFAULT); gtk_widget_grab_default (ok_button); */ gtk_widget_show (ok_button); apply_button = sg_stock_button(GNOME_STOCK_BUTTON_APPLY); gtk_box_pack_start (GTK_BOX (action_area), apply_button, FALSE, FALSE, 0); gtk_widget_show (apply_button); cancel_button = sg_stock_button(GNOME_STOCK_BUTTON_CLOSE); gtk_box_pack_start (GTK_BOX (action_area), cancel_button, FALSE, FALSE, 0); gtk_widget_show (cancel_button); right_sub_box = gtk_vbox_new(FALSE, 0); gtk_box_pack_start(GTK_BOX(right_box), right_sub_box, TRUE, TRUE, 0); main_frame = gtk_frame_new(NULL); gtk_frame_set_shadow_type(GTK_FRAME(main_frame), GTK_SHADOW_IN); gtk_box_pack_start(GTK_BOX(right_sub_box), main_frame, TRUE, TRUE, 0); frame = gtk_frame_new(NULL); gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN); gtk_box_pack_end(GTK_BOX(main_box), frame, FALSE, FALSE, 0); label = gtk_label_new("Layer control"); gtk_misc_set_alignment(GTK_MISC(label), 0., 0.); gtk_container_add(GTK_CONTAINER(frame), label); /* connect signals */ gtk_signal_connect(GTK_OBJECT(tree), "tree_select_row", (GtkSignalFunc)open_dialog, NULL); gtk_signal_connect (GTK_OBJECT (ok_button), "clicked", GTK_SIGNAL_FUNC (button_press_ok), window); gtk_signal_connect (GTK_OBJECT (apply_button), "clicked", GTK_SIGNAL_FUNC (button_press_apply), window); gtk_signal_connect (GTK_OBJECT (cancel_button), "clicked", GTK_SIGNAL_FUNC (destroy_dialog), window); /******************************************************************/ gtk_signal_connect (GTK_OBJECT (window), "destroy", GTK_SIGNAL_FUNC (mw_destroy),NULL); /* Show widgets */ expand_tree(path); gtk_widget_show_all (window); /******************************************************************/ }