2

I'm using goocanvas to draw a simple diagram on a GTK frame and diagram dimensions are based on the values on same window. The diagram should change it's dimensions in real time, when the user changes the values on the interface using spinner buttons.

I successfully managed to render the initial diagram on top of the gtk window->hbox->frame.

Problem is when changes the values. It redraws on top of the drawing.

So is there any "clear" functionality available for goo canvas?

Or is there any other method to achieve desired results?

Edit:

Current code:

/*
 * Compile me with:
 * gcc -o dia dia.c `pkg-config --libs --cflags gtk+-2.0 goocanvas` -rdynamic -I./headers/ -lm
 * 
 */

#include <stdio.h>
#include <gtk/gtk.h>
#include <goocanvas.h>

/*Common structs and varaibles*/

struct dia_struct
{
    gdouble diam;
    const gchar *tbp, *thtp, *wt;
};

struct dia_struct set_dia; /* intitializing the structure */

/* Goo canvas items */
GooCanvasItem *root, *path, *path2;

GtkWidget  *canvas;

/*
 * Function:  ofdra
 * --------------------
 * This is the main function to draw the diagram on screen
 *  
 *  returns: none
 */
void ofdra (double diam)
{ 
    double dfactor = diam*50;

    path = NULL;
    path2 = NULL;

    double x = (465-dfactor)/2;
    double y = 465-x;

    char buf[100];
    char buf2[100];
    sprintf(buf, "M 0 %f L 1000 %f", x, x);
    sprintf(buf2, "M 0 %f L 1000 %f", y, y);

    path = goo_canvas_path_new (root, buf, "stroke-color", "red", NULL);
    path2 = goo_canvas_path_new (root, buf2, "stroke-color", "red", NULL);

    /*goo_canvas_item_update (path, TRUE, );*/
    /*goo_canvas_item_update (path2);*/

}

/*
 * Function:  ofruta
 * --------------------
 * This is the main function to run when in a user changed a value.
 *
 *  glade_wdgets: widget-object
 *  pObList: array of objects to go through
 *  
 *  returns: none
 */
void ofruta (GtkWidget *glade_wdgets, gpointer *pObList)
{
    /* common varaibles needed */

    struct dia_struct dia; /* intitializing the structure */

    /* getters */
    dia.diam = gtk_spin_button_get_value (GTK_SPIN_BUTTON(pObList[0])); /* diameter reading */

    set_diamond.diam = diamond.diam;

    gtk_spin_button_set_value(GTK_SPIN_BUTTON(pObList[0]), set_diamond.diam);

    /* Loads all dynamically generated diagram drawing */
    ofdra(set_diamond.diam);
}

//===========================================================================
/*
 * main
 *
 * Program begins here
 */
int main( int argc, char **argv )
{
    GtkBuilder *builder;
    GtkWidget  *window;
    GError     *error = NULL;
    GtkButton *button;
    GtkLabel *label;

    cairo_surface_t *surface;

    /* Init GTK+ */
    gtk_init( &argc, &argv );

    /* 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, "dia_glade.glade", &error ) )
    {
        g_warning( "%s", error->message );
        g_free( error );
        return( 1 );
    }

    /* Get main window pointer from UI */
    window = GTK_WIDGET( gtk_builder_get_object( builder, "window1" ) );

    gpointer spinners[] = { gtk_builder_get_object( builder, "diam" )};

    /* Connect signals */
    gtk_builder_connect_signals( builder, spinners );

    g_signal_connect(G_OBJECT(window), "delete-event", (GCallback)gtk_main_quit, NULL);
    g_signal_connect(G_OBJECT("measure"), "clicked", (GCallback)ofruta, spinners);

    canvas = goo_canvas_new ();

    gtk_widget_set_size_request (canvas, 600, 465);
    goo_canvas_set_bounds (GOO_CANVAS (canvas), 0, 0, 1000, 1000);
    gtk_widget_show (canvas);

    gtk_container_add (GTK_CONTAINER (gtk_builder_get_object( builder, "draw_area" )), canvas);

    root = goo_canvas_get_root_item (GOO_CANVAS (canvas));

    /* Destroy builder, since we don't need it anymore */
    g_object_unref( G_OBJECT( builder ) );

    /* Show window. All other widgets are automatically shown by GtkBuilder */
    gtk_widget_show( window );

    /* Start main loop */
    gtk_main();

    return( 0 );
}

When click on button called "measure" it handler called "ofruta" in "ofruta" it calls the drawing function.

Is this a correct method?

Ziezi
  • 6,375
  • 3
  • 39
  • 49
inckka
  • 345
  • 7
  • 21
  • Draw full-canvas-sized filled rect with your 'clear' colour. – keltar Jan 29 '16 at 09:21
  • @keltar Actually I intend to use a video feed as an background. Is it still possible? – inckka Jan 29 '16 at 09:23
  • Quite the same, if performance would be acceptable. Just draw image, it should overwrite previous contents. – keltar Jan 29 '16 at 09:46
  • @keltar Can you see my code above (just updated). I'm calling a function to draw the paths. I need to refresh/update the cavas/items somehow. – inckka Jan 29 '16 at 10:02
  • 1
    Well you're creating paths each time so as a result you have more and more paths on each call. You should either remove old paths with `goo_canvas_item_remove` before creating new path (but check for NULL, of course), or use separate path model and modify it (may be harder but logically better). Try removing old paths first, it is fairly simple. – keltar Jan 29 '16 at 10:30
  • @keltar Hey that worked. I struggled for 6 hours to find this. Great. I'm eager to implement the model (which would be the correct way). Can you make an example? – inckka Jan 29 '16 at 10:40
  • 1
    I'll look into that later today, will let you know. – keltar Jan 29 '16 at 10:47

1 Answers1

1

Here is an example based on https://developer.gnome.org/goocanvas/unstable/goocanvas-model-view-canvas.html :

#include <stdlib.h>
#include <goocanvas.h>

static gboolean on_rect_button_press (GooCanvasItem  *view,
        GooCanvasItem  *target,
        GdkEventButton *event,
        gpointer        data);

static gboolean on_delete_event      (GtkWidget      *window,
        GdkEvent       *event,
        gpointer        unused_data);


GooCanvasItemModel *root, *rect_model, *text_model, *path;

int main (int argc, char *argv[]) {
    GtkWidget *window, *scrolled_win, *canvas;
    GooCanvasItem *rect_item;

    gtk_set_locale ();
    gtk_init (&argc, &argv);

    window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
    gtk_window_set_default_size (GTK_WINDOW (window), 640, 600);
    gtk_widget_show (window);
    g_signal_connect (window, "delete_event", (GtkSignalFunc) on_delete_event,
            NULL);

    scrolled_win = gtk_scrolled_window_new (NULL, NULL);
    gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_win),
            GTK_SHADOW_IN);
    gtk_widget_show (scrolled_win);
    gtk_container_add (GTK_CONTAINER (window), scrolled_win);

    canvas = goo_canvas_new ();
    gtk_widget_set_size_request (canvas, 600, 450);
    goo_canvas_set_bounds (GOO_CANVAS (canvas), 0, 0, 1000, 1000);
    gtk_widget_show (canvas);
    gtk_container_add (GTK_CONTAINER (scrolled_win), canvas);

    root = goo_canvas_group_model_new (NULL, NULL);

    rect_model = goo_canvas_rect_model_new (root, 100, 100, 400, 400,
            "line-width", 10.0,
            "radius-x", 20.0,
            "radius-y", 10.0,
            "stroke-color", "yellow",
            "fill-color", "red",
            NULL);

    text_model = goo_canvas_text_model_new (root, "Hello World", 300, 300, -1,
            GTK_ANCHOR_CENTER,
            "font", "Sans 24",
            NULL);
    goo_canvas_item_model_rotate (text_model, 45, 300, 300);

    goo_canvas_set_root_item_model (GOO_CANVAS (canvas), root);

    GooCanvasLineDash *dash = goo_canvas_line_dash_new (2, 5.0, 5.0);
    const char *buf = "M 0 128 L 1000 256";
    path = goo_canvas_path_model_new (root, buf,
            "stroke-color", "red",
            "line-dash", dash,
            NULL);

    rect_item = goo_canvas_get_item (GOO_CANVAS (canvas), rect_model);
    g_signal_connect (rect_item, "button_press_event",
            (GtkSignalFunc) on_rect_button_press, NULL);

    goo_canvas_line_dash_unref(dash);

    gtk_main ();

    return 0;
}


static gboolean on_rect_button_press (GooCanvasItem  *item,
        GooCanvasItem  *target,
        GdkEventButton *event,
        gpointer        data) {
    g_print ("rect item received button press event\n");

    static float a = 128, b = 256;
    a += 16, b += 16;

    char buf[64];
    snprintf(buf, sizeof(buf), "M 0 %f L 1000 %f", a, b);
    g_object_set(G_OBJECT(path), "data", buf, NULL);

    return TRUE;
}


static gboolean on_delete_event (GtkWidget *window,
        GdkEvent  *event,
        gpointer   unused_data) {
    exit (0);
}

By modifying path's data property with g_object_set it moves when click on rectangle occurs. Properties names should be taken from documentation, e.g. https://developer.gnome.org/goocanvas/unstable/GooCanvasPathModel.html

keltar
  • 17,711
  • 2
  • 37
  • 42
  • Above model code worked. Thanks. However how to make a dashed line (path) with this model. There's no any documentations available. – inckka Feb 11 '16 at 07:53
  • 1
    It should be a separate question, but anyway - it is done by setting `line-dash` property. https://git.gnome.org/browse/goocanvas/tree/demo/demo-events.c have an example for rect, but it is the same. Don't forget to unref it with `goo_canvas_line_dash_unref`. – keltar Feb 11 '16 at 13:59
  • Isn't this the way for GooCanvasItem(simple)? My current approach is using GooCanvasItemModel. If I create dashed line using simple method, I cant include that in to the GooCanvasItemModel parent 'root'. And gives me a compiling warning: http://paste.ubuntu.com/15021932/ – inckka Feb 12 '16 at 04:01
  • 1
    Model have the same property. See updated code in answer. – keltar Feb 12 '16 at 04:28
  • That is perfect. it works. Thanks a lot. I have another problem about goocanvas http://stackoverflow.com/questions/35355077/how-to-overlay-a-live-video-behind-a-gtk-goocanvas-drawing Ideas are welcome. – inckka Feb 12 '16 at 04:56
  • Please let me know, how can I transparent the background of goocanvas? – inckka Feb 12 '16 at 06:46