Added a new parameter to o_redraw and o_cue_redraw_all,
[geda-gaf/whiteaudio.git] / gschem / src / o_picture.c
blob3d6e69003541af81954ccf8f33f9ef96f9db8c2d
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
19 #include <config.h>
20 #include <math.h>
21 #include <stdio.h>
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
43 * structure.
44 * <B>x</B> and <B>y</B> are current coordinates of the pointer in screen
45 * coordinates.
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)
60 #if DEBUG
61 printf("o_picture_start called\n");
62 #endif
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)
91 int x1, y1;
92 int x2, y2;
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);
98 return;
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);
120 return;
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);
142 /* draw it */
143 o_redraw_single(w_current, w_current->page_current->object_tail);
145 #if DEBUG
146 printf("coords: %d %d %d %d\n", x1, y2, x2, y2);
147 #endif
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!!!
161 * \brief
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) {
171 #if DEBUG
172 printf("Creating new picture file selection dialog\n");
173 #endif
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),
179 GTK_WIN_POS_NONE);
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),
186 "clicked",
187 G_CALLBACK (picture_selection_ok),
188 w_current);
191 * Ensure that the dialog box is destroyed when the user clicks the
192 * cancel button.
194 g_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (file_selector)->cancel_button),
195 "clicked",
196 G_CALLBACK (picture_selection_cancel),
197 w_current);
201 /* Display that dialog */
202 if (!GTK_WIDGET_VISIBLE (w_current->pfswindow)) {
203 gtk_widget_show (w_current->pfswindow);
204 #if 0
205 gtk_grab_add (w_current->pfswindow);
206 #endif
207 } else {
208 gdk_window_raise(w_current->pfswindow->window);
212 /*! \todo Finish function documentation!!!
213 * \brief
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;
221 GdkPixbuf *pixbuf;
222 GError *error;
225 selected_filename = (char *) g_strdup(gtk_file_selection_get_filename (GTK_FILE_SELECTION (file_selector)));
226 #if DEBUG
227 g_print ("Selected picture: %s\n", selected_filename);
228 #endif
229 picture_selection_cancel(widget, w_current);
231 error = NULL;
232 pixbuf = gdk_pixbuf_new_from_file (selected_filename, &error);
234 if (!pixbuf) {
235 GtkWidget *dialog;
237 dialog = gtk_message_dialog_new (GTK_WINDOW (w_current->main_window),
238 GTK_DIALOG_DESTROY_WITH_PARENT,
239 GTK_MESSAGE_ERROR,
240 GTK_BUTTONS_CLOSE,
241 _("Failed to load picture: %s"),
242 error->message);
243 g_error_free (error);
245 g_signal_connect (dialog, "response",
246 G_CALLBACK (gtk_widget_destroy), NULL);
248 gtk_widget_show (dialog);
249 return;
252 #if DEBUG
253 printf("Picture loaded succesfully.\n");
254 #endif
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;
269 i_allow_expose();
270 i_set_state(w_current, DRAWPICTURE);
274 /*! \todo Finish function documentation!!!
275 * \brief
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!!!
288 * \brief
289 * \par Function Description
291 * \note
292 * used in button cancel code in x_events.c
294 void o_picture_eraserubber(TOPLEVEL *w_current)
296 #if DEBUG
297 printf("o_picture_eraserubber called\n");
298 #endif
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)
319 #if DEBUG
320 printf("o_picture_rubberbox called\n");
321 #endif
322 if (w_current->inside_action == 0) {
323 o_redraw(w_current, w_current->page_current->object_head, TRUE);
324 return;
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
353 * selection color.
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);
367 #if DEBUG
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);
374 #endif
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,
380 GDK_JOIN_MITER);
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) {
403 return;
407 * The function now recalculates the OBJECT as a picture. It involves
408 * calculating every single dimensions according to the zoom factor the
409 * position, @dots{}.
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
412 * draw it !
414 o_picture_recalc(w_current, o_current);
416 /* Get read to check for visibility of this line by using it's
417 * bounding picture
419 world_get_picture_bounds(w_current, o_current->picture,
420 &wleft, &wtop, &wright, &wbottom);
422 if (!visible(w_current, wleft, wtop, wright, wbottom)) {
423 return;
426 #if DEBUG
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));
438 #endif
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");
459 return;
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");
468 return;
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");
482 return;
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);
498 else {
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);
528 } else {
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)
547 #if DEBUG
548 printf("o_picture_draw_grips called\n");
549 #endif
550 if (w_current->draw_grips == FALSE)
551 return;
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)
600 #if DEBUG
601 printf("o_picture_erase_grips called\n");
602 #endif
603 if (w_current->draw_grips == FALSE)
604 return;
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)
657 #if DEBUG
658 printf("o_picture_erase called\n");
659 #endif
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
671 * the current sheet.
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;
685 int color;
687 #if DEBUG
688 printf("o_picture_draw_xor called.\n");
689 #endif
690 if (o_current->picture == NULL) {
691 return;
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;
701 } else {
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,
710 screen_x1 + dx,
711 screen_y1 + dy,
712 abs(screen_x2 - screen_x1),
713 abs(screen_y2 - screen_y1));
716 /*! \todo Finish function documentation!!!
717 * \brief
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!!!
730 * \brief
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;
738 GdkPixbuf *pixbuf;
739 GError *error;
740 SELECTION *list;
742 selected_filename = (char *) g_strdup(gtk_file_selection_get_filename (GTK_FILE_SELECTION (file_selector)));
743 #if DEBUG
744 g_print ("Selected picture: %s\n", selected_filename);
745 #endif
746 picture_change_selection_cancel(widget, w_current);
748 error = NULL;
749 pixbuf = gdk_pixbuf_new_from_file (selected_filename, &error);
751 if (!pixbuf) {
752 GtkWidget *dialog;
754 dialog = gtk_message_dialog_new (GTK_WINDOW (w_current->main_window),
755 GTK_DIALOG_DESTROY_WITH_PARENT,
756 GTK_MESSAGE_ERROR,
757 GTK_BUTTONS_CLOSE,
758 _("Failed to load picture: %s"),
759 error->message);
760 g_error_free (error);
762 g_signal_connect (dialog, "response",
763 G_CALLBACK (gtk_widget_destroy), NULL);
765 gtk_widget_show (dialog);
766 return;
768 #if DEBUG
769 printf("Picture loaded succesfully.\n");
770 #endif
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) {
780 OBJECT *object;
782 object = list->selected_object;
783 if (object == NULL) {
784 fprintf(stderr, _("ERROR: NULL object!\n"));
785 exit(-1);
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");
808 return;
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);
820 list = list->next;
823 g_free ((char *) selected_filename);
824 g_object_unref(pixbuf);
825 w_current->page_current->CHANGED=1;
827 i_allow_expose();
831 /*! \todo Finish function documentation!!!
832 * \brief
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) {
843 #if DEBUG
844 printf("Creating change picture file selection dialog\n");
845 #endif
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),
852 GTK_WIN_POS_NONE);
854 g_signal_connect (G_OBJECT(file_selector), "destroy",
855 G_CALLBACK(picture_change_selection_cancel),
856 w_current);
859 g_signal_connect (GTK_OBJECT(GTK_FILE_SELECTION(file_selector)->ok_button),
860 "clicked",
861 G_CALLBACK(picture_change_selection_ok),
862 w_current);
865 * Ensure that the dialog box is destroyed when the user clicks the
866 * cancel button.
868 g_signal_connect (GTK_OBJECT(GTK_FILE_SELECTION(file_selector)->cancel_button),
869 "clicked",
870 G_CALLBACK (picture_change_selection_cancel),
871 w_current);
875 /* Display that dialog */
876 if (!GTK_WIDGET_VISIBLE (w_current->pcfswindow)) {
877 gtk_widget_show (w_current->pcfswindow);
878 #if 0
879 gtk_grab_add (w_current->pcfswindow);
880 #endif
881 } else {
882 gdk_window_raise(w_current->pcfswindow->window);