2011/04/28

Silly random placement rectangle drawer in gtk with cairo

Wow that was a mouthful.  I've been working with cairo/gtk for a design project so I thought it might be fun to do something stupid but fun(at least for me) with it.  Shitty code but meh.


While taking a screen shot I realized that if you drag a window over it clears that section etc.  oopsy   If i have time and if I care I'll look into that. 

Here's the C code randraw.c:
#include <stdio.h>
#include <stdlib.h>
#include <gtk/gtk.h>
#include <cairo.h>

/* compile with
 *      gcc -o randraw randraw.c $(pkg-config --cflags --libs gtk+-2.0 gmodule-2.0 cairo)
 */

//all the data needed
typedef struct {
        int x_len;
        int y_len;
        int num;
        double red;
        double green;
        double blue;
        GtkWidget *drawA1;
        GtkWidget *drawA2;
} data_t;

//global pointer for the data
data_t *gdata;

//function to clear the drawing area
void clear_screen (){
        cairo_t *cr;
        cr = gdk_cairo_create(gdata->drawA1->window);
        cairo_set_source_rgba(cr,0,0,0,1);
        cairo_paint_with_alpha(cr,1);

        cairo_destroy(cr);
}

//displays the preview of the color to be drawn
void preview(){
        cairo_t *cr;
        cr = gdk_cairo_create(gdata->drawA2->window);
        cairo_set_source_rgba(cr,gdata->red,gdata->green,gdata->blue,1);
        //cairo_fill(cr);
        cairo_paint_with_alpha(cr,1);

        cairo_destroy(cr);
}

//for when the draw button is pressed, does all of the drawing, hurp
G_MODULE_EXPORT void draw(GtkWidget *widget, gpointer data){
        cairo_t *cr;
        int i = 0;
        int ranW, ranH;

        cr = gdk_cairo_create(gdata->drawA1->window);

        for (i = 0; i < gdata->num; i++){
                //calc the random points
                do {
                        ranW = rand() % gdata->drawA1->allocation.width;
                } while (ranW + gdata->x_len >= gdata->drawA1->allocation.width);

                do {
                        ranH = rand() % gdata->drawA1->allocation.height;
                } while (ranH + gdata->y_len >= gdata->drawA1->allocation.height);

                //selects the color
                cairo_set_source_rgb(cr,gdata->red,gdata->green,gdata->blue);
                //draws a rectange
                cairo_rectangle(cr, ranW, ranH, gdata->x_len, gdata->y_len);
                //draws the rects it to cr
                cairo_fill(cr);
        }

        cairo_destroy(cr);

}
//updates on the buttons
G_MODULE_EXPORT void y_update(GtkWidget *y_len_i, gpointer data){
        const gchar *string;
        int temp = 0;
        string = gtk_entry_get_text(GTK_ENTRY(y_len_i));
        if(sscanf(string,"%d",&temp) != 0){
                if (temp > 0){
                        gdata->y_len = temp;
                } else
                        fprintf(stderr, "y has to be greater than 0\n");
        } 
}

G_MODULE_EXPORT void x_update(GtkWidget *x_len_i, gpointer data){
        const gchar *string;
        int temp = 0;
        string = gtk_entry_get_text(GTK_ENTRY(x_len_i));
        if(sscanf(string,"%d",&temp) != 0){
                if (temp > 0){
                        gdata->x_len = temp;
                } else
                        fprintf(stderr, "x has to be greater than 0\n");
        }
}

G_MODULE_EXPORT void num_update(GtkWidget *num_i, gpointer data){
        const gchar *string;
        int temp = 0;
        string = gtk_entry_get_text(GTK_ENTRY(num_i));
        if(sscanf(string,"%d",&temp) != 0){
                if (temp > 0) {
                        gdata->num = temp;
                } else
                        fprintf(stderr, "pixel count has to be greater than 0\n");
        }
}

