#include #include #include #include #include "gtk_app.h" #include "gtk_cb.h" #include "gtk_app_p.h" #include "sim.h" //#define REDIRECT_STDOUT_TO_TEXTVIEW static struct gtk_app_t s_gtk_app; void gtk_app_update_osd(gtk_app_h h_gtk_app) { APP_ASSERT(h_gtk_app); APP_ASSERT(h_gtk_app->osd_widget); APP_ASSERT(h_gtk_app->pixbuf); gdk_threads_enter(); gtk_image_set_from_pixbuf(GTK_IMAGE(h_gtk_app->osd_widget), h_gtk_app->pixbuf ); gdk_threads_leave(); } void gtk_app_get_osd_info(gtk_app_h h_gtk_app, unsigned char **pixels, int *pitch, int *width, int *height) { APP_ASSERT(h_gtk_app); APP_ASSERT(h_gtk_app->pixbuf); APP_ASSERT(pixels); APP_ASSERT(pitch); APP_ASSERT(width); APP_ASSERT(height); gdk_threads_enter(); *pixels = gdk_pixbuf_get_pixels(h_gtk_app->pixbuf); *pitch = gdk_pixbuf_get_rowstride(h_gtk_app->pixbuf); *width = gdk_pixbuf_get_width(h_gtk_app->pixbuf); *height = gdk_pixbuf_get_height(h_gtk_app->pixbuf); gdk_threads_leave(); } /* This is a callback function to watch data in standard output and write to a view text widget. */ void gtk_app_input_callback( gpointer data, gint source, GdkInputCondition condition ) { gtk_app_h h_gtk_app = (gtk_app_h)data; static gchar buf[1024]; gint chars_read; GtkTextIter iter; chars_read = 1024; gdk_threads_enter(); gtk_text_buffer_get_end_iter(h_gtk_app->out_buffer, &iter); gdk_threads_leave(); while (chars_read == 1024) { chars_read = read(h_gtk_app->fds_out[0], buf, 1024); fprintf(stderr, "%i\n", chars_read); // fprintf(stderr, "%i chars: %s\n", chars_read, buf); gdk_threads_enter(); gtk_text_buffer_insert (h_gtk_app->out_buffer, &iter, buf, chars_read); gdk_threads_leave(); } } static gboolean gtk_app_delete_event( GtkWidget *widget, GdkEvent *event, gpointer data ) { /* If you return FALSE in the "delete-event" signal handler, * GTK will emit the "destroy" signal. Returning TRUE means * you don't want the window to be destroyed. * This is useful for popping up 'are you sure you want to quit?' * type dialogs. */ g_print ("delete event occurred\n"); /* Change TRUE to FALSE and the main window will be destroyed with * a "delete-event". */ return TRUE; } /* Another callback */ static void gtk_app_destroy( GtkWidget *widget, gpointer data ) { gtk_app_h h_gtk_app = (gtk_app_h)data; gtk_app_done(h_gtk_app); } static int gtk_app_open_doc(gtk_app_h h_gtk_app) { GtkWidget *dialog; int result = -1; dialog = gtk_file_chooser_dialog_new ("Open File", NULL, GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL); if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) { char *filename; filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog)); // gtk_app_add_doc_item(h_gtk_app,filename); g_free (filename); result = 0; } gtk_widget_destroy (dialog); return result; } #define MAX_DESC_LEN 64 GtkListStore* gtk_app_screen_liststore(gtk_app_h h_gtk_app) { GtkTreeIter iter; int i; GtkListStore *list_store; list_store = gtk_list_store_new(2,G_TYPE_INT, G_TYPE_STRING); for (i = 0; i < sim_screen_num(h_gtk_app->h_sim); ++i) { char desc[MAX_DESC_LEN+1]; sim_screen_get_desc(h_gtk_app->h_sim,i,desc,MAX_DESC_LEN); /* Append a row and fill in some data */ gtk_list_store_append (list_store, &iter); gtk_list_store_set (list_store, &iter, 0, i, 1, desc, -1); } return list_store; } void gtk_app_screen_populate(gtk_app_h h_gtk_app) { GtkListStore *list_store; list_store = gtk_app_screen_liststore(h_gtk_app); gtk_tree_view_set_model (GTK_TREE_VIEW (h_gtk_app->screen_list), GTK_TREE_MODEL(list_store)); g_object_unref(list_store); } static void gtk_app_sim_init(gtk_app_h h_gtk_app) { GError *error = NULL; GtkBuilder *builder; GtkCellRenderer *renderer; GtkTreeSelection *tvs; int width,height; width = 720; height = 480; /* Create new GtkBuilder object */ builder = gtk_builder_new(); /* Load UI from file. If error occurs, report it and quit application. * Replace "tut.glade" with your saved project. */ if ( ! gtk_builder_add_from_file( builder, "../src/sim/sim.glade", &error ) ) { g_warning( "%s", error->message ); g_free( error ); g_object_unref( G_OBJECT( builder ) ); return; } /* Get widget pointers */ h_gtk_app->window = GTK_WIDGET( gtk_builder_get_object( builder, "sim_window" ) ); APP_ASSERT(h_gtk_app->window); h_gtk_app->osd_widget = GTK_WIDGET( gtk_builder_get_object( builder, "OSD" ) ); APP_ASSERT(h_gtk_app->osd_widget); h_gtk_app->remote = GTK_WIDGET( gtk_builder_get_object( builder, "remote_eventbox" ) ); APP_ASSERT(h_gtk_app->remote); h_gtk_app->about_dlg = GTK_DIALOG( gtk_builder_get_object( builder, "about_dialog" ) ); APP_ASSERT(h_gtk_app->about_dlg); #ifdef REDIRECT_STDOUT_TO_TEXTVIEW h_gtk_app->out_textview = GTK_TEXT_VIEW( gtk_builder_get_object( builder, "output_textview" ) ); APP_ASSERT(h_gtk_app->out_textview); h_gtk_app->out_buffer = gtk_text_view_get_buffer(h_gtk_app->out_textview); APP_ASSERT(h_gtk_app->out_buffer); gtk_text_buffer_set_text (h_gtk_app->out_buffer, "Hello, this is some text", -1); #endif h_gtk_app->screen_list = GTK_TREE_VIEW( gtk_builder_get_object( builder, "screen_treeview" ) ); APP_ASSERT(h_gtk_app->screen_list); tvs = gtk_tree_view_get_selection(h_gtk_app->screen_list); gtk_tree_selection_set_mode(tvs,GTK_SELECTION_SINGLE); g_signal_connect(h_gtk_app->screen_list, "row-activated", (GCallback) gtk_cb_screen_select, h_gtk_app); renderer = gtk_cell_renderer_text_new (); gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (h_gtk_app->screen_list), 0, "id", renderer, "text", 0, NULL); renderer = gtk_cell_renderer_text_new (); gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (h_gtk_app->screen_list), 1, "Name", renderer, "text", 1, NULL); gtk_confirm_dlg_init(&h_gtk_app->confirm_dlg,builder); gtk_alert_dlg_init(&h_gtk_app->alert_dlg,builder); gtk_widget_add_events(h_gtk_app->remote,GDK_BUTTON_PRESS_MASK); g_signal_connect (G_OBJECT (h_gtk_app->remote), "button-press-event", G_CALLBACK (gtk_cb_remote_clicked), h_gtk_app); #ifdef REDIRECT_STDOUT_TO_TEXTVIEW gdk_input_add (h_gtk_app->fds_out[0],GDK_INPUT_READ,gtk_app_input_callback,h_gtk_app); #endif /* Connect signals */ gtk_builder_connect_signals( builder, NULL ); gtk_cb_menu_init(h_gtk_app,builder); g_object_unref( G_OBJECT( builder ) ); h_gtk_app->pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB,TRUE,8,width,height); APP_ASSERT(h_gtk_app->pixbuf); gtk_app_screen_populate(h_gtk_app); /* Show window. All other widgets are automatically shown by GtkBuilder */ gtk_widget_show( h_gtk_app->window ); h_gtk_app->state = eAPP_STATE_INITIALIZED; } gtk_app_h gtk_app_init(int argc, char *argv[]) { memset(&s_gtk_app,0,sizeof(s_gtk_app)); g_thread_init(NULL); gdk_threads_init(); /* Init GTK+ */ gtk_init( &argc, &argv ); s_gtk_app.state = eAPP_STATE_INITIALIZED; return &s_gtk_app; } void gtk_app_done(gtk_app_h h_gtk_app) { gtk_main_quit (); } void gtk_app_run(gtk_app_h h_gtk_app) { #ifdef REDIRECT_STDOUT_TO_TEXTVIEW pipe(h_gtk_app->fds_out); dup2(h_gtk_app->fds_out[1],STDOUT_FILENO); #endif gtk_app_sim_init(h_gtk_app); h_gtk_app->h_sim = sim_init(h_gtk_app); /* Start main loop */ gdk_threads_enter(); gtk_main(); gdk_threads_leave(); h_gtk_app->state = eAPP_STATE_DEFAULT; } void gtk_app_new(void) { } void gtk_app_open(void) { } void gtk_app_quit(void) { gtk_app_done(&s_gtk_app); }