Mercurial > pidgin.yaz
annotate src/gtkwhiteboard.c @ 11549:8b494b5763c2
[gaim-migrate @ 13804]
We were both adding and removing /gaim/gtk/conversations/send_formatting,
I figured that wasn't right so I removed it completely.
Also, do we really want to be calling stylize in gtkutils.c? It seems
like that would conflict with all the formatting done by the gtkimhtml.
Can someone please look at that? It shouldn't take too long to figure
it out if you're familiar with gtkimhtml.
committer: Tailor Script <tailor@pidgin.im>
author | Mark Doliner <mark@kingant.net> |
---|---|
date | Thu, 15 Sep 2005 04:54:26 +0000 |
parents | 88d504770c60 |
children | 19941a47405c |
rev | line source |
---|---|
11475 | 1 /* |
2 * gaim | |
3 * | |
4 * Gaim is the legal property of its developers, whose names are too numerous | |
5 * to list here. Please refer to the COPYRIGHT file distributed with this | |
6 * source distribution. | |
7 * | |
8 * This program is free software; you can redistribute it and/or modify | |
9 * it under the terms of the GNU General Public License as published by | |
10 * the Free Software Foundation; either version 2 of the License, or | |
11 * (at your option) any later version. | |
12 * | |
13 * This program is distributed in the hope that it will be useful, | |
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 * GNU General Public License for more details. | |
17 * | |
18 * You should have received a copy of the GNU General Public License | |
19 * along with this program; if not, write to the Free Software | |
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
21 * | |
22 */ | |
23 | |
24 // INCLUDES ============================================================================================ | |
25 | |
26 #include <stdlib.h> | |
27 | |
28 #include "blist.h" | |
29 | |
30 #include "gtkwhiteboard.h" | |
31 | |
32 // GLOBALS ============================================================================================= | |
33 | |
34 //GList *buttonList = NULL; | |
35 | |
36 //GdkColor DefaultColor[PALETTE_NUM_COLORS]; | |
37 | |
38 static gboolean LocalShutdownRequest; | |
39 | |
40 static int LastX; // Tracks last position of the mouse when drawing | |
41 static int LastY; | |
42 static int MotionCount; // Tracks how many brush motions made | |
43 static int BrushState = BRUSH_STATE_UP; | |
44 | |
45 static GaimWhiteboardUiOps ui_ops = | |
46 { | |
47 gaim_gtk_whiteboard_create, | |
48 gaim_gtk_whiteboard_destroy, | |
49 gaim_gtk_whiteboard_set_dimensions, | |
50 gaim_gtk_whiteboard_draw_brush_point, | |
51 gaim_gtk_whiteboard_draw_brush_line, | |
52 gaim_gtk_whiteboard_clear | |
53 }; | |
54 | |
55 // FUNCTIONS ============================================================================================ | |
56 | |
57 GaimWhiteboardUiOps *gaim_gtk_whiteboard_get_ui_ops( void ) | |
58 { | |
59 return( &ui_ops ); | |
60 } | |
61 | |
62 // ------------------------------------------------------------------------------------------------------ | |
63 | |
64 void gaim_gtk_whiteboard_create( GaimWhiteboard *wb ) | |
65 { | |
66 //g_print( "gaim_gtk_whiteboard_create()\n" ); | |
67 | |
68 int i; | |
69 | |
70 GtkWidget *window; | |
71 GtkWidget *drawing_area; | |
72 | |
73 GtkWidget *hbox_palette; | |
74 GtkWidget *vbox_palette_above_canvas_and_controls; | |
75 GtkWidget *hbox_canvas_and_controls; | |
76 GtkWidget *vbox_controls; | |
77 | |
78 // -------------------------- | |
79 // |[][][][palette[][][][][]| | |
80 // |------------------------| | |
81 // | canvas | con | | |
82 // | | trol| | |
83 // | | s | | |
84 // | | | | |
85 // | | | | |
86 // -------------------------- | |
87 | |
88 GtkWidget *clear_button; | |
89 GtkWidget *save_button; | |
90 | |
91 GtkWidget *palette_color_box[PALETTE_NUM_COLORS]; | |
11484
4539174a88bd
[gaim-migrate @ 13726]
Richard Laager <rlaager@wiktel.com>
parents:
11475
diff
changeset
|
92 /* GdkPixbuf *palette_color_area[PALETTE_NUM_COLORS]; */ |
11475 | 93 |
94 GaimGtkWhiteboard *gtkwb = g_new0( GaimGtkWhiteboard, 1 ); | |
11506
88d504770c60
[gaim-migrate @ 13751]
Richard Laager <rlaager@wiktel.com>
parents:
11484
diff
changeset
|
95 |
88d504770c60
[gaim-migrate @ 13751]
Richard Laager <rlaager@wiktel.com>
parents:
11484
diff
changeset
|
96 const char *window_title; |
88d504770c60
[gaim-migrate @ 13751]
Richard Laager <rlaager@wiktel.com>
parents:
11484
diff
changeset
|
97 |
11475 | 98 gtkwb->wb = wb; |
99 wb->ui_data = gtkwb; | |
100 | |
101 // Get dimensions (default?) for the whiteboard canvas | |
102 if( wb->prpl_ops && wb->prpl_ops->get_dimensions ) | |
103 wb->prpl_ops->get_dimensions( wb, >kwb->width, >kwb->height ); | |
104 | |
105 window = gtk_window_new( GTK_WINDOW_TOPLEVEL ); | |
106 gtkwb->window = window; | |
107 gtk_widget_set_name( window, wb->who ); | |
108 | |
109 // Try and set window title as the name of the buddy, else just use their username | |
11506
88d504770c60
[gaim-migrate @ 13751]
Richard Laager <rlaager@wiktel.com>
parents:
11484
diff
changeset
|
110 window_title = gaim_contact_get_alias( gaim_buddy_get_contact( gaim_find_buddy( wb->account, wb->who ) ) ); |
11475 | 111 if( window_title ) |
112 gtk_window_set_title( ( GtkWindow* )( window ), window_title ); | |
113 else | |
114 gtk_window_set_title( ( GtkWindow* )( window ), wb->who ); | |
115 | |
116 gtk_window_set_resizable( ( GtkWindow* )( window ), FALSE ); | |
117 | |
118 g_signal_connect( G_OBJECT( window ), "destroy", | |
119 G_CALLBACK( gaim_gtk_whiteboard_exit ), ( gpointer )( gtkwb ) ); | |
120 | |
121 // Create vertical box to place palette above the canvas and controls | |
122 vbox_palette_above_canvas_and_controls = gtk_vbox_new( FALSE, 0 ); | |
123 gtk_container_add( GTK_CONTAINER( window ), vbox_palette_above_canvas_and_controls ); | |
124 gtk_widget_show( vbox_palette_above_canvas_and_controls ); | |
125 | |
126 // Create horizontal box for the palette and all its entries | |
127 hbox_palette = gtk_hbox_new( FALSE, 0 ); | |
128 gtk_container_add( GTK_CONTAINER( vbox_palette_above_canvas_and_controls ), hbox_palette ); | |
129 gtk_widget_show( hbox_palette ); | |
130 | |
131 // Create horizontal box to seperate the canvas from the controls | |
132 hbox_canvas_and_controls = gtk_hbox_new( FALSE, 0 ); | |
133 gtk_container_add( GTK_CONTAINER( vbox_palette_above_canvas_and_controls ), hbox_canvas_and_controls ); | |
134 gtk_widget_show( hbox_canvas_and_controls ); | |
135 | |
136 for( i = 0; i < PALETTE_NUM_COLORS; i++ ) | |
137 { | |
138 //palette_color_area[i] = | |
139 | |
140 palette_color_box[i] = gtk_image_new_from_pixbuf( NULL ); | |
141 gtk_widget_set_size_request( palette_color_box[i], gtkwb->width / PALETTE_NUM_COLORS ,32 ); | |
142 gtk_container_add( GTK_CONTAINER( hbox_palette ), palette_color_box[i] ); | |
143 | |
144 | |
145 | |
146 gtk_widget_show( palette_color_box[i] ); | |
147 } | |
148 | |
149 // Create the drawing area | |
150 drawing_area = gtk_drawing_area_new(); | |
151 gtkwb->drawing_area = drawing_area; | |
152 gtk_widget_set_size_request( GTK_WIDGET( drawing_area ), gtkwb->width, gtkwb->height ); | |
153 gtk_box_pack_start( GTK_BOX( hbox_canvas_and_controls ), drawing_area, TRUE, TRUE, 8 ); | |
154 | |
155 gtk_widget_show( drawing_area ); | |
156 | |
157 // Signals used to handle backing pixmap | |
158 g_signal_connect( G_OBJECT( drawing_area ), "expose_event", | |
159 G_CALLBACK( gaim_gtk_whiteboard_expose_event ), ( gpointer )( gtkwb ) ); | |
160 | |
161 g_signal_connect( G_OBJECT( drawing_area ), "configure_event", | |
162 G_CALLBACK( gaim_gtk_whiteboard_configure_event ), ( gpointer )( gtkwb ) ); | |
163 | |
164 // Event signals | |
165 g_signal_connect( G_OBJECT( drawing_area ), "button_press_event", | |
166 G_CALLBACK( gaim_gtk_whiteboard_brush_down ), ( gpointer )( gtkwb ) ); | |
167 | |
168 g_signal_connect( G_OBJECT( drawing_area ), "motion_notify_event", | |
169 G_CALLBACK( gaim_gtk_whiteboard_brush_motion ), ( gpointer )( gtkwb ) ); | |
170 | |
171 g_signal_connect( G_OBJECT( drawing_area ), "button_release_event", | |
172 G_CALLBACK( gaim_gtk_whiteboard_brush_up ), ( gpointer )( gtkwb ) ); | |
173 | |
174 gtk_widget_set_events( drawing_area, GDK_EXPOSURE_MASK | | |
175 GDK_LEAVE_NOTIFY_MASK | | |
176 GDK_BUTTON_PRESS_MASK | | |
177 GDK_POINTER_MOTION_MASK | | |
178 GDK_BUTTON_RELEASE_MASK | | |
179 GDK_POINTER_MOTION_HINT_MASK ); | |
180 | |
181 // Create vertical box to contain the controls | |
182 vbox_controls = gtk_vbox_new( FALSE, 0 ); | |
183 gtk_container_add( GTK_CONTAINER( hbox_canvas_and_controls ), vbox_controls ); | |
184 gtk_widget_show( vbox_controls ); | |
185 | |
186 // Add a clear button | |
187 clear_button = gtk_button_new_with_label( "Clear" ); | |
188 gtk_widget_set_size_request( clear_button, 96 ,32 ); | |
189 gtk_box_pack_start( GTK_BOX( vbox_controls ), clear_button, FALSE, FALSE, 0 ); | |
190 gtk_widget_show( clear_button ); | |
191 | |
192 g_signal_connect( G_OBJECT( clear_button ), "clicked", | |
193 G_CALLBACK( gaim_gtk_whiteboard_button_clear_press ), ( gpointer )( gtkwb ) ); | |
194 | |
195 // Add a save button | |
196 save_button = gtk_button_new_with_label( "Save" ); | |
197 gtk_widget_set_size_request( save_button, 96 ,32 ); | |
198 gtk_box_pack_start( GTK_BOX( vbox_controls ), save_button, FALSE, FALSE, 8 ); | |
199 gtk_widget_show( save_button ); | |
200 | |
201 g_signal_connect( G_OBJECT( save_button ), "clicked", | |
202 G_CALLBACK( gaim_gtk_whiteboard_button_save_press ), ( gpointer )( gtkwb ) ); | |
203 | |
204 // Make all this (window) visible | |
205 gtk_widget_show( window ); | |
206 | |
207 gaim_gtk_whiteboard_set_canvas_as_icon( gtkwb ); | |
208 | |
209 // TODO Specific protocol/whiteboard assignment here? Needs a UI Op? | |
210 // Set default brush size and color | |
211 //ds->brush_size = DOODLE_BRUSH_MEDIUM; | |
212 //ds->brush_color = 0; // black | |
213 } | |
214 | |
215 // ------------------------------------------------------------------------------------------------------ | |
216 | |
217 void gaim_gtk_whiteboard_destroy( GaimWhiteboard *wb ) | |
218 { | |
219 //g_print( "gaim_gtk_whiteboard_destroy()\n" ); | |
220 | |
221 GaimGtkWhiteboard *gtkwb = wb->ui_data; | |
222 | |
223 // TODO Ask if user wants to save picture before the session is closed | |
224 | |
225 // Clear graphical memory | |
226 if( gtkwb->pixmap ) | |
227 { | |
228 //g_print( "---gtkwb->pixmap = %p\n", gtkwb->pixmap ); | |
229 g_object_unref( gtkwb->pixmap ); | |
230 gtkwb->pixmap = NULL; | |
231 } | |
232 | |
233 if( gtkwb->window ) | |
234 { | |
235 //g_print( "---gtkwb->window = %p\n", gtkwb->window ); | |
236 gtk_widget_destroy( gtkwb->window ); | |
237 gtkwb->window = NULL; | |
238 } | |
239 } | |
240 | |
241 // ------------------------------------------------------------------------------------------------------ | |
242 | |
243 void gaim_gtk_whiteboard_exit( GtkWidget *widget, gpointer data ) | |
244 { | |
245 //g_print( "gaim_gtk_whiteboard_exit()\n" ); | |
246 | |
247 GaimGtkWhiteboard *gtkwb = ( GaimGtkWhiteboard* )( data ); | |
248 GaimWhiteboard *wb = gtkwb->wb; | |
249 | |
250 if( gtkwb->window && gtkwb->pixmap ) | |
251 { | |
252 LocalShutdownRequest = TRUE; | |
253 | |
254 //g_print( "---gtkwb->window = %p\n", gtkwb->window ); | |
255 gaim_gtk_whiteboard_destroy( wb ); | |
256 } | |
257 else | |
258 LocalShutdownRequest = FALSE; | |
259 | |
260 if( gtkwb ) | |
261 { | |
262 //g_print( "---gtkwb = %p\n", gtkwb ); | |
263 g_free( gtkwb ); | |
264 | |
265 gtkwb = NULL; | |
266 wb->ui_data = NULL; | |
267 } | |
268 | |
269 // Destroy whiteboard core, if the local user exited the whiteboard window | |
270 if( wb && LocalShutdownRequest ) | |
271 { | |
272 //g_print( "---wb = %p\n", wb ); | |
273 gaim_whiteboard_destroy( wb ); | |
274 wb = NULL; | |
275 } | |
276 } | |
277 | |
278 // ------------------------------------------------------------------------------------------------------ | |
279 /* | |
280 // Whiteboard start button on conversation window (move this code to gtkconv? and use new prpl_info member?) | |
281 void gaim_gtkwhiteboard_button_start_press( GtkButton *button, gpointer data ) | |
282 { | |
283 GaimConversation *conv = data; | |
284 GaimAccount *account = gaim_conversation_get_account( conv ); | |
285 GaimConnection *gc = gaim_account_get_connection( account ); | |
286 char *to = ( char* )( gaim_conversation_get_name( conv ) ); | |
287 | |
288 // Only handle this if local client requested Doodle session (else local client would have sent one) | |
289 GaimWhiteboard *wb = gaim_whiteboard_get( account, to ); | |
290 | |
291 // Write a local message to this conversation showing that | |
292 // a request for a Doodle session has been made | |
293 gaim_conv_im_write( GAIM_CONV_IM( conv ), "", _("Sent Doodle request."), | |
294 GAIM_MESSAGE_NICK | GAIM_MESSAGE_RECV, time( NULL ) ); | |
295 | |
296 yahoo_doodle_command_send_request( gc, to ); | |
297 yahoo_doodle_command_send_ready( gc, to ); | |
298 | |
299 // Insert this 'session' in the list. At this point, it's only a requested session. | |
300 wb = gaim_whiteboard_create( account, to, DOODLE_STATE_REQUESTING ); | |
301 } | |
302 */ | |
303 // ------------------------------------------------------------------------------------------------------ | |
304 | |
305 gboolean gaim_gtk_whiteboard_configure_event( GtkWidget *widget, GdkEventConfigure *event, gpointer data ) | |
306 { | |
307 //g_print( "gaim_gtk_whiteboard_configure_event | %s\n", ds->who ); | |
308 | |
309 GaimGtkWhiteboard *gtkwb = ( GaimGtkWhiteboard* )( data ); | |
310 | |
311 GdkPixmap *pixmap = gtkwb->pixmap; | |
312 | |
313 if( pixmap ) | |
314 g_object_unref( pixmap ); | |
315 | |
316 pixmap = gdk_pixmap_new( widget->window, | |
317 widget->allocation.width, | |
318 widget->allocation.height, | |
319 -1 ); | |
320 | |
321 gtkwb->pixmap = pixmap; | |
322 | |
323 gdk_draw_rectangle( pixmap, | |
324 widget->style->white_gc, | |
325 TRUE, | |
326 0, 0, | |
327 widget->allocation.width, | |
328 widget->allocation.height ); | |
329 | |
330 return( TRUE ); | |
331 } | |
332 | |
333 // ------------------------------------------------------------------------------------------------------ | |
334 | |
335 gboolean gaim_gtk_whiteboard_expose_event( GtkWidget *widget, GdkEventExpose *event, gpointer data ) | |
336 { | |
337 //g_print( "gaim_gtk_whiteboard_expose_event | %s\n", ds->who ); | |
338 | |
339 GaimGtkWhiteboard *gtkwb = ( GaimGtkWhiteboard* )( data ); | |
340 GdkPixmap *pixmap = gtkwb->pixmap; | |
341 | |
342 gdk_draw_drawable( widget->window, | |
343 widget->style->fg_gc[GTK_WIDGET_STATE( widget )], | |
344 pixmap, | |
345 event->area.x, event->area.y, | |
346 event->area.x, event->area.y, | |
347 event->area.width, event->area.height ); | |
348 | |
349 return( FALSE ); | |
350 } | |
351 | |
352 // ------------------------------------------------------------------------------------------------------ | |
353 | |
354 gboolean gaim_gtk_whiteboard_brush_down( GtkWidget *widget, GdkEventButton *event, gpointer data ) | |
355 { | |
356 GaimGtkWhiteboard *gtkwb = ( GaimGtkWhiteboard* )( data ); | |
357 //g_print( "gaim_gtk_whiteboard_brush_down | %s\n", gtkwb->wb->who ); | |
358 GdkPixmap *pixmap = gtkwb->pixmap; | |
359 | |
360 GaimWhiteboard *wb = gtkwb->wb; | |
361 GList *draw_list = wb->draw_list; | |
362 | |
363 int *x0 = NULL; | |
364 int *y0 = NULL; | |
365 | |
366 if( BrushState != BRUSH_STATE_UP ) | |
367 { | |
368 // Potential double-click DOWN to DOWN? | |
369 | |
370 g_print( "***Bad brush state transition %d to DOWN\n", BrushState ); | |
371 | |
372 BrushState = BRUSH_STATE_DOWN; | |
373 | |
374 //return( FALSE ); | |
375 } | |
376 | |
377 BrushState = BRUSH_STATE_DOWN; | |
378 | |
379 if( event->button == 1 && pixmap != NULL ) | |
380 { | |
381 // Check if draw_list has contents; if so, clear it | |
382 if( draw_list ) | |
383 draw_list = gaim_whiteboard_draw_list_destroy( draw_list ); | |
384 | |
385 x0 = g_new0( int, 1 ); | |
386 y0 = g_new0( int, 1 ); | |
387 | |
388 *x0 = event->x; | |
389 *y0 = event->y; | |
390 | |
391 // Set tracking variables | |
392 LastX = *x0; | |
393 LastY = *y0; | |
394 | |
395 MotionCount = 0; | |
396 | |
397 draw_list = g_list_append( draw_list, ( gpointer )( x0 ) ); | |
398 draw_list = g_list_append( draw_list, ( gpointer )( y0 ) ); | |
399 | |
400 gaim_gtk_whiteboard_draw_brush_point( gtkwb->wb, | |
401 event->x, event->y, | |
402 0,5 );//gtkwb->brush_color, gtkwb->brush_size ); NOTE temp const prot uiop | |
403 } | |
404 | |
405 wb->draw_list = draw_list; | |
406 | |
407 return( TRUE ); | |
408 } | |
409 | |
410 // ------------------------------------------------------------------------------------------------------ | |
411 | |
412 gboolean gaim_gtk_whiteboard_brush_motion( GtkWidget *widget, GdkEventMotion *event, gpointer data ) | |
413 { | |
414 int x; | |
415 int y; | |
416 int *dx; | |
417 int *dy; | |
418 | |
419 GdkModifierType state; | |
420 | |
421 GaimGtkWhiteboard *gtkwb = ( GaimGtkWhiteboard* )( data ); | |
422 //g_print( "gaim_gtk_whiteboard_brush_motion | %s\n", gtkwb->wb->who ); | |
423 GdkPixmap *pixmap = gtkwb->pixmap; | |
424 | |
425 GaimWhiteboard *wb = gtkwb->wb; | |
426 GList *draw_list = wb->draw_list; | |
427 | |
428 if( event->is_hint ) | |
429 gdk_window_get_pointer( event->window, &x, &y, &state ); | |
430 else | |
431 { | |
432 x = event->x; | |
433 y = event->y; | |
434 state = event->state; | |
435 } | |
436 | |
437 if( state & GDK_BUTTON1_MASK && pixmap != NULL ) | |
438 { | |
439 if( ( BrushState != BRUSH_STATE_DOWN ) && ( BrushState != BRUSH_STATE_MOTION ) ) | |
440 { | |
441 g_print( "***Bad brush state transition %d to MOTION\n", BrushState ); | |
442 | |
443 BrushState = BRUSH_STATE_MOTION; | |
444 | |
445 return( FALSE ); | |
446 } | |
447 BrushState = BRUSH_STATE_MOTION; | |
448 | |
449 dx = g_new0( int, 1 ); | |
450 dy = g_new0( int, 1 ); | |
451 | |
452 *dx = x - LastX; | |
453 *dy = y - LastY; | |
454 | |
455 MotionCount++; | |
456 | |
457 // NOTE 100 is a temporary constant for how many deltas/motions in a stroke (needs UI Ops?) | |
458 if( MotionCount == 100 ) | |
459 { | |
11506
88d504770c60
[gaim-migrate @ 13751]
Richard Laager <rlaager@wiktel.com>
parents:
11484
diff
changeset
|
460 int *x0 = g_new0( int, 1 ); |
88d504770c60
[gaim-migrate @ 13751]
Richard Laager <rlaager@wiktel.com>
parents:
11484
diff
changeset
|
461 int *y0 = g_new0( int, 1 ); |
88d504770c60
[gaim-migrate @ 13751]
Richard Laager <rlaager@wiktel.com>
parents:
11484
diff
changeset
|
462 |
11475 | 463 draw_list = g_list_append( draw_list, ( gpointer )( dx ) ); |
464 draw_list = g_list_append( draw_list, ( gpointer )( dy ) ); | |
465 | |
466 // Send draw list to prpl draw_list handler | |
467 if( gtkwb->wb->prpl_ops && gtkwb->wb->prpl_ops->send_draw_list ) | |
468 gtkwb->wb->prpl_ops->send_draw_list( gtkwb->wb, draw_list ); | |
469 | |
470 // The brush stroke is finished, clear the list for another one | |
471 if( draw_list ) | |
472 draw_list = gaim_whiteboard_draw_list_destroy( draw_list ); | |
473 | |
474 *x0 = LastX; | |
475 *y0 = LastY; | |
476 | |
477 // Reset motion tracking | |
478 MotionCount = 0; | |
479 | |
480 draw_list = g_list_append( draw_list, ( gpointer )( x0 ) ); | |
481 draw_list = g_list_append( draw_list, ( gpointer )( y0 ) ); | |
482 | |
483 dx = g_new0( int, 1 ); | |
484 dy = g_new0( int, 1 ); | |
485 | |
486 *dx = x - LastX; | |
487 *dy = y - LastY; | |
488 } | |
489 | |
490 draw_list = g_list_append( draw_list, ( gpointer )( dx ) ); | |
491 draw_list = g_list_append( draw_list, ( gpointer )( dy ) ); | |
492 | |
493 gaim_gtk_whiteboard_draw_brush_line( gtkwb->wb, | |
494 LastX, LastY, | |
495 x, y, | |
496 0, 5 );//gtkwb->brush_color, gtkwb->brush_size ); temp const proto ui ops? | |
497 | |
498 // Set tracking variables | |
499 LastX = x; | |
500 LastY = y; | |
501 } | |
502 | |
503 wb->draw_list = draw_list; | |
504 | |
505 return( TRUE ); | |
506 } | |
507 | |
508 // ------------------------------------------------------------------------------------------------------ | |
509 | |
510 gboolean gaim_gtk_whiteboard_brush_up( GtkWidget *widget, GdkEventButton *event, gpointer data ) | |
511 { | |
512 GaimGtkWhiteboard *gtkwb = ( GaimGtkWhiteboard* )( data ); | |
513 //g_print( "gaim_gtk_whiteboard_brush_up | %s\n", gtkwb->wb->who ); | |
514 GdkPixmap *pixmap = gtkwb->pixmap; | |
515 | |
516 GaimWhiteboard *wb = gtkwb->wb; | |
517 GList *draw_list = wb->draw_list; | |
518 | |
519 if( ( BrushState != BRUSH_STATE_DOWN ) && ( BrushState != BRUSH_STATE_MOTION ) ) | |
520 { | |
521 g_print( "***Bad brush state transition %d to UP\n", BrushState ); | |
522 | |
523 BrushState = BRUSH_STATE_UP; | |
524 | |
525 return( FALSE ); | |
526 } | |
527 BrushState = BRUSH_STATE_UP; | |
528 | |
529 if( event->button == 1 && pixmap != NULL ) | |
530 { | |
531 // If the brush was never moved, express two sets of two deltas | |
532 // That's a 'point,' but not for Yahoo! | |
533 //if( ( event->x == LastX ) && ( event->y == LastY ) ) | |
534 if( MotionCount == 0 ) | |
535 { | |
536 int index; | |
537 | |
538 for( index = 0; index < 2; index++ ) // NOTE Yahoo Doodle specific! | |
539 { | |
540 int *x0 = NULL; | |
541 int *y0 = NULL; | |
542 | |
543 x0 = g_new0( int, 1 ); | |
544 y0 = g_new0( int, 1 ); | |
545 | |
546 draw_list = g_list_append( draw_list, ( gpointer )( x0 ) ); | |
547 draw_list = g_list_append( draw_list, ( gpointer )( y0 ) ); | |
548 } | |
549 } | |
550 //else | |
551 // MotionCount = 0; | |
552 | |
553 // Send draw list to prpl draw_list handler | |
554 if( gtkwb->wb->prpl_ops && gtkwb->wb->prpl_ops->send_draw_list ) | |
555 gtkwb->wb->prpl_ops->send_draw_list( gtkwb->wb, draw_list ); | |
556 | |
557 gaim_gtk_whiteboard_set_canvas_as_icon( gtkwb ); | |
558 | |
559 // The brush stroke is finished, clear the list for another one | |
560 if( draw_list ) | |
561 draw_list = gaim_whiteboard_draw_list_destroy( draw_list ); | |
562 | |
563 wb->draw_list = draw_list; | |
564 } | |
565 | |
566 return( TRUE ); | |
567 } | |
568 | |
569 // ------------------------------------------------------------------------------------------------------ | |
570 | |
571 // void gaim_gtk_whiteboard_draw_brush_point( GtkWidget *widget, GaimGtkWhiteboard *gtkwb, | |
572 // int x, int y, int color, int size ) | |
573 void gaim_gtk_whiteboard_draw_brush_point( GaimWhiteboard *wb, int x, int y, int color, int size ) | |
574 { | |
575 //g_print( "goodle_doodle_session_draw_brush | %s\n", ds->who ); | |
576 | |
577 GaimGtkWhiteboard *gtkwb = wb->ui_data; | |
578 GtkWidget *widget = gtkwb->drawing_area; | |
579 GdkPixmap *pixmap = gtkwb->pixmap; | |
580 | |
581 GdkRectangle update_rect; | |
582 | |
11506
88d504770c60
[gaim-migrate @ 13751]
Richard Laager <rlaager@wiktel.com>
parents:
11484
diff
changeset
|
583 GdkGC *gfx_con = gdk_gc_new( pixmap ); |
88d504770c60
[gaim-migrate @ 13751]
Richard Laager <rlaager@wiktel.com>
parents:
11484
diff
changeset
|
584 GdkColor col; |
88d504770c60
[gaim-migrate @ 13751]
Richard Laager <rlaager@wiktel.com>
parents:
11484
diff
changeset
|
585 |
11475 | 586 update_rect.x = x - size / 2; |
587 update_rect.y = y - size / 2; | |
588 update_rect.width = size; | |
589 update_rect.height = size; | |
590 | |
591 // Interpret and convert color | |
592 gaim_gtk_whiteboard_rgb24_to_rgb48( color, &col ); | |
593 | |
594 gdk_gc_set_rgb_fg_color( gfx_con, &col ); | |
595 //gdk_gc_set_rgb_bg_color( gfx_con, &col ); | |
596 | |
597 // NOTE 5 is a size constant for now... this is because of how poorly the gdk_draw_arc draws small circles | |
598 if( size < 5 ) | |
599 { | |
600 // Draw a rectangle/square | |
601 gdk_draw_rectangle( pixmap, | |
602 gfx_con, | |
603 TRUE, | |
604 update_rect.x, update_rect.y, | |
605 update_rect.width, update_rect.height ); | |
606 } | |
607 else | |
608 { | |
609 // Draw a circle | |
610 gdk_draw_arc( pixmap, | |
611 gfx_con, | |
612 TRUE, | |
613 update_rect.x, update_rect.y, | |
614 update_rect.width, update_rect.height, | |
615 0, FULL_CIRCLE_DEGREES ); | |
616 } | |
617 | |
618 gtk_widget_queue_draw_area( widget, | |
619 update_rect.x, update_rect.y, | |
620 update_rect.width, update_rect.height ); | |
621 | |
622 gdk_gc_unref( gfx_con ); | |
623 } | |
624 | |
625 // ------------------------------------------------------------------------------------------------------ | |
626 // Uses Bresenham's algorithm (as provided by Wikipedia) | |
627 // void gaim_gtk_whiteboard_draw_brush_line( GtkWidget *widget, GaimGtkWhiteboard *gtkwb, | |
628 // int x0, int y0, int x1, int y1, int color, int size ) | |
629 void gaim_gtk_whiteboard_draw_brush_line( GaimWhiteboard *wb, int x0, int y0, int x1, int y1, int color, int size ) | |
630 { | |
631 int temp; | |
632 | |
633 int xstep; | |
634 int ystep; | |
635 | |
11506
88d504770c60
[gaim-migrate @ 13751]
Richard Laager <rlaager@wiktel.com>
parents:
11484
diff
changeset
|
636 int dx; |
88d504770c60
[gaim-migrate @ 13751]
Richard Laager <rlaager@wiktel.com>
parents:
11484
diff
changeset
|
637 int dy; |
88d504770c60
[gaim-migrate @ 13751]
Richard Laager <rlaager@wiktel.com>
parents:
11484
diff
changeset
|
638 |
88d504770c60
[gaim-migrate @ 13751]
Richard Laager <rlaager@wiktel.com>
parents:
11484
diff
changeset
|
639 int error; |
88d504770c60
[gaim-migrate @ 13751]
Richard Laager <rlaager@wiktel.com>
parents:
11484
diff
changeset
|
640 int derror; |
88d504770c60
[gaim-migrate @ 13751]
Richard Laager <rlaager@wiktel.com>
parents:
11484
diff
changeset
|
641 |
88d504770c60
[gaim-migrate @ 13751]
Richard Laager <rlaager@wiktel.com>
parents:
11484
diff
changeset
|
642 int x; |
88d504770c60
[gaim-migrate @ 13751]
Richard Laager <rlaager@wiktel.com>
parents:
11484
diff
changeset
|
643 int y; |
88d504770c60
[gaim-migrate @ 13751]
Richard Laager <rlaager@wiktel.com>
parents:
11484
diff
changeset
|
644 |
11475 | 645 gboolean steep = abs( y1 - y0 ) > abs( x1 - x0 ); |
646 | |
647 if( steep ) | |
648 { | |
649 temp = x0; x0 = y0; y0 = temp; | |
650 temp = x1; x1 = y1; y1 = temp; | |
651 } | |
652 | |
11506
88d504770c60
[gaim-migrate @ 13751]
Richard Laager <rlaager@wiktel.com>
parents:
11484
diff
changeset
|
653 dx = abs( x1 - x0 ); |
88d504770c60
[gaim-migrate @ 13751]
Richard Laager <rlaager@wiktel.com>
parents:
11484
diff
changeset
|
654 dy = abs( y1 - y0 ); |
11475 | 655 |
11506
88d504770c60
[gaim-migrate @ 13751]
Richard Laager <rlaager@wiktel.com>
parents:
11484
diff
changeset
|
656 error = 0; |
88d504770c60
[gaim-migrate @ 13751]
Richard Laager <rlaager@wiktel.com>
parents:
11484
diff
changeset
|
657 derror = dy; |
11475 | 658 |
11506
88d504770c60
[gaim-migrate @ 13751]
Richard Laager <rlaager@wiktel.com>
parents:
11484
diff
changeset
|
659 x = x0; |
88d504770c60
[gaim-migrate @ 13751]
Richard Laager <rlaager@wiktel.com>
parents:
11484
diff
changeset
|
660 y = y0; |
11475 | 661 |
662 if( x0 < x1 ) | |
663 xstep = 1; | |
664 else | |
665 xstep = -1; | |
666 | |
667 if( y0 < y1 ) | |
668 ystep = 1; | |
669 else | |
670 ystep = -1; | |
671 | |
672 if( steep ) | |
673 gaim_gtk_whiteboard_draw_brush_point( wb, y, x, color, size ); | |
674 else | |
675 gaim_gtk_whiteboard_draw_brush_point( wb, x, y, color, size ); | |
676 | |
677 while( x != x1 ) | |
678 { | |
679 x = x + xstep; | |
680 error = error + derror; | |
681 | |
682 if( ( error * 2 ) >= dx ) | |
683 { | |
684 y = y + ystep; | |
685 error = error - dx; | |
686 } | |
687 | |
688 if( steep ) | |
689 gaim_gtk_whiteboard_draw_brush_point( wb, y, x, color, size ); | |
690 else | |
691 gaim_gtk_whiteboard_draw_brush_point( wb, x, y, color, size ); | |
692 } | |
693 } | |
694 | |
695 // ------------------------------------------------------------------------------------------------------ | |
696 | |
697 void gaim_gtk_whiteboard_set_dimensions( GaimWhiteboard *wb, int width, int height ) | |
698 { | |
699 GaimGtkWhiteboard *gtkwb = wb->ui_data; | |
700 | |
701 gtkwb->width = width; | |
702 gtkwb->height = height; | |
703 } | |
704 | |
705 // ------------------------------------------------------------------------------------------------------ | |
706 | |
707 void gaim_gtk_whiteboard_clear( GaimWhiteboard *wb ) | |
708 { | |
709 GaimGtkWhiteboard *gtkwb = wb->ui_data; | |
710 GdkPixmap *pixmap = gtkwb->pixmap; | |
711 GtkWidget *drawing_area = gtkwb->drawing_area; | |
712 | |
713 gdk_draw_rectangle( pixmap, | |
714 drawing_area->style->white_gc, | |
715 TRUE, | |
716 0, 0, | |
717 drawing_area->allocation.width, drawing_area->allocation.height ); | |
718 | |
719 gtk_widget_queue_draw_area( drawing_area, | |
720 0, 0, | |
721 drawing_area->allocation.width, drawing_area->allocation.height ); | |
722 } | |
723 | |
724 // ------------------------------------------------------------------------------------------------------ | |
725 | |
726 void gaim_gtk_whiteboard_button_clear_press( GtkWidget *widget, gpointer data ) | |
727 { | |
728 GaimGtkWhiteboard *gtkwb = ( GaimGtkWhiteboard* )( data ); | |
729 | |
730 gaim_gtk_whiteboard_clear( gtkwb->wb ); | |
731 | |
732 gaim_gtk_whiteboard_set_canvas_as_icon( gtkwb ); | |
733 | |
734 // Do protocol specific clearing procedures | |
735 if( gtkwb->wb->prpl_ops && gtkwb->wb->prpl_ops->clear ) | |
736 gtkwb->wb->prpl_ops->clear( gtkwb->wb ); | |
737 } | |
738 | |
739 // ------------------------------------------------------------------------------------------------------ | |
740 | |
741 void gaim_gtk_whiteboard_button_save_press( GtkWidget *widget, gpointer data ) | |
742 { | |
743 GaimGtkWhiteboard *gtkwb = ( GaimGtkWhiteboard* )( data ); | |
744 GdkPixbuf *pixbuf; | |
745 | |
746 GtkWidget *dialog; | |
747 | |
11506
88d504770c60
[gaim-migrate @ 13751]
Richard Laager <rlaager@wiktel.com>
parents:
11484
diff
changeset
|
748 int result; |
88d504770c60
[gaim-migrate @ 13751]
Richard Laager <rlaager@wiktel.com>
parents:
11484
diff
changeset
|
749 |
11475 | 750 dialog = gtk_file_chooser_dialog_new ("Save File", |
751 GTK_WINDOW(gtkwb->window), | |
752 GTK_FILE_CHOOSER_ACTION_SAVE, | |
753 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, | |
754 GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, | |
755 NULL ); | |
756 | |
757 //gtk_file_chooser_set_do_overwrite_confirmation( GTK_FILE_CHOOSER( dialog ), (gboolean)(TRUE) ); | |
758 | |
759 // if( user_edited_a_new_document ) | |
760 { | |
761 // gtk_file_chooser_set_current_folder( GTK_FILE_CHOOSER( dialog ), default_folder_for_saving ); | |
762 gtk_file_chooser_set_current_name( GTK_FILE_CHOOSER( dialog ), "whiteboard.jpg" ); | |
763 } | |
764 // else | |
765 // gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (dialog), filename_for_existing_document); | |
766 | |
11506
88d504770c60
[gaim-migrate @ 13751]
Richard Laager <rlaager@wiktel.com>
parents:
11484
diff
changeset
|
767 result = gtk_dialog_run( GTK_DIALOG( dialog ) ); |
11475 | 768 |
769 if( result == GTK_RESPONSE_ACCEPT ) | |
770 { | |
771 char *filename; | |
772 | |
773 filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER( dialog ) ); | |
774 | |
775 gtk_widget_destroy( dialog ); | |
776 | |
777 // Makes an icon from the whiteboard's canvas 'image' | |
778 pixbuf = gdk_pixbuf_get_from_drawable( NULL, | |
779 ( GdkDrawable* )( gtkwb->pixmap ), | |
780 gdk_drawable_get_colormap( gtkwb->pixmap ), | |
781 0, 0, | |
782 0, 0, | |
783 gtkwb->width, gtkwb->height ); | |
784 | |
785 if( gdk_pixbuf_save( pixbuf, | |
786 filename, | |
787 "jpeg", | |
788 NULL, | |
789 "quality", | |
790 "100", | |
791 NULL ) ) | |
792 g_print( "File Saved...\n" ); | |
793 else | |
794 g_print( "File not Saved... Error\n" ); | |
795 } | |
796 else | |
797 if( result == GTK_RESPONSE_CANCEL ) | |
798 { | |
799 gtk_widget_destroy( dialog ); | |
800 | |
801 g_print( "File not Saved... Canceled\n" ); | |
802 } | |
803 } | |
804 | |
805 // ------------------------------------------------------------------------------------------------------ | |
806 | |
807 void gaim_gtk_whiteboard_set_canvas_as_icon( GaimGtkWhiteboard *gtkwb ) | |
808 { | |
809 GdkPixbuf *pixbuf; | |
810 | |
811 // Makes an icon from the whiteboard's canvas 'image' | |
812 pixbuf = gdk_pixbuf_get_from_drawable( NULL, | |
813 ( GdkDrawable* )( gtkwb->pixmap ), | |
814 gdk_drawable_get_colormap( gtkwb->pixmap ), | |
815 0, 0, | |
816 0, 0, | |
817 gtkwb->width, gtkwb->height ); | |
818 | |
819 gtk_window_set_icon( ( GtkWindow* )( gtkwb->window ), pixbuf ); | |
820 } | |
821 | |
822 // ------------------------------------------------------------------------------------------------------ | |
823 | |
824 void gaim_gtk_whiteboard_rgb24_to_rgb48( int color_rgb, GdkColor *color ) | |
825 { | |
826 color->red = ( color_rgb >> 8 ) | 0xFF; | |
827 color->green = ( color_rgb & 0xFF00 ) | 0xFF; | |
828 color->blue = ( ( color_rgb & 0xFF ) << 8 ) | 0xFF; | |
829 } | |
830 | |
831 // ------------------------------------------------------------------------------------------------------ | |
832 |