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