From b3dda9f9defa98c604484b561e30be2bb5fd6cb7 Mon Sep 17 00:00:00 2001 From: rds <rds> Date: Tue, 21 Oct 2008 17:32:48 +0000 Subject: [PATCH] Added apply button to the column configure widget --- src/zmapWindow/zmapWindowColConfig.c | 956 ++++++++++++++++----------- src/zmapWindow/zmapWindowContainer.c | 67 +- src/zmapWindow/zmapWindowContainer.h | 8 +- 3 files changed, 642 insertions(+), 389 deletions(-) diff --git a/src/zmapWindow/zmapWindowColConfig.c b/src/zmapWindow/zmapWindowColConfig.c index 7d4c4cfb7..7177ea6ee 100755 --- a/src/zmapWindow/zmapWindowColConfig.c +++ b/src/zmapWindow/zmapWindowColConfig.c @@ -26,12 +26,13 @@ * * Exported functions: See ZMap/zmapWindow.h * HISTORY: - * Last edited: Jun 25 08:54 2008 (rds) + * Last edited: Oct 21 18:32 2008 (rds) * Created: Thu Mar 2 09:07:44 2006 (edgrif) - * CVS info: $Id: zmapWindowColConfig.c,v 1.24 2008-09-04 14:15:57 rds Exp $ + * CVS info: $Id: zmapWindowColConfig.c,v 1.25 2008-10-21 17:32:48 rds Exp $ *------------------------------------------------------------------- */ +#include <string.h> #include <ZMap/zmapUtils.h> #include <zmapWindow_P.h> #include <zmapWindowContainer.h> @@ -42,9 +43,14 @@ #define SHOWHIDE_LABEL "Default" #define HIDE_LABEL "Hide" +#define RADIO_BUTTONS_CONTAINER "button_widget" -#define CONF_DATA "col_data" -typedef struct +typedef struct _ColConfigureStruct *ColConfigure; + +typedef void (*ColConfigureReturnFunc)(ColConfigure configure_data); + +#define CONFIGURE_DATA "col_data" +typedef struct _ColConfigureStruct { ZMapWindow window ; @@ -52,37 +58,37 @@ typedef struct GtkWidget *forward_button_container ; GtkWidget *reverse_label_container ; GtkWidget *reverse_button_container ; -} ColConfigureStruct, *ColConfigure ; - -#define BUTTON_DATA "button_data" + ColConfigureReturnFunc return_func; + + unsigned int has_apply_button : 1 ; + unsigned int apply_now : 1 ; + unsigned int reposition : 1 ; +} ColConfigureStruct; + +/* Not really required anymore, but I've left it in as I can see that + * it might need replacing in the future with a struct to get hold of + * a valid column group if column groups appear/disappear... */ typedef struct { - ZMapWindow window ; FooCanvasGroup *column_group ; - GtkWidget *button_box ; } ButDataStruct, *ButData ; - -#define SELECT_DATA "select_data" typedef struct { - ZMapWindow window ; - - GtkWidget *frame_widg ; + GtkWidget *radio_groups_container ; + ZMapStyleColumnDisplayState select_button_state; } SelectAllConfigureStruct, *SelectAllConfigure ; - - +/* Arrgh, pain this is needed. Also, will fall over when multiple alignments... */ typedef struct { - ZMapStyleColumnDisplayState col_state ; - char *but_text ; - GtkWidget *button ; -} FindButStruct, *FindBut ; + GList *forward, *reverse; +}ForwardReverseColumnListsStruct, *ForwardReverseColumnLists; +/* required for the sizing of the widget... */ typedef struct { unsigned int debug : 1 ; @@ -94,28 +100,33 @@ typedef struct } SizingDataStruct, *SizingData; -static GtkWidget *makeMenuBar(ColConfigure search_data) ; -static GtkWidget *makeColsPanel(ZMapWindow window, char *frame_title, GList *column_groups, - GtkWidget **label_container_out, GtkWidget **button_container_out) ; -static void makeColList(ZMapWindow window, GList **forward_cols, GList **reverse_cols) ; -static void getSetGroupCB(FooCanvasGroup *container, FooCanvasPoints *points, - ZMapContainerLevelType level, gpointer user_data) ; +static GtkWidget *make_menu_bar(ColConfigure configure_data); +static GtkWidget *make_cols_panel(ZMapWindow window, char *frame_title, GList *column_groups, + GtkWidget **label_container_out, GtkWidget **button_container_out) ; +static char *label_text_from_column(FooCanvasGroup *column_group); +static GtkWidget *create_label(GtkWidget *parent, ButData *button_data_out, char *text); +static void create_radio_buttons(GtkWidget *parent, ButData button_data, ZMapFeatureTypeStyle style); +static GtkWidget *create_apply_button(GtkWidget *parent, ColConfigure configure_data); + + static void colConfigure(ZMapWindow window, GList *forward_cols, GList *reverse_cols) ; static void simpleConfigure(ZMapWindow window, ZMapWindowColConfigureMode configure_mode, FooCanvasGroup *column_group) ; static void requestDestroyCB(gpointer data, guint callback_action, GtkWidget *widget) ; static void destroyCB(GtkWidget *widget, gpointer cb_data) ; -static void destroyLabelCB(GtkWidget *widget, gpointer cb_data) ; -static void destroyFrameCB(GtkWidget *widget, gpointer cb_data) ; +static void destroy_label_cb(GtkWidget *widget, gpointer cb_data) ; static void helpCB(gpointer data, guint callback_action, GtkWidget *w) ; static void showButCB(GtkToggleButton *togglebutton, gpointer user_data) ; -static void selectButtons(GtkWidget *button, gpointer user_data) ; -static void allButtonsToggleCB(gpointer data, gpointer user_data); -static void changeButtonState(GtkWidget *toplevel, - FooCanvasGroup *column_group, ZMapWindowColConfigureMode configure_mode) ; -static gint findGroupCB(gconstpointer a, gconstpointer b) ; -static GtkWidget *findButton(GtkWidget *hbox, ZMapStyleColumnDisplayState col_state) ; -static void findButtonCB(GtkWidget *widget, gpointer data) ; + +static ZMapStyleColumnDisplayState button_label_to_state(const char *button_label_text); + +static void select_all_buttons(GtkWidget *button, gpointer user_data); +static void toggle_column_radio_group_activate_matching_state(GtkWidget *toplevel, + FooCanvasGroup *column_group, + ZMapWindowColConfigureMode mode); +static void set_column_lists_cb(FooCanvasGroup *container, FooCanvasPoints *points, + ZMapContainerLevelType level, gpointer user_data); + static gboolean zmapAddSizingSignalHandlers(GtkWidget *widget, gboolean debug, int width, int height); @@ -164,7 +175,6 @@ void zmapWindowColumnConfigure(ZMapWindow window, FooCanvasGroup *column_group, case ZMAPWINDOWCOLUMN_SHOW: simpleConfigure(window, configure_mode, column_group) ; break ; - case ZMAPWINDOWCOLUMN_CONFIGURE: case ZMAPWINDOWCOLUMN_CONFIGURE_ALL: { @@ -184,9 +194,22 @@ void zmapWindowColumnConfigure(ZMapWindow window, FooCanvasGroup *column_group, else reverse_columns = g_list_append(reverse_columns, column_group) ; } + else if(column_group) + { + zmapWindowContainerBlockGetColumnLists(column_group, + &forward_columns, + &reverse_columns); + } else { - makeColList(window, &forward_columns, &reverse_columns) ; + ForwardReverseColumnListsStruct for_rev_lists = {NULL}; + + zmapWindowContainerExecute(window->feature_root_group, + ZMAPCONTAINER_LEVEL_FEATURESET, + set_column_lists_cb, &for_rev_lists); + + forward_columns = for_rev_lists.forward; + reverse_columns = for_rev_lists.reverse; } colConfigure(window, forward_columns, reverse_columns) ; @@ -201,9 +224,23 @@ void zmapWindowColumnConfigure(ZMapWindow window, FooCanvasGroup *column_group, break ; } - if (configure_mode == ZMAPWINDOWCOLUMN_HIDE || configure_mode == ZMAPWINDOWCOLUMN_SHOW) - zmapWindowFullReposition(window) ; - + if(window->col_config_window) + { + ColConfigure configure_data; + + if((configure_data = g_object_get_data(G_OBJECT(window->col_config_window), + CONFIGURE_DATA))) + { + /* fix up the relevant flags */ + if(!configure_data->has_apply_button) + { + configure_data->apply_now = TRUE; + configure_data->reposition = TRUE; + } + } + + } + return ; } @@ -239,7 +276,8 @@ static void simpleConfigure(ZMapWindow window, ZMapWindowColConfigureMode config * change, otherwise operate directly on column. */ if (window->col_config_window) { - changeButtonState(window->col_config_window, column_group, configure_mode) ; + toggle_column_radio_group_activate_matching_state(window->col_config_window, + column_group, configure_mode) ; } else { @@ -247,10 +285,9 @@ static void simpleConfigure(ZMapWindow window, ZMapWindowColConfigureMode config col_state = ZMAPSTYLE_COLDISPLAY_HIDE ; else col_state = ZMAPSTYLE_COLDISPLAY_SHOW ; - + + /* TRUE makes the function do a zmapWindowFullReposition() if needed */ zmapWindowColumnSetState(window, column_group, col_state, TRUE) ; - - zmapWindowFullReposition(window) ; } return ; @@ -274,7 +311,7 @@ static void colConfigure(ZMapWindow window, GList *forward_cols, GList *reverse_ configure_data->window->col_config_window = toplevel = gtk_window_new(GTK_WINDOW_TOPLEVEL) ; g_signal_connect(GTK_OBJECT(toplevel), "destroy", GTK_SIGNAL_FUNC(destroyCB), (gpointer)configure_data) ; - g_object_set_data(G_OBJECT(toplevel), CONF_DATA, configure_data) ; + g_object_set_data(G_OBJECT(toplevel), CONFIGURE_DATA, configure_data) ; gtk_container_border_width(GTK_CONTAINER(toplevel), 5) ; title = zMapGUIMakeTitleString("Column configuration", @@ -285,7 +322,7 @@ static void colConfigure(ZMapWindow window, GList *forward_cols, GList *reverse_ vbox = gtk_vbox_new(FALSE, 0) ; gtk_container_add(GTK_CONTAINER(toplevel), vbox) ; - menubar = makeMenuBar(configure_data) ; + menubar = make_menu_bar(configure_data) ; gtk_box_pack_start(GTK_BOX(vbox), menubar, FALSE, FALSE, 0); hbox = gtk_hbox_new(FALSE, 0) ; @@ -293,64 +330,50 @@ static void colConfigure(ZMapWindow window, GList *forward_cols, GList *reverse_ if (reverse_cols) { - cols = makeColsPanel(window, "Reverse Strand", reverse_cols, - &(configure_data->reverse_label_container), - &(configure_data->reverse_button_container)) ; + cols = make_cols_panel(window, "Reverse Strand", reverse_cols, + &(configure_data->reverse_label_container), + &(configure_data->reverse_button_container)) ; gtk_box_pack_start(GTK_BOX(hbox), cols, TRUE, TRUE, 0) ; } if (forward_cols) { - cols = makeColsPanel(window, "Forward Strand", forward_cols, - &(configure_data->forward_label_container), - &(configure_data->forward_button_container)) ; + cols = make_cols_panel(window, "Forward Strand", forward_cols, + &(configure_data->forward_label_container), + &(configure_data->forward_button_container)) ; gtk_box_pack_start(GTK_BOX(hbox), cols, TRUE, TRUE, 0) ; } + if((reverse_cols && forward_cols) || + g_list_length(reverse_cols) > 1 || + g_list_length(forward_cols) > 1) + configure_data->has_apply_button = TRUE; -#ifdef ED_G_NEVER_INCLUDE_THIS_CODE - /* We don't need this just yet.... */ - - buttonBox = gtk_hbutton_box_new(); - gtk_button_box_set_layout (GTK_BUTTON_BOX (buttonBox), GTK_BUTTONBOX_END); - gtk_box_set_spacing (GTK_BOX(buttonBox), - ZMAP_WINDOW_GTK_BUTTON_BOX_SPACING); - gtk_container_set_border_width (GTK_CONTAINER (buttonBox), - ZMAP_WINDOW_GTK_CONTAINER_BORDER_WIDTH); - - apply_button = gtk_button_new_with_label("Apply") ; - gtk_container_add(GTK_CONTAINER(buttonBox), apply_button) ; - gtk_signal_connect(GTK_OBJECT(apply_button), "clicked", - GTK_SIGNAL_FUNC(applyCB), (gpointer)configure_data) ; - /* set apply button as default. */ - GTK_WIDGET_SET_FLAGS(apply_button, GTK_CAN_DEFAULT) ; - gtk_window_set_default(GTK_WINDOW(toplevel), apply_button) ; - - frame = gtk_frame_new(NULL) ; - gtk_container_set_border_width(GTK_CONTAINER(frame), - ZMAP_WINDOW_GTK_CONTAINER_BORDER_WIDTH); - gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 0) ; + if(configure_data->has_apply_button) + { + GtkWidget *apply_button; - gtk_container_add(GTK_CONTAINER(frame), buttonBox); -#endif /* ED_G_NEVER_INCLUDE_THIS_CODE */ + apply_button = create_apply_button(vbox, configure_data); + gtk_window_set_default(GTK_WINDOW(toplevel), apply_button) ; + } gtk_widget_show_all(toplevel) ; return ; } - -GtkWidget *makeMenuBar(ColConfigure configure_data) +/* Simple make menu bar function */ +static GtkWidget *make_menu_bar(ColConfigure configure_data) { GtkAccelGroup *accel_group; GtkItemFactory *item_factory; GtkWidget *menubar ; gint nmenu_items = sizeof (menu_items_G) / sizeof (menu_items_G[0]); - accel_group = gtk_accel_group_new (); + accel_group = gtk_accel_group_new (); item_factory = gtk_item_factory_new (GTK_TYPE_MENU_BAR, "<main>", accel_group ); @@ -364,113 +387,271 @@ GtkWidget *makeMenuBar(ColConfigure configure_data) return menubar ; } +static void free_select_all_data_cb(gpointer user_data) +{ + g_free(user_data); + + return ; +} + +static void create_select_all_button(GtkWidget *button_box, char *label, + GtkWidget *radio_group_container, + ZMapStyleColumnDisplayState state) +{ + GtkWidget *button; + SelectAllConfigure select_all ; + + button = gtk_button_new_with_label(label); + + gtk_box_pack_start(GTK_BOX(button_box), button, TRUE, TRUE, 0); + + select_all = g_new0(SelectAllConfigureStruct, 1); + + select_all->radio_groups_container = radio_group_container; + select_all->select_button_state = state; -GtkWidget *makeColsPanel(ZMapWindow window, char *frame_title, GList *columns_list, - GtkWidget **label_container_out, GtkWidget **button_container_out) + g_signal_connect_data(G_OBJECT(button), "clicked", + G_CALLBACK(select_all_buttons), select_all, + (GClosureNotify)free_select_all_data_cb, 0); + return ; +} + +static GtkWidget *make_cols_panel(ZMapWindow window, char *frame_title, GList *columns_list, + GtkWidget **label_container_out, GtkWidget **button_container_out) { GtkWidget *cols_panel, *named_frame, *vbox, *hbox, *label_box, *column_box ; GtkWidget *scroll_vbox, *scrolled, *viewport; GList *column = NULL ; + int list_length = 0; + /* Create a new frame (Forward|Reverse Strand) */ cols_panel = named_frame = gtk_frame_new(frame_title) ; gtk_container_set_border_width(GTK_CONTAINER(named_frame), ZMAP_WINDOW_GTK_CONTAINER_BORDER_WIDTH); - + /* A vbox to go in the frame */ vbox = gtk_vbox_new(FALSE, 0); gtk_container_add(GTK_CONTAINER(named_frame), vbox) ; - + /* A scrolled window to go in the vbox ... */ scrolled = gtk_scrolled_window_new(NULL, NULL); - gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); - gtk_container_add(GTK_CONTAINER(vbox), scrolled); + /* ... which needs a box to put the viewport in ... */ scroll_vbox = gtk_vbox_new(FALSE, 0) ; gtk_container_set_border_width(GTK_CONTAINER(scroll_vbox), ZMAP_WINDOW_GTK_CONTAINER_BORDER_WIDTH); + /* ... which we need to put the rows of radio buttons in for when + * there's a large number of canvas columns. */ viewport = gtk_viewport_new(NULL, NULL); gtk_container_add(GTK_CONTAINER(viewport), scroll_vbox); gtk_viewport_set_shadow_type(GTK_VIEWPORT(viewport), GTK_SHADOW_NONE); gtk_container_add(GTK_CONTAINER(scrolled), viewport); + /* A box for the label and column boxes */ hbox = gtk_hbox_new(FALSE, 0) ; gtk_container_add(GTK_CONTAINER(scroll_vbox), hbox) ; - + /* A box for the labels */ label_box = gtk_vbox_new(FALSE, 0) ; gtk_container_add(GTK_CONTAINER(hbox), label_box) ; *label_container_out = label_box ; + /* A box for the columns */ column_box = gtk_vbox_new(FALSE, 0) ; gtk_container_add(GTK_CONTAINER(hbox), column_box) ; *button_container_out = column_box ; + /* Make sure we get the correctly sized widget... */ zmapAddSizingSignalHandlers(viewport, FALSE, -1, -1); - column = g_list_first(columns_list) ; - do + if((column = g_list_first(columns_list))) { - FooCanvasGroup *column_group = (FooCanvasGroup *)(column->data) ; - ButData button_data ; - ZMapWindowItemFeatureSetData set_data ; - ZMapFeatureTypeStyle style ; - GtkWidget *col_box, *active_button, *label, *radio_show, *radio_maybe, *radio_hide ; - ZMapStyleColumnDisplayState col_state ; + do + { + FooCanvasGroup *column_group = FOO_CANVAS_GROUP(column->data) ; + ZMapWindowItemFeatureSetData set_data ; + ButData button_data ; + GtkWidget *label, *button_box; + char *label_text; + label_text = label_text_from_column(column_group); - button_data = g_new0(ButDataStruct, 1) ; - button_data->window = window ; - button_data->column_group = column_group ; + /* create the label that the user can understand */ + /* this also creates the button_data... */ + label = create_label(label_box, &button_data, label_text); + + /* Set the button_data we need for the individual buttons */ + button_data->column_group = column_group ; + button_box = gtk_hbox_new(FALSE, 0) ; + /* Show set of radio buttons for each column to change column display state. */ + gtk_box_pack_start(GTK_BOX(column_box), button_box, TRUE, TRUE, 0); - /* Get hold of the style. */ - set_data = g_object_get_data(G_OBJECT(column_group), ITEM_FEATURE_SET_DATA) ; - zMapAssert(set_data) ; - style = set_data->style ; + g_object_set_data(G_OBJECT(label), RADIO_BUTTONS_CONTAINER, button_box); + /* create the actual radio buttons... */ + set_data = g_object_get_data(G_OBJECT(column_group), ITEM_FEATURE_SET_DATA) ; + create_radio_buttons(button_box, button_data, set_data->style); - /* show the column name. */ - label = gtk_label_new(g_quark_to_string(zMapStyleGetID(set_data->style))) ; - /* x, y alignments between 0.0 (left, top) and 1.0 (right, bottom) [0.5 == centered] */ - gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5); - gtk_box_pack_start(GTK_BOX(label_box), label, TRUE, TRUE, 0) ; - g_object_set_data(G_OBJECT(label), BUTTON_DATA, button_data) ; - g_signal_connect(GTK_OBJECT(label), "destroy", - GTK_SIGNAL_FUNC(destroyLabelCB), (gpointer)button_data) ; + list_length++; + } + while ((column = g_list_next(column))) ; + } + /* We don't need this for a single column. */ + if (list_length > 1) + { + GtkWidget *frame, *button_box; + + frame = gtk_frame_new(NULL) ; + + gtk_container_set_border_width(GTK_CONTAINER(frame), + ZMAP_WINDOW_GTK_CONTAINER_BORDER_WIDTH); + + gtk_box_pack_end(GTK_BOX(vbox), frame, FALSE, FALSE, 0); + + button_box = gtk_hbutton_box_new(); + + gtk_container_add(GTK_CONTAINER(frame), button_box) ; + + create_select_all_button(button_box, SHOW_LABEL " All", + column_box, + ZMAPSTYLE_COLDISPLAY_SHOW); + + create_select_all_button(button_box, SHOWHIDE_LABEL " All", + column_box, + ZMAPSTYLE_COLDISPLAY_SHOW_HIDE); + + create_select_all_button(button_box, HIDE_LABEL " All", + column_box, + ZMAPSTYLE_COLDISPLAY_HIDE); + } + + return cols_panel ; +} + +static char *label_text_from_column(FooCanvasGroup *column_group) +{ + ZMapWindowItemFeatureSetData set_data ; + ZMapFeatureTypeStyle style; + char *label_text; + + /* Get hold of the style. */ + set_data = g_object_get_data(G_OBJECT(column_group), ITEM_FEATURE_SET_DATA) ; + zMapAssert(set_data) ; + + style = set_data->style; + + label_text = (char *)(g_quark_to_string(zMapStyleGetID(style))); + + return label_text; +} + +/* Quick function to create an aligned label with the name of the style. + * Label has a destroy callback for the button_data! + */ +static GtkWidget *create_label(GtkWidget *parent, ButData *button_data_out, char *text) +{ + GtkWidget *label; + ButData button_data ; - /* Show set of radio buttons for each column to change column display state. */ - col_box = gtk_hbox_new(FALSE, 0) ; - gtk_box_pack_start(GTK_BOX(column_box), col_box, TRUE, TRUE, 0); + /* show the column name. */ + label = gtk_label_new(text); + + /* x, y alignments between 0.0 (left, top) and 1.0 (right, bottom) [0.5 == centered] */ + gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5); + + gtk_box_pack_start(GTK_BOX(parent), label, TRUE, TRUE, 0) ; + + /* Create button data for this column */ + button_data = g_new0(ButDataStruct, 1) ; - button_data->button_box = col_box ; + /* Setup the destruction of the button_data too. */ + g_signal_connect(G_OBJECT(label), "destroy", + G_CALLBACK(destroy_label_cb), (gpointer)button_data) ; - radio_show = gtk_radio_button_new_with_label(NULL, SHOW_LABEL) ; - gtk_box_pack_start(GTK_BOX(col_box), radio_show, TRUE, TRUE, 0) ; - g_signal_connect_data(G_OBJECT(radio_show), "toggled", - G_CALLBACK(showButCB), GINT_TO_POINTER(ZMAPSTYLE_COLDISPLAY_SHOW), - NULL, 0) ; - g_object_set_data(G_OBJECT(radio_show), BUTTON_DATA, button_data) ; + if(button_data_out) + *button_data_out = button_data; - radio_maybe = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(radio_show), SHOWHIDE_LABEL) ; - gtk_box_pack_start(GTK_BOX(col_box), radio_maybe, TRUE, TRUE, 0) ; - g_signal_connect_data(G_OBJECT(radio_maybe), "toggled", - G_CALLBACK(showButCB), GINT_TO_POINTER(ZMAPSTYLE_COLDISPLAY_SHOW_HIDE), - NULL, 0) ; - g_object_set_data(G_OBJECT(radio_maybe), BUTTON_DATA, button_data) ; + return label; +} - radio_hide = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(radio_show), HIDE_LABEL) ; - gtk_box_pack_start(GTK_BOX(col_box), radio_hide, TRUE, TRUE, 0) ; - g_signal_connect_data(G_OBJECT(radio_hide), "toggled", - G_CALLBACK(showButCB), GINT_TO_POINTER(ZMAPSTYLE_COLDISPLAY_HIDE), - NULL, 0) ; - g_object_set_data(G_OBJECT(radio_hide), BUTTON_DATA, button_data) ; +static void finished_press_cb(ColConfigure configure_data) +{ + configure_data->reposition = configure_data->apply_now = FALSE; + configure_data->return_func = NULL; + return; +} +/* This allows for the temporary immediate redraw, see + * finished_press_cb and ->return_func invocation in showButCB */ +/* Implemented like this as I couldn't find how to "wrap" the "toggle" signal */ +static gboolean press_button_cb(GtkWidget *widget, GdkEvent *event, gpointer user_data) +{ + GdkModifierType unwanted = (GDK_LOCK_MASK | GDK_MOD2_MASK | GDK_MOD3_MASK | GDK_MOD4_MASK | GDK_MOD5_MASK); + GtkWidget *toplevel; + ColConfigure configure_data; + + switch(event->type) + { + case GDK_BUTTON_PRESS: + case GDK_BUTTON_RELEASE: + { + GdkEventButton *button = (GdkEventButton *)event; + GdkModifierType locks, control = GDK_CONTROL_MASK; + + locks = button->state & unwanted; + control |= locks; + + if(button->state & control) + { + toplevel = zMapGUIFindTopLevel(widget); + + configure_data = g_object_get_data(G_OBJECT(toplevel), CONFIGURE_DATA); + + configure_data->apply_now = configure_data->reposition = TRUE; + configure_data->return_func = finished_press_cb; + } + } + break; + default: + break; + } + + return FALSE; +} + +/* Create enough radio buttons for the user to toggle between all the states of column visibility */ +static void create_radio_buttons(GtkWidget *parent, ButData button_data, ZMapFeatureTypeStyle style) +{ + GtkWidget *radio_show, *radio_maybe, *radio_hide; + GtkRadioButton *radio_group_button; + + radio_show = gtk_radio_button_new_with_label(NULL, SHOW_LABEL) ; + + radio_group_button = GTK_RADIO_BUTTON(radio_show); + + gtk_box_pack_start(GTK_BOX(parent), radio_show, TRUE, TRUE, 0) ; + + radio_maybe = gtk_radio_button_new_with_label_from_widget(radio_group_button, + SHOWHIDE_LABEL) ; + + gtk_box_pack_start(GTK_BOX(parent), radio_maybe, TRUE, TRUE, 0) ; + + radio_hide = gtk_radio_button_new_with_label_from_widget(radio_group_button, + HIDE_LABEL) ; + gtk_box_pack_start(GTK_BOX(parent), radio_hide, TRUE, TRUE, 0) ; + + if(style) + { + ZMapStyleColumnDisplayState col_state ; + GtkWidget *active_button; + col_state = zMapStyleGetDisplay(style) ; switch(col_state) { @@ -484,72 +665,105 @@ GtkWidget *makeColsPanel(ZMapWindow window, char *frame_title, GList *columns_li active_button = radio_show ; break ; } - + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(active_button), TRUE) ; + } -#ifdef ED_G_NEVER_INCLUDE_THIS_CODE - /* Not needed yet.... */ + g_signal_connect(G_OBJECT(radio_show), "toggled", + G_CALLBACK(showButCB), button_data) ; + g_signal_connect(G_OBJECT(radio_show), "event", + G_CALLBACK(press_button_cb), button_data) ; - /* This should be a button at the bottom of the window... */ - button = gtk_button_new_with_label("Advanced configuration") ; - gtk_box_pack_end(GTK_BOX(col_box), button, FALSE, FALSE, 0) ; -#endif /* ED_G_NEVER_INCLUDE_THIS_CODE */ + g_signal_connect(G_OBJECT(radio_maybe), "toggled", + G_CALLBACK(showButCB), button_data); + g_signal_connect(G_OBJECT(radio_maybe), "event", + G_CALLBACK(press_button_cb), button_data); - } - while ((column = g_list_next(column))) ; + g_signal_connect(G_OBJECT(radio_hide), "toggled", + G_CALLBACK(showButCB), button_data); + g_signal_connect(G_OBJECT(radio_hide), "event", + G_CALLBACK(press_button_cb), button_data); + return ; +} - /* We don't need this for a single column. */ - if (g_list_length(columns_list) > 1) +static void apply_state_cb(GtkWidget *widget, gpointer user_data) +{ + if(GTK_IS_TOGGLE_BUTTON(widget)) + { + if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) + g_signal_emit_by_name(G_OBJECT(widget), "toggled"); + } + else if(GTK_IS_CONTAINER(widget)) { - SelectAllConfigure select_data ; - GtkWidget *frame, *button_box, *button; + gtk_container_foreach(GTK_CONTAINER(widget), + apply_state_cb, user_data); + } + else + zMapLogWarning("widget '%s' is not a radio button", G_OBJECT_TYPE_NAME(G_OBJECT(widget))); - select_data = g_new0(SelectAllConfigureStruct, 1) ; - select_data->window = window ; - select_data->frame_widg = column_box ; + return ; +} - frame = gtk_frame_new(NULL) ; - gtk_container_set_border_width(GTK_CONTAINER(frame), ZMAP_WINDOW_GTK_CONTAINER_BORDER_WIDTH); - g_signal_connect(GTK_OBJECT(frame), "destroy", - GTK_SIGNAL_FUNC(destroyFrameCB), (gpointer)select_data) ; - gtk_box_pack_end(GTK_BOX(vbox), frame, FALSE, FALSE, 0); +static void apply_button_cb(GtkButton *apply_button, gpointer user_data) +{ + ColConfigure configure_data = (ColConfigure)user_data; + gboolean save_apply_now, save_reposition; + save_apply_now = configure_data->apply_now; + save_reposition = configure_data->reposition; - button_box = gtk_hbutton_box_new(); - gtk_container_add(GTK_CONTAINER(frame), button_box) ; + configure_data->apply_now = TRUE; + configure_data->reposition = FALSE; - button = gtk_button_new_with_label(SHOW_LABEL " All"); - gtk_box_pack_start(GTK_BOX(button_box), button, TRUE, TRUE, 0); - g_signal_connect_data(G_OBJECT(button), "clicked", - G_CALLBACK(selectButtons), - GINT_TO_POINTER(ZMAPSTYLE_COLDISPLAY_SHOW), - NULL, - 0); - g_object_set_data(G_OBJECT(button), SELECT_DATA, select_data) ; - - button = gtk_button_new_with_label(SHOWHIDE_LABEL " All"); - gtk_box_pack_start(GTK_BOX(button_box), button, TRUE, TRUE, 0); - g_signal_connect_data(G_OBJECT(button), "clicked", - G_CALLBACK(selectButtons), - GINT_TO_POINTER(ZMAPSTYLE_COLDISPLAY_SHOW_HIDE), - NULL, 0) ; - g_object_set_data(G_OBJECT(button), SELECT_DATA, select_data) ; - - button = gtk_button_new_with_label(HIDE_LABEL " All"); - gtk_box_pack_start(GTK_BOX(button_box), button, TRUE, TRUE, 0); - g_signal_connect_data(G_OBJECT(button), "clicked", - G_CALLBACK(selectButtons), - GINT_TO_POINTER(ZMAPSTYLE_COLDISPLAY_HIDE), - NULL, 0) ; - g_object_set_data(G_OBJECT(button), SELECT_DATA, select_data) ; - } + if(configure_data->forward_button_container) + gtk_container_foreach(GTK_CONTAINER(configure_data->forward_button_container), + apply_state_cb, configure_data); - return cols_panel ; + if(configure_data->reverse_button_container) + gtk_container_foreach(GTK_CONTAINER(configure_data->reverse_button_container), + apply_state_cb, configure_data); + + configure_data->apply_now = save_apply_now; + configure_data->reposition = save_reposition; + + zmapWindowFullReposition(configure_data->window); + + return ; } +static GtkWidget *create_apply_button(GtkWidget *parent, ColConfigure configure_data) +{ + GtkWidget *button_box, *apply_button, *frame; + + button_box = gtk_hbutton_box_new(); + gtk_button_box_set_layout (GTK_BUTTON_BOX (button_box), GTK_BUTTONBOX_END); + gtk_box_set_spacing (GTK_BOX(button_box), + ZMAP_WINDOW_GTK_BUTTON_BOX_SPACING); + gtk_container_set_border_width (GTK_CONTAINER (button_box), + ZMAP_WINDOW_GTK_CONTAINER_BORDER_WIDTH); + + apply_button = gtk_button_new_with_label("Apply") ; + gtk_container_add(GTK_CONTAINER(button_box), apply_button) ; + + gtk_signal_connect(GTK_OBJECT(apply_button), "clicked", + GTK_SIGNAL_FUNC(apply_button_cb), (gpointer)configure_data) ; + + /* set apply button as default. */ + GTK_WIDGET_SET_FLAGS(apply_button, GTK_CAN_DEFAULT) ; + + frame = gtk_frame_new(NULL) ; + gtk_container_set_border_width(GTK_CONTAINER(frame), + ZMAP_WINDOW_GTK_CONTAINER_BORDER_WIDTH); + gtk_box_pack_start(GTK_BOX(parent), frame, FALSE, FALSE, 0) ; + + gtk_container_add(GTK_CONTAINER(frame), button_box); + + return apply_button; +} + /* This is not the way to do help, we should really used html and have a set of help files. */ static void helpCB(gpointer data, guint callback_action, GtkWidget *w) { @@ -571,7 +785,9 @@ static void helpCB(gpointer data, guint callback_action, GtkWidget *w) "the column is bumped, the window mark and compress options. Column display can be\n" "overridden however to always show or always hide columns.\n" "\n" - "Note that changing the column setting immediately redraws that column." + "To redraw the display, either click the \"Apply\" button, or if there is no button the\n" + "display will be redrawn immediately. To temporarily turn on the immediate redraw hold\n" + "Control while selecting the radio button." "\n" ; zMapGUIShowText(title, help_text, FALSE) ; @@ -605,42 +821,37 @@ static void destroyCB(GtkWidget *widget, gpointer cb_data) } -static void destroyLabelCB(GtkWidget *widget, gpointer cb_data) +static void destroy_label_cb(GtkWidget *widget, gpointer cb_data) { ButData button_data = (ButData)cb_data ; + /* Just freeing the struct. Nothing else is our responsibility */ g_free(button_data) ; return ; } -static void destroyFrameCB(GtkWidget *widget, gpointer cb_data) -{ - SelectAllConfigure select_data = (SelectAllConfigure)cb_data ; - - g_free(select_data) ; - return ; -} - - - - - -#ifdef ED_G_NEVER_INCLUDE_THIS_CODE -static void applyCB(GtkWidget *widget, gpointer cb_data) +static ZMapStyleColumnDisplayState button_label_to_state(const char *button_label_text) { -#ifdef RDS_DONT_INCLUDE_UNUSED - ColConfigure configure_data = (ColConfigure)cb_data ; -#endif - /* WE NEED TO CALL COLUMN REPOSITION HERE.... OR MAYBE MORE THAN THAT... */ - printf("not implemented yet\n") ; - - return ; -} -#endif /* ED_G_NEVER_INCLUDE_THIS_CODE */ + ZMapStyleColumnDisplayState col_state = ZMAPSTYLE_COLDISPLAY_SHOW; + if(button_label_text != NULL) + { + if(strcmp(SHOW_LABEL, button_label_text) == 0) + col_state = ZMAPSTYLE_COLDISPLAY_SHOW; + else if(strcmp(SHOWHIDE_LABEL, button_label_text) == 0) + col_state = ZMAPSTYLE_COLDISPLAY_SHOW_HIDE; + else if(strcmp(HIDE_LABEL, button_label_text) == 0) + col_state = ZMAPSTYLE_COLDISPLAY_HIDE; + else /* Something wrong */ + zMapLogWarning("Label '%s', not recognised", button_label_text); + } + else + zMapLogWarning("Label == NULL!", button_label_text); + return col_state; +} /* Called when user selects one of the display state radio buttons. * @@ -653,251 +864,226 @@ static void showButCB(GtkToggleButton *togglebutton, gpointer user_data) /* Only do something if the button was pressed on. */ if ((but_pressed = gtk_toggle_button_get_active(togglebutton))) { - ButData button_data ; + const char *button_label_text; + ButData button_data = (ButData)user_data; + ColConfigure configure_data; ZMapStyleColumnDisplayState col_state ; + GtkWidget *toplevel; + + /* Get the toplevel widget... */ + toplevel = zMapGUIFindTopLevel(GTK_WIDGET(togglebutton)); + + /* ...so we can et hold of it's data. */ + configure_data = g_object_get_data(G_OBJECT(toplevel), CONFIGURE_DATA); - /* Set column state according to which button was clicked. */ - button_data = g_object_get_data(G_OBJECT(togglebutton), BUTTON_DATA) ; + /* which column state are we setting? Get label, */ + button_label_text = gtk_button_get_label(GTK_BUTTON(togglebutton)); + /* and translate it... */ + col_state = button_label_to_state(button_label_text); - col_state = GPOINTER_TO_INT(user_data) ; + /* Set the correct state. */ + /* We only do this if there is no apply button. */ + if(configure_data->apply_now) + zmapWindowColumnSetState(configure_data->window, button_data->column_group, + col_state, configure_data->reposition) ; - zmapWindowColumnSetState(button_data->window, button_data->column_group, col_state, TRUE) ; + if(configure_data->return_func) + (configure_data->return_func)(configure_data); } return ; } - -/* May want to make this into a container group function as it contains some quite awkward - * stuff.... */ -static void makeColList(ZMapWindow window, GList **forward_cols_out, GList **reverse_cols_out) +static void toggle_radio_group_activate_matching_state(gpointer widget_data, gpointer user_data) { - GList *forward_col_list = NULL, *reverse_col_list = NULL ; - FooCanvasGroup *curr_level ; - FooCanvasGroup *strand_parent ; + GtkWidget *widget = GTK_WIDGET(widget_data); - /* Starting at root move down to the block level so we can get at the forward and reverse strands. */ - curr_level = window->feature_root_group ; - while (zmapWindowContainerGetLevel(curr_level) != ZMAPCONTAINER_LEVEL_BLOCK) + if(GTK_IS_RADIO_BUTTON(widget)) { - FooCanvasGroup *child_group ; - GList *children ; - - child_group = zmapWindowContainerGetFeatures(curr_level) ; + ZMapStyleColumnDisplayState button_col_state, user_state; + const char *button_label_text = NULL; - children = child_group->item_list ; + button_label_text = gtk_button_get_label(GTK_BUTTON(widget)); + + button_col_state = button_label_to_state(button_label_text); + + user_state = GPOINTER_TO_INT(user_data); - curr_level = children->data ; + if(button_col_state == user_state) + { + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), TRUE) ; + } } - - /* Get the reverse strand which will be the first group in the block level "features" */ - strand_parent = zmapWindowContainerGetStrandGroup(curr_level, ZMAPSTRAND_REVERSE); - - zmapWindowContainerExecute(strand_parent, ZMAPCONTAINER_LEVEL_FEATURESET, - getSetGroupCB, &reverse_col_list); - - /* Get the forward strand which will be the first group in the block level "features" */ - strand_parent = zmapWindowContainerGetStrandGroup(curr_level, ZMAPSTRAND_FORWARD); - - zmapWindowContainerExecute(strand_parent, ZMAPCONTAINER_LEVEL_FEATURESET, - getSetGroupCB, &forward_col_list); - - /* Return the column lists. */ - *forward_cols_out = forward_col_list ; - *reverse_cols_out = reverse_col_list ; - - return ; -} - - - -/* Adds this columns group to the list supplied as user data. */ -static void getSetGroupCB(FooCanvasGroup *container, FooCanvasPoints *points, ZMapContainerLevelType level, gpointer user_data) -{ - GList **return_list = (GList **)user_data ; - GList *col_list = *return_list ; - - if (level == ZMAPCONTAINER_LEVEL_FEATURESET) + else if(GTK_IS_CONTAINER(widget)) { - col_list = g_list_append(col_list, container) ; - *return_list = col_list ; + gtk_container_foreach(GTK_CONTAINER(widget), + (GtkCallback)toggle_radio_group_activate_matching_state, user_data); } - + else + zMapLogWarning("widget '%s' is not a radio button", G_OBJECT_TYPE_NAME(G_OBJECT(widget))); return ; } - -/* Set all column buttons for a strand to the state given by user_data. */ -static void selectButtons(GtkWidget *button, gpointer user_data) +static void select_all_buttons(GtkWidget *button, gpointer user_data) { - SelectAllConfigure select_data ; - GList *button_boxes ; + GList *button_boxes; + gboolean needs_reposition; + ColConfigure configure_data; + GtkWidget *radio_groups_container, *toplevel; + SelectAllConfigure select_all = (SelectAllConfigure)user_data; - select_data = g_object_get_data(G_OBJECT(button), SELECT_DATA) ; + toplevel = zMapGUIFindTopLevel(button); - button_boxes = gtk_container_get_children(GTK_CONTAINER(select_data->frame_widg)) ; + configure_data = g_object_get_data(G_OBJECT(toplevel), CONFIGURE_DATA); - g_list_foreach(button_boxes, allButtonsToggleCB, user_data) ; - - zmapWindowFullReposition(select_data->window) ; - - return ; -} + radio_groups_container = select_all->radio_groups_container; + button_boxes = gtk_container_get_children(GTK_CONTAINER(radio_groups_container)); -static void allButtonsToggleCB(gpointer data, gpointer user_data) -{ - GtkWidget *hbox = (GtkWidget *)data ; - ZMapStyleColumnDisplayState col_state = GPOINTER_TO_INT(user_data) ; - GtkWidget *button ; - ButData button_data = NULL; - gint blocked = 0; - - /* Find the right button to toggle on for the given state. */ - button = findButton(hbox, col_state) ; - - /* We do the toggling by blocking the callbacks otherwise there is a load - * of flickering...???? */ - if ((button_data = g_object_get_data(G_OBJECT(button), BUTTON_DATA)) - && (blocked = g_signal_handlers_block_matched(G_OBJECT(button), - G_SIGNAL_MATCH_FUNC, - 0, 0, - NULL, - showButCB, - NULL))) - { - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), TRUE) ; + needs_reposition = configure_data->reposition; - zmapWindowColumnSetState(button_data->window, button_data->column_group, col_state, FALSE) ; + configure_data->reposition = FALSE; - g_signal_handlers_unblock_matched(G_OBJECT(button), - G_SIGNAL_MATCH_FUNC, - 0, 0, - NULL, - showButCB, - NULL); - } + g_list_foreach(button_boxes, toggle_radio_group_activate_matching_state, + GINT_TO_POINTER(select_all->select_button_state)); + + if((configure_data->reposition = needs_reposition)) + zmapWindowFullReposition(configure_data->window); return ; } - -static GtkWidget *findButton(GtkWidget *hbox, ZMapStyleColumnDisplayState col_state) +static gint match_label_with_text_cb(gconstpointer label_data, gconstpointer text_data) { - GtkWidget *button = NULL ; - FindButStruct cb_data = {col_state, NULL, NULL} ; - - switch(col_state) - { - case ZMAPSTYLE_COLDISPLAY_HIDE: - cb_data.but_text = HIDE_LABEL ; - break ; - case ZMAPSTYLE_COLDISPLAY_SHOW_HIDE: - cb_data.but_text = SHOWHIDE_LABEL ; - break ; - default: /* ZMAPSTYLE_COLDISPLAY_SHOW */ - cb_data.but_text = SHOW_LABEL ; - break ; - } - - gtk_container_foreach(GTK_CONTAINER(hbox), findButtonCB, &cb_data) ; + GtkWidget *label = GTK_WIDGET(label_data); + char *text = (char *)text_data; + const char *label_text = NULL; + int match = -1; - if (cb_data.button) - button = cb_data.button ; + label_text = gtk_label_get_text(GTK_LABEL(label)); + + if(strcmp(text, label_text) == 0) + match = 0; - return button ; + return match; } +/* Finds the button which represents column_group and sets its state to match configure_mode. */ +/* Tactic. + * - Get the correct strand container for labels + * - Get the label matching the column_group + * - Get the children of the labels->button_data->button_box + * - Search these for the correct radio button to toggle. + * */ -/* A GtkCallback() to find a button with a given label. */ -static void findButtonCB(GtkWidget *widget, gpointer data) +static void toggle_column_radio_group_activate_matching_state(GtkWidget *toplevel, + FooCanvasGroup *column_group, + ZMapWindowColConfigureMode mode) { - FindBut cb_data = (FindBut)data ; - - if (g_ascii_strcasecmp(cb_data->but_text, gtk_button_get_label(GTK_BUTTON(widget))) == 0) - cb_data->button = widget ; - - return ; -} + ColConfigure configure_data; + GtkWidget *label_container, *column_label = NULL; + ZMapStrand strand; + GList *labels, *matching_label; + char *column_text = NULL; + /* First get the configure_data */ + configure_data = g_object_get_data(G_OBJECT(toplevel), CONFIGURE_DATA); - -/* Finds the button which represents column_group and sets its state to match configure_mode. */ -static void changeButtonState(GtkWidget *toplevel, - FooCanvasGroup *column_group, ZMapWindowColConfigureMode configure_mode) -{ - ColConfigure configure_data ; - GList *label_el = NULL ; - GtkWidget *label, *button ; - gboolean col_visible ; - ZMapStrand strand ; - GtkWidget *label_container, *button_container ; - GList *labels ; - ButData button_data ; - ZMapStyleColumnDisplayState col_state ; - + /* - Get the correct strand container for labels */ strand = zmapWindowContainerGetStrand(column_group); zMapAssert(strand == ZMAPSTRAND_FORWARD || strand == ZMAPSTRAND_REVERSE) ; - configure_data = g_object_get_data(G_OBJECT(toplevel), CONF_DATA) ; - if (strand == ZMAPSTRAND_FORWARD) - { - label_container = configure_data->forward_label_container ; - button_container = configure_data->forward_button_container ; - } + label_container = configure_data->forward_label_container ; else - { - label_container = configure_data->reverse_label_container ; - button_container = configure_data->reverse_button_container ; - } + label_container = configure_data->reverse_label_container ; labels = gtk_container_get_children(GTK_CONTAINER(label_container)) ; + + /* - Get the label matching the column_group. We use the text for this... */ + column_text = label_text_from_column(column_group); - label_el = g_list_find_custom(labels, column_group, findGroupCB) ; - zMapAssert(label_el) ; + if((matching_label = g_list_find_custom(labels, column_text, match_label_with_text_cb))) + column_label = GTK_WIDGET(matching_label->data); - label = label_el->data ; + /* so long as we've got a label, proceed... */ + if(column_label) + { + ZMapStyleColumnDisplayState col_state; + GtkWidget *button_container; + GList *buttons = NULL; + gboolean save_apply_now, save_reposition; - button_data = g_object_get_data(G_OBJECT(label), BUTTON_DATA) ; + /* - Get the children of the labels->button_data->button_box */ + button_container = g_object_get_data(G_OBJECT(column_label), RADIO_BUTTONS_CONTAINER); - if (configure_mode == ZMAPWINDOWCOLUMN_HIDE) - { - col_state = ZMAPSTYLE_COLDISPLAY_HIDE ; - } - else - { - col_state = ZMAPSTYLE_COLDISPLAY_SHOW ; - } - col_visible = TRUE ; + buttons = gtk_container_get_children(GTK_CONTAINER(button_container)); + + if (mode == ZMAPWINDOWCOLUMN_HIDE) + col_state = ZMAPSTYLE_COLDISPLAY_HIDE ; + else + col_state = ZMAPSTYLE_COLDISPLAY_SHOW ; - button = findButton(button_data->button_box, col_state) ; + /* - Search these for the correct radio button to toggle. */ + save_apply_now = configure_data->apply_now; + save_reposition = configure_data->reposition; - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), col_visible) ; + configure_data->apply_now = TRUE; + configure_data->reposition = TRUE; + + g_list_foreach(buttons, toggle_radio_group_activate_matching_state, + GINT_TO_POINTER(col_state)); + + configure_data->apply_now = save_apply_now; + configure_data->reposition = save_reposition; + } return ; } - -/* A GCompareFunc() to look for the canvas group attached to a button. */ -static gint findGroupCB(gconstpointer a, gconstpointer b) +/* Direct copy from zmapWindowContainer.c ... */ +static void set_column_lists_cb(FooCanvasGroup *container, FooCanvasPoints *points, + ZMapContainerLevelType level, gpointer user_data) { - gint result = -1 ; - GtkWidget *button = (GtkWidget *)a ; - FooCanvasGroup *column_group = (FooCanvasGroup *)b ; - ButData button_data ; + switch(level) + { + case ZMAPCONTAINER_LEVEL_FEATURESET: + { + ForwardReverseColumnLists lists_data; + ZMapWindowItemFeatureSetData set_data; - button_data = g_object_get_data(G_OBJECT(button), BUTTON_DATA) ; + lists_data = (ForwardReverseColumnLists)user_data; - if (button_data->column_group == column_group) - result = 0 ; + if((set_data = g_object_get_data(G_OBJECT(container), ITEM_FEATURE_SET_DATA))) + { + if(set_data->strand == ZMAPSTRAND_FORWARD) + lists_data->forward = g_list_append(lists_data->forward, container); + else + lists_data->reverse = g_list_append(lists_data->reverse, container); + } + } + break; + default: + break; + } - return result ; + return ; } +/* ********************************************************* + * * Code to do the resizing of the widget, according to * + * * available space, and to add scrollbar when required * + * ********************************************************* + */ + +/* Entry point is zmapAddSizingSignalHandlers() */ + + +/* Called by widget_size_request() */ + static void handle_scrollbars(GtkWidget *widget, GtkRequisition *requisition_inout) { @@ -942,6 +1128,8 @@ static void handle_scrollbars(GtkWidget *widget, return ; } +/* Called by widget_size_request() */ + static void restrict_screen_size_to_toplevel(GtkWidget *widget, GtkRequisition *screen_size) { @@ -957,6 +1145,8 @@ static void restrict_screen_size_to_toplevel(GtkWidget *widget, return ; } +/* Called by widget_size_request() */ + static void get_screen_size(GtkWidget *widget, double screen_percentage, GtkRequisition *requisition_inout) diff --git a/src/zmapWindow/zmapWindowContainer.c b/src/zmapWindow/zmapWindowContainer.c index 7b848dd9b..330164163 100755 --- a/src/zmapWindow/zmapWindowContainer.c +++ b/src/zmapWindow/zmapWindowContainer.c @@ -28,9 +28,9 @@ * * Exported functions: See zmapWindowContainer.h * HISTORY: - * Last edited: Apr 15 08:11 2008 (rds) + * Last edited: Oct 21 17:11 2008 (rds) * Created: Wed Dec 21 12:32:25 2005 (edgrif) - * CVS info: $Id: zmapWindowContainer.c,v 1.51 2008-04-15 07:36:27 rds Exp $ + * CVS info: $Id: zmapWindowContainer.c,v 1.52 2008-10-21 17:32:48 rds Exp $ *------------------------------------------------------------------- */ @@ -124,7 +124,10 @@ typedef struct ContainerRecursionDataStruct_ } ContainerRecursionDataStruct, *ContainerRecursionData; - +typedef struct +{ + GList *forward, *reverse; +}ForwardReverseColumnListsStruct, *ForwardReverseColumnLists; typedef void (*ContainerWorldCoordsDataFunc)(FooCanvasGroup *container_parent, FooCanvasPoints *world_coords, @@ -159,7 +162,8 @@ static void maximise_container_background(FooCanvasGroup *container, ContainerData container_data); static void maximise_container_overlays(FooCanvasGroup *container, FooCanvasPoints *this_points, ContainerData container_data) ; - +static void set_column_lists_cb(FooCanvasGroup *container, FooCanvasPoints *points, + ZMapContainerLevelType level, gpointer user_data); /* To cache the points when recursing ... */ static ContainerPointsCache containerPointsCacheCreate(void); @@ -627,6 +631,33 @@ FooCanvasGroup *zmapWindowContainerGetStrandSeparatorGroup(FooCanvasGroup *stran return strand_group; } +gboolean zmapWindowContainerBlockGetColumnLists(FooCanvasGroup *column_container, + GList **forward_columns_out, + GList **reverse_columns_out) +{ + FooCanvasGroup *block_container; + gboolean found_block = FALSE; /* about all we gonna do. */ + + if((column_container) && + (block_container = zmapWindowContainerGetParentLevel(FOO_CANVAS_ITEM(column_container), + ZMAPCONTAINER_LEVEL_BLOCK))) + { + ForwardReverseColumnListsStruct for_rev_lists = {NULL}; + + zmapWindowContainerExecute(block_container, + ZMAPCONTAINER_LEVEL_FEATURESET, + set_column_lists_cb, &for_rev_lists); + + /* Return the column lists. */ + if(forward_columns_out) + *forward_columns_out = for_rev_lists.forward; + if(reverse_columns_out) + *reverse_columns_out = for_rev_lists.reverse; + } + + return found_block; +} + ZMapContainerLevelType zmapWindowContainerGetLevel(FooCanvasGroup *container_parent) { ContainerData container_data ; @@ -2092,6 +2123,34 @@ static void maximise_container_overlays(FooCanvasGroup *container, return ; } +static void set_column_lists_cb(FooCanvasGroup *container, FooCanvasPoints *points, + ZMapContainerLevelType level, gpointer user_data) +{ + switch(level) + { + case ZMAPCONTAINER_LEVEL_FEATURESET: + { + ForwardReverseColumnLists lists_data; + ZMapWindowItemFeatureSetData set_data; + + lists_data = (ForwardReverseColumnLists)user_data; + + if((set_data = g_object_get_data(G_OBJECT(container), ITEM_FEATURE_SET_DATA))) + { + if(set_data->strand == ZMAPSTRAND_FORWARD) + lists_data->forward = g_list_append(lists_data->forward, container); + else + lists_data->reverse = g_list_append(lists_data->reverse, container); + } + } + break; + default: + break; + } + + return ; +} + static ContainerPointsCache containerPointsCacheCreate(void) { diff --git a/src/zmapWindow/zmapWindowContainer.h b/src/zmapWindow/zmapWindowContainer.h index acc9f55d0..47769ced9 100755 --- a/src/zmapWindow/zmapWindowContainer.h +++ b/src/zmapWindow/zmapWindowContainer.h @@ -26,9 +26,9 @@ * feature context. * * HISTORY: - * Last edited: May 9 11:52 2008 (rds) + * Last edited: Oct 17 16:47 2008 (rds) * Created: Fri Dec 9 16:40:20 2005 (edgrif) - * CVS info: $Id: zmapWindowContainer.h,v 1.26 2008-05-09 10:59:06 rds Exp $ + * CVS info: $Id: zmapWindowContainer.h,v 1.27 2008-10-21 17:32:48 rds Exp $ *------------------------------------------------------------------- */ #ifndef ZMAP_WINDOW_CONTAINER_H @@ -192,6 +192,10 @@ gboolean zmapWindowContainerIsStrandSeparator(FooCanvasGroup *container); void zmapWindowContainerSetAsStrandSeparator(FooCanvasGroup *container); FooCanvasGroup *zmapWindowContainerGetStrandSeparatorGroup(FooCanvasGroup *strand_parent); +gboolean zmapWindowContainerBlockGetColumnLists(FooCanvasGroup *column_container, + GList **forward_columns_out, + GList **reverse_columns_out); + /* this should be somewhere else I think....or renamed.... */ void zmapWindowCanvasGroupChildSort(FooCanvasGroup *group_inout) ; -- GitLab