From: compudj Date: Sat, 27 Sep 2003 14:10:17 +0000 (+0000) Subject: control flow .c move X-Git-Tag: v0.12.20~3227 X-Git-Url: https://git.lttng.org./?a=commitdiff_plain;h=3ebbe6bd449c83f8c95ba0ad46a8e19873f2571b;p=lttv.git control flow .c move git-svn-id: http://ltt.polymtl.ca/svn@262 04897980-b3bd-0310-b5e0-8ef037075253 --- diff --git a/ltt/branches/poly/lttv/modules/guiControlFlow.c b/ltt/branches/poly/lttv/modules/guiControlFlow.c deleted file mode 100644 index fb623330..00000000 --- a/ltt/branches/poly/lttv/modules/guiControlFlow.c +++ /dev/null @@ -1,773 +0,0 @@ -/*! \defgroup guiEvents libguiControlFlow: The GUI ControlFlow display plugin */ -/*\@{*/ - -/*! \file guiControlFlow.c - * \brief Graphical plugin for showing control flow of a trace. - * - * This plugin adds a Control Flow Viewer functionnality to Linux TraceToolkit - * GUI when this plugin is loaded. The init and destroy functions add the - * viewer's insertion menu item and toolbar icon by calling gtkTraceSet's - * API functions. Then, when a viewer's object is created, the constructor - * creates ans register through API functions what is needed to interact - * with the TraceSet window. - * - * This plugin uses the gdk library to draw the events and gtk to interact - * with the user. - * - * Author : Mathieu Desnoyers, June 2003 - */ - -#include -#include -#include -#include - -#include -#include - -//#include "guiControlFlow.h" -#include "icons/hGuiControlFlowInsert.xpm" - -#include "gtktreeprivate.h" - -//FIXME by including ltt.h -#include -typedef time_t ltt_time; - -typedef struct _ltt_time_interval -{ - ltt_time time_begin, time_end; -} ltt_time_interval; - - -/***************************************************************************** - * Definition of structures * - *****************************************************************************/ - -typedef struct _DrawingAreaInfo { - - guint height, width; - -} DrawingAreaInfo ; - -typedef struct _ControlFlowData { - - GtkWidget *Drawing_Area_V; - GtkWidget *Scrolled_Window_VC; - - GtkWidget *Process_List_VC; - - /* Model containing list data */ - GtkListStore *Store_M; - - GtkWidget *HBox_V; - GtkWidget *Inside_HBox_V; - - GtkAdjustment *VAdjust_C ; - - /* Trace information */ - TraceSet *Trace_Set; - TraceStatistics *Trace_Statistics; - - /* Shown events information */ - guint First_Event, Last_Event; - ltt_time Begin_Time, End_Time; - - - /* Drawing Area Info */ - DrawingAreaInfo Drawing_Area_Info; - - /* TEST DATA, TO BE READ FROM THE TRACE */ - gint Number_Of_Events ; - guint Currently_Selected_Event ; - gboolean Selected_Event ; - guint Number_Of_Process; - -} ControlFlowData ; - -/* Structure used to store and use information relative to one events refresh - * request. Typically filled in by the expose event callback, then passed to the - * library call, then used by the drawing hooks. Then, once all the events are - * sent, it is freed by the hook called after the reading. - */ -typedef struct _EventRequest -{ - ControlFlowData *Control_Flow_Data; - ltt_time time_begin, time_end; - /* Fill the Events_Context during the initial expose, before calling for - * events. - */ - GArray Events_Context; //FIXME -} EventRequest ; - - -/** Array containing instanced objects. Used when module is unloaded */ -static GSList *sControl_Flow_Data_List = NULL ; - - -/***************************************************************************** - * Function prototypes * - *****************************************************************************/ -//! Control Flow Viewer's constructor hook -GtkWidget *hGuiControlFlow(GtkWidget *pmParentWindow); -//! Control Flow Viewer's constructor -ControlFlowData *GuiControlFlow(void); -//! Control Flow Viewer's destructor -void GuiControlFlow_Destructor(ControlFlowData *Control_Flow_Data); - - -static int Event_Selected_Hook(void *hook_data, void *call_data); - -static lttv_hooks - *Draw_Before_Hooks, - *Draw_Event_Hooks, - *Draw_After_Hooks; - -Draw_Before_Hook(void *hook_data, void *call_data) -Draw_Event_Hook(void *hook_data, void *call_data) -Draw_After_Hook(void *hook_data, void *call_data) - - -//void Tree_V_set_cursor(ControlFlowData *Control_Flow_Data); -//void Tree_V_get_cursor(ControlFlowData *Control_Flow_Data); - -/* Prototype for selection handler callback */ -//static void tree_selection_changed_cb (GtkTreeSelection *selection, gpointer data); -static void v_scroll_cb (GtkAdjustment *adjustment, gpointer data); -//static void Tree_V_size_allocate_cb (GtkWidget *widget, GtkAllocation *alloc, gpointer data); -//static void Tree_V_size_request_cb (GtkWidget *widget, GtkRequisition *requisition, gpointer data); -//static void Tree_V_cursor_changed_cb (GtkWidget *widget, gpointer data); -//static void Tree_V_move_cursor_cb (GtkWidget *widget, GtkMovementStep arg1, gint arg2, gpointer data); - -static void expose_event_cb (GtkWidget *widget, GdkEventExpose *expose, gpointer data); - -void add_test_process(ControlFlowData *Control_Flow_Data); - -static void get_test_data(guint Event_Number, guint List_Height, - ControlFlowData *Control_Flow_Data); - -void add_test_data(ControlFlowData *Control_Flow_Data); -void test_draw(ControlFlowData *Control_Flow_Data); - -void Drawing_Area_Init(ControlFlowData *Control_Flow_Data); - - - -/***************************************************************************** - * Functions for module loading/unloading * - *****************************************************************************/ -/** - * plugin's init function - * - * This function initializes the Control Flow Viewer functionnality through the - * gtkTraceSet API. - */ -G_MODULE_EXPORT void init() { - g_critical("GUI ControlFlow Viewer init()"); - - /* Register the toolbar insert button */ - //ToolbarItemReg(guiEventsInsert_xpm, "Insert Control Flow Viewer", guiEvent); - - /* Register the menu item insert entry */ - //MenuItemReg("/", "Insert Control Flow Viewer", guiEvent); - - /* Setup the hooks */ - Draw_Before_Hooks = lttv_hooks_new(); - Draw_Event_Hooks = lttv_hooks_new(); - Draw_After_Hooks = lttv_hooks_new(); - - lttv_hooks_add(Draw_Before_Hooks, Draw_Before_Hook, NULL); - lttv_hooks_add(Draw_Event_Hooks, Draw_Event_Hook, NULL); - lttv_hooks_add(Draw_After_Hooks, Draw_After_Hook, NULL); - -} - -void destroy_walk(gpointer data, gpointer user_data) -{ - GuiControlFlow_Destructor((ControlFlowData*)data); -} - - - -/** - * plugin's destroy function - * - * This function releases the memory reserved by the module and unregisters - * everything that has been registered in the gtkTraceSet API. - */ -G_MODULE_EXPORT void destroy() { - g_critical("GUI Control Flow Viewer destroy()"); - int i; - - ControlFlowData *Control_Flow_Data; - - g_critical("GUI Event Viewer destroy()"); - - g_slist_foreach(sControl_Flow_Data_List, destroy_walk, NULL ); - - lttv_hooks_destroy(Draw_Before_Hooks); - lttv_hooks_destroy(Draw_Event_Hooks); - lttv_hooks_destroy(Draw_After_Hooks); - - /* Unregister the toolbar insert button */ - //ToolbarItemUnreg(hGuiEvents); - - /* Unregister the menu item insert entry */ - //MenuItemUnreg(hGuiEvents); -} - - -/***************************************************************************** - * Control Flow Viewer class implementation * - *****************************************************************************/ - - -/* Enumeration of the columns */ -enum -{ - PROCESS_COLUMN, - N_COLUMNS -}; - - - -/** - * Control Flow Viewer's constructor - * - * This constructor is given as a parameter to the menuitem and toolbar button - * registration. It creates the drawing widget. - * @param ParentWindow A pointer to the parent window. - * @return The widget created. - */ -ControlFlowData * -GuiControlFlow(void) -{ - - GtkTreeViewColumn *column; - GtkCellRenderer *renderer; - - ControlFlowData* Control_Flow_Data = g_new(ControlFlowData,1) ; - Control_Flow_Data->Drawing_Area_V = gtk_drawing_area_new (); - - - /* TEST DATA, TO BE READ FROM THE TRACE */ - Control_Flow_Data->Number_Of_Events = 1000 ; - Control_Flow_Data->Currently_Selected_Event = FALSE ; - Control_Flow_Data->Selected_Event = 0; - Control_Flow_Data->Number_Of_Process = 10; - - /* FIXME register Event_Selected_Hook */ - - - - /* Create the Process list */ - Control_Flow_Data->Store_M = gtk_list_store_new ( N_COLUMNS, - G_TYPE_STRING); - - - Control_Flow_Data->Process_List_VC = gtk_tree_view_new_with_model (GTK_TREE_MODEL (Control_Flow_Data->Store_M)); - - g_object_unref (G_OBJECT (Control_Flow_Data->Store_M)); - - gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(Control_Flow_Data->Process_List_VC), FALSE); - - /* Create a column, associating the "text" attribute of the - * cell_renderer to the first column of the model */ - /* Columns alignment : 0.0 : Left 0.5 : Center 1.0 : Right */ - renderer = gtk_cell_renderer_text_new (); - column = gtk_tree_view_column_new_with_attributes ("Process", - renderer, - "text", PROCESS_COLUMN, - NULL); - gtk_tree_view_column_set_alignment (column, 0.0); - gtk_tree_view_column_set_fixed_width (column, 45); - gtk_tree_view_append_column (GTK_TREE_VIEW (Control_Flow_Data->Process_List_VC), column); - - - - Control_Flow_Data->Inside_HBox_V = gtk_hbox_new(0, 0); - - gtk_box_pack_start(GTK_BOX(Control_Flow_Data->Inside_HBox_V), Control_Flow_Data->Process_List_VC, FALSE, TRUE, 0); - gtk_box_pack_start(GTK_BOX(Control_Flow_Data->Inside_HBox_V), Control_Flow_Data->Drawing_Area_V, TRUE, TRUE, 0); - - - Control_Flow_Data->VAdjust_C = GTK_ADJUSTMENT(gtk_adjustment_new(0.0, /* Value */ - 0.0, /* Lower */ - 0.0, /* Upper */ - 0.0, /* Step inc. */ - 0.0, /* Page inc. */ - 0.0 )); /* page size */ - - - Control_Flow_Data->Scrolled_Window_VC = gtk_scrolled_window_new (NULL, - Control_Flow_Data->VAdjust_C); - gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW(Control_Flow_Data->Scrolled_Window_VC) , - GTK_POLICY_NEVER, - GTK_POLICY_AUTOMATIC); - - gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(Control_Flow_Data->Scrolled_Window_VC), - Control_Flow_Data->Inside_HBox_V); - - - g_signal_connect (G_OBJECT (Control_Flow_Data->Drawing_Area_V), "expose_event", - G_CALLBACK (expose_event_cb), Control_Flow_Data); - - - - g_signal_connect (G_OBJECT (Control_Flow_Data->VAdjust_C), "value-changed", - G_CALLBACK (v_scroll_cb), - Control_Flow_Data); - - add_test_process(Control_Flow_Data); - - - - /* Set the size of the drawing area */ - Drawing_Area_Init(Control_Flow_Data); - - /* Get trace statistics */ - Control_Flow_Data->Trace_Statistics = get_trace_statistics(Trace); - - - gtk_widget_show(Control_Flow_Data->Drawing_Area_V); - gtk_widget_show(Control_Flow_Data->Process_List_VC); - gtk_widget_show(Control_Flow_Data->Inside_HBox_V); - gtk_widget_show(Control_Flow_Data->Scrolled_Window_VC); - - test_draw(Control_Flow_Data); - - return Control_Flow_Data; - -} - -void -GuiControlFlow_Destructor(ControlFlowData *Control_Flow_Data) -{ - guint index; - - /* May already been done by GTK window closing */ - if(GTK_IS_WIDGET(Control_Flow_Data->HBox_V)) - gtk_widget_destroy(Control_Flow_Data->HBox_V); - - /* Destroy the Tree View */ - //gtk_widget_destroy(Control_Flow_Data->Tree_V); - - /* Clear raw event list */ - //gtk_list_store_clear(Control_Flow_Data->Store_M); - //gtk_widget_destroy(GTK_WIDGET(Control_Flow_Data->Store_M)); - - g_slist_remove(sControl_Flow_Data_List,Control_Flow_Data); -} - -//FIXME : call hGuiEvents_Destructor for corresponding data upon widget destroy - - - -/***************************************************************************** - * Drawing functions * - *****************************************************************************/ - -typedef enum -{ - RED, - GREEN, - BLUE, - WHITE, - BLACK - -} ControlFlowColors; - -/* Vector of unallocated colors */ -static GdkColor CF_Colors [] = -{ - { 0, 0xffff, 0x0000, 0x0000 }, // RED - { 0, 0x0000, 0xffff, 0x0000 }, // GREEN - { 0, 0x0000, 0x0000, 0xffff }, // BLUE - { 0, 0xffff, 0xffff, 0xffff }, // WHITE - { 0, 0x0000, 0x0000, 0x0000 } // BLACK -}; - - -gint get_cell_height(GtkTreeView *TreeView) -{ - gint height, width; - GtkTreeViewColumn *Column = gtk_tree_view_get_column(TreeView, 0); - GList *Render_List = gtk_tree_view_column_get_cell_renderers(Column); - GtkCellRenderer *Renderer = g_list_first(Render_List)->data; - - gtk_tree_view_column_cell_get_size(Column, NULL, NULL, NULL, NULL, &height); - g_critical("cell 0 height : %u",height); - - return height; -} - - -/* get_time_from_pixels - * - * Get the time interval from window time and pixels, and pixels requested. This - * function uses TimeMul, which should only be used if the float value is lower - * that 4, and here it's always lower than 1, so it's ok. - */ -void get_time_from_pixels(guint area_x, guint area_width, - guint window_width, - ltt_time &window_time_begin, ltt_time &window_time_end, - ltt_time &time_begin, ltt_time &time_end) -{ - ltt_time window_time_interval; - - TimeSub(window_time_interval, window_time_end, window_time_begin); - - - TimeMul(time_begin, window_time_interval, (area_x/(float)window_width)); - TimeAdd(time_begin, window_time_begin, time_begin); - - TimeMul(time_end, window_time_interval, (area_width/(float)window_width)); - TimeAdd(time_end, time_begin, time_end); - -} - -void Drawing_Area_Init(ControlFlowData *Control_Flow_Data) -{ - DrawingAreaInfo *Drawing_Area_Info = &Control_Flow_Data->Drawing_Area_Info; - guint w; - - w = 500; - - - Drawing_Area_Info->height = - get_cell_height(GTK_TREE_VIEW(Control_Flow_Data->Process_List_VC)) - * Control_Flow_Data->Number_Of_Process ; - - gtk_widget_modify_bg(Control_Flow_Data->Drawing_Area_V, - GTK_STATE_NORMAL, - &CF_Colors[BLACK]); - - - gtk_widget_set_size_request (Control_Flow_Data->Drawing_Area_V, - w, - Drawing_Area_Info->height); - - -} - - - -void add_test_process(ControlFlowData *Control_Flow_Data) -{ - GtkTreeIter iter; - int i; - gchar *process[] = { "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten" }; - - for(i=0; iNumber_Of_Process; i++) - { - /* Add a new row to the model */ - gtk_list_store_append (Control_Flow_Data->Store_M, &iter); - gtk_list_store_set (Control_Flow_Data->Store_M, &iter, - PROCESS_COLUMN, process[i], - -1); - } - -} - - - -void test_draw(ControlFlowData *Control_Flow_Data) -{ - /* Draw event states using available height, Number of process, cell height - * (don't forget to remove two pixels at beginning and end). - * For horizontal : use width, Time_Begin, Time_End. - * This function calls the reading library to get the draw_hook called - * for the desired period of time. */ - - DrawingAreaInfo *Drawing_Area_Info = &Control_Flow_Data->Drawing_Area_Info; - - -} - - -/***************************************************************************** - * Hooks to be called by the main window * - *****************************************************************************/ -/** - * Event Viewer's constructor hook - * - * This constructor is given as a parameter to the menuitem and toolbar button - * registration. It creates the list. - * @param pmParentWindow A pointer to the parent window. - * @return The widget created. - */ -GtkWidget * -hGuiControlFlow(GtkWidget *pmParentWindow) -{ - ControlFlowData* Control_Flow_Data = GuiControlFlow() ; - - return Control_Flow_Data->HBox_V ; - -} - -int Event_Selected_Hook(void *hook_data, void *call_data) -{ - ControlFlowData *Control_Flow_Data = (ControlFlowData*) hook_data; - guint *Event_Number = (guint*) call_data; - - g_critical("DEBUG : event selected by main window : %u", *Event_Number); - -// Control_Flow_Data->Currently_Selected_Event = *Event_Number; -// Control_Flow_Data->Selected_Event = TRUE ; - -// Tree_V_set_cursor(Control_Flow_Data); - -} - - -/* Hook called before drawing. Gets the initial context at the beginning of the - * drawing interval and copy it to the context in Event_Request. - */ -Draw_Before_Hook(void *hook_data, void *call_data) -{ - EventRequest *Event_Request = (EventRequest*)hook_data; - EventsContext Events_Context = (EventsContext*)call_data; - - Event_Request->Events_Context = Events_Context; -} - -/* - * The draw event hook is called by the reading API to have a - * particular event drawn on the screen. - * @param hook_data ControlFlowData structure of the viewer. - * @param call_data Event context. - * - * This function basically draw lines and icons. Two types of lines are drawn : - * one small (3 pixels?) representing the state of the process and the second - * type is thicker (10 pixels?) representing on which CPU a process is running - * (and this only in running state). - * - * Extremums of the lines : - * x_min : time of the last event context for this process kept in memory. - * x_max : time of the current event. - * y : middle of the process in the process list. The process is found in the - * list, therefore is it's position in pixels. - * - * The choice of lines'color is defined by the context of the last event for this - * process. - */ -Draw_Event_Hook(void *hook_data, void *call_data) -{ - EventRequest *Event_Request = (EventRequest*)hook_data; - -} - - -Draw_After_Hook(void *hook_data, void *call_data) -{ - EventRequest *Event_Request = (EventRequest*)hook_data; - - g_free(Event_Request); -} - -/***************************************************************************** - * Callbacks used for the viewer * - *****************************************************************************/ -void expose_event_cb (GtkWidget *widget, GdkEventExpose *expose, gpointer data) -{ - ControlFlowData *Control_Flow_Data = (ControlFlowData*)data; - - EventRequest *Event_Request = g_new(sizeof(EventRequest)); - - Event_Request->Control_Flow_Data = Control_Flow_Data; - - /* Calculate, from pixels in expose, the time interval to get data */ - - get_time_from_pixels(expose->area.x, expose->area.width, - Control_Flow_Data->Drawing_Area_Info.width, - &Control_Flow_Data->Begin_Time, &Control_Flow_Data->End_Time, - &Event_Request->time_begin, &Event_Request->time_end) - - /* Look in statistics of the trace the processes present during the - * whole time interval _shown on the screen_. Modify the list of - * processes to match it. NOTE : modify, not recreate. If recreation is - * needed,keep a pointer to the currently selected event in the list. - */ - - /* Call the reading API to have events sent to drawing hooks */ - lttv_trace_set_process( Control_Flow_Data->Trace_Set, - Draw_Before_Hooks, - Draw_Event_Hooks, - Draw_After_Hooks, - NULL, //FIXME : filter here - Event_Request->time_begin, - Event_Request->time_end); - -} - -#ifdef DEBUG -void test_draw() { - gint cell_height = get_cell_height(GTK_TREE_VIEW(Control_Flow_Data->Process_List_VC)); - GdkGC *GC = gdk_gc_new(widget->window); - GdkColor color = CF_Colors[GREEN]; - - gdk_color_alloc (gdk_colormap_get_system () , &color); - - g_critical("expose"); - - /* When redrawing, use widget->allocation.width to get the width of - * drawable area. */ - Control_Flow_Data->Drawing_Area_Info.width = widget->allocation.width; - - test_draw(Control_Flow_Data); - - gdk_gc_copy(GC,widget->style->white_gc); - gdk_gc_set_foreground(GC,&color); - - //gdk_draw_arc (widget->window, - // widget->style->fg_gc[GTK_WIDGET_STATE (widget)], - // TRUE, - // //0, 0, widget->allocation.width, widget->allocation.height, - // 0, 0, widget->allocation.width, - // Control_Flow_Data->Drawing_Area_Info.height, - // 0, 64 * 360); - - - //Drawing_Area_Init(Control_Flow_Data); - - // 2 pixels for the box around the drawing area, 1 pixel for off-by-one - // (starting from 0) - //gdk_gc_copy (&GC, widget->style->fg_gc[GTK_WIDGET_STATE (widget)]); - - gdk_gc_set_line_attributes(GC,12, GDK_LINE_SOLID, GDK_CAP_NOT_LAST,GDK_JOIN_MITER); - - gdk_draw_line (widget->window, - GC, - 0, (cell_height-1)/2, - widget->allocation.width, (cell_height-1)/2); - - color = CF_Colors[BLUE]; - - gdk_color_alloc (gdk_colormap_get_system () , &color); - - gdk_gc_set_foreground(GC,&color); - - - gdk_gc_set_line_attributes(GC,3, GDK_LINE_SOLID, GDK_CAP_NOT_LAST,GDK_JOIN_MITER); - - gdk_draw_line (widget->window, - GC, - 0, (cell_height-1)/2, - widget->allocation.width,(cell_height-1)/2); - - - - - - - g_object_unref(GC); - - //gdk_colormap_alloc_colors(gdk_colormap_get_system(), TRUE, - - //gdk_gc_set_line_attributes(GC,5, GDK_LINE_SOLID, GDK_CAP_NOT_LAST,GDK_JOIN_MITER); - //gdk_gc_set_foreground(GC, - - //gdk_draw_line (widget->window, - // GC, - // 0, (2*cell_height)-2-1, - // 50, (2*cell_height)-2-1); - -} -#endif //DEBUG - -void v_scroll_cb (GtkAdjustment *adjustment, gpointer data) -{ - ControlFlowData *Control_Flow_Data = (ControlFlowData*)data; - GtkTreePath *Tree_Path; - - g_critical("DEBUG : scroll signal, value : %f", adjustment->value); - - //get_test_data((int)adjustment->value, Control_Flow_Data->Num_Visible_Events, - // Control_Flow_Data); - - - -} - - - - - - -static void destroy_cb( GtkWidget *widget, - gpointer data ) -{ - gtk_main_quit (); -} - - - -/***************************************************************************** - * test routines * - *****************************************************************************/ - - -int main(int argc, char **argv) -{ - GtkWidget *Window; - GtkWidget *CF_Viewer; - GtkWidget *VBox_V; - GtkWidget *HScroll_VC; - ControlFlowData *Control_Flow_Data; - guint ev_sel = 444 ; - /* Horizontal scrollbar and it's adjustment */ - GtkWidget *VScroll_VC; - GtkAdjustment *VAdjust_C ; - - /* Initialize i18n support */ - gtk_set_locale (); - - /* Initialize the widget set */ - gtk_init (&argc, &argv); - - init(); - - Window = gtk_window_new (GTK_WINDOW_TOPLEVEL); - gtk_window_set_title (GTK_WINDOW (Window), ("Test Window")); - - g_signal_connect (G_OBJECT (Window), "destroy", - G_CALLBACK (destroy_cb), NULL); - - - VBox_V = gtk_vbox_new(0, 0); - gtk_container_add (GTK_CONTAINER (Window), VBox_V); - - //ListViewer = hGuiEvents(Window); - //gtk_box_pack_start(GTK_BOX(VBox_V), ListViewer, TRUE, TRUE, 0); - - //ListViewer = hGuiEvents(Window); - //gtk_box_pack_start(GTK_BOX(VBox_V), ListViewer, FALSE, TRUE, 0); - - Control_Flow_Data = GuiControlFlow(); - CF_Viewer = Control_Flow_Data->Scrolled_Window_VC; - gtk_box_pack_start(GTK_BOX(VBox_V), CF_Viewer, TRUE, TRUE, 0); - - /* Create horizontal scrollbar and pack it */ - HScroll_VC = gtk_hscrollbar_new(NULL); - gtk_box_pack_start(GTK_BOX(VBox_V), HScroll_VC, FALSE, TRUE, 0); - - - gtk_widget_show (HScroll_VC); - gtk_widget_show (VBox_V); - gtk_widget_show (Window); - - //Event_Selected_Hook(Control_Flow_Data, &ev_sel); - - gtk_main (); - - g_critical("main loop finished"); - - //hGuiEvents_Destructor(ListViewer); - - //g_critical("GuiEvents Destructor finished"); - destroy(); - - return 0; -} - -/*\@}*/ diff --git a/ltt/branches/poly/lttv/modules/guiControlFlow/guiControlFlow.c b/ltt/branches/poly/lttv/modules/guiControlFlow/guiControlFlow.c new file mode 100644 index 00000000..fb623330 --- /dev/null +++ b/ltt/branches/poly/lttv/modules/guiControlFlow/guiControlFlow.c @@ -0,0 +1,773 @@ +/*! \defgroup guiEvents libguiControlFlow: The GUI ControlFlow display plugin */ +/*\@{*/ + +/*! \file guiControlFlow.c + * \brief Graphical plugin for showing control flow of a trace. + * + * This plugin adds a Control Flow Viewer functionnality to Linux TraceToolkit + * GUI when this plugin is loaded. The init and destroy functions add the + * viewer's insertion menu item and toolbar icon by calling gtkTraceSet's + * API functions. Then, when a viewer's object is created, the constructor + * creates ans register through API functions what is needed to interact + * with the TraceSet window. + * + * This plugin uses the gdk library to draw the events and gtk to interact + * with the user. + * + * Author : Mathieu Desnoyers, June 2003 + */ + +#include +#include +#include +#include + +#include +#include + +//#include "guiControlFlow.h" +#include "icons/hGuiControlFlowInsert.xpm" + +#include "gtktreeprivate.h" + +//FIXME by including ltt.h +#include +typedef time_t ltt_time; + +typedef struct _ltt_time_interval +{ + ltt_time time_begin, time_end; +} ltt_time_interval; + + +/***************************************************************************** + * Definition of structures * + *****************************************************************************/ + +typedef struct _DrawingAreaInfo { + + guint height, width; + +} DrawingAreaInfo ; + +typedef struct _ControlFlowData { + + GtkWidget *Drawing_Area_V; + GtkWidget *Scrolled_Window_VC; + + GtkWidget *Process_List_VC; + + /* Model containing list data */ + GtkListStore *Store_M; + + GtkWidget *HBox_V; + GtkWidget *Inside_HBox_V; + + GtkAdjustment *VAdjust_C ; + + /* Trace information */ + TraceSet *Trace_Set; + TraceStatistics *Trace_Statistics; + + /* Shown events information */ + guint First_Event, Last_Event; + ltt_time Begin_Time, End_Time; + + + /* Drawing Area Info */ + DrawingAreaInfo Drawing_Area_Info; + + /* TEST DATA, TO BE READ FROM THE TRACE */ + gint Number_Of_Events ; + guint Currently_Selected_Event ; + gboolean Selected_Event ; + guint Number_Of_Process; + +} ControlFlowData ; + +/* Structure used to store and use information relative to one events refresh + * request. Typically filled in by the expose event callback, then passed to the + * library call, then used by the drawing hooks. Then, once all the events are + * sent, it is freed by the hook called after the reading. + */ +typedef struct _EventRequest +{ + ControlFlowData *Control_Flow_Data; + ltt_time time_begin, time_end; + /* Fill the Events_Context during the initial expose, before calling for + * events. + */ + GArray Events_Context; //FIXME +} EventRequest ; + + +/** Array containing instanced objects. Used when module is unloaded */ +static GSList *sControl_Flow_Data_List = NULL ; + + +/***************************************************************************** + * Function prototypes * + *****************************************************************************/ +//! Control Flow Viewer's constructor hook +GtkWidget *hGuiControlFlow(GtkWidget *pmParentWindow); +//! Control Flow Viewer's constructor +ControlFlowData *GuiControlFlow(void); +//! Control Flow Viewer's destructor +void GuiControlFlow_Destructor(ControlFlowData *Control_Flow_Data); + + +static int Event_Selected_Hook(void *hook_data, void *call_data); + +static lttv_hooks + *Draw_Before_Hooks, + *Draw_Event_Hooks, + *Draw_After_Hooks; + +Draw_Before_Hook(void *hook_data, void *call_data) +Draw_Event_Hook(void *hook_data, void *call_data) +Draw_After_Hook(void *hook_data, void *call_data) + + +//void Tree_V_set_cursor(ControlFlowData *Control_Flow_Data); +//void Tree_V_get_cursor(ControlFlowData *Control_Flow_Data); + +/* Prototype for selection handler callback */ +//static void tree_selection_changed_cb (GtkTreeSelection *selection, gpointer data); +static void v_scroll_cb (GtkAdjustment *adjustment, gpointer data); +//static void Tree_V_size_allocate_cb (GtkWidget *widget, GtkAllocation *alloc, gpointer data); +//static void Tree_V_size_request_cb (GtkWidget *widget, GtkRequisition *requisition, gpointer data); +//static void Tree_V_cursor_changed_cb (GtkWidget *widget, gpointer data); +//static void Tree_V_move_cursor_cb (GtkWidget *widget, GtkMovementStep arg1, gint arg2, gpointer data); + +static void expose_event_cb (GtkWidget *widget, GdkEventExpose *expose, gpointer data); + +void add_test_process(ControlFlowData *Control_Flow_Data); + +static void get_test_data(guint Event_Number, guint List_Height, + ControlFlowData *Control_Flow_Data); + +void add_test_data(ControlFlowData *Control_Flow_Data); +void test_draw(ControlFlowData *Control_Flow_Data); + +void Drawing_Area_Init(ControlFlowData *Control_Flow_Data); + + + +/***************************************************************************** + * Functions for module loading/unloading * + *****************************************************************************/ +/** + * plugin's init function + * + * This function initializes the Control Flow Viewer functionnality through the + * gtkTraceSet API. + */ +G_MODULE_EXPORT void init() { + g_critical("GUI ControlFlow Viewer init()"); + + /* Register the toolbar insert button */ + //ToolbarItemReg(guiEventsInsert_xpm, "Insert Control Flow Viewer", guiEvent); + + /* Register the menu item insert entry */ + //MenuItemReg("/", "Insert Control Flow Viewer", guiEvent); + + /* Setup the hooks */ + Draw_Before_Hooks = lttv_hooks_new(); + Draw_Event_Hooks = lttv_hooks_new(); + Draw_After_Hooks = lttv_hooks_new(); + + lttv_hooks_add(Draw_Before_Hooks, Draw_Before_Hook, NULL); + lttv_hooks_add(Draw_Event_Hooks, Draw_Event_Hook, NULL); + lttv_hooks_add(Draw_After_Hooks, Draw_After_Hook, NULL); + +} + +void destroy_walk(gpointer data, gpointer user_data) +{ + GuiControlFlow_Destructor((ControlFlowData*)data); +} + + + +/** + * plugin's destroy function + * + * This function releases the memory reserved by the module and unregisters + * everything that has been registered in the gtkTraceSet API. + */ +G_MODULE_EXPORT void destroy() { + g_critical("GUI Control Flow Viewer destroy()"); + int i; + + ControlFlowData *Control_Flow_Data; + + g_critical("GUI Event Viewer destroy()"); + + g_slist_foreach(sControl_Flow_Data_List, destroy_walk, NULL ); + + lttv_hooks_destroy(Draw_Before_Hooks); + lttv_hooks_destroy(Draw_Event_Hooks); + lttv_hooks_destroy(Draw_After_Hooks); + + /* Unregister the toolbar insert button */ + //ToolbarItemUnreg(hGuiEvents); + + /* Unregister the menu item insert entry */ + //MenuItemUnreg(hGuiEvents); +} + + +/***************************************************************************** + * Control Flow Viewer class implementation * + *****************************************************************************/ + + +/* Enumeration of the columns */ +enum +{ + PROCESS_COLUMN, + N_COLUMNS +}; + + + +/** + * Control Flow Viewer's constructor + * + * This constructor is given as a parameter to the menuitem and toolbar button + * registration. It creates the drawing widget. + * @param ParentWindow A pointer to the parent window. + * @return The widget created. + */ +ControlFlowData * +GuiControlFlow(void) +{ + + GtkTreeViewColumn *column; + GtkCellRenderer *renderer; + + ControlFlowData* Control_Flow_Data = g_new(ControlFlowData,1) ; + Control_Flow_Data->Drawing_Area_V = gtk_drawing_area_new (); + + + /* TEST DATA, TO BE READ FROM THE TRACE */ + Control_Flow_Data->Number_Of_Events = 1000 ; + Control_Flow_Data->Currently_Selected_Event = FALSE ; + Control_Flow_Data->Selected_Event = 0; + Control_Flow_Data->Number_Of_Process = 10; + + /* FIXME register Event_Selected_Hook */ + + + + /* Create the Process list */ + Control_Flow_Data->Store_M = gtk_list_store_new ( N_COLUMNS, + G_TYPE_STRING); + + + Control_Flow_Data->Process_List_VC = gtk_tree_view_new_with_model (GTK_TREE_MODEL (Control_Flow_Data->Store_M)); + + g_object_unref (G_OBJECT (Control_Flow_Data->Store_M)); + + gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(Control_Flow_Data->Process_List_VC), FALSE); + + /* Create a column, associating the "text" attribute of the + * cell_renderer to the first column of the model */ + /* Columns alignment : 0.0 : Left 0.5 : Center 1.0 : Right */ + renderer = gtk_cell_renderer_text_new (); + column = gtk_tree_view_column_new_with_attributes ("Process", + renderer, + "text", PROCESS_COLUMN, + NULL); + gtk_tree_view_column_set_alignment (column, 0.0); + gtk_tree_view_column_set_fixed_width (column, 45); + gtk_tree_view_append_column (GTK_TREE_VIEW (Control_Flow_Data->Process_List_VC), column); + + + + Control_Flow_Data->Inside_HBox_V = gtk_hbox_new(0, 0); + + gtk_box_pack_start(GTK_BOX(Control_Flow_Data->Inside_HBox_V), Control_Flow_Data->Process_List_VC, FALSE, TRUE, 0); + gtk_box_pack_start(GTK_BOX(Control_Flow_Data->Inside_HBox_V), Control_Flow_Data->Drawing_Area_V, TRUE, TRUE, 0); + + + Control_Flow_Data->VAdjust_C = GTK_ADJUSTMENT(gtk_adjustment_new(0.0, /* Value */ + 0.0, /* Lower */ + 0.0, /* Upper */ + 0.0, /* Step inc. */ + 0.0, /* Page inc. */ + 0.0 )); /* page size */ + + + Control_Flow_Data->Scrolled_Window_VC = gtk_scrolled_window_new (NULL, + Control_Flow_Data->VAdjust_C); + gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW(Control_Flow_Data->Scrolled_Window_VC) , + GTK_POLICY_NEVER, + GTK_POLICY_AUTOMATIC); + + gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(Control_Flow_Data->Scrolled_Window_VC), + Control_Flow_Data->Inside_HBox_V); + + + g_signal_connect (G_OBJECT (Control_Flow_Data->Drawing_Area_V), "expose_event", + G_CALLBACK (expose_event_cb), Control_Flow_Data); + + + + g_signal_connect (G_OBJECT (Control_Flow_Data->VAdjust_C), "value-changed", + G_CALLBACK (v_scroll_cb), + Control_Flow_Data); + + add_test_process(Control_Flow_Data); + + + + /* Set the size of the drawing area */ + Drawing_Area_Init(Control_Flow_Data); + + /* Get trace statistics */ + Control_Flow_Data->Trace_Statistics = get_trace_statistics(Trace); + + + gtk_widget_show(Control_Flow_Data->Drawing_Area_V); + gtk_widget_show(Control_Flow_Data->Process_List_VC); + gtk_widget_show(Control_Flow_Data->Inside_HBox_V); + gtk_widget_show(Control_Flow_Data->Scrolled_Window_VC); + + test_draw(Control_Flow_Data); + + return Control_Flow_Data; + +} + +void +GuiControlFlow_Destructor(ControlFlowData *Control_Flow_Data) +{ + guint index; + + /* May already been done by GTK window closing */ + if(GTK_IS_WIDGET(Control_Flow_Data->HBox_V)) + gtk_widget_destroy(Control_Flow_Data->HBox_V); + + /* Destroy the Tree View */ + //gtk_widget_destroy(Control_Flow_Data->Tree_V); + + /* Clear raw event list */ + //gtk_list_store_clear(Control_Flow_Data->Store_M); + //gtk_widget_destroy(GTK_WIDGET(Control_Flow_Data->Store_M)); + + g_slist_remove(sControl_Flow_Data_List,Control_Flow_Data); +} + +//FIXME : call hGuiEvents_Destructor for corresponding data upon widget destroy + + + +/***************************************************************************** + * Drawing functions * + *****************************************************************************/ + +typedef enum +{ + RED, + GREEN, + BLUE, + WHITE, + BLACK + +} ControlFlowColors; + +/* Vector of unallocated colors */ +static GdkColor CF_Colors [] = +{ + { 0, 0xffff, 0x0000, 0x0000 }, // RED + { 0, 0x0000, 0xffff, 0x0000 }, // GREEN + { 0, 0x0000, 0x0000, 0xffff }, // BLUE + { 0, 0xffff, 0xffff, 0xffff }, // WHITE + { 0, 0x0000, 0x0000, 0x0000 } // BLACK +}; + + +gint get_cell_height(GtkTreeView *TreeView) +{ + gint height, width; + GtkTreeViewColumn *Column = gtk_tree_view_get_column(TreeView, 0); + GList *Render_List = gtk_tree_view_column_get_cell_renderers(Column); + GtkCellRenderer *Renderer = g_list_first(Render_List)->data; + + gtk_tree_view_column_cell_get_size(Column, NULL, NULL, NULL, NULL, &height); + g_critical("cell 0 height : %u",height); + + return height; +} + + +/* get_time_from_pixels + * + * Get the time interval from window time and pixels, and pixels requested. This + * function uses TimeMul, which should only be used if the float value is lower + * that 4, and here it's always lower than 1, so it's ok. + */ +void get_time_from_pixels(guint area_x, guint area_width, + guint window_width, + ltt_time &window_time_begin, ltt_time &window_time_end, + ltt_time &time_begin, ltt_time &time_end) +{ + ltt_time window_time_interval; + + TimeSub(window_time_interval, window_time_end, window_time_begin); + + + TimeMul(time_begin, window_time_interval, (area_x/(float)window_width)); + TimeAdd(time_begin, window_time_begin, time_begin); + + TimeMul(time_end, window_time_interval, (area_width/(float)window_width)); + TimeAdd(time_end, time_begin, time_end); + +} + +void Drawing_Area_Init(ControlFlowData *Control_Flow_Data) +{ + DrawingAreaInfo *Drawing_Area_Info = &Control_Flow_Data->Drawing_Area_Info; + guint w; + + w = 500; + + + Drawing_Area_Info->height = + get_cell_height(GTK_TREE_VIEW(Control_Flow_Data->Process_List_VC)) + * Control_Flow_Data->Number_Of_Process ; + + gtk_widget_modify_bg(Control_Flow_Data->Drawing_Area_V, + GTK_STATE_NORMAL, + &CF_Colors[BLACK]); + + + gtk_widget_set_size_request (Control_Flow_Data->Drawing_Area_V, + w, + Drawing_Area_Info->height); + + +} + + + +void add_test_process(ControlFlowData *Control_Flow_Data) +{ + GtkTreeIter iter; + int i; + gchar *process[] = { "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten" }; + + for(i=0; iNumber_Of_Process; i++) + { + /* Add a new row to the model */ + gtk_list_store_append (Control_Flow_Data->Store_M, &iter); + gtk_list_store_set (Control_Flow_Data->Store_M, &iter, + PROCESS_COLUMN, process[i], + -1); + } + +} + + + +void test_draw(ControlFlowData *Control_Flow_Data) +{ + /* Draw event states using available height, Number of process, cell height + * (don't forget to remove two pixels at beginning and end). + * For horizontal : use width, Time_Begin, Time_End. + * This function calls the reading library to get the draw_hook called + * for the desired period of time. */ + + DrawingAreaInfo *Drawing_Area_Info = &Control_Flow_Data->Drawing_Area_Info; + + +} + + +/***************************************************************************** + * Hooks to be called by the main window * + *****************************************************************************/ +/** + * Event Viewer's constructor hook + * + * This constructor is given as a parameter to the menuitem and toolbar button + * registration. It creates the list. + * @param pmParentWindow A pointer to the parent window. + * @return The widget created. + */ +GtkWidget * +hGuiControlFlow(GtkWidget *pmParentWindow) +{ + ControlFlowData* Control_Flow_Data = GuiControlFlow() ; + + return Control_Flow_Data->HBox_V ; + +} + +int Event_Selected_Hook(void *hook_data, void *call_data) +{ + ControlFlowData *Control_Flow_Data = (ControlFlowData*) hook_data; + guint *Event_Number = (guint*) call_data; + + g_critical("DEBUG : event selected by main window : %u", *Event_Number); + +// Control_Flow_Data->Currently_Selected_Event = *Event_Number; +// Control_Flow_Data->Selected_Event = TRUE ; + +// Tree_V_set_cursor(Control_Flow_Data); + +} + + +/* Hook called before drawing. Gets the initial context at the beginning of the + * drawing interval and copy it to the context in Event_Request. + */ +Draw_Before_Hook(void *hook_data, void *call_data) +{ + EventRequest *Event_Request = (EventRequest*)hook_data; + EventsContext Events_Context = (EventsContext*)call_data; + + Event_Request->Events_Context = Events_Context; +} + +/* + * The draw event hook is called by the reading API to have a + * particular event drawn on the screen. + * @param hook_data ControlFlowData structure of the viewer. + * @param call_data Event context. + * + * This function basically draw lines and icons. Two types of lines are drawn : + * one small (3 pixels?) representing the state of the process and the second + * type is thicker (10 pixels?) representing on which CPU a process is running + * (and this only in running state). + * + * Extremums of the lines : + * x_min : time of the last event context for this process kept in memory. + * x_max : time of the current event. + * y : middle of the process in the process list. The process is found in the + * list, therefore is it's position in pixels. + * + * The choice of lines'color is defined by the context of the last event for this + * process. + */ +Draw_Event_Hook(void *hook_data, void *call_data) +{ + EventRequest *Event_Request = (EventRequest*)hook_data; + +} + + +Draw_After_Hook(void *hook_data, void *call_data) +{ + EventRequest *Event_Request = (EventRequest*)hook_data; + + g_free(Event_Request); +} + +/***************************************************************************** + * Callbacks used for the viewer * + *****************************************************************************/ +void expose_event_cb (GtkWidget *widget, GdkEventExpose *expose, gpointer data) +{ + ControlFlowData *Control_Flow_Data = (ControlFlowData*)data; + + EventRequest *Event_Request = g_new(sizeof(EventRequest)); + + Event_Request->Control_Flow_Data = Control_Flow_Data; + + /* Calculate, from pixels in expose, the time interval to get data */ + + get_time_from_pixels(expose->area.x, expose->area.width, + Control_Flow_Data->Drawing_Area_Info.width, + &Control_Flow_Data->Begin_Time, &Control_Flow_Data->End_Time, + &Event_Request->time_begin, &Event_Request->time_end) + + /* Look in statistics of the trace the processes present during the + * whole time interval _shown on the screen_. Modify the list of + * processes to match it. NOTE : modify, not recreate. If recreation is + * needed,keep a pointer to the currently selected event in the list. + */ + + /* Call the reading API to have events sent to drawing hooks */ + lttv_trace_set_process( Control_Flow_Data->Trace_Set, + Draw_Before_Hooks, + Draw_Event_Hooks, + Draw_After_Hooks, + NULL, //FIXME : filter here + Event_Request->time_begin, + Event_Request->time_end); + +} + +#ifdef DEBUG +void test_draw() { + gint cell_height = get_cell_height(GTK_TREE_VIEW(Control_Flow_Data->Process_List_VC)); + GdkGC *GC = gdk_gc_new(widget->window); + GdkColor color = CF_Colors[GREEN]; + + gdk_color_alloc (gdk_colormap_get_system () , &color); + + g_critical("expose"); + + /* When redrawing, use widget->allocation.width to get the width of + * drawable area. */ + Control_Flow_Data->Drawing_Area_Info.width = widget->allocation.width; + + test_draw(Control_Flow_Data); + + gdk_gc_copy(GC,widget->style->white_gc); + gdk_gc_set_foreground(GC,&color); + + //gdk_draw_arc (widget->window, + // widget->style->fg_gc[GTK_WIDGET_STATE (widget)], + // TRUE, + // //0, 0, widget->allocation.width, widget->allocation.height, + // 0, 0, widget->allocation.width, + // Control_Flow_Data->Drawing_Area_Info.height, + // 0, 64 * 360); + + + //Drawing_Area_Init(Control_Flow_Data); + + // 2 pixels for the box around the drawing area, 1 pixel for off-by-one + // (starting from 0) + //gdk_gc_copy (&GC, widget->style->fg_gc[GTK_WIDGET_STATE (widget)]); + + gdk_gc_set_line_attributes(GC,12, GDK_LINE_SOLID, GDK_CAP_NOT_LAST,GDK_JOIN_MITER); + + gdk_draw_line (widget->window, + GC, + 0, (cell_height-1)/2, + widget->allocation.width, (cell_height-1)/2); + + color = CF_Colors[BLUE]; + + gdk_color_alloc (gdk_colormap_get_system () , &color); + + gdk_gc_set_foreground(GC,&color); + + + gdk_gc_set_line_attributes(GC,3, GDK_LINE_SOLID, GDK_CAP_NOT_LAST,GDK_JOIN_MITER); + + gdk_draw_line (widget->window, + GC, + 0, (cell_height-1)/2, + widget->allocation.width,(cell_height-1)/2); + + + + + + + g_object_unref(GC); + + //gdk_colormap_alloc_colors(gdk_colormap_get_system(), TRUE, + + //gdk_gc_set_line_attributes(GC,5, GDK_LINE_SOLID, GDK_CAP_NOT_LAST,GDK_JOIN_MITER); + //gdk_gc_set_foreground(GC, + + //gdk_draw_line (widget->window, + // GC, + // 0, (2*cell_height)-2-1, + // 50, (2*cell_height)-2-1); + +} +#endif //DEBUG + +void v_scroll_cb (GtkAdjustment *adjustment, gpointer data) +{ + ControlFlowData *Control_Flow_Data = (ControlFlowData*)data; + GtkTreePath *Tree_Path; + + g_critical("DEBUG : scroll signal, value : %f", adjustment->value); + + //get_test_data((int)adjustment->value, Control_Flow_Data->Num_Visible_Events, + // Control_Flow_Data); + + + +} + + + + + + +static void destroy_cb( GtkWidget *widget, + gpointer data ) +{ + gtk_main_quit (); +} + + + +/***************************************************************************** + * test routines * + *****************************************************************************/ + + +int main(int argc, char **argv) +{ + GtkWidget *Window; + GtkWidget *CF_Viewer; + GtkWidget *VBox_V; + GtkWidget *HScroll_VC; + ControlFlowData *Control_Flow_Data; + guint ev_sel = 444 ; + /* Horizontal scrollbar and it's adjustment */ + GtkWidget *VScroll_VC; + GtkAdjustment *VAdjust_C ; + + /* Initialize i18n support */ + gtk_set_locale (); + + /* Initialize the widget set */ + gtk_init (&argc, &argv); + + init(); + + Window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_window_set_title (GTK_WINDOW (Window), ("Test Window")); + + g_signal_connect (G_OBJECT (Window), "destroy", + G_CALLBACK (destroy_cb), NULL); + + + VBox_V = gtk_vbox_new(0, 0); + gtk_container_add (GTK_CONTAINER (Window), VBox_V); + + //ListViewer = hGuiEvents(Window); + //gtk_box_pack_start(GTK_BOX(VBox_V), ListViewer, TRUE, TRUE, 0); + + //ListViewer = hGuiEvents(Window); + //gtk_box_pack_start(GTK_BOX(VBox_V), ListViewer, FALSE, TRUE, 0); + + Control_Flow_Data = GuiControlFlow(); + CF_Viewer = Control_Flow_Data->Scrolled_Window_VC; + gtk_box_pack_start(GTK_BOX(VBox_V), CF_Viewer, TRUE, TRUE, 0); + + /* Create horizontal scrollbar and pack it */ + HScroll_VC = gtk_hscrollbar_new(NULL); + gtk_box_pack_start(GTK_BOX(VBox_V), HScroll_VC, FALSE, TRUE, 0); + + + gtk_widget_show (HScroll_VC); + gtk_widget_show (VBox_V); + gtk_widget_show (Window); + + //Event_Selected_Hook(Control_Flow_Data, &ev_sel); + + gtk_main (); + + g_critical("main loop finished"); + + //hGuiEvents_Destructor(ListViewer); + + //g_critical("GuiEvents Destructor finished"); + destroy(); + + return 0; +} + +/*\@}*/