1 /* gEDA - GPL Electronic Design Automation
2 * gschem - gEDA Schematic Capture
3 * Copyright (C) 1998-2000 Ales V. Hvezda
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
23 #include <libgeda/libgeda.h>
24 #include <gdk-pixbuf/gdk-pixbuf.h>
25 #include "../include/globals.h"
26 #include "../include/prototype.h"
28 /* This works, but using one macro inside of other doesn't */
29 #define GET_PICTURE_WIDTH(w) \
30 abs((w)->last_x - (w)->start_x)
31 #define GET_PICTURE_HEIGHT(w) \
32 (w)->pixbuf_wh_ratio == 0 ? 0 : abs((w)->last_x - (w)->start_x)/(w)->pixbuf_wh_ratio
33 #define GET_PICTURE_LEFT(w) \
34 min((w)->start_x, (w)->last_x);
35 #define GET_PICTURE_TOP(w) \
36 (w)->start_y < (w)->last_y ? (w)->start_y : \
37 (w)->start_y-abs((w)->last_x - (w)->start_x)/(w)->pixbuf_wh_ratio;
39 /*! \brief Start process to input a new picture.
40 * \par Function Description
41 * This function starts the process to input a new picture. Parameters
42 * for this picture are put into/extracted from the <B>w_current</B> toplevel
44 * <B>x</B> and <B>y</B> are current coordinates of the pointer in screen
47 * The first step is to input one corner of the picture. This corner is
48 * (<B>x</B>,<B>y</B>) snapped to the grid and saved in
49 * <B>w_current->start_x</B> and <B>w_current->start_y</B>.
51 * The other corner will be saved in (<B>w_current->last_x</B>,
52 * <B>w_current->last_y</B>).
54 * \param [in] w_current The TOPLEVEL object.
55 * \param [in] x Current x coordinate of pointer in screen units.
56 * \param [in] y Current y coordinate of pointer in screen units.
58 void o_picture_start(TOPLEVEL
*w_current
, int x
, int y
)
61 printf("o_picture_start called\n");
63 /* init start_[x|y], last_[x|y] to describe box */
64 w_current
->last_x
= w_current
->start_x
= fix_x(w_current
, x
);
65 w_current
->last_y
= w_current
->start_y
= fix_y(w_current
, y
);
67 /* start to draw the box */
68 o_picture_rubberbox_xor(w_current
);
72 /*! \brief End the input of a circle.
73 * \par Function Description
74 * This function ends the input of the second corner of a picture.
75 * The (<B>x</B>,<B>y</B>) point is set to be this second corner. The picture
76 * is then defined by (<B>w_current->start_x</B>,<B>w_current->start_y</B>
77 * and (<B>w_current->last_x</B>,<B>w_current->last_y</B> that is a snapped
78 * version of (<B>x</B>,<B>y</B>).
79 * <B>x</B> and <B>y</B> are in screen unit.
81 * The temporary picture is erased ; a new picture object is allocated,
82 * initialized and linked to the object list ; The object is finally
83 * drawn on the current sheet.
85 * \param [in] w_current The TOPLEVEL object.
86 * \param [in] x Current x coordinate of pointer in screen units.
87 * \param [in] y Current y coordinate of pointer in screen units.
89 void o_picture_end(TOPLEVEL
*w_current
, int x
, int y
)
93 int picture_width
, picture_height
;
94 int picture_left
, picture_top
;
96 if (w_current
->inside_action
== 0) {
97 o_redraw(w_current
, w_current
->page_current
->object_head
, TRUE
);
101 /* get the last coords of the pointer */
102 w_current
->last_x
= fix_x(w_current
, x
);
103 w_current
->last_y
= fix_y(w_current
, y
);
105 /* erase the temporary picture */
106 o_picture_rubberbox_xor(w_current
);
108 picture_width
= GET_PICTURE_WIDTH (w_current
);
109 picture_height
= GET_PICTURE_HEIGHT(w_current
);
110 picture_left
= GET_PICTURE_LEFT (w_current
);
111 picture_top
= GET_PICTURE_TOP (w_current
);
113 /* pictures with null width and height are not allowed */
114 if ((picture_width
== 0) && (picture_height
== 0)) {
115 /* cancel the object creation */
116 w_current
->start_x
= (-1);
117 w_current
->start_y
= (-1);
118 w_current
->last_x
= (-1);
119 w_current
->last_y
= (-1);
123 /* calculate the world coords of the upper left and lower right corners */
124 SCREENtoWORLD(w_current
, picture_left
, picture_top
, &x1
, &y1
);
125 SCREENtoWORLD(w_current
,
126 picture_left
+ picture_width
,
127 picture_top
+ picture_height
, &x2
, &y2
);
128 x1
= snap_grid(w_current
, x1
);
129 y1
= snap_grid(w_current
, y1
);
130 x2
= snap_grid(w_current
, x2
);
131 y2
= snap_grid(w_current
, y2
);
133 /* create the object */
134 w_current
->page_current
->object_tail
=
135 o_picture_add(w_current
,
136 w_current
->page_current
->object_tail
,
137 w_current
->current_pixbuf
,
138 w_current
->pixbuf_filename
,
139 w_current
->pixbuf_wh_ratio
,
140 OBJ_PICTURE
, x1
, y1
, x2
, y2
, 0, FALSE
, FALSE
);
143 o_redraw_single(w_current
, w_current
->page_current
->object_tail
);
146 printf("coords: %d %d %d %d\n", x1
, y2
, x2
, y2
);
149 w_current
->start_x
= (-1);
150 w_current
->start_y
= (-1);
151 w_current
->last_x
= (-1);
152 w_current
->last_y
= (-1);
154 w_current
->page_current
->CHANGED
= 1;
156 o_undo_savestate(w_current
, UNDO_ALL
);
160 /*! \todo Finish function documentation!!!
162 * \par Function Description
165 void picture_selection_dialog (TOPLEVEL
*w_current
)
167 GtkWidget
*file_selector
;
169 /* Create the selector */
170 if (!w_current
->pfswindow
) {
172 printf("Creating new picture file selection dialog\n");
174 w_current
->pfswindow
= gtk_file_selection_new (_("Please select a picture file."));
175 file_selector
= w_current
->pfswindow
;
176 if (w_current
->pixbuf_filename
)
177 gtk_file_selection_set_filename(GTK_FILE_SELECTION(file_selector
), w_current
->pixbuf_filename
);
178 gtk_window_position(GTK_WINDOW (w_current
->pfswindow
),
181 g_signal_connect (G_OBJECT (file_selector
), "destroy",
182 G_CALLBACK (picture_selection_cancel
), w_current
);
185 g_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (file_selector
)->ok_button
),
187 G_CALLBACK (picture_selection_ok
),
191 * Ensure that the dialog box is destroyed when the user clicks the
194 g_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (file_selector
)->cancel_button
),
196 G_CALLBACK (picture_selection_cancel
),
201 /* Display that dialog */
202 if (!GTK_WIDGET_VISIBLE (w_current
->pfswindow
)) {
203 gtk_widget_show (w_current
->pfswindow
);
205 gtk_grab_add (w_current
->pfswindow
);
208 gdk_window_raise(w_current
->pfswindow
->window
);
212 /*! \todo Finish function documentation!!!
214 * \par Function Description
217 void picture_selection_ok (GtkWidget
*widget
, TOPLEVEL
*w_current
)
219 GtkWidget
*file_selector
= (GtkWidget
*)w_current
->pfswindow
;
220 const gchar
*selected_filename
;
225 selected_filename
= (char *) g_strdup(gtk_file_selection_get_filename (GTK_FILE_SELECTION (file_selector
)));
227 g_print ("Selected picture: %s\n", selected_filename
);
229 picture_selection_cancel(widget
, w_current
);
232 pixbuf
= gdk_pixbuf_new_from_file (selected_filename
, &error
);
237 dialog
= gtk_message_dialog_new (GTK_WINDOW (w_current
->main_window
),
238 GTK_DIALOG_DESTROY_WITH_PARENT
,
241 _("Failed to load picture: %s"),
243 g_error_free (error
);
245 g_signal_connect (dialog
, "response",
246 G_CALLBACK (gtk_widget_destroy
), NULL
);
248 gtk_widget_show (dialog
);
253 printf("Picture loaded succesfully.\n");
256 exit_if_null(w_current
);
258 o_erase_rubber(w_current
);
260 i_update_middle_button(w_current
, i_callback_add_picture
, _("Picture"));
261 w_current
->inside_action
= 0;
263 o_picture_set_pixbuf(w_current
, pixbuf
, (char *) selected_filename
);
264 /* o_picture_set_pixbuf allocates memory for filename, so free the pointer */
265 g_free((char *)selected_filename
);
267 w_current
->page_current
->CHANGED
=1;
270 i_set_state(w_current
, DRAWPICTURE
);
274 /*! \todo Finish function documentation!!!
276 * \par Function Description
279 void picture_selection_cancel (GtkWidget
*widget
, TOPLEVEL
*w_current
)
281 i_set_state(w_current
, SELECT
);
282 i_update_toolbar(w_current
);
283 gtk_widget_destroy(w_current
->pfswindow
);
284 w_current
->pfswindow
=NULL
;
287 /*! \todo Finish function documentation!!!
289 * \par Function Description
292 * used in button cancel code in x_events.c
294 void o_picture_eraserubber(TOPLEVEL
*w_current
)
297 printf("o_picture_eraserubber called\n");
299 o_picture_rubberbox_xor(w_current
);
302 /*! \brief Draw temporary picture while dragging edge.
303 * \par Function Description
304 * This function is used to draw the box while dragging one of its edge or
305 * angle. It erases the previous temporary box drawn before, and draws
306 * a new updated one. <B>x</B> and <B>y</B> are the new position of the mobile
307 * point, ie the mouse.
309 * The old values are inside the <B>w_current</B> pointed structure. Old
310 * width, height and left and top values are recomputed by the corresponding
311 * macros. The box is then erased by performing a xor-drawing over the box.
313 * \param [in] w_current The TOPLEVEL object.
314 * \param [in] x Current x coordinate of pointer in screen units.
315 * \param [in] y Current y coordinate of pointer in screen units.
317 void o_picture_rubberbox(TOPLEVEL
*w_current
, int x
, int y
)
320 printf("o_picture_rubberbox called\n");
322 if (w_current
->inside_action
== 0) {
323 o_redraw(w_current
, w_current
->page_current
->object_head
, TRUE
);
327 /* erase the previous temporary box */
328 o_picture_rubberbox_xor(w_current
);
331 * New values are fixed according to the <B>x</B> and <B>y</B> parameters. These are saved in <B>w_current</B> pointed structure as new temporary values. The new box is then drawn.
335 /* update the coords of the corner */
336 w_current
->last_x
= fix_x(w_current
, x
);
337 w_current
->last_y
= fix_y(w_current
, y
);
339 /* draw the new temporary box */
340 o_picture_rubberbox_xor(w_current
);
344 /*! \brief Draw picture from TOPLEVEL object.
345 * \par Function Description
346 * This function draws the box from the variables in the toplevel
347 * structure <B>*w_current</B>.
348 * One corner of the box is at (<B>w_current->start_x</B>,
349 * <B>w_current->start_y</B>) and the second corner is at
350 * (<B>w_current->last_x</B>,<B>w_current->last_y</B>.
352 * The box is drawn with a xor-function over the current sheet with the
355 * \param [in] w_current The TOPLEVEL object.
357 void o_picture_rubberbox_xor(TOPLEVEL
*w_current
)
359 int picture_width
, picture_height
, picture_left
, picture_top
;
361 /* get the width/height and the upper left corner of the picture */
362 picture_width
= GET_PICTURE_WIDTH (w_current
);
363 picture_height
= GET_PICTURE_HEIGHT(w_current
);
364 picture_left
= GET_PICTURE_LEFT (w_current
);
365 picture_top
= GET_PICTURE_TOP (w_current
);
368 printf("o_picture_rubberbox_xor called:\n");
369 printf("pixbuf wh ratio: %i\n", w_current
->pixbuf_wh_ratio
);
370 printf("start: %i, %i\n", w_current
->start_x
, w_current
->start_y
);
371 printf("last: %i, %i\n", w_current
->last_x
, w_current
->last_y
);
372 printf("Left: %i\nTop: %i\nWidth: %i\nHeight: %i\n",
373 picture_left
, picture_top
, picture_width
, picture_height
);
375 /* draw the picture from the previous variables */
376 gdk_gc_set_foreground(w_current
->xor_gc
,
377 x_get_darkcolor(w_current
->select_color
));
378 gdk_gc_set_line_attributes(w_current
->xor_gc
, 0,
379 GDK_LINE_SOLID
, GDK_CAP_NOT_LAST
,
381 gdk_draw_rectangle(w_current
->window
, w_current
->xor_gc
,
382 FALSE
, picture_left
, picture_top
,
383 picture_width
, picture_height
);
386 /*! \brief Draw a picture on the screen.
387 * \par Function Description
388 * This function is used to draw a picture on screen. The picture is
389 * described in the OBJECT which is referred by <B>o_current</B>. The picture
390 * is displayed according to the current state, described in the
391 * TOPLEVEL object pointed by <B>w_current</B>.
393 * It first checks if the OBJECT pointed is valid or not. If not it
394 * returns and do not output anything. That should never happen though.
396 * \param [in] w_current The TOPLEVEL object.
397 * \param [in] o_current Picture OBJECT to draw.
399 void o_picture_draw(TOPLEVEL
*w_current
, OBJECT
*o_current
)
401 int wleft
, wright
, wtop
, wbottom
; /* world bounds */
402 if (o_current
->picture
== NULL
) {
407 * The function now recalculates the OBJECT as a picture. It involves
408 * calculating every single dimensions according to the zoom factor the
410 * It also recalculates the bounding picture of the object and check
411 * whether this object is visible or not. If not there is no reason to
414 o_picture_recalc(w_current
, o_current
);
416 /* Get read to check for visibility of this line by using it's
419 world_get_picture_bounds(w_current
, o_current
->picture
,
420 &wleft
, &wtop
, &wright
, &wbottom
);
422 if (!visible(w_current
, wleft
, wtop
, wright
, wbottom
)) {
427 printf("drawing picture\n\n");
429 printf("drawing picture: %d %d %d %d\n",
430 o_current
->picture
->screen_upper_x
,
431 o_current
->picture
->screen_upper_y
,
432 o_current
->picture
->screen_upper_x
+
433 abs(o_current
->picture
->screen_lower_x
-
434 o_current
->picture
->screen_upper_x
),
435 o_current
->picture
->screen_upper_y
+
436 abs(o_current
->picture
->screen_lower_y
-
437 o_current
->picture
->screen_upper_y
));
441 * First, the picture is drawn.
442 * Finally the function takes care of the grips.
445 if (o_current
->picture
->displayed_picture
!= NULL
) {
446 g_object_unref(o_current
->picture
->displayed_picture
);
447 o_current
->picture
->displayed_picture
= NULL
;
449 /* If it's not drawing using the background color then draw the image */
450 if (w_current
->override_color
!= w_current
->background_color
) {
451 GdkPixbuf
*temp_pixbuf1
, *temp_pixbuf2
;
453 /* Create a copy of the pixbuf rotated */
454 temp_pixbuf1
= gdk_pixbuf_rotate(o_current
->picture
->original_picture
,
455 o_current
->picture
->angle
);
457 if (temp_pixbuf1
== NULL
) {
458 fprintf(stderr
, "Couldn't get enough memory for rotating the picture\n");
462 temp_pixbuf2
= gdk_pixbuf_mirror_flip(temp_pixbuf1
,
463 o_current
->picture
->mirrored
, FALSE
);
464 g_object_unref(temp_pixbuf1
);
466 if (temp_pixbuf2
== NULL
) {
467 fprintf(stderr
, "Couldn't get enough memory for mirroring the picture\n");
471 o_current
->picture
->displayed_picture
=
472 gdk_pixbuf_scale_simple(temp_pixbuf2
,
473 abs(o_current
->picture
->screen_lower_x
-
474 o_current
->picture
->screen_upper_x
),
475 abs(o_current
->picture
->screen_lower_y
-
476 o_current
->picture
->screen_upper_y
),
477 GDK_INTERP_BILINEAR
);
478 g_object_unref(temp_pixbuf2
);
480 if (o_current
->picture
->displayed_picture
== NULL
) {
481 fprintf(stderr
, "Couldn't get enough memory for scaling the picture\n");
485 if (w_current
->DONT_REDRAW
== 0) {
486 gdk_draw_pixbuf(w_current
->window
, w_current
->gc
,
487 o_current
->picture
->displayed_picture
,
488 0, 0, o_current
->picture
->screen_upper_x
,
489 o_current
->picture
->screen_upper_y
,
490 -1, -1, GDK_RGB_DITHER_NONE
, 0, 0);
491 gdk_draw_pixbuf(w_current
->backingstore
, w_current
->gc
,
492 o_current
->picture
->displayed_picture
,
493 0, 0, o_current
->picture
->screen_upper_x
,
494 o_current
->picture
->screen_upper_y
,
495 -1, -1, GDK_RGB_DITHER_NONE
, 0, 0);
499 if (w_current
->DONT_REDRAW
== 0) {
500 /* Erase the picture, drawing a rectangle with the background color */
501 gdk_gc_set_foreground(w_current
->gc
,
502 x_get_color(w_current
->background_color
));
503 gdk_draw_rectangle(w_current
->window
, w_current
->gc
, TRUE
,
504 o_current
->picture
->screen_upper_x
,
505 o_current
->picture
->screen_upper_y
,
506 abs(o_current
->picture
->screen_lower_x
-
507 o_current
->picture
->screen_upper_x
),
508 abs(o_current
->picture
->screen_lower_y
-
509 o_current
->picture
->screen_upper_y
));
510 gdk_draw_rectangle(w_current
->backingstore
, w_current
->gc
, TRUE
,
511 o_current
->picture
->screen_upper_x
,
512 o_current
->picture
->screen_upper_y
,
513 abs(o_current
->picture
->screen_lower_x
-
514 o_current
->picture
->screen_upper_x
),
515 abs(o_current
->picture
->screen_lower_y
-
516 o_current
->picture
->screen_upper_y
));
520 /* Grip specific stuff */
521 if ((o_current
->draw_grips
== TRUE
) && (w_current
->draw_grips
== TRUE
)) {
522 if (!o_current
->selected
) {
523 /* object is no more selected, erase the grips */
524 o_current
->draw_grips
= FALSE
;
525 if (w_current
->DONT_REDRAW
== 0) {
526 o_picture_erase_grips(w_current
, o_current
);
529 /* object is selected, draw the grips on the picture */
530 if (w_current
->DONT_REDRAW
== 0) {
531 o_picture_draw_grips(w_current
, o_current
);
537 /*! \brief Draw grip marks on picture.
538 * \par Function Description
539 * This function draws four grips on the corners of the picture described
540 * by <B>*o_current</B>.
542 * \param [in] w_current The TOPLEVEL object.
543 * \param [in] o_current Picture OBJECT to draw grip points on.
545 void o_picture_draw_grips(TOPLEVEL
*w_current
, OBJECT
*o_current
)
548 printf("o_picture_draw_grips called\n");
550 if (w_current
->draw_grips
== FALSE
)
553 /* grip on upper left corner (whichone = PICTURE_UPPER_LEFT) */
554 o_grips_draw(w_current
,
555 o_current
->picture
->screen_upper_x
,
556 o_current
->picture
->screen_upper_y
);
558 /* grip on upper right corner (whichone = PICTURE_UPPER_RIGHT) */
559 o_grips_draw(w_current
,
560 o_current
->picture
->screen_lower_x
,
561 o_current
->picture
->screen_upper_y
);
563 /* grip on lower left corner (whichone = PICTURE_LOWER_LEFT) */
564 o_grips_draw(w_current
,
565 o_current
->picture
->screen_upper_x
,
566 o_current
->picture
->screen_lower_y
);
568 /* grip on lower right corner (whichone = PICTURE_LOWER_RIGHT) */
569 o_grips_draw(w_current
,
570 o_current
->picture
->screen_lower_x
,
571 o_current
->picture
->screen_lower_y
);
573 /* Box surrounding the picture */
574 gdk_draw_rectangle(w_current
->window
, w_current
->gc
, FALSE
,
575 o_current
->picture
->screen_upper_x
,
576 o_current
->picture
->screen_upper_y
,
577 abs(o_current
->picture
->screen_upper_x
-
578 o_current
->picture
->screen_lower_x
),
579 abs(o_current
->picture
->screen_upper_y
-
580 o_current
->picture
->screen_lower_y
));
581 gdk_draw_rectangle(w_current
->backingstore
, w_current
->gc
, FALSE
,
582 o_current
->picture
->screen_upper_x
,
583 o_current
->picture
->screen_upper_y
,
584 abs(o_current
->picture
->screen_upper_x
-
585 o_current
->picture
->screen_lower_x
),
586 abs(o_current
->picture
->screen_upper_y
-
587 o_current
->picture
->screen_lower_y
));
590 /*! \brief Erase grip marks from box.
591 * \par Function Description
592 * This function erases the four grips displayed on the <B>*o_current</B>
593 * picture object. These grips are on each of the corner.
595 * \param [in] w_current The TOPLEVEL object.
596 * \param [in] o_current Picture OBJECT to erase grip marks from.
598 void o_picture_erase_grips(TOPLEVEL
*w_current
, OBJECT
*o_current
)
601 printf("o_picture_erase_grips called\n");
603 if (w_current
->draw_grips
== FALSE
)
606 /* grip on upper left corner (whichone = PICTURE_UPPER_LEFT) */
607 o_grips_erase(w_current
,
608 o_current
->picture
->screen_upper_x
,
609 o_current
->picture
->screen_upper_y
);
611 /* grip on upper right corner (whichone = PICTURE_UPPER_RIGHT) */
612 o_grips_erase(w_current
,
613 o_current
->picture
->screen_lower_x
,
614 o_current
->picture
->screen_upper_y
);
616 /* grip on lower left corner (whichone = PICTURE_LOWER_LEFT) */
617 o_grips_erase(w_current
,
618 o_current
->picture
->screen_upper_x
,
619 o_current
->picture
->screen_lower_y
);
621 /* grip on lower right corner (whichone = PICTURE_LOWER_RIGHT) */
622 o_grips_erase(w_current
,
623 o_current
->picture
->screen_lower_x
,
624 o_current
->picture
->screen_lower_y
);
626 /* Box surrounding the picture */
627 gdk_draw_rectangle(w_current
->window
, w_current
->gc
, FALSE
,
628 o_current
->picture
->screen_upper_x
,
629 o_current
->picture
->screen_upper_y
,
630 abs(o_current
->picture
->screen_upper_x
-
631 o_current
->picture
->screen_lower_x
),
632 abs(o_current
->picture
->screen_upper_y
-
633 o_current
->picture
->screen_lower_y
));
634 gdk_draw_rectangle(w_current
->backingstore
, w_current
->gc
, FALSE
,
635 o_current
->picture
->screen_upper_x
,
636 o_current
->picture
->screen_upper_y
,
637 abs(o_current
->picture
->screen_upper_x
-
638 o_current
->picture
->screen_lower_x
),
639 abs(o_current
->picture
->screen_upper_y
-
640 o_current
->picture
->screen_lower_y
));
643 /*! \brief Erase a picture described by OBJECT.
644 * \par Function Description
645 * This function erases a picture, described in a <B>OBJECT</B> structure
646 * pointed by <B>o_current</B>.
648 * It makes a call to the function #o_picture_draw() after setting
649 * the special color. Therefore a picture is drawn with background color
650 * over the previous one.
652 * \param [in] w_current The TOPLEVEL object.
653 * \param [in] o_current Picture OBJECT to erase.
655 void o_picture_erase(TOPLEVEL
*w_current
, OBJECT
*o_current
)
658 printf("o_picture_erase called\n");
660 gdk_gc_set_foreground(w_current
->gc
,
661 x_get_color(w_current
->background_color
));
662 w_current
->override_color
= w_current
->background_color
;
663 o_picture_draw(w_current
, o_current
);
664 w_current
->override_color
= -1;
667 /*! \brief Draw a picture described by OBJECT with translation
668 * \par Function Description
669 * This function daws the picture object described by <B>*o_current</B>
670 * translated by the vector (<B>dx</B>,<B>dy</B>) with an xor-function over
672 * The translation vector is in screen unit.
674 * The picture is displayed with the color of the object.
676 * \param [in] w_current The TOPLEVEL object.
677 * \param [in] dx Delta x coordinate for picture.
678 * \param [in] dy Delta y coordinate for picture.
679 * \param [in] o_current Picture OBJECT to draw.
681 void o_picture_draw_xor(TOPLEVEL
*w_current
, int dx
, int dy
, OBJECT
*o_current
)
683 int screen_x1
, screen_y1
;
684 int screen_x2
, screen_y2
;
688 printf("o_picture_draw_xor called.\n");
690 if (o_current
->picture
== NULL
) {
694 screen_x1
= o_current
->picture
->screen_upper_x
;
695 screen_y1
= o_current
->picture
->screen_upper_y
;
696 screen_x2
= o_current
->picture
->screen_lower_x
;
697 screen_y2
= o_current
->picture
->screen_lower_y
;
699 if (o_current
->saved_color
!= -1) {
700 color
= o_current
->saved_color
;
702 color
= o_current
->color
;
705 gdk_gc_set_foreground(w_current
->outline_xor_gc
,
706 x_get_darkcolor(color
));
708 gdk_draw_rectangle(w_current
->window
,
709 w_current
->outline_xor_gc
, FALSE
,
712 abs(screen_x2
- screen_x1
),
713 abs(screen_y2
- screen_y1
));
716 /*! \todo Finish function documentation!!!
718 * \par Function Description
721 void picture_change_selection_cancel (GtkWidget
*widget
, TOPLEVEL
*w_current
)
723 i_set_state(w_current
, SELECT
);
724 i_update_toolbar(w_current
);
725 gtk_widget_destroy(w_current
->pcfswindow
);
726 w_current
->pcfswindow
=NULL
;
729 /*! \todo Finish function documentation!!!
731 * \par Function Description
734 void picture_change_selection_ok (GtkWidget
*widget
, TOPLEVEL
*w_current
)
736 GtkWidget
*file_selector
= (GtkWidget
*)w_current
->pcfswindow
;
737 const gchar
*selected_filename
;
742 selected_filename
= (char *) g_strdup(gtk_file_selection_get_filename (GTK_FILE_SELECTION (file_selector
)));
744 g_print ("Selected picture: %s\n", selected_filename
);
746 picture_change_selection_cancel(widget
, w_current
);
749 pixbuf
= gdk_pixbuf_new_from_file (selected_filename
, &error
);
754 dialog
= gtk_message_dialog_new (GTK_WINDOW (w_current
->main_window
),
755 GTK_DIALOG_DESTROY_WITH_PARENT
,
758 _("Failed to load picture: %s"),
760 g_error_free (error
);
762 g_signal_connect (dialog
, "response",
763 G_CALLBACK (gtk_widget_destroy
), NULL
);
765 gtk_widget_show (dialog
);
769 printf("Picture loaded succesfully.\n");
772 exit_if_null(w_current
);
774 o_erase_rubber(w_current
);
776 w_current
->inside_action
= 0;
778 list
= w_current
->page_current
->selection2_head
->next
;
779 while (list
!= NULL
) {
782 object
= list
->selected_object
;
783 if (object
== NULL
) {
784 fprintf(stderr
, _("ERROR: NULL object!\n"));
787 if (!object
->attached_to
) {
788 /* It's selected. Then change picture if it's a picture */
789 if (object
->type
== OBJ_PICTURE
) {
790 /* Erase previous picture */
791 o_picture_erase(w_current
, object
);
793 /* Change picture attributes */
794 if (object
->picture
->original_picture
!= NULL
) {
795 g_object_unref(object
->picture
->original_picture
);
796 object
->picture
->original_picture
=NULL
;
799 if (object
->picture
->filename
!= NULL
) {
800 g_free(object
->picture
->filename
);
801 object
->picture
->filename
=NULL
;
803 /* Create a copy of the pixbuf rotated */
804 object
->picture
->original_picture
= gdk_pixbuf_rotate(pixbuf
, 0);
806 if (object
->picture
->original_picture
== NULL
) {
807 fprintf(stderr
, "change picture: Couldn't get enough memory for the new picture\n");
811 object
->picture
->filename
= (char *) g_strdup(selected_filename
);
813 object
->picture
->ratio
= gdk_pixbuf_get_width(pixbuf
) /
814 gdk_pixbuf_get_height(pixbuf
);
815 /* Draw new picture */
816 o_picture_draw(w_current
, object
);
823 g_free ((char *) selected_filename
);
824 g_object_unref(pixbuf
);
825 w_current
->page_current
->CHANGED
=1;
831 /*! \todo Finish function documentation!!!
833 * \par Function Description
836 void picture_change_filename_dialog (TOPLEVEL
*w_current
)
839 GtkWidget
*file_selector
;
841 /* Create the selector */
842 if (!w_current
->pcfswindow
) {
844 printf("Creating change picture file selection dialog\n");
846 w_current
->pcfswindow
= gtk_file_selection_new (_("Please select a picture file."));
847 file_selector
= w_current
->pcfswindow
;
848 if (w_current
->pixbuf_filename
)
849 gtk_file_selection_set_filename(GTK_FILE_SELECTION(file_selector
),
850 w_current
->pixbuf_filename
);
851 gtk_window_position(GTK_WINDOW(w_current
->pcfswindow
),
854 g_signal_connect (G_OBJECT(file_selector
), "destroy",
855 G_CALLBACK(picture_change_selection_cancel
),
859 g_signal_connect (GTK_OBJECT(GTK_FILE_SELECTION(file_selector
)->ok_button
),
861 G_CALLBACK(picture_change_selection_ok
),
865 * Ensure that the dialog box is destroyed when the user clicks the
868 g_signal_connect (GTK_OBJECT(GTK_FILE_SELECTION(file_selector
)->cancel_button
),
870 G_CALLBACK (picture_change_selection_cancel
),
875 /* Display that dialog */
876 if (!GTK_WIDGET_VISIBLE (w_current
->pcfswindow
)) {
877 gtk_widget_show (w_current
->pcfswindow
);
879 gtk_grab_add (w_current
->pcfswindow
);
882 gdk_window_raise(w_current
->pcfswindow
->window
);