Tue, 06 Aug 2019 03:18:32 -0400
Re-arrange whiteboard to avoid prototypes.
| pidgin/gtkwhiteboard.c | file | annotate | diff | comparison | revisions |
--- a/pidgin/gtkwhiteboard.c Tue Aug 06 01:49:55 2019 -0400 +++ b/pidgin/gtkwhiteboard.c Tue Aug 06 03:18:32 2019 -0400 @@ -74,43 +74,6 @@ }; /****************************************************************************** - * Prototypes - *****************************************************************************/ -static void pidgin_whiteboard_create(PurpleWhiteboard *wb); - -static void pidgin_whiteboard_destroy(PurpleWhiteboard *wb); -static gboolean whiteboard_close_cb(GtkWidget *widget, GdkEvent *event, PidginWhiteboard *gtkwb); - -/*static void pidginwhiteboard_button_start_press(GtkButton *button, gpointer data); */ - -static gboolean pidgin_whiteboard_configure_event(GtkWidget *widget, GdkEventConfigure *event, gpointer data); -static gboolean -pidgin_whiteboard_draw_event(GtkWidget *widget, cairo_t *cr, - gpointer _gtkwb); - -static gboolean pidgin_whiteboard_brush_down(GtkWidget *widget, GdkEventButton *event, gpointer data); -static gboolean pidgin_whiteboard_brush_motion(GtkWidget *widget, GdkEventMotion *event, gpointer data); -static gboolean pidgin_whiteboard_brush_up(GtkWidget *widget, GdkEventButton *event, gpointer data); - -static void pidgin_whiteboard_draw_brush_point(PurpleWhiteboard *wb, - int x, int y, int color, int size); -static void pidgin_whiteboard_draw_brush_line(PurpleWhiteboard *wb, int x0, int y0, - int x1, int y1, int color, int size); - -static void pidgin_whiteboard_set_dimensions(PurpleWhiteboard *wb, int width, int height); -static void pidgin_whiteboard_set_brush(PurpleWhiteboard *wb, int size, int color); -static void pidgin_whiteboard_clear(PurpleWhiteboard *wb); - -static void pidgin_whiteboard_button_clear_press(GtkWidget *widget, gpointer data); -static void pidgin_whiteboard_button_save_press(GtkWidget *widget, gpointer data); - -static void pidgin_whiteboard_set_canvas_as_icon(PidginWhiteboard *gtkwb); - -static void pidgin_whiteboard_rgb24_to_rgba(int color_rgb, GdkRGBA *color); - -static void color_selected(GtkColorButton *button, PidginWhiteboard *gtkwb); - -/****************************************************************************** * Globals *****************************************************************************/ @@ -119,207 +82,15 @@ static int MotionCount; /* Tracks how many brush motions made */ static PidginWhiteboardBrushState brush_state = PIDGIN_WHITEBOARD_BRUSH_UP; -static PurpleWhiteboardUiOps ui_ops = -{ - pidgin_whiteboard_create, - pidgin_whiteboard_destroy, - pidgin_whiteboard_set_dimensions, - pidgin_whiteboard_set_brush, - pidgin_whiteboard_draw_brush_point, - pidgin_whiteboard_draw_brush_line, - pidgin_whiteboard_clear, - NULL, - NULL, - NULL, - NULL -}; - /****************************************************************************** - * API + * Helpers *****************************************************************************/ -PurpleWhiteboardUiOps *pidgin_whiteboard_get_ui_ops(void) -{ - return &ui_ops; -} - -static void pidgin_whiteboard_create(PurpleWhiteboard *wb) +static void +pidgin_whiteboard_rgb24_to_rgba(int color_rgb, GdkRGBA *color) { - PurpleBuddy *buddy; - GtkWidget *window; - GtkWidget *drawing_area; - GtkWidget *vbox_controls; - GtkWidget *hbox_canvas_and_controls; - - /* - -------------------------- - |[][][][palette[][][][][]| - |------------------------| - | canvas | con | - | | trol| - | | s | - | | | - | | | - -------------------------- - */ - GtkWidget *clear_button; - GtkWidget *save_button; - GtkWidget *color_button; - GdkRGBA color; - - PidginWhiteboard *gtkwb = g_new0(PidginWhiteboard, 1); - gtkwb->priv = g_new0(PidginWhiteboardPrivate, 1); - - gtkwb->wb = wb; - purple_whiteboard_set_ui_data(wb, gtkwb); - - /* Get dimensions (default?) for the whiteboard canvas */ - if (!purple_whiteboard_get_dimensions(wb, >kwb->width, >kwb->height)) - { - /* Give some initial board-size */ - gtkwb->width = 300; - gtkwb->height = 250; - } - - if (!purple_whiteboard_get_brush(wb, >kwb->brush_size, >kwb->brush_color)) - { - /* Give some initial brush-info */ - gtkwb->brush_size = 2; - gtkwb->brush_color = 0xff0000; - } - - /* Try and set window title as the name of the buddy, else just use their - * username - */ - buddy = purple_blist_find_buddy(purple_whiteboard_get_account(wb), purple_whiteboard_get_who(wb)); - - window = pidgin_create_window(buddy != NULL ? purple_buddy_get_contact_alias(buddy) : purple_whiteboard_get_who(wb), 0, NULL, FALSE); - gtkwb->window = window; - gtk_widget_set_name(window, purple_whiteboard_get_who(wb)); - - g_signal_connect(G_OBJECT(window), "delete_event", - G_CALLBACK(whiteboard_close_cb), gtkwb); - - hbox_canvas_and_controls = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); - gtk_widget_show(hbox_canvas_and_controls); - - gtk_container_add(GTK_CONTAINER(window), hbox_canvas_and_controls); - gtk_container_set_border_width(GTK_CONTAINER(window), PIDGIN_HIG_BORDER); - - /* Create the drawing area */ - drawing_area = gtk_drawing_area_new(); - gtkwb->drawing_area = drawing_area; - gtk_widget_set_size_request(GTK_WIDGET(drawing_area), gtkwb->width, gtkwb->height); - gtk_box_pack_start(GTK_BOX(hbox_canvas_and_controls), drawing_area, TRUE, TRUE, PIDGIN_HIG_BOX_SPACE); - - gtk_widget_show(drawing_area); - - /* Signals used to handle backing pixmap */ - g_signal_connect(G_OBJECT(drawing_area), "draw", - G_CALLBACK(pidgin_whiteboard_draw_event), gtkwb); - - g_signal_connect(G_OBJECT(drawing_area), "configure-event", - G_CALLBACK(pidgin_whiteboard_configure_event), gtkwb); - - /* Event signals */ - g_signal_connect(G_OBJECT(drawing_area), "button_press_event", - G_CALLBACK(pidgin_whiteboard_brush_down), gtkwb); - - g_signal_connect(G_OBJECT(drawing_area), "motion_notify_event", - G_CALLBACK(pidgin_whiteboard_brush_motion), gtkwb); - - g_signal_connect(G_OBJECT(drawing_area), "button_release_event", - G_CALLBACK(pidgin_whiteboard_brush_up), gtkwb); - - gtk_widget_set_events(drawing_area, - GDK_EXPOSURE_MASK | - GDK_LEAVE_NOTIFY_MASK | - GDK_BUTTON_PRESS_MASK | - GDK_POINTER_MOTION_MASK | - GDK_BUTTON_RELEASE_MASK | - GDK_POINTER_MOTION_HINT_MASK); - - /* Create vertical box to contain the controls */ - vbox_controls = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); - gtk_box_pack_start(GTK_BOX(hbox_canvas_and_controls), - vbox_controls, FALSE, FALSE, PIDGIN_HIG_BOX_SPACE); - gtk_widget_show(vbox_controls); - - /* Add a clear button */ - clear_button = gtk_button_new_from_stock(GTK_STOCK_CLEAR); - gtk_box_pack_start(GTK_BOX(vbox_controls), clear_button, FALSE, FALSE, PIDGIN_HIG_BOX_SPACE); - gtk_widget_show(clear_button); - g_signal_connect(G_OBJECT(clear_button), "clicked", - G_CALLBACK(pidgin_whiteboard_button_clear_press), gtkwb); - - /* Add a save button */ - save_button = gtk_button_new_from_stock(GTK_STOCK_SAVE); - gtk_box_pack_start(GTK_BOX(vbox_controls), save_button, FALSE, FALSE, PIDGIN_HIG_BOX_SPACE); - gtk_widget_show(save_button); - - g_signal_connect(G_OBJECT(save_button), "clicked", - G_CALLBACK(pidgin_whiteboard_button_save_press), gtkwb); - - /* Add a color selector */ - color_button = gtk_color_button_new(); - gtk_box_pack_start(GTK_BOX(vbox_controls), color_button, FALSE, FALSE, PIDGIN_HIG_BOX_SPACE); - gtk_widget_show(color_button); - - gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(color_button), FALSE); - pidgin_whiteboard_rgb24_to_rgba(gtkwb->brush_color, &color); - gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(color_button), &color); - - g_signal_connect(G_OBJECT(color_button), "color-set", - G_CALLBACK(color_selected), gtkwb); - - /* Make all this (window) visible */ - gtk_widget_show(window); - - pidgin_whiteboard_set_canvas_as_icon(gtkwb); - - /* TODO Specific protocol/whiteboard assignment here? Needs a UI Op? */ - /* Set default brush size and color */ - /* - ds->brush_size = DOODLE_BRUSH_MEDIUM; - ds->brush_color = 0; - */ -} - -static void pidgin_whiteboard_destroy(PurpleWhiteboard *wb) -{ - PidginWhiteboard *gtkwb; - GtkWidget *colour_dialog; - - g_return_if_fail(wb != NULL); - gtkwb = purple_whiteboard_get_ui_data(wb); - g_return_if_fail(gtkwb != NULL); - - /* TODO Ask if user wants to save picture before the session is closed */ - - /* Clear graphical memory */ - if (gtkwb->priv->cr) { - cairo_destroy(gtkwb->priv->cr); - gtkwb->priv->cr = NULL; - } - if (gtkwb->priv->surface) { - cairo_surface_destroy(gtkwb->priv->surface); - gtkwb->priv->surface = NULL; - } - - colour_dialog = g_object_get_data(G_OBJECT(gtkwb->window), "colour-dialog"); - if (colour_dialog) { - gtk_widget_destroy(colour_dialog); - g_object_set_data(G_OBJECT(gtkwb->window), "colour-dialog", NULL); - } - - if(gtkwb->window) - { - gtk_widget_destroy(gtkwb->window); - gtkwb->window = NULL; - } - - g_free(gtkwb->priv); - g_free(gtkwb); - purple_whiteboard_set_ui_data(wb, NULL); + color->red = ((color_rgb >> 16) & 0xFF) / 255.0f; + color->green = ((color_rgb >> 8) & 0xFF) / 255.0f; + color->blue = (color_rgb & 0xFF) / 255.0f; } static gboolean whiteboard_close_cb(GtkWidget *widget, GdkEvent *event, PidginWhiteboard *gtkwb) @@ -335,42 +106,6 @@ return FALSE; } -/* - * Whiteboard start button on conversation window (move this code to gtkconv? - * and use new protocol member?) - */ -#if 0 -static void pidginwhiteboard_button_start_press(GtkButton *button, gpointer data) -{ - PurpleConversation *conv = data; - PurpleAccount *account = purple_conversation_get_account(conv); - PurpleConnection *gc = purple_account_get_connection(account); - char *to = (char*)(purple_conversation_get_name(conv)); - - /* Only handle this if local client requested Doodle session (else local - * client would have sent one) - */ - PurpleWhiteboard *wb = purple_whiteboard_get(account, to); - - /* Write a local message to this conversation showing that a request for a - * Doodle session has been made - */ - /* XXXX because otherwise gettext will see this string, even though it's - * in an #if 0 block. Remove the XXXX if you want to use this code. - * But, it really shouldn't be a Yahoo-specific string. ;) */ - purple_im_conversation_write_message(PURPLE_CONV_IM(conv), "", XXXX_("Sent Doodle request."), - PURPLE_MESSAGE_NICK | PURPLE_MESSAGE_RECV, time(NULL)); - - yahoo_doodle_command_send_request(gc, to); - yahoo_doodle_command_send_ready(gc, to); - - /* Insert this 'session' in the list. At this point, it's only a requested - * session. - */ - wb = purple_whiteboard_new(account, to, DOODLE_STATE_REQUESTING); -} -#endif - static gboolean pidgin_whiteboard_configure_event(GtkWidget *widget, GdkEventConfigure *event, gpointer data) { PidginWhiteboard *gtkwb = (PidginWhiteboard*)data; @@ -407,6 +142,114 @@ return FALSE; } +static void +pidgin_whiteboard_set_canvas_as_icon(PidginWhiteboard *gtkwb) +{ + GdkPixbuf *pixbuf; + + /* Makes an icon from the whiteboard's canvas 'image' */ + pixbuf = gdk_pixbuf_get_from_surface(gtkwb->priv->surface, 0, 0, + gtkwb->width, gtkwb->height); + gtk_window_set_icon(GTK_WINDOW(gtkwb->window), pixbuf); + g_object_unref(pixbuf); +} + +static void +pidgin_whiteboard_draw_brush_point(PurpleWhiteboard *wb, int x, int y, + int color, int size) +{ + PidginWhiteboard *gtkwb = purple_whiteboard_get_ui_data(wb); + GtkWidget *widget = gtkwb->drawing_area; + cairo_t *gfx_con = gtkwb->priv->cr; + GdkRGBA rgba; + + /* Interpret and convert color */ + pidgin_whiteboard_rgb24_to_rgba(color, &rgba); + gdk_cairo_set_source_rgba(gfx_con, &rgba); + + /* Draw a circle */ + cairo_arc(gfx_con, x, y, size / 2.0, 0.0, 2.0 * M_PI); + cairo_fill(gfx_con); + + gtk_widget_queue_draw_area(widget, x - size / 2, y - size / 2, size, + size); +} +/* Uses Bresenham's algorithm (as provided by Wikipedia) */ +static void +pidgin_whiteboard_draw_brush_line(PurpleWhiteboard *wb, int x0, int y0, int x1, + int y1, int color, int size) +{ + int temp; + + int xstep; + int ystep; + + int dx; + int dy; + + int error; + int derror; + + int x; + int y; + + gboolean steep = abs(y1 - y0) > abs(x1 - x0); + + if (steep) { + temp = x0; + x0 = y0; + y0 = temp; + temp = x1; + x1 = y1; + y1 = temp; + } + + dx = abs(x1 - x0); + dy = abs(y1 - y0); + + error = 0; + derror = dy; + + x = x0; + y = y0; + + if (x0 < x1) { + xstep = 1; + } else { + xstep = -1; + } + + if (y0 < y1) { + ystep = 1; + } else { + ystep = -1; + } + + if (steep) { + pidgin_whiteboard_draw_brush_point(wb, y, x, color, size); + } else { + pidgin_whiteboard_draw_brush_point(wb, x, y, color, size); + } + + while (x != x1) { + x += xstep; + error += derror; + + if ((error * 2) >= dx) { + y += ystep; + error -= dx; + } + + if (steep) { + pidgin_whiteboard_draw_brush_point(wb, y, x, color, + size); + } else { + pidgin_whiteboard_draw_brush_point(wb, x, y, color, + size); + } + } +} + static gboolean pidgin_whiteboard_brush_down(GtkWidget *widget, GdkEventButton *event, gpointer data) { PidginWhiteboard *gtkwb = (PidginWhiteboard*)data; @@ -566,32 +409,28 @@ /* If the brush was never moved, express two sets of two deltas That's a * 'point,' but not for Yahoo! */ - /* if((event->x == LastX) && (event->y == LastY)) */ if(MotionCount == 0) { int index; /* For Yahoo!, a (0 0) indicates the end of drawing */ /* FIXME: Yahoo Doodle specific! */ - for(index = 0; index < 2; index++) - { + for (index = 0; index < 2; index++) { draw_list = g_list_append(draw_list, 0); draw_list = g_list_append(draw_list, 0); } } - /* - else - MotionCount = 0; - */ /* Send draw list to protocol draw_list handler */ purple_whiteboard_send_draw_list(gtkwb->wb, draw_list); pidgin_whiteboard_set_canvas_as_icon(gtkwb); - /* The brush stroke is finished, clear the list for another one */ - if(draw_list) + /* The brush stroke is finished, clear the list for another one + */ + if (draw_list) { purple_whiteboard_draw_list_destroy(draw_list); + } purple_whiteboard_set_draw_list(wb, NULL); } @@ -599,96 +438,6 @@ return TRUE; } -static void pidgin_whiteboard_draw_brush_point(PurpleWhiteboard *wb, int x, int y, int color, int size) -{ - PidginWhiteboard *gtkwb = purple_whiteboard_get_ui_data(wb); - GtkWidget *widget = gtkwb->drawing_area; - cairo_t *gfx_con = gtkwb->priv->cr; - GdkRGBA rgba; - - /* Interpret and convert color */ - pidgin_whiteboard_rgb24_to_rgba(color, &rgba); - gdk_cairo_set_source_rgba(gfx_con, &rgba); - - /* Draw a circle */ - cairo_arc(gfx_con, - x, y, - size / 2.0, - 0.0, 2.0 * M_PI); - cairo_fill(gfx_con); - - gtk_widget_queue_draw_area(widget, - x - size / 2, y - size / 2, - size, size); -} - -/* Uses Bresenham's algorithm (as provided by Wikipedia) */ -static void pidgin_whiteboard_draw_brush_line(PurpleWhiteboard *wb, int x0, int y0, int x1, int y1, int color, int size) -{ - int temp; - - int xstep; - int ystep; - - int dx; - int dy; - - int error; - int derror; - - int x; - int y; - - gboolean steep = abs(y1 - y0) > abs(x1 - x0); - - if(steep) - { - temp = x0; x0 = y0; y0 = temp; - temp = x1; x1 = y1; y1 = temp; - } - - dx = abs(x1 - x0); - dy = abs(y1 - y0); - - error = 0; - derror = dy; - - x = x0; - y = y0; - - if(x0 < x1) - xstep = 1; - else - xstep = -1; - - if(y0 < y1) - ystep = 1; - else - ystep = -1; - - if(steep) - pidgin_whiteboard_draw_brush_point(wb, y, x, color, size); - else - pidgin_whiteboard_draw_brush_point(wb, x, y, color, size); - - while(x != x1) - { - x += xstep; - error += derror; - - if((error * 2) >= dx) - { - y += ystep; - error -= dx; - } - - if(steep) - pidgin_whiteboard_draw_brush_point(wb, y, x, color, size); - else - pidgin_whiteboard_draw_brush_point(wb, x, y, color, size); - } -} - static void pidgin_whiteboard_set_dimensions(PurpleWhiteboard *wb, int width, int height) { PidginWhiteboard *gtkwb = purple_whiteboard_get_ui_data(wb); @@ -795,24 +544,6 @@ gtk_widget_destroy(dialog); } -static void pidgin_whiteboard_set_canvas_as_icon(PidginWhiteboard *gtkwb) -{ - GdkPixbuf *pixbuf; - - /* Makes an icon from the whiteboard's canvas 'image' */ - pixbuf = gdk_pixbuf_get_from_surface(gtkwb->priv->surface, - 0, 0, gtkwb->width, gtkwb->height); - gtk_window_set_icon(GTK_WINDOW(gtkwb->window), pixbuf); - g_object_unref(pixbuf); -} - -static void pidgin_whiteboard_rgb24_to_rgba(int color_rgb, GdkRGBA *color) -{ - color->red = ((color_rgb >> 16) & 0xFF) / 255.0f; - color->green = ((color_rgb >> 8) & 0xFF) / 255.0f; - color->blue = (color_rgb & 0xFF) / 255.0f; -} - static void color_selected(GtkColorButton *button, PidginWhiteboard *gtkwb) { @@ -831,3 +562,220 @@ purple_whiteboard_send_brush(wb, old_size, new_color); } +static void +pidgin_whiteboard_create(PurpleWhiteboard *wb) +{ + PurpleBuddy *buddy; + GtkWidget *window; + GtkWidget *drawing_area; + GtkWidget *vbox_controls; + GtkWidget *hbox_canvas_and_controls; + + /* + -------------------------- + |[][][][palette[][][][][]| + |------------------------| + | canvas | con | + | | trol| + | | s | + | | | + | | | + -------------------------- + */ + GtkWidget *clear_button; + GtkWidget *save_button; + GtkWidget *color_button; + GdkRGBA color; + + PidginWhiteboard *gtkwb = g_new0(PidginWhiteboard, 1); + gtkwb->priv = g_new0(PidginWhiteboardPrivate, 1); + + gtkwb->wb = wb; + purple_whiteboard_set_ui_data(wb, gtkwb); + + /* Get dimensions (default?) for the whiteboard canvas */ + if (!purple_whiteboard_get_dimensions(wb, >kwb->width, + >kwb->height)) { + /* Give some initial board-size */ + gtkwb->width = 300; + gtkwb->height = 250; + } + + if (!purple_whiteboard_get_brush(wb, >kwb->brush_size, + >kwb->brush_color)) { + /* Give some initial brush-info */ + gtkwb->brush_size = 2; + gtkwb->brush_color = 0xff0000; + } + + /* Try and set window title as the name of the buddy, else just use + * their username + */ + buddy = purple_blist_find_buddy(purple_whiteboard_get_account(wb), + purple_whiteboard_get_who(wb)); + + window = pidgin_create_window( + buddy != NULL ? purple_buddy_get_contact_alias(buddy) + : purple_whiteboard_get_who(wb), + 0, NULL, FALSE); + gtkwb->window = window; + gtk_widget_set_name(window, purple_whiteboard_get_who(wb)); + + g_signal_connect(G_OBJECT(window), "delete_event", + G_CALLBACK(whiteboard_close_cb), gtkwb); + + hbox_canvas_and_controls = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); + gtk_widget_show(hbox_canvas_and_controls); + + gtk_container_add(GTK_CONTAINER(window), hbox_canvas_and_controls); + gtk_container_set_border_width(GTK_CONTAINER(window), + PIDGIN_HIG_BORDER); + + /* Create the drawing area */ + drawing_area = gtk_drawing_area_new(); + gtkwb->drawing_area = drawing_area; + gtk_widget_set_size_request(GTK_WIDGET(drawing_area), gtkwb->width, + gtkwb->height); + gtk_box_pack_start(GTK_BOX(hbox_canvas_and_controls), drawing_area, + TRUE, TRUE, PIDGIN_HIG_BOX_SPACE); + + gtk_widget_show(drawing_area); + + /* Signals used to handle backing pixmap */ + g_signal_connect(G_OBJECT(drawing_area), "draw", + G_CALLBACK(pidgin_whiteboard_draw_event), gtkwb); + + g_signal_connect(G_OBJECT(drawing_area), "configure-event", + G_CALLBACK(pidgin_whiteboard_configure_event), gtkwb); + + /* Event signals */ + g_signal_connect(G_OBJECT(drawing_area), "button_press_event", + G_CALLBACK(pidgin_whiteboard_brush_down), gtkwb); + + g_signal_connect(G_OBJECT(drawing_area), "motion_notify_event", + G_CALLBACK(pidgin_whiteboard_brush_motion), gtkwb); + + g_signal_connect(G_OBJECT(drawing_area), "button_release_event", + G_CALLBACK(pidgin_whiteboard_brush_up), gtkwb); + + gtk_widget_set_events( + drawing_area, + GDK_EXPOSURE_MASK | GDK_LEAVE_NOTIFY_MASK | + GDK_BUTTON_PRESS_MASK | GDK_POINTER_MOTION_MASK | + GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_HINT_MASK); + + /* Create vertical box to contain the controls */ + vbox_controls = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); + gtk_box_pack_start(GTK_BOX(hbox_canvas_and_controls), vbox_controls, + FALSE, FALSE, PIDGIN_HIG_BOX_SPACE); + gtk_widget_show(vbox_controls); + + /* Add a clear button */ + clear_button = gtk_button_new_from_stock(GTK_STOCK_CLEAR); + gtk_box_pack_start(GTK_BOX(vbox_controls), clear_button, FALSE, FALSE, + PIDGIN_HIG_BOX_SPACE); + gtk_widget_show(clear_button); + g_signal_connect(G_OBJECT(clear_button), "clicked", + G_CALLBACK(pidgin_whiteboard_button_clear_press), + gtkwb); + + /* Add a save button */ + save_button = gtk_button_new_from_stock(GTK_STOCK_SAVE); + gtk_box_pack_start(GTK_BOX(vbox_controls), save_button, FALSE, FALSE, + PIDGIN_HIG_BOX_SPACE); + gtk_widget_show(save_button); + + g_signal_connect(G_OBJECT(save_button), "clicked", + G_CALLBACK(pidgin_whiteboard_button_save_press), + gtkwb); + + /* Add a color selector */ + color_button = gtk_color_button_new(); + gtk_box_pack_start(GTK_BOX(vbox_controls), color_button, FALSE, FALSE, + PIDGIN_HIG_BOX_SPACE); + gtk_widget_show(color_button); + + gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(color_button), FALSE); + pidgin_whiteboard_rgb24_to_rgba(gtkwb->brush_color, &color); + gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(color_button), &color); + + g_signal_connect(G_OBJECT(color_button), "color-set", + G_CALLBACK(color_selected), gtkwb); + + /* Make all this (window) visible */ + gtk_widget_show(window); + + pidgin_whiteboard_set_canvas_as_icon(gtkwb); + + /* TODO Specific protocol/whiteboard assignment here? Needs a UI Op? */ + /* Set default brush size and color */ + /* + ds->brush_size = DOODLE_BRUSH_MEDIUM; + ds->brush_color = 0; + */ +} + +static void +pidgin_whiteboard_destroy(PurpleWhiteboard *wb) +{ + PidginWhiteboard *gtkwb; + GtkWidget *colour_dialog; + + g_return_if_fail(wb != NULL); + gtkwb = purple_whiteboard_get_ui_data(wb); + g_return_if_fail(gtkwb != NULL); + + /* TODO Ask if user wants to save picture before the session is closed + */ + + /* Clear graphical memory */ + if (gtkwb->priv->cr) { + cairo_destroy(gtkwb->priv->cr); + gtkwb->priv->cr = NULL; + } + if (gtkwb->priv->surface) { + cairo_surface_destroy(gtkwb->priv->surface); + gtkwb->priv->surface = NULL; + } + + colour_dialog = + g_object_get_data(G_OBJECT(gtkwb->window), "colour-dialog"); + if (colour_dialog) { + gtk_widget_destroy(colour_dialog); + g_object_set_data(G_OBJECT(gtkwb->window), "colour-dialog", + NULL); + } + + if (gtkwb->window) { + gtk_widget_destroy(gtkwb->window); + gtkwb->window = NULL; + } + + g_free(gtkwb->priv); + g_free(gtkwb); + purple_whiteboard_set_ui_data(wb, NULL); +} + +/****************************************************************************** + * API + *****************************************************************************/ +static PurpleWhiteboardUiOps ui_ops = +{ + pidgin_whiteboard_create, + pidgin_whiteboard_destroy, + pidgin_whiteboard_set_dimensions, + pidgin_whiteboard_set_brush, + pidgin_whiteboard_draw_brush_point, + pidgin_whiteboard_draw_brush_line, + pidgin_whiteboard_clear, + NULL, + NULL, + NULL, + NULL +}; + +PurpleWhiteboardUiOps * +pidgin_whiteboard_get_ui_ops(void) +{ + return &ui_ops; +}