/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ #+ #+ Internet Radio Automation & Encoding Toolkit #+ #+ Copyright (C) 2018, 2019, 2020 by Kevin C. O'Kane #+ #+ Kevin C. O'Kane #+ kc.okane@gmail.com #+ https://www.cs.uni.edu/~okane #+ https://threadsafebooks.com/ #+ #+ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #+ #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ // July 23, 2020 #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include GtkWidget *p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8, *p9, *p10, *p11, *p12; GtkWidget *image[12], *appImage; // images to be placed in buttons GtkBuilder *builder; GtkWidget *window, *imageWindow; // main and popup windows GtkWidget *fixed1, *fixed2; // main and popup containers GdkPixbuf *pix[12]; // scaled pictures GdkPixbuf *pixIn[12]; // original (unscaled) pictures GdkPixbuf *tmp_pixbuf; // temp storage GdkPixbuf *source_pixbuf; // temp storage void on_window_main_destroy() ; int drag_source, drag_target; GtkCssProvider *cssProvider_button; // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // paint css on a widget // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ void css_set(GtkCssProvider * cssProvider, GtkWidget *g_widget) { GtkStyleContext *context; context = gtk_widget_get_style_context(g_widget); gtk_style_context_add_provider (context, GTK_STYLE_PROVIDER(cssProvider), 1000); } int main(int argc, char *argv[]) { char tmp[1024]; gtk_init(&argc, &argv); builder = gtk_builder_new_from_resource ("/part1/pics.glade"); window = GTK_WIDGET(gtk_builder_get_object(builder, "window_main")); gtk_builder_connect_signals(builder, NULL); g_signal_connect(window, "destroy", G_CALLBACK(on_window_main_destroy), NULL); fixed2 = GTK_WIDGET(gtk_builder_get_object(builder, "fixed2")); // popup window container imageWindow = GTK_WIDGET(gtk_builder_get_object(builder, "imageWindow")); // popup window appImage = GTK_WIDGET(gtk_builder_get_object(builder, "appImage")); // popup window image p1 = GTK_WIDGET(gtk_builder_get_object(builder, "p1")); // buttons p2 = GTK_WIDGET(gtk_builder_get_object(builder, "p2")); p3 = GTK_WIDGET(gtk_builder_get_object(builder, "p3")); p4 = GTK_WIDGET(gtk_builder_get_object(builder, "p4")); p5 = GTK_WIDGET(gtk_builder_get_object(builder, "p5")); p6 = GTK_WIDGET(gtk_builder_get_object(builder, "p6")); p7 = GTK_WIDGET(gtk_builder_get_object(builder, "p7")); p8 = GTK_WIDGET(gtk_builder_get_object(builder, "p8")); p9 = GTK_WIDGET(gtk_builder_get_object(builder, "p9")); p10 = GTK_WIDGET(gtk_builder_get_object(builder, "p10")); p11 = GTK_WIDGET(gtk_builder_get_object(builder, "p11")); p12 = GTK_WIDGET(gtk_builder_get_object(builder, "p12")); image[0] = GTK_WIDGET(gtk_builder_get_object(builder, "image1")); //images image[1] = GTK_WIDGET(gtk_builder_get_object(builder, "image2")); image[2] = GTK_WIDGET(gtk_builder_get_object(builder, "image3")); image[3] = GTK_WIDGET(gtk_builder_get_object(builder, "image4")); image[4] = GTK_WIDGET(gtk_builder_get_object(builder, "image5")); image[5] = GTK_WIDGET(gtk_builder_get_object(builder, "image6")); image[6] = GTK_WIDGET(gtk_builder_get_object(builder, "image7")); image[7] = GTK_WIDGET(gtk_builder_get_object(builder, "image8")); image[8] = GTK_WIDGET(gtk_builder_get_object(builder, "image9")); image[9] = GTK_WIDGET(gtk_builder_get_object(builder, "image10")); image[10] = GTK_WIDGET(gtk_builder_get_object(builder, "image11")); image[11] = GTK_WIDGET(gtk_builder_get_object(builder, "image12")); fixed1 = GTK_WIDGET(gtk_builder_get_object(builder, "fixed1")); GError *err; FILE *f1 = popen("ls album", "r"); char ftmp[1024], filename[1024]; int i = 0, lx; while (1) { if (!fgets(ftmp, 1024, f1)) break; ftmp[strlen(ftmp)-1] = 0; // chop new line character strcpy(filename, "album/"); // subdirectory strcat(filename, ftmp); // image file name printf("%s\n", filename); err = NULL; pixIn[i] = gdk_pixbuf_new_from_file (filename, &err); // unscaled pixbuf pix[i] = gdk_pixbuf_scale_simple (pixIn[i], 150, 100, GDK_INTERP_NEAREST); // scaled pixbuf gtk_image_set_from_pixbuf (image[i], pix[i]); i++; if (i >= 12) break; } fclose(f1); // add some fancy button effects cssProvider_button = gtk_css_provider_new(); gtk_css_provider_load_from_resource(cssProvider_button, "/part1/css/albumButton.css"); css_set(cssProvider_button, p1 ); css_set(cssProvider_button, p2 ); css_set(cssProvider_button, p3 ); css_set(cssProvider_button, p4 ); css_set(cssProvider_button, p5 ); css_set(cssProvider_button, p6 ); css_set(cssProvider_button, p7 ); css_set(cssProvider_button, p8 ); css_set(cssProvider_button, p9 ); css_set(cssProvider_button, p10 ); css_set(cssProvider_button, p11 ); css_set(cssProvider_button, p12 ); gtk_widget_show(window); GdkColor color; color.red = 0x5555; color.green = 0x5555; color.blue = 0x6666; gtk_widget_modify_bg(window, GTK_STATE_NORMAL, &color); gtk_widget_show_all(window); gtk_window_move(GTK_WINDOW(window), 230, 300); // position windows gtk_window_move(GTK_WINDOW(imageWindow), 900, 300); GtkTargetEntry targs[1] = {"dummy", GTK_TARGET_SAME_APP, 1}; // GtkTargetEntry structure: // gchar *target; // guint flags; // guint info; // GDK_BUTTON1_MASK means first (left) mouse button // GTK_DESTINATION_DEFAULT_ALL turns on all options // macro code ------------------------- // enable up drag/drop permissions #define P_BUTTON_DRAG_SETUP(NBR) \ gtk_drag_source_set(p## NBR, GDK_BUTTON1_MASK, targs, 1, GDK_ACTION_COPY); \ gtk_drag_dest_set(p## NBR , GTK_DEST_DEFAULT_DROP | GTK_DEST_DEFAULT_HIGHLIGHT | GTK_DEST_DEFAULT_MOTION, \ targs, 1, GDK_ACTION_COPY); P_BUTTON_DRAG_SETUP(1) P_BUTTON_DRAG_SETUP(2) P_BUTTON_DRAG_SETUP(3) P_BUTTON_DRAG_SETUP(4) P_BUTTON_DRAG_SETUP(5) P_BUTTON_DRAG_SETUP(6) P_BUTTON_DRAG_SETUP(7) P_BUTTON_DRAG_SETUP(8) P_BUTTON_DRAG_SETUP(9) P_BUTTON_DRAG_SETUP(10) P_BUTTON_DRAG_SETUP(11) P_BUTTON_DRAG_SETUP(12) gtk_widget_hide(imageWindow); // show when needed gtk_main(); // here we go! } // ---------------------------------------------------------------- void on_window_main_destroy() { gtk_main_quit(); } // Don't destroy popup window - hide it gboolean on_imageWindow_delete_event(GtkWindow *w) { gtk_widget_hide(imageWindow); return TRUE; // no further processing } // macro code ------------------------- // button left click #define P_BUTTON_CLICKED(NBR) \ void on_p## NBR ##_clicked(GtkWidget *b) { \ printf("left click %d\n", NBR); \ } P_BUTTON_CLICKED(1) P_BUTTON_CLICKED(2) P_BUTTON_CLICKED(3) P_BUTTON_CLICKED(4) P_BUTTON_CLICKED(5) P_BUTTON_CLICKED(6) P_BUTTON_CLICKED(7) P_BUTTON_CLICKED(8) P_BUTTON_CLICKED(9) P_BUTTON_CLICKED(10) P_BUTTON_CLICKED(11) P_BUTTON_CLICKED(12) // macro code - several routines ------ // drag functions // Note: always use /* ... */ style comments in macros and not // style #define P_BUTTON_DRAG(NBR) \ void on_p## NBR ##_drag_begin (GtkWidget *w, GdkDragContext *dc) { \ /* drag has begun */ \ printf("drag begin %d\n", NBR); \ drag_source = NBR; \ } \ \ void on_p## NBR ##_drag_drop (GtkWidget *w, GdkDragContext *dc) { \ /* drag has ended (button released) */ \ /* NBR will be number of target button */ \ printf("drop %d\n", NBR); \ drag_target = NBR; /* buttton number 1-12 */ \ } \ \ void on_p## NBR ##_drag_data_get (GtkWidget *w, GdkDragContext *dc) { \ /*** drag has ended (button released) */ \ /*** NBR will be NBR of source button - not used here */ \ printf("get %d\n", NBR); \ } \ \ void on_p## NBR ##_drag_end (GtkWidget *w, GdkDragContext *dc) { \ /* last function to be called */ \ printf("move from tile %d to tile %d\n", drag_source, drag_target); \ /*** swap scaled pixbufs */ \ tmp_pixbuf = pix [ drag_target - 1]; \ pix[ drag_target - 1] = pix[ drag_source - 1]; \ pix[ drag_source - 1] = tmp_pixbuf; \ /*** swap un-scaled pixbufs */ \ tmp_pixbuf = pixIn [ drag_target - 1]; \ pixIn[ drag_target - 1] = pixIn[ drag_source - 1]; \ pixIn[ drag_source - 1] = tmp_pixbuf; \ /*** re-paint images */ \ gtk_image_set_from_pixbuf (image[drag_target - 1], pix[drag_target - 1]); \ gtk_image_set_from_pixbuf (image[drag_source - 1], pix[drag_source - 1]); \ drag_source = drag_target = -1; } P_BUTTON_DRAG(1) P_BUTTON_DRAG(2) P_BUTTON_DRAG(3) P_BUTTON_DRAG(4) P_BUTTON_DRAG(5) P_BUTTON_DRAG(6) P_BUTTON_DRAG(7) P_BUTTON_DRAG(8) P_BUTTON_DRAG(9) P_BUTTON_DRAG(10) P_BUTTON_DRAG(11) P_BUTTON_DRAG(12) // macro code ------------------------- #define P_BUTTON_PRESS(NBR) \ gboolean on_p## NBR ##_button_press_event \ (GtkButton *btn, GdkEventButton *event, gpointer user_data) { \ printf("button press %d\n", NBR); \ if (event->state == GDK_CONTROL_MASK) printf("ctrl key pressed\n"); \ /* return TRUE: no futher processing of this signal */ \ /* return FALSE: continue processing this signal */ \ if (event->button == 1 ) return FALSE; /* left click - processing done elsewhere */ \ printf("right click\n"); \ gtk_widget_show(imageWindow); /* show popup window */ \ gtk_window_move(GTK_WINDOW(imageWindow), 900, 300); /* reposition it */ \ /* scale popup window image */ \ tmp_pixbuf = gdk_pixbuf_scale_simple (pixIn[NBR - 1], 640, 480, GDK_INTERP_NEAREST); \ gtk_image_set_from_pixbuf (appImage, tmp_pixbuf); \ g_object_unref(tmp_pixbuf); /* no longer needed - free it */ \ return TRUE; /* no further processing for this event */ \ } P_BUTTON_PRESS(1) P_BUTTON_PRESS(2) P_BUTTON_PRESS(3) P_BUTTON_PRESS(4) P_BUTTON_PRESS(5) P_BUTTON_PRESS(6) P_BUTTON_PRESS(7) P_BUTTON_PRESS(8) P_BUTTON_PRESS(9) P_BUTTON_PRESS(10) P_BUTTON_PRESS(11) P_BUTTON_PRESS(12)