]> git.tdb.fi Git - ext/subsurface.git/blobdiff - gtk-gui.c
Distinguish internally between min pressure and end pressure
[ext/subsurface.git] / gtk-gui.c
index da2a94dc192c21a9701145fddb434015eca6018a..87cd8bf87de49c2eec6377d4c2841b84e150be5e 100644 (file)
--- a/gtk-gui.c
+++ b/gtk-gui.c
@@ -17,7 +17,7 @@
 
 #include "libdivecomputer.h"
 
-GtkWidget *main_window, *divelist_window;
+GtkWidget *main_window;
 GtkWidget *main_vbox;
 GtkWidget *error_info_bar;
 GtkWidget *error_label;
@@ -460,36 +460,87 @@ 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;
 
-       /* We don't detatch twice */
-       if (divelist_window)
+       /* 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;
 
-       divelist_window = win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
-       gtk_window_set_title(GTK_WINDOW(win), "Dive List");
+       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 */
-       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);
+       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);
 
-       vbox = gtk_vbox_new(FALSE, 0);
+       nbdp->box = vbox = gtk_vbox_new(FALSE, 0);
        gtk_container_add(GTK_CONTAINER(win), vbox);
 
        notebook = gtk_notebook_new();
-       gtk_notebook_set_group_id(GTK_NOTEBOOK(notebook), gtk_notebook_get_group_id(source));
+       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, 350, 250);
+       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;
@@ -499,6 +550,9 @@ void init_ui(int argc, char **argv)
        GtkWidget *equipment;
        GtkWidget *menubar;
        GtkWidget *vbox;
+       static const GtkTargetEntry notebook_target = {
+               "GTK_NOTEBOOK_TAB", GTK_TARGET_SAME_APP, 0
+       };
 
        gtk_init(&argc, &argv);
 
@@ -539,17 +593,25 @@ void init_ui(int argc, char **argv)
        /* 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_window_creation_hook(create_new_notebook_window, NULL, NULL);
+       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, &notebook_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);
 
        /* 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();