G_MODULE_EXPORT void red_update(GtkWidget *red_i, gpointer data){
        const gchar *string;
        float temp  = 0.0;
        string = gtk_entry_get_text(GTK_ENTRY(red_i));
        if(sscanf(string,"%f",&temp) != 0){
                if ( !(temp < 0.0 || temp > 1.0)) {
                        gdata->red = temp;
                        preview();
                } else
                        fprintf(stderr, "red component has to be >= 0 and <= 1\n");
        }
}

G_MODULE_EXPORT void green_update(GtkWidget *green_i, gpointer data){
        const gchar *string;
        float temp  = 0.0;
        string = gtk_entry_get_text(GTK_ENTRY(green_i));
        if(sscanf(string,"%f",&temp) != 0){
                if ( !(temp < 0.0 || temp > 1.0)) {
                        gdata->green = temp;
                        preview();
                } else
                        fprintf(stderr, "green component has to be >= 0 and <= 1\n");
        }
}

G_MODULE_EXPORT void blue_update(GtkWidget *blue_i, gpointer data){
        const gchar *string;
        float temp  = 0.0;
        string = gtk_entry_get_text(GTK_ENTRY(blue_i));
        if(sscanf(string,"%f",&temp) != 0){
                if ( !(temp < 0.0 || temp > 1.0)) {
                        gdata->blue = temp;
                        preview();
                } else
                        fprintf(stderr, "blue component has to be >= 0 and <= 1\n");
        }
}

//for calling the preview on startup
G_MODULE_EXPORT void init_preview(GtkWidget *widget, gpointer data){
        preview();
}

//for setting the screen color on start up
G_MODULE_EXPORT void clear_scn(GtkWidget *widget, gpointer data){
        //clear_screen();
}

int main(int argc, char **argv){
        GtkBuilder *builder;
        GtkWidget *window;
        GError *error = NULL;
        data_t maindata;
        gdata = &maindata;

        maindata.x_len = 1;
        maindata.y_len = 1;
        maindata.num = 1;
        maindata.red = 1.0;
        maindata.blue = 1.0;
        maindata.green = 1.0;

        /* init gtk+ and strip the gtk arguments */
        gtk_init(&argc, &argv);

        /* creat new gtkbuilder object */
        builder = gtk_builder_new();

        /* load UI from file, if there's an arror it quits */
        if(!gtk_builder_add_from_file(builder, "randraw.glade", &error)){
                g_warning("%s", error->message);
                g_free(error);
                return 1;
        }

        /* gets main window pointer */ 
        window = GTK_WIDGET(gtk_builder_get_object(builder, "window1"));
        gdata->drawA1 = GTK_WIDGET(gtk_builder_get_object(builder, "drawingarea1"));
        gdata->drawA2 = GTK_WIDGET(gtk_builder_get_object(builder, "drawingarea2"));
       
        /* connects the signals */
        gtk_builder_connect_signals(builder, NULL);

        /* destorys builder since it isn't needed */
        g_object_unref(G_OBJECT(builder));


        /* for stopping the main gtk when the window gets destroyed */
        g_signal_connect (G_OBJECT (window), "delete_event", G_CALLBACK (gtk_main_quit), NULL);
        g_signal_connect (G_OBJECT (window), "destroy", G_CALLBACK (gtk_main_quit), NULL);

        gtk_widget_set_app_paintable(gdata->drawA1, TRUE);
        gtk_widget_set_app_paintable(gdata->drawA2, TRUE);

        /* shows window */
        gtk_widget_show(window);

        clear_screen();

        /* main loop */
        gtk_main();
       
        return 0;
}
Ugh, I need to find a better way to post code on here.
here's the glade file randraw.glade:
<?xml version="1.0"?>
<interface>
  <requires lib="gtk+" version="2.16"/>
  <!-- interface-naming-policy project-wide -->
  <object class="GtkWindow" id="window1">
    <property name="width_request">800</property>
    <property name="height_request">600</property>
    <property name="title" translatable="yes">Larks Randow Rectangle Drawer</property>
    <child>
      <object class="GtkHBox" id="hbox1">
        <property name="visible">True</property>
        <property name="spacing">3</property>
        <child>
          <object class="GtkDrawingArea" id="drawingarea1">
            <property name="width_request">600</property>
            <property name="visible">True</property>
            <signal name="expose_event" handler="clear_screen"/>
          </object>
          <packing>
            <property name="position">0</property>
          </packing>
        </child>
        <child>
          <object class="GtkTable" id="table1">
            <property name="visible">True</property>
            <property name="n_rows">15</property>
            <property name="n_columns">2</property>
            <child>
              <object class="GtkEntry" id="x_len_i">
                <property name="visible">True</property>
                <property name="can_focus">True</property>
                <property name="invisible_char">&#x25CF;</property>
                <property name="text" translatable="yes">1</property>
                <signal name="changed" handler="x_update"/>
              </object>
              <packing>
                <property name="left_attach">1</property>
                <property name="right_attach">2</property>
                <property name="x_options"></property>
              </packing>
            </child>
            <child>
              <object class="GtkLabel" id="x_len_l">
                <property name="visible">True</property>
                <property name="label" translatable="yes">x length (int)</property>
              </object>
              <packing>
                <property name="x_options"></property>
              </packing>
            </child>
            <child>
              <object class="GtkLabel" id="y_len_l">
                <property name="visible">True</property>
                <property name="label" translatable="yes">y length (int)</property>
              </object>
              <packing>
                <property name="top_attach">2</property>
                <property name="bottom_attach">3</property>
                <property name="x_options"></property>
              </packing>
            </child>
            <child>
              <object class="GtkEntry" id="y_len_i">
                <property name="visible">True</property>
                <property name="can_focus">True</property>
                <property name="invisible_char">&#x25CF;</property>
                <property name="text" translatable="yes">1</property>
                <signal name="changed" handler="y_update"/>
              </object>
              <packing>
                <property name="left_attach">1</property>
                <property name="right_attach">2</property>
                <property name="top_attach">2</property>
                <property name="bottom_attach">3</property>
                <property name="x_options"></property>
              </packing>
            </child>
            <child>
              <object class="GtkLabel" id="num_l">
                <property name="visible">True</property>
                <property name="label" translatable="yes">Number of
pixels (int)</property>
              </object>
              <packing>
                <property name="top_attach">4</property>
                <property name="bottom_attach">5</property>
                <property name="x_options"></property>
              </packing>
            </child>
            <child>
              <object class="GtkEntry" id="num_i">
                <property name="visible">True</property>
                <property name="can_focus">True</property>
                <property name="invisible_char">&#x25CF;</property>
                <property name="text" translatable="yes">1</property>
                <signal name="changed" handler="num_update"/>
              </object>
              <packing>
                <property name="left_attach">1</property>
                <property name="right_attach">2</property>
                <property name="top_attach">4</property>
                <property name="bottom_attach">5</property>
                <property name="x_options"></property>
              </packing>
            </child>
            <child>
              <object class="GtkLabel" id="red_l">
                <property name="visible">True</property>
                <property name="yalign">0.55000001192092896</property>
                <property name="label" translatable="yes">Red (float)
(0.0 - 1.0)</property>
              </object>
              <packing>
                <property name="top_attach">6</property>
                <property name="bottom_attach">7</property>
                <property name="x_options"></property>
              </packing>
            </child>
            <child>
              <object class="GtkLabel" id="green_l">
                <property name="visible">True</property>
                <property name="label" translatable="yes">Green (float)
  (0.0 - 1.0)</property>
              </object>
              <packing>
                <property name="top_attach">8</property>
                <property name="bottom_attach">9</property>
                <property name="x_options"></property>
              </packing>
            </child>
            <child>
              <object class="GtkLabel" id="blue_l">
                <property name="visible">True</property>
                <property name="label" translatable="yes">Blue (float)
(0.0 - 1.0)</property>
              </object>
              <packing>
                <property name="top_attach">10</property>
                <property name="bottom_attach">11</property>
                <property name="x_options"></property>
              </packing>
            </child>
            <child>
              <object class="GtkEntry" id="red_i">
                <property name="visible">True</property>
                <property name="can_focus">True</property>
                <property name="invisible_char">&#x25CF;</property>
                <property name="text" translatable="yes">1.0</property>
                <signal name="changed" handler="red_update"/>
              </object>
              <packing>
                <property name="left_attach">1</property>
                <property name="right_attach">2</property>
                <property name="top_attach">6</property>
                <property name="bottom_attach">7</property>
                <property name="x_options"></property>
              </packing>
            </child>
            <child>
              <object class="GtkEntry" id="green_i">
                <property name="visible">True</property>
                <property name="can_focus">True</property>
                <property name="invisible_char">&#x25CF;</property>
                <property name="text" translatable="yes">1.0</property>
                <signal name="changed" handler="green_update"/>
              </object>
              <packing>
                <property name="left_attach">1</property>
                <property name="right_attach">2</property>
                <property name="top_attach">8</property>
                <property name="bottom_attach">9</property>
                <property name="x_options"></property>
              </packing>
            </child>
            <child>
              <object class="GtkEntry" id="blue_i">
                <property name="visible">True</property>
                <property name="can_focus">True</property>
                <property name="invisible_char">&#x25CF;</property>
                <property name="text" translatable="yes">1.0</property>
                <signal name="changed" handler="blue_update"/>
              </object>
              <packing>
                <property name="left_attach">1</property>
                <property name="right_attach">2</property>
                <property name="top_attach">10</property>
                <property name="bottom_attach">11</property>
                <property name="x_options"></property>
              </packing>
            </child>
            <child>
              <object class="GtkTable" id="table2">
                <property name="visible">True</property>
                <property name="n_rows">3</property>
                <property name="n_columns">3</property>
                <property name="column_spacing">20</property>
                <property name="row_spacing">20</property>
                <child>
                  <object class="GtkButton" id="draw_b">
                    <property name="label" translatable="yes">Draw</property>
                    <property name="visible">True</property>
                    <property name="can_focus">True</property>
                    <property name="receives_default">True</property>
                    <signal name="clicked" handler="draw"/>
                  </object>
                  <packing>
                    <property name="left_attach">1</property>
                    <property name="right_attach">2</property>
                    <property name="top_attach">1</property>
                    <property name="bottom_attach">2</property>
                    <property name="x_options">GTK_FILL</property>
                    <property name="y_options">GTK_FILL</property>
                  </packing>
                </child>
                <child>
                  <placeholder/>
                </child>
                <child>
                  <placeholder/>
                </child>
                <child>
                  <placeholder/>
                </child>
                <child>
                  <placeholder/>
                </child>
                <child>
                  <placeholder/>
                </child>
                <child>
                  <placeholder/>
                </child>
                <child>
                  <placeholder/>
                </child>
                <child>
                  <placeholder/>
                </child>
              </object>
              <packing>
                <property name="top_attach">14</property>
                <property name="bottom_attach">15</property>
                <property name="x_options"></property>
              </packing>
            </child>
            <child>
              <placeholder/>
            </child>
            <child>
              <placeholder/>
            </child>
            <child>
              <placeholder/>
            </child>
            <child>
              <placeholder/>
            </child>
            <child>
              <placeholder/>
            </child>
            <child>
              <placeholder/>
            </child>
            <child>
              <placeholder/>
            </child>
            <child>
              <placeholder/>
            </child>
            <child>
              <placeholder/>
            </child>
            <child>
              <placeholder/>
            </child>
            <child>
              <placeholder/>
            </child>
            <child>
              <placeholder/>
            </child>
            <child>
              <placeholder/>
            </child>
            <child>
              <placeholder/>
            </child>
            <child>
              <object class="GtkTable" id="table3">
                <property name="visible">True</property>
                <property name="n_rows">3</property>
                <property name="n_columns">3</property>
                <property name="column_spacing">20</property>
                <property name="row_spacing">20</property>
                <child>
                  <object class="GtkButton" id="clear_b">
                    <property name="label" translatable="yes">Clear screen</property>
                    <property name="visible">True</property>
                    <property name="can_focus">True</property>
                    <property name="receives_default">True</property>
                    <signal name="clicked" handler="clear_scn"/>
                  </object>
                  <packing>
                    <property name="left_attach">1</property>
                    <property name="right_attach">2</property>
                    <property name="top_attach">1</property>
                    <property name="bottom_attach">2</property>
                    <property name="x_options">GTK_FILL</property>
                    <property name="y_options">GTK_FILL</property>
                  </packing>
                </child>
                <child>
                  <placeholder/>
                </child>
                <child>
                  <placeholder/>
                </child>
                <child>
                  <placeholder/>
                </child>
                <child>
                  <placeholder/>
                </child>
                <child>
                  <placeholder/>
                </child>
                <child>
                  <placeholder/>
                </child>
                <child>
                  <placeholder/>
                </child>
                <child>
                  <placeholder/>
                </child>
              </object>
              <packing>
                <property name="left_attach">1</property>
                <property name="right_attach">2</property>
                <property name="top_attach">14</property>
                <property name="bottom_attach">15</property>
                <property name="x_options"></property>
              </packing>
            </child>
            <child>
              <object class="GtkLabel" id="preview_l">
                <property name="visible">True</property>
                <property name="label" translatable="yes">Preview Color</property>
              </object>
              <packing>
                <property name="top_attach">12</property>
                <property name="bottom_attach">13</property>
                <property name="x_options"></property>
              </packing>
            </child>
            <child>
              <object class="GtkTable" id="table4">
                <property name="visible">True</property>
                <property name="n_rows">3</property>
                <property name="n_columns">3</property>
                <child>
                  <object class="GtkDrawingArea" id="drawingarea2">
                    <property name="width_request">75</property>
                    <property name="height_request">50</property>
                    <property name="visible">True</property>
                    <signal name="no_expose_event" handler="init_preview"/>
                    <signal name="expose_event" handler="init_preview"/>
                  </object>
                  <packing>
                    <property name="left_attach">1</property>
                    <property name="right_attach">2</property>
                    <property name="top_attach">1</property>
                    <property name="bottom_attach">3</property>
                    <property name="x_options"></property>
                    <property name="y_options"></property>
                  </packing>
                </child>
                <child>
                  <placeholder/>
                </child>
                <child>
                  <placeholder/>
                </child>
                <child>
                  <placeholder/>
                </child>
                <child>
                  <placeholder/>
                </child>
                <child>
                  <placeholder/>
                </child>
                <child>
                  <placeholder/>
                </child>
                <child>
                  <placeholder/>
                </child>
              </object>
              <packing>
                <property name="left_attach">1</property>
                <property name="right_attach">2</property>
                <property name="top_attach">12</property>
                <property name="bottom_attach">13</property>
                <property name="x_options"></property>
                <property name="y_options"></property>
              </packing>
            </child>
          </object>
          <packing>
            <property name="expand">False</property>
            <property name="fill">False</property>
            <property name="padding">4</property>
            <property name="position">1</property>
          </packing>
        </child>
      </object>
    </child>
  </object>
</interface>
Assuming you're not brain damaged I also tarballed them and put them on mediafire here.

2011/04/24

Move to Different X-screens with a Perl Script

I tried writing this in a bash script but for some reason I failed miserably so I wrote it in some I knew.   I have my XFCE WM where it focuses where the mouse is so if you don't have it set up like that, it may not completely work right, I dunno. 

#!/usr/bin/perl
use strict;
use warnings;

my $display = $ENV{'DISPLAY'};
#print "my dispaly is $display\n";
if (!(defined $display)){
        exit 1;
}
elsif ($display eq ":0.1") {
        system("xdotool mousemove --screen 0 640 512");
        #print("Switching to xscreen 0\n");
}
else {
        system("xdotool mousemove --screen 1 920 600");
        #print("Switching to xscreen 1\n");
}

exit 0;
 This can easily be changed to suit your own needs.  You could have one called move right, left etc if you have more than two x-screens.  The "640 512" and "920 600" are the x y cords of the middle of my screen.  See the man page for xdotool for more info.

It's a real quick and dirty script so.  If you make any improvements to it, please let me know!