X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=gtk-gui.c;h=002b804148cb977a10d79a45138b96d1ce8f4799;hb=c15f798a85db53dae404a9113266a4d2bc72fbc6;hp=519bca50743991b1339d2d37f740cb493a158d4f;hpb=5c3bdd9fc85e1003a0537d286d968cdd008b1b95;p=ext%2Fsubsurface.git diff --git a/gtk-gui.c b/gtk-gui.c index 519bca5..002b804 100644 --- a/gtk-gui.c +++ b/gtk-gui.c @@ -33,10 +33,13 @@ struct units output_units; static GtkWidget *dive_profile; +visible_cols_t visible_cols = {TRUE, FALSE}; + void repaint_dive(void) { update_dive(current_dive); - gtk_widget_queue_draw(dive_profile); + if (dive_profile) + gtk_widget_queue_draw(dive_profile); } static char *existing_filename; @@ -100,6 +103,8 @@ static void file_open(GtkWidget *w, gpointer data) filter = gtk_file_filter_new(); gtk_file_filter_add_pattern(filter, "*.xml"); gtk_file_filter_add_pattern(filter, "*.XML"); + gtk_file_filter_add_pattern(filter, "*.sda"); + gtk_file_filter_add_pattern(filter, "*.SDA"); gtk_file_filter_add_mime_type(filter, "text/xml"); gtk_file_filter_set_name(filter, "XML file"); gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(dialog), filter); @@ -252,10 +257,19 @@ UNITCALLBACK(set_cuft, volume, CUFT) UNITCALLBACK(set_celsius, temperature, CELSIUS) UNITCALLBACK(set_fahrenheit, temperature, FAHRENHEIT) +#define OPTIONCALLBACK(name, option) \ +static void name(GtkWidget *w, gpointer data) \ +{ \ + option = GTK_TOGGLE_BUTTON(w)->active; \ +} + +OPTIONCALLBACK(otu_toggle, visible_cols.otu) +OPTIONCALLBACK(sac_toggle, visible_cols.sac) + static void preferences_dialog(GtkWidget *w, gpointer data) { int result; - GtkWidget *dialog, *font, *frame, *box, *vbox; + GtkWidget *dialog, *font, *frame, *box, *vbox, *button; menu_units = output_units; @@ -293,6 +307,22 @@ static void preferences_dialog(GtkWidget *w, gpointer data) "Fahrenheit", set_fahrenheit, (output_units.temperature == FAHRENHEIT), NULL); + frame = gtk_frame_new("Columns"); + gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), frame, FALSE, FALSE, 5); + + box = gtk_hbox_new(FALSE, 6); + gtk_container_add(GTK_CONTAINER(frame), box); + + button = gtk_check_button_new_with_label("Show SAC"); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), visible_cols.sac); + gtk_box_pack_start(GTK_BOX(box), button, FALSE, FALSE, 6); + g_signal_connect(G_OBJECT(button), "toggled", G_CALLBACK(sac_toggle), NULL); + + button = gtk_check_button_new_with_label("Show OTU"); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), visible_cols.otu); + gtk_box_pack_start(GTK_BOX(box), button, FALSE, FALSE, 6); + g_signal_connect(G_OBJECT(button), "toggled", G_CALLBACK(otu_toggle), NULL); + font = gtk_font_button_new_with_font(divelist_font); gtk_box_pack_start(GTK_BOX(vbox), font, FALSE, FALSE, 5); @@ -308,10 +338,13 @@ static void preferences_dialog(GtkWidget *w, gpointer data) output_units = menu_units; update_dive_list_units(); repaint_dive(); + update_dive_list_col_visibility(); gconf_client_set_bool(gconf, GCONF_NAME(feet), output_units.length == FEET, NULL); gconf_client_set_bool(gconf, GCONF_NAME(psi), output_units.pressure == PSI, NULL); gconf_client_set_bool(gconf, GCONF_NAME(cuft), output_units.volume == CUFT, NULL); gconf_client_set_bool(gconf, GCONF_NAME(fahrenheit), output_units.temperature == FAHRENHEIT, NULL); + gconf_client_set_bool(gconf, GCONF_NAME(SAC), ! visible_cols.sac, NULL); /* inverted to get the correct default */ + gconf_client_set_bool(gconf, GCONF_NAME(OTU), visible_cols.otu, NULL); gconf_client_set_string(gconf, GCONF_NAME(divelist_font), divelist_font, NULL); } gtk_widget_destroy(dialog); @@ -429,17 +462,99 @@ static void switch_page(GtkNotebook *notebook, gint arg1, gpointer user_data) repaint_dive(); } +static const char notebook_group[] = "123"; +#define GRP_ID ((void *)notebook_group) +typedef struct { + char *name; + GtkWidget *widget; + GtkWidget *box; + gulong delete_handler; + gulong destroy_handler; +} notebook_data_t; + +static notebook_data_t nbd[2]; /* we rip at most two notebook pages off */ + +static GtkNotebook *create_new_notebook_window(GtkNotebook *source, + GtkWidget *page, + gint x, gint y, gpointer data) +{ + GtkWidget *win, *notebook, *vbox; + notebook_data_t *nbdp; + + /* pick the right notebook page data and return if both are detached */ + if (nbd[0].widget == NULL) + nbdp = nbd; + else if (nbd[1].widget == NULL) + nbdp = nbd + 1; + else + return NULL; + + nbdp->name = strdup(gtk_widget_get_name(page)); + nbdp->widget = win = gtk_window_new(GTK_WINDOW_TOPLEVEL); + gtk_window_set_title(GTK_WINDOW(win), nbdp->name); + gtk_window_move(GTK_WINDOW(win), x, y); + + /* Destroying the dive list will kill the application */ + nbdp->delete_handler = g_signal_connect(G_OBJECT(win), "delete-event", G_CALLBACK(on_delete), NULL); + nbdp->destroy_handler = g_signal_connect(G_OBJECT(win), "destroy", G_CALLBACK(on_destroy), NULL); + + nbdp->box = vbox = gtk_vbox_new(FALSE, 0); + gtk_container_add(GTK_CONTAINER(win), vbox); + + notebook = gtk_notebook_new(); + gtk_notebook_set_group(GTK_NOTEBOOK(notebook), GRP_ID); + gtk_widget_set_name(notebook, nbdp->name); + /* disallow drop events */ + gtk_drag_dest_set(notebook, 0, NULL, 0, 0); + gtk_box_pack_start(GTK_BOX(vbox), notebook, TRUE, TRUE, 6); + gtk_widget_set_size_request(notebook, 450, 350); + + gtk_widget_show_all(win); + return GTK_NOTEBOOK(notebook); +} + +static void drag_cb(GtkWidget *widget, GdkDragContext *context, + gint x, gint y, guint time, + gpointer user_data) +{ + GtkWidget *source; + notebook_data_t *nbdp; + + source = gtk_drag_get_source_widget(context); + if (nbd[0].name && ! strcmp(nbd[0].name,gtk_widget_get_name(source))) + nbdp = nbd; + else if (nbd[1].name && ! strcmp(nbd[1].name,gtk_widget_get_name(source))) + nbdp = nbd + 1; + else + /* HU? */ + return; + + gtk_drag_finish(context, TRUE, TRUE, time); + + /* we no longer need the widget - but getting rid of this is hard; + * remove the signal handler, remove the notebook from the box + * then destroy the widget (and clear out our data structure) */ + g_signal_handler_disconnect(nbdp->widget,nbdp->delete_handler); + g_signal_handler_disconnect(nbdp->widget,nbdp->destroy_handler); + gtk_container_remove(GTK_CONTAINER(nbdp->box), source); + gtk_widget_destroy(nbdp->widget); + nbdp->widget = NULL; + free(nbdp->name); + nbdp->name = NULL; +} + void init_ui(int argc, char **argv) { GtkWidget *win; - GtkWidget *paned; - GtkWidget *info_box; GtkWidget *notebook; GtkWidget *dive_info; GtkWidget *dive_list; GtkWidget *equipment; GtkWidget *menubar; GtkWidget *vbox; + static const GtkTargetEntry notebook_target = { + "GTK_NOTEBOOK_TAB", GTK_TARGET_SAME_APP, 0 + }; gtk_init(&argc, &argv); @@ -454,7 +569,11 @@ void init_ui(int argc, char **argv) output_units.volume = CUFT; if (gconf_client_get_bool(gconf, GCONF_NAME(fahrenheit), NULL)) output_units.temperature = FAHRENHEIT; - + /* an unset key is FALSE - so in order to get the default behavior right we + invert the meaning of the SAC key */ + visible_cols.otu = gconf_client_get_bool(gconf, GCONF_NAME(OTU), NULL); + visible_cols.sac = ! gconf_client_get_bool(gconf, GCONF_NAME(SAC), NULL); + divelist_font = gconf_client_get_string(gconf, GCONF_NAME(divelist_font), NULL); if (!divelist_font) divelist_font = DIVELIST_DEFAULT_FONT; @@ -462,7 +581,7 @@ void init_ui(int argc, char **argv) error_info_bar = NULL; win = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_icon_from_file(GTK_WINDOW(win), "icon.svg", NULL); - g_signal_connect(G_OBJECT(win), "delete-event", G_CALLBACK (on_delete), NULL); + g_signal_connect(G_OBJECT(win), "delete-event", G_CALLBACK(on_delete), NULL); g_signal_connect(G_OBJECT(win), "destroy", G_CALLBACK(on_destroy), NULL); main_window = win; @@ -473,26 +592,28 @@ void init_ui(int argc, char **argv) menubar = get_menubar_menu(win); gtk_box_pack_start(GTK_BOX(vbox), menubar, FALSE, FALSE, 0); - /* HPane for left the dive list, and right the dive info */ - paned = gtk_vpaned_new(); - gtk_box_pack_end(GTK_BOX(vbox), paned, TRUE, TRUE, 0); - - /* Create the actual divelist */ - dive_list = dive_list_create(); - gtk_paned_add2(GTK_PANED(paned), dive_list); - - /* VBox for dive info, and tabs */ - info_box = gtk_vbox_new(FALSE, 6); - gtk_paned_add1(GTK_PANED(paned), info_box); - /* Notebook for dive info vs profile vs .. */ notebook = gtk_notebook_new(); + gtk_box_pack_start(GTK_BOX(vbox), notebook, TRUE, TRUE, 6); + gtk_notebook_set_group(GTK_NOTEBOOK(notebook), GRP_ID); + g_signal_connect(notebook, "create-window", G_CALLBACK(create_new_notebook_window), NULL); + gtk_drag_dest_set(notebook, GTK_DEST_DEFAULT_ALL, ¬ebook_target, 1, GDK_ACTION_MOVE); + g_signal_connect(notebook, "drag-drop", G_CALLBACK(drag_cb), notebook); g_signal_connect(notebook, "switch-page", G_CALLBACK(switch_page), NULL); - gtk_box_pack_start(GTK_BOX(info_box), notebook, TRUE, TRUE, 6); + + /* Create the actual divelist */ + dive_list = dive_list_create(); + gtk_widget_set_name(dive_list, "Dive List"); + gtk_notebook_append_page(GTK_NOTEBOOK(notebook), dive_list, gtk_label_new("Dive List")); + gtk_notebook_set_tab_detachable(GTK_NOTEBOOK(notebook), dive_list, 1); + gtk_notebook_set_tab_reorderable(GTK_NOTEBOOK(notebook), dive_list, 1); /* Frame for dive profile */ dive_profile = dive_profile_widget(); + gtk_widget_set_name(dive_profile, "Dive Profile"); gtk_notebook_append_page(GTK_NOTEBOOK(notebook), dive_profile, gtk_label_new("Dive Profile")); + gtk_notebook_set_tab_detachable(GTK_NOTEBOOK(notebook), dive_profile, 1); + gtk_notebook_set_tab_reorderable(GTK_NOTEBOOK(notebook), dive_profile, 1); /* Frame for extended dive info */ dive_info = extended_dive_info_widget(); @@ -513,46 +634,6 @@ void run_ui(void) gtk_main(); } -/* get the filenames the user selects and call the parsing function - * on them - * return 0 if the user cancelled the dialog - */ -int open_import_file_dialog(char *filterpattern, char *filtertext, - void(* parse_function)(char *)) -{ - int ret=0; - - GtkWidget *dialog; - GtkFileFilter *filter = gtk_file_filter_new (); - gtk_file_filter_add_pattern (filter, filterpattern); - gtk_file_filter_set_name(filter, filtertext); - dialog = gtk_file_chooser_dialog_new("Open File", - GTK_WINDOW(main_window), - GTK_FILE_CHOOSER_ACTION_OPEN, - GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, - GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, - NULL); - gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog), TRUE); - gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog),filter); - - if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) { - GSList *filenames; - char *filename; - filenames = gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(dialog)); - while(filenames != NULL) { - filename = (char *)filenames->data; - parse_function(filename); - g_free(filename); - filenames = g_slist_next(filenames); - } - g_slist_free(filenames); - ret = 1; - } - gtk_widget_destroy(dialog); - - return ret; -} - static gboolean expose_event(GtkWidget *widget, GdkEventExpose *event, gpointer data) { struct dive *dive = current_dive;