123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227 |
- // Gtk C code implementing a
- // Contact Process model
- // in a Gtk3 written GUI
- // _________________________
- // Juan E. Keymer
- //
- // Institute for Advanced Studies
- // Shenzhen X-Institute
- // Shenzhen China, May 2024
- // Libraries
- #include <gtk/gtk.h> // GUI, Gtk Lib
- #include "CP_core_IPS.h" // Simulation Structures
- #include "IPS_graphics.h" // Graphics for IPS
- // Structure & pointer
- IPSmodel s, *ptr_s;
- // Update function
- // simulates the stochastic process
- // updates the lattice configuration
- int update_lattice(gpointer data)\
- {
- update_IPS(ptr_s); //Monte Carlo Step
- paint_lattice(data, ptr_s);
- g_print ("\tGeneration:\t%u\t\tOccupancy:\t%f\n", s.generation_time, (s.occupancy/(X_SIZE * Y_SIZE)));
- return 0;
- }
- // time handler
- // connects update function
- // to the Gtk loop for its computation
- gboolean time_handler (gpointer data)
- {
- update_lattice(data);
- return TRUE;
- }
- // callback to initialize the lattice
- static void init_lattice(GtkWidget *widget, gpointer data)
- {
- initialize_IPS(ptr_s);
- paint_lattice(data, ptr_s);
- // log to console
- g_print ("\tGeneration:\t%u\t\tOccupancy:\t%f\n", s.generation_time, (s.occupancy/(X_SIZE * Y_SIZE)));
- g_print ("Lattice initialized\n");
- }
- // callback to start the simulation
- static void start_simulation (GtkWidget *widget, gpointer data)
- {
- if(!s.running && s.initialized)
- {
- s.run = g_idle_add((GSourceFunc) (GSourceFunc) time_handler, GTK_IMAGE(data));
- s.running = TRUE;
- // log to console
- g_print ("Simulation started\n");
- }
- }
-
- // callback to stop simulation
- static void stop_simulation (GtkWidget *widget, gpointer data)
- {
- if(s.running)
- {
- g_source_remove(s.run);
- s.running = FALSE;
- // log to console
- g_print ("Simulation Stopped\n");
- }
- }
- // callback to respond parameter change scale
- static void mortality_scale_moved (GtkRange *range, gpointer data)
- {
- GtkWidget *label = data;
- gdouble pos = gtk_range_get_value (range);
- s.dead_rate = (float) pos;
- gchar *str = g_strdup_printf ("death = %.2f", pos);
- gtk_label_set_text (GTK_LABEL (label), str);
- g_free(str);
- }
- // to render parameter control
- GtkWidget * render_parameter(void)
- {
- // to control the parameter of the process
- GtkWidget *mortality_scale, *mortality_label;
- GtkWidget *box, *parameter_frame;
-
- // Container to pack: horizontal box
- box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
- // label for motality
- mortality_label = gtk_label_new ("death rate"); /* LABEL*/
- gtk_box_pack_start(GTK_BOX(box), mortality_label, TRUE, TRUE, 0);
-
- // Scale to set mortality
- mortality_scale = gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,0,1,0.01);
- gtk_range_set_value (GTK_RANGE(mortality_scale), (gfloat) MORTALITY);
- gtk_box_pack_start(GTK_BOX(box), mortality_scale, TRUE, TRUE, 0);
- // connect scale and label to handler
- g_signal_connect (mortality_scale,"value-changed", G_CALLBACK (mortality_scale_moved), mortality_label);
-
- // put it all in a frame to return it
- parameter_frame = gtk_frame_new ("Parameters");
- gtk_container_add (GTK_CONTAINER (parameter_frame), box);
- return parameter_frame;
- }
- // to render an image display
- // for lattice configuration
- GtkWidget * render_image(void)
- {
- // Gtk image widget
- GtkWidget *image;
- // Gdk pixbuffer to make an image
- GdkPixbuf *pixbuf;
- // pixbuffer
- pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, 0, 8, X_SIZE, Y_SIZE);
- image = gtk_image_new_from_pixbuf(pixbuf);
- paint_a_background(image);
- return image;
- }
- // to render simulation controls
- // initialize, start, stop, about, quit
- GtkWidget * render_simulation_ctrls(GtkWidget *window, GtkWidget *image_lattice)
- {
- // Widgets
- GtkWidget *button, *button_box, *ctrl_frame;
- ctrl_frame = gtk_frame_new ("Simulation Control");
- button_box = gtk_button_box_new (GTK_ORIENTATION_HORIZONTAL);
- // init
- button = gtk_button_new_with_label ("Init");
- g_signal_connect (button, "clicked", G_CALLBACK (init_lattice), GTK_IMAGE (image_lattice));
- gtk_container_add (GTK_CONTAINER (button_box), button);
- // start
- button = gtk_button_new_with_label ("Start");
- g_signal_connect (button, "clicked", G_CALLBACK (start_simulation), GTK_IMAGE (image_lattice));
- gtk_container_add (GTK_CONTAINER (button_box), button);
- // stop
- button = gtk_button_new_with_label ("Stop");
- g_signal_connect (button, "clicked", G_CALLBACK (stop_simulation), NULL /* (gpointer) ptr_s*/);
- gtk_container_add (GTK_CONTAINER (button_box), button);
- // about
- button = gtk_button_new_with_label ("About");
- g_signal_connect (button, "clicked", G_CALLBACK (show_about), NULL);
- gtk_container_add (GTK_CONTAINER (button_box), button);
- // quit
- button = gtk_button_new_with_label ("Quit");
- g_signal_connect (button, "clicked", G_CALLBACK (stop_simulation), NULL);
- g_signal_connect_swapped (button, "clicked", G_CALLBACK (gtk_widget_destroy), window);
- gtk_container_add (GTK_CONTAINER (button_box), button);
- // Add all buttons into a frame
- gtk_container_add (GTK_CONTAINER (ctrl_frame), button_box);
- // Return the frame
- return ctrl_frame;
- };
- // ACTIVATE function with all Widget Initialization and creation
- static void activate (GtkApplication *app, gpointer user_data)
- {
- // get the address (pointer) of the global structure
- ptr_s = &s;
- // set up default values
- //(GUI--IPS_defult_Parameters + randomness)
- prepare_IPS(ptr_s);
- // declare a bunch of Gtk widgets for the GUI
- GtkWidget *window,*grid, *image_lattice,*frame;
- // Gdk Pixbuffer to draw an image
- GdkPixbuf *pixbuf;
- // Create a window and set its title
- window = gtk_application_window_new (app);
- gtk_window_set_title (GTK_WINDOW (window), "Langton Ant IPS");
- gtk_window_set_resizable (GTK_WINDOW(window), FALSE);
-
- // Make a grid to pack our Widgets
- grid = gtk_grid_new ();
- // Pack the grid in the window
- gtk_container_add (GTK_CONTAINER (window), grid);
-
- // Parameter control
- frame = render_parameter();
- gtk_grid_attach (GTK_GRID (grid), frame, 0, 0, 4, 1);
- // Lattice configuration image
- image_lattice = render_image();
- gtk_grid_attach (GTK_GRID (grid), image_lattice, 0, 1, 4, 1); // position (0,1) spanning 5 col and 1 raw)
- // Simulation Control
- frame = render_simulation_ctrls(window, image_lattice);
- gtk_grid_attach (GTK_GRID (grid), frame, 0, 2, 4, 1);
- // Show the window and all widgets
- gtk_widget_show_all (window);
- }
- // Main
- int main (int argc, char **argv)
- {
- GtkApplication *app;
- int status;
- app = gtk_application_new ("keymer.lab.CP_IPS", G_APPLICATION_FLAGS_NONE);
- g_signal_connect (app, "activate", G_CALLBACK (activate), NULL);
- status = g_application_run (G_APPLICATION (app), argc, argv);
- g_object_unref (app);
- return status;
- }
|