/* * * dpaned.c * * Copyright 2010 Alexander Petukhov * * 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., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301, USA. */ /* * Working with debug paned. */ #include #include #include #include extern GeanyData *geany_data; #include "dpaned.h" #include "tabs.h" #include "breakpoints.h" #include "debug.h" #include "btnpanel.h" #include "stree.h" #include "dconfig.h" #define NOTEBOOK_GROUP "notebook-438948394" #define HPANED_BORDER_WIDTH 4 #define CONNECT_PAGE_SIGNALS(X) \ switch_left_handler_id = g_signal_connect(G_OBJECT(debug_notebook_left), "switch-page", G_CALLBACK(on_change_current_page), NULL); \ switch_right_handler_id = g_signal_connect(G_OBJECT(debug_notebook_right), "switch-page", G_CALLBACK(on_change_current_page), NULL); \ reorder_left_handler_id = g_signal_connect(G_OBJECT(debug_notebook_left), "page-reordered", G_CALLBACK(on_page_reordered), NULL); \ reorder_right_handler_id = g_signal_connect(G_OBJECT(debug_notebook_right), "page-reordered", G_CALLBACK(on_page_reordered), NULL); \ add_left_handler_id = g_signal_connect(G_OBJECT(debug_notebook_left), "page-added", G_CALLBACK(on_page_added), NULL); \ add_right_handler_id = g_signal_connect(G_OBJECT(debug_notebook_right), "page-added", G_CALLBACK(on_page_added), NULL); \ remove_left_handler_id = g_signal_connect(G_OBJECT(debug_notebook_left), "page-removed", G_CALLBACK(on_page_removed), NULL); \ remove_right_handler_id = g_signal_connect(G_OBJECT(debug_notebook_right), "page-removed", G_CALLBACK(on_page_removed), NULL); #define DISCONNECT_PAGE_SIGNALS(X) \ g_signal_handler_disconnect(G_OBJECT(debug_notebook_left), switch_left_handler_id); \ g_signal_handler_disconnect(G_OBJECT(debug_notebook_right), switch_right_handler_id); \ g_signal_handler_disconnect(G_OBJECT(debug_notebook_left), reorder_left_handler_id); \ g_signal_handler_disconnect(G_OBJECT(debug_notebook_right), reorder_right_handler_id); \ g_signal_handler_disconnect(G_OBJECT(debug_notebook_left), add_left_handler_id); \ g_signal_handler_disconnect(G_OBJECT(debug_notebook_right), add_right_handler_id); \ g_signal_handler_disconnect(G_OBJECT(debug_notebook_left), remove_left_handler_id); \ g_signal_handler_disconnect(G_OBJECT(debug_notebook_right), remove_right_handler_id); #define CONNECT_ALLOCATED_PAGE_SIGNALS(X) \ allocate_handler_id = g_signal_connect(G_OBJECT(hpaned), "size-allocate", G_CALLBACK(on_size_allocate), NULL); #define DISCONNECT_ALLOCATED_PAGE_SIGNALS(X) \ g_signal_handler_disconnect(G_OBJECT(hpaned), allocate_handler_id); \ /* pane */ static GtkWidget *hpaned = NULL; /* left and right notebooks */ static GtkWidget *debug_notebook_left = NULL; static GtkWidget *debug_notebook_right = NULL; /* notebook signal handler ids */ static gulong allocate_handler_id; static gulong switch_left_handler_id; static gulong switch_right_handler_id; static gulong reorder_left_handler_id; static gulong reorder_right_handler_id; static gulong add_left_handler_id; static gulong add_right_handler_id; static gulong remove_left_handler_id; static gulong remove_right_handler_id; /* * first allocation handler to properly set paned position */ static void on_size_allocate(GtkWidget *widget,GdkRectangle *allocation, gpointer user_data) { int position; DISCONNECT_ALLOCATED_PAGE_SIGNALS(); position = (allocation->width - 2 * HPANED_BORDER_WIDTH) * 0.5; gtk_paned_set_position(GTK_PANED(hpaned), position); } /* * page added event handler */ static void on_page_added(GtkNotebook *notebook, GtkWidget *child, guint page_num, gpointer user_data) { gboolean is_left = (GTK_NOTEBOOK(debug_notebook_left) == notebook); gboolean is_tabbed = config_get_tabbed(); int *tabs = NULL, *array, *new_tabs; gsize length; GtkWidget *page; tab_id id; int config_part; if (!is_tabbed) tabs = config_get_tabs(&length); else if (is_left) tabs = config_get_left_tabs(&length); else tabs = config_get_right_tabs(&length); array = g_malloc((length + 2) * sizeof(int)); new_tabs = array + 1; memcpy(new_tabs, tabs, length * sizeof(int)); memmove(new_tabs + page_num + 1, new_tabs + page_num, (length - page_num) * sizeof(int)); page = gtk_notebook_get_nth_page(GTK_NOTEBOOK(is_left ? debug_notebook_left : debug_notebook_right), page_num); id = tabs_get_tab_id(page); new_tabs[page_num] = id; if (!is_tabbed) config_part = CP_OT_TABS; else if (is_left) config_part = CP_TT_LTABS; else config_part = CP_TT_RTABS; array[0] = length + 1; memcpy(array + 1, new_tabs, length + 1); config_set_panel(config_part, array, 0); g_free(tabs); g_free(array); } /* * page reordered event handler */ static void on_page_reordered(GtkNotebook *notebook, GtkWidget *child, guint page_num, gpointer user_data) { gboolean is_left = (GTK_NOTEBOOK(debug_notebook_left) == notebook); gboolean is_tabbed = config_get_tabbed(); int *tabs = NULL; gsize length; gsize prev_index, min, max; GtkWidget *page; tab_id id; int i; int config_part_tabs; int config_part_selected_index; int *array; if (!is_tabbed) tabs = config_get_tabs(&length); else if (is_left) tabs = config_get_left_tabs(&length); else tabs = config_get_right_tabs(&length); page = gtk_notebook_get_nth_page(GTK_NOTEBOOK(is_left ? debug_notebook_left : debug_notebook_right), page_num); id = tabs_get_tab_id(page); for (prev_index = 0; prev_index < length; prev_index++) { if (id == tabs[prev_index]) { break; } } min = MIN(prev_index, page_num); max = MAX(prev_index, page_num); for (i = min; i < max; i++) { int tmp = tabs[i]; tabs[i] = tabs[i + 1]; tabs[i + 1] = tmp; } if (!is_tabbed) { config_part_tabs = CP_OT_TABS; config_part_selected_index = CP_OT_SELECTED; } else if (is_left) { config_part_tabs = CP_TT_LTABS; config_part_selected_index = CP_TT_LSELECTED; } else { config_part_tabs = CP_TT_RTABS; config_part_selected_index = CP_TT_RSELECTED; } array = g_malloc((length + 1) * sizeof(int)); array[0] = length; memcpy(array + 1, tabs, length * sizeof(int)); config_set_panel( config_part_tabs, array, config_part_selected_index, &page_num, 0 ); g_free(tabs); g_free(array); } /* * page removed event handler */ static void on_page_removed(GtkNotebook *notebook, GtkWidget *child, guint page_num, gpointer user_data) { gboolean is_left = (GTK_NOTEBOOK(debug_notebook_left) == notebook); gboolean is_tabbed = config_get_tabbed(); int *tabs = NULL; gsize length; int config_part; if (!is_tabbed) tabs = config_get_tabs(&length); else if (is_left) tabs = config_get_left_tabs(&length); else tabs = config_get_right_tabs(&length); memmove(tabs + page_num, tabs + page_num + 1, (length - page_num - 1) * sizeof(int)); memmove(tabs + 1, tabs, (length - 1) * sizeof(int)); tabs[0] = length - 1; if (!is_tabbed) config_part = CP_OT_TABS; else if (is_left) config_part = CP_TT_LTABS; else config_part = CP_TT_RTABS; config_set_panel(config_part, tabs, 0); g_free(tabs); } /* * active page changed event handler */ static gboolean on_change_current_page(GtkNotebook *notebook, gpointer arg1, guint arg2, gpointer user_data) { gboolean is_left = (GTK_NOTEBOOK(debug_notebook_left) == notebook); gboolean is_tabbed = config_get_tabbed(); int config_part; if (!is_tabbed) config_part = CP_OT_SELECTED; else if (is_left) config_part = CP_TT_LSELECTED; else config_part = CP_TT_RSELECTED; config_set_panel(config_part, (gpointer)&arg2, 0); return TRUE; } /* * create GUI and check config */ void dpaned_init(void) { /* create paned */ hpaned = gtk_hpaned_new(); /* create notebooks */ debug_notebook_left = gtk_notebook_new(); debug_notebook_right = gtk_notebook_new(); /* setup notebooks */ gtk_notebook_set_scrollable(GTK_NOTEBOOK(debug_notebook_left), TRUE); gtk_notebook_set_scrollable(GTK_NOTEBOOK(debug_notebook_right), TRUE); gtk_notebook_set_group_name(GTK_NOTEBOOK(debug_notebook_left), NOTEBOOK_GROUP); gtk_notebook_set_group_name(GTK_NOTEBOOK(debug_notebook_right), NOTEBOOK_GROUP); gtk_notebook_set_tab_pos(GTK_NOTEBOOK(debug_notebook_left), GTK_POS_TOP); gtk_notebook_set_tab_pos(GTK_NOTEBOOK(debug_notebook_right), GTK_POS_TOP); /* add notebooks */ gtk_paned_add1(GTK_PANED(hpaned), debug_notebook_left); gtk_paned_add2(GTK_PANED(hpaned), debug_notebook_right); if (config_get_tabbed()) { gsize length; int *tab_ids, i; /* left */ tab_ids = config_get_left_tabs(&length); for (i = 0; i < length; i++) { GtkWidget *tab = tabs_get_tab((tab_id)tab_ids[i]); gtk_notebook_append_page(GTK_NOTEBOOK(debug_notebook_left), tab, gtk_label_new(tabs_get_label(tab_ids[i]))); gtk_notebook_set_tab_detachable(GTK_NOTEBOOK(debug_notebook_left), tab, TRUE); gtk_notebook_set_tab_reorderable(GTK_NOTEBOOK(debug_notebook_left), tab, TRUE); } g_free(tab_ids); /* right */ tab_ids = config_get_right_tabs(&length); for (i = 0; i < length; i++) { GtkWidget *tab = tabs_get_tab((tab_id)tab_ids[i]); gtk_notebook_append_page(GTK_NOTEBOOK(debug_notebook_right), tab, gtk_label_new(tabs_get_label(tab_ids[i]))); gtk_notebook_set_tab_detachable(GTK_NOTEBOOK(debug_notebook_right), tab, TRUE); gtk_notebook_set_tab_reorderable(GTK_NOTEBOOK(debug_notebook_right), tab, TRUE); } g_free(tab_ids); gtk_widget_show_all(hpaned); gtk_notebook_set_current_page(GTK_NOTEBOOK(debug_notebook_left), config_get_left_selected_tab_index()); gtk_notebook_set_current_page(GTK_NOTEBOOK(debug_notebook_right),config_get_right_selected_tab_index()); } else { gsize i, length; int *tab_ids; g_object_ref(debug_notebook_right); gtk_container_remove(GTK_CONTAINER(hpaned), debug_notebook_right); tab_ids = config_get_tabs(&length); for (i = 0; i < length; i++) { GtkWidget *tab = tabs_get_tab((tab_id)tab_ids[i]); gtk_notebook_append_page(GTK_NOTEBOOK(debug_notebook_left), tab, gtk_label_new(tabs_get_label(tab_ids[i]))); gtk_notebook_set_tab_detachable(GTK_NOTEBOOK(debug_notebook_left), tab, TRUE); gtk_notebook_set_tab_reorderable(GTK_NOTEBOOK(debug_notebook_left), tab, TRUE); } g_free(tab_ids); gtk_widget_show_all(hpaned); gtk_notebook_set_current_page(GTK_NOTEBOOK(debug_notebook_left), config_get_selected_tab_index()); } CONNECT_PAGE_SIGNALS(); CONNECT_ALLOCATED_PAGE_SIGNALS(); } /* * free local data, disconnect signals */ void dpaned_destroy(void) { DISCONNECT_PAGE_SIGNALS(); } /* * gets widget */ GtkWidget* dpaned_get_paned(void) { return hpaned; } /* * sets tabs mode */ void dpaned_set_tabbed(gboolean tabbed) { DISCONNECT_PAGE_SIGNALS(); if (!tabbed) { gsize length; int *tab_ids; int i; g_object_ref(debug_notebook_right); gtk_container_remove(GTK_CONTAINER(hpaned), debug_notebook_right); tab_ids = config_get_tabs(&length); for (i = 0; i < length; i++) { GtkWidget *tab = tabs_get_tab((tab_id)tab_ids[i]); if (-1 == gtk_notebook_page_num(GTK_NOTEBOOK(debug_notebook_left), tab)) { g_object_ref(tab); gtk_container_remove(GTK_CONTAINER(debug_notebook_right), tab); gtk_notebook_insert_page(GTK_NOTEBOOK(debug_notebook_left), tab, gtk_label_new(tabs_get_label(tab_ids[i])), i); g_object_unref(tab); gtk_notebook_set_tab_detachable(GTK_NOTEBOOK(debug_notebook_left), tab, TRUE); gtk_notebook_set_tab_reorderable(GTK_NOTEBOOK(debug_notebook_left), tab, TRUE); } } g_free(tab_ids); gtk_notebook_set_current_page(GTK_NOTEBOOK(debug_notebook_left), config_get_selected_tab_index()); gtk_widget_show_all(hpaned); } else { gsize length; int i; int *tab_ids; gtk_paned_add2(GTK_PANED(hpaned), debug_notebook_right); g_object_unref(debug_notebook_right); tab_ids = config_get_right_tabs(&length); for (i = 0; i < length; i++) { GtkWidget *tab = tabs_get_tab((tab_id)tab_ids[i]); g_object_ref(tab); gtk_container_remove(GTK_CONTAINER(debug_notebook_left), tab); gtk_notebook_insert_page(GTK_NOTEBOOK(debug_notebook_right), tab, gtk_label_new(tabs_get_label(tab_ids[i])), i); g_object_unref(tab); gtk_notebook_set_tab_detachable(GTK_NOTEBOOK(debug_notebook_right), tab, TRUE); gtk_notebook_set_tab_reorderable(GTK_NOTEBOOK(debug_notebook_right), tab, TRUE); } g_free(tab_ids); gtk_notebook_set_current_page(GTK_NOTEBOOK(debug_notebook_left), config_get_left_selected_tab_index()); gtk_notebook_set_current_page(GTK_NOTEBOOK(debug_notebook_right), config_get_right_selected_tab_index()); gtk_widget_show_all(hpaned); } CONNECT_PAGE_SIGNALS(); config_set_panel(CP_TABBED_MODE, (gpointer)&tabbed, 0); }