11 #include "icons/img_unknown.xpm"
14 static gchar *zoom_as_text(gint zoom, gfloat scale);
15 static void set_zoom_label(GtkWidget *label, gint zoom, gfloat scale);
16 static void set_info_label(GtkWidget *label, gint width, gint height, gint size, gint unknown);
17 static void set_window_title(ImageWindow *imd, gchar *text);
19 static gint image_area_size_top_window(ImageWindow *imd, gint w, gint h);
21 static void image_area_recalc_size(ImageWindow *imd, GtkAllocation *allocation);
23 static void image_area_redraw(ImageWindow *imd);
24 static gint image_area_size_cb(GtkWidget *widget, GtkAllocation *allocation, gpointer data);
25 static gint image_area_update_cb(GtkWidget *widget, GdkEventConfigure *event, gpointer data);
27 static void set_mouse_cursor (GdkWindow *window, gint icon);
28 static void image_area_mouse_moved(GtkWidget *widget, GdkEventButton *bevent, gpointer data);
29 static void image_area_mouse_pressed(GtkWidget *widget, GdkEventButton *bevent, gpointer data);
30 static void image_area_mouse_released(GtkWidget *widget, GdkEventButton *bevent, gpointer data);
31 static void image_area_mouse_drag(GtkWidget *widget, GdkDragContext *context, gpointer data);
34 *-----------------------------------------------------------------------------
35 * image status widget update routines (private)
36 *-----------------------------------------------------------------------------
39 static gchar *zoom_as_text(gint zoom, gfloat scale)
44 if (zoom > 1) l = zoom;
45 if (zoom < -1) r = -zoom;
46 if (zoom == 0 && scale != 0)
48 if (scale < 1) r = 1 / scale + 0.5;
51 return g_strdup_printf("%d :%s%d", l, approx, r);
54 static void set_zoom_label(GtkWidget *label, gint zoom, gfloat scale)
57 buf = zoom_as_text(zoom, scale);
58 gtk_label_set(GTK_LABEL(label), buf);
62 static void set_info_label(GtkWidget *label, gint width, gint height, gint size, gint unknown)
66 sprintf(buf, _("( ? x ? ) %d bytes"), size);
68 sprintf(buf, _("( %d x %d ) %d bytes"), width, height, size);
69 gtk_label_set(GTK_LABEL(label), buf);
72 static void set_window_title(ImageWindow *imd, gchar *text)
75 if (!imd->top_window) return;
79 title = g_strconcat(imd->title, imd->image_name, text, NULL);
83 title = g_strconcat(imd->image_name, text, NULL);
86 gtk_window_set_title(GTK_WINDOW(imd->top_window), title);
91 *-----------------------------------------------------------------------------
92 * fit window to image utility (private)
93 *-----------------------------------------------------------------------------
96 static gint image_area_size_top_window(ImageWindow *imd, gint w, gint h)
98 if (!imd->top_window) return FALSE;
99 if (imd == full_screen_image) return FALSE;
100 if (imd == normal_image && !toolwindow) return FALSE;
101 if (!fit_window) return FALSE;
103 if (imd == normal_image)
105 /* account for border frame */
110 if (limit_window_size)
112 gint sw = gdk_screen_width() * max_window_size / 100;
113 gint sh = gdk_screen_height() * max_window_size / 100;
119 /* to cheat on a prob a little, don't resize if within 1 either way...
120 ...dumb off by 1 errors! ;) */
122 /* if (w >= (imd->top_window)->allocation.width - 1 &&
123 w <= (imd->top_window)->allocation.width + 1 &&
124 h >= (imd->top_window)->allocation.height - 1 &&
125 h <= (imd->top_window)->allocation.height + 1)
128 if (debug) printf("auto sized to %d x %d\n", w, h);
130 gdk_window_resize(imd->top_window->window, w, h);
131 gtk_widget_set_usize(imd->top_window, w, h);
137 *-----------------------------------------------------------------------------
138 * image widget zoom/recalc routines
139 *-----------------------------------------------------------------------------
142 void image_area_scroll(ImageWindow *imd, gint x, gint y)
146 GtkAdjustment *h = gtk_viewport_get_hadjustment(GTK_VIEWPORT(imd->viewport));
147 gfloat val = h->value + x;
148 if (val < h->lower) val = h->lower;
149 if (val > h->upper - h->page_size) val = h->upper - h->page_size;
150 gtk_adjustment_set_value(GTK_ADJUSTMENT(h), val);
155 GtkAdjustment *v = gtk_viewport_get_vadjustment(GTK_VIEWPORT(imd->viewport));
156 gfloat val = v->value + y;
157 if (val < v->lower) val = v->lower;
158 if (val > v->upper - v->page_size) val = v->upper - v->page_size;
159 gtk_adjustment_set_value(GTK_ADJUSTMENT(v), val);
163 gint image_area_get_zoom(ImageWindow *imd)
168 void image_area_adjust_zoom(ImageWindow *imd, gint increment)
170 gint zoom = imd->zoom;
173 while (increment < 0)
176 if (zoom == 0 || zoom == -1) zoom = -2;
179 if (zoom < -8) zoom = -8;
183 while (increment > 0)
186 if (zoom == -1) zoom = 1;
189 if (zoom > 3) zoom = 3;
191 if (zoom != imd->zoom)
192 image_area_set_zoom(imd, zoom);
195 void image_area_set_zoom(ImageWindow *imd, gint zoom)
197 if (zoom == imd->zoom && imd->width > 0 && imd->height > 0) return;
200 image_area_recalc_size(imd, NULL);
202 gtk_widget_set_usize (imd->table, imd->width, imd->height);
203 gtk_drawing_area_size(GTK_DRAWING_AREA(imd->image), imd->width, imd->height);
206 static void image_area_recalc_size(ImageWindow *imd, GtkAllocation *allocation)
209 gfloat scale_factor = 1;
211 w = imd->image_data->rgb_width;
212 h = imd->image_data->rgb_height;
215 ww = allocation->width;
216 wh = allocation->height;
220 ww = (imd->eventbox)->allocation.width;
221 wh = (imd->eventbox)->allocation.height;
224 if (imd == normal_image)
226 /* account for frame */
231 if (imd->zoom == 0) /* zoom to fit */
233 if (imd == normal_image && imd->width == 0 && imd->height == 0 &&
234 fit_window && toolwindow)
236 if (limit_window_size)
238 ww = (gdk_screen_width() * max_window_size / 100) - 4;
239 wh = (gdk_screen_height() * max_window_size / 100) - 4;
247 if (w > ww || h > wh)
249 if ((gfloat)ww / w > (gfloat)wh / h)
251 scale_factor = (gfloat) wh / h;
253 w = w * scale_factor + 0.5;
258 scale_factor = (gfloat)ww / w;
260 h = h * scale_factor + 0.5;
267 else if (imd->zoom > 0) /* zoom orig, in */
269 scale_factor = imd->zoom;
270 w = w * scale_factor;
271 h = h * scale_factor;
273 else if (imd->zoom < -1) /* zoom out */
275 scale_factor = (- imd->zoom);
276 w = w / scale_factor;
277 h = h / scale_factor;
283 if (debug) printf("recalc %d x %d @ %f\n", w, h, scale_factor);
287 set_zoom_label(imd->zoom_label, imd->zoom, scale_factor);
290 /* this is causing problems with resizing
291 if (imd->top_window && imd->show_title_zoom)
293 gchar *buf = zoom_as_text(imd->zoom, scale_factor);
294 gchar *zbuf = g_strconcat(" [ ", buf, "]", NULL);
296 set_window_title(imd, zbuf);
301 if (image_area_size_top_window(imd, w, h))
304 imd->artificial_size = TRUE;
305 gtk_grab_add (info_zoom);
306 while(gtk_events_pending()) gtk_main_iteration();
307 gtk_grab_remove(info_zoom);
308 imd->artificial_size = FALSE;
313 *-----------------------------------------------------------------------------
314 * image widget set/get image information
315 *-----------------------------------------------------------------------------
318 void image_area_set_path(ImageWindow *imd, gchar *newpath)
320 if (!imd->image_path || !newpath) return;
322 g_free(imd->image_path);
323 imd->image_path = g_strdup(newpath);
324 imd->image_name = filename_from_path(imd->image_path);
328 set_window_title(imd, NULL);
332 gchar *image_area_get_path(ImageWindow *imd)
334 return imd->image_path;
337 gchar *image_area_get_name(ImageWindow *imd)
339 return imd->image_name;
342 void image_area_set_image(ImageWindow *imd, gchar *path, gint zoom)
344 if (path && imd->image_path && !strcmp(path, imd->image_path)) return;
346 g_free(imd->image_path);
349 imd->image_path = g_strdup(path);
350 imd->image_name = filename_from_path(imd->image_path);
354 imd->image_path = NULL;
355 imd->image_name = " ";
359 if (imd->image_data) gdk_imlib_destroy_image(imd->image_data);
360 if (path && isfile(path))
362 imd->image_data = gdk_imlib_load_image(path);
363 if (!imd->image_data)
365 imd->image_data = gdk_imlib_create_image_from_xpm_data((gchar **)img_unknown_xpm);
370 imd->unknown = FALSE;
372 imd->size = filesize(path);
377 imd->image_data = gdk_imlib_create_image_from_xpm_data((gchar **)img_unknown_xpm);
379 imd->image_data = gdk_imlib_create_image_from_data((char *)logo, NULL, logo_width, logo_height);
384 imd->width = imd->old_width = 0;
385 imd->height = imd->old_height = 0;
389 set_window_title(imd, NULL);
393 set_info_label(imd->info_label, imd->image_data->rgb_width, imd->image_data->rgb_height, imd->size, imd->unknown);
396 /* do info area updates here */
399 image_area_set_zoom(imd, zoom);
403 *-----------------------------------------------------------------------------
404 * image widget redraw/callbacks (private)
405 *-----------------------------------------------------------------------------
408 static void image_area_redraw(ImageWindow *imd)
410 GdkBitmap *mask = NULL;
412 if (debug) printf("redrawn %d x %d\n", imd->width, imd->height);
414 if (!imd->image_data) return;
416 if (imd->width == imd->old_width && imd->height == imd->old_height)
418 if (debug) printf("redraw cancelled\n");
422 if (imd->image_pixmap) gdk_imlib_free_pixmap(imd->image_pixmap);
423 imd->image_pixmap = NULL;
425 gdk_imlib_render(imd->image_data, imd->width, imd->height);
426 imd->image_pixmap = gdk_imlib_move_image(imd->image_data);
427 mask = gdk_imlib_move_mask(imd->image_data);
429 gdk_window_set_back_pixmap(imd->image->window, imd->image_pixmap, FALSE);
430 gdk_window_shape_combine_mask (imd->image->window, mask, 0, 0);
431 gdk_window_clear(imd->image->window);
434 imd->old_width = imd->width;
435 imd->old_height = imd->height;
438 static gint image_area_size_cb(GtkWidget *widget, GtkAllocation *allocation, gpointer data)
440 ImageWindow *imd = data;
449 if (imd->artificial_size) return FALSE;
451 h = gtk_viewport_get_hadjustment(GTK_VIEWPORT(imd->viewport));
452 v = gtk_viewport_get_vadjustment(GTK_VIEWPORT(imd->viewport));
455 h_max = allocation->width;
457 v_max = allocation->height;
459 if (imd == normal_image)
465 if (h_pos > h->upper - h_max) h_pos = h->upper - h_max;
466 if (v_pos > v->upper - v_max) v_pos = v->upper - v_max;
470 imd->new_img = FALSE;
471 gtk_adjustment_clamp_page(h, 0.0, h_max);
472 gtk_adjustment_clamp_page(v, 0.0, v_max);
476 gtk_adjustment_clamp_page(h, h_pos, h_max);
477 gtk_adjustment_clamp_page(v, v_pos, v_max);
480 gtk_adjustment_changed(h);
481 gtk_adjustment_changed(v);
483 if (!imd->image_data || imd->zoom != 0) return FALSE;
487 image_area_recalc_size(imd, allocation);
488 if (old_w != imd->width || old_h != imd->height)
490 gtk_widget_set_usize (imd->table, imd->width, imd->height);
491 gtk_drawing_area_size(GTK_DRAWING_AREA(imd->image), imd->width, imd->height);
494 if (debug) printf("sized %d x %d (%d x %d)\n", allocation->width, allocation->height, imd->width, imd->height);
499 static gint image_area_update_cb(GtkWidget *widget, GdkEventConfigure *event, gpointer data)
501 ImageWindow *imd = data;
503 if (imd->artificial_size) return FALSE;
505 image_area_redraw(imd);
511 *-----------------------------------------------------------------------------
512 * image widget mouse routines (private)
513 *-----------------------------------------------------------------------------
516 static void set_mouse_cursor (GdkWindow *window, gint icon)
526 cursor = gdk_cursor_new (icon);
529 gdk_window_set_cursor (window, cursor);
531 if (cursor) gdk_cursor_destroy (cursor);
534 static void image_area_mouse_moved(GtkWidget *widget, GdkEventButton *bevent, gpointer data)
536 ImageWindow *imd = data;
542 if (!imd->in_drag || !gdk_pointer_is_grabbed()) return;
544 if (imd->drag_moved < 4)
550 set_mouse_cursor (imd->eventbox->window, GDK_FLEUR);
553 h = gtk_viewport_get_hadjustment(GTK_VIEWPORT(imd->viewport));
554 v = gtk_viewport_get_vadjustment(GTK_VIEWPORT(imd->viewport));
556 x = imd->drag_last_x - bevent->x;
557 y = imd->drag_last_y - bevent->y;
560 if (h->upper - h->page_size > 0)
562 val = (float)h->value + x;
563 if (val < 0 ) val = 0;
564 if (val > h->upper - h->page_size) val = h->upper - h->page_size;
566 gtk_adjustment_set_value (GTK_ADJUSTMENT(h), val);
570 if (v->upper - v->page_size > 0)
573 if (val < 0 ) val = 0;
574 if (val > v->upper - v->page_size) val = v->upper - v->page_size;
576 gtk_adjustment_set_value (GTK_ADJUSTMENT(v), val);
579 gtk_adjustment_value_changed(h);
580 gtk_adjustment_value_changed(v);
582 imd->drag_last_x = bevent->x;
583 imd->drag_last_y = bevent->y;
586 static void image_area_mouse_pressed(GtkWidget *widget, GdkEventButton *bevent, gpointer data)
588 ImageWindow *imd = data;
589 switch (bevent->button)
593 imd->drag_last_x = bevent->x;
594 imd->drag_last_y = bevent->y;
596 gdk_pointer_grab (imd->eventbox->window, FALSE,
597 GDK_POINTER_MOTION_MASK |
598 GDK_BUTTON_RELEASE_MASK,
599 NULL, NULL, bevent->time);
600 gtk_grab_add (imd->eventbox);
607 imd->func_btn3(imd, bevent, imd->data_btn3);
612 gtk_widget_grab_focus(imd->viewport);
615 static void image_area_mouse_released(GtkWidget *widget, GdkEventButton *bevent, gpointer data)
617 ImageWindow *imd = data;
618 if (gdk_pointer_is_grabbed() && GTK_WIDGET_HAS_GRAB (imd->eventbox))
620 gtk_grab_remove (imd->eventbox);
621 gdk_pointer_ungrab (bevent->time);
622 set_mouse_cursor (imd->eventbox->window, -1);
625 if (bevent->button == 1)
627 if (imd->drag_moved < 4 && imd->func_btn1)
628 imd->func_btn1(imd, bevent, imd->data_btn1);
631 if (bevent->button == 2)
633 if (imd->drag_moved < 4 && imd->func_btn2)
634 imd->func_btn2(imd, bevent, imd->data_btn2);
637 imd->in_drag = FALSE;
640 static void image_area_mouse_drag(GtkWidget *widget, GdkDragContext *context, gpointer data)
642 ImageWindow *imd = data;
647 *-----------------------------------------------------------------------------
648 * image widget setup routines
649 *-----------------------------------------------------------------------------
652 void image_area_set_topwindow(ImageWindow *imd, GtkWidget *window, gchar *title, gint show_zoom)
654 imd->top_window = window;
655 imd->show_title_zoom = show_zoom;
659 imd->title = g_strdup(title);
664 void image_area_set_labels(ImageWindow *imd, GtkWidget *info, GtkWidget *zoom)
666 imd->info_label = info;
667 imd->zoom_label = zoom;
670 void image_area_set_button(ImageWindow *imd, gint button,
671 void (*func)(ImageWindow *, GdkEventButton *, gpointer), gpointer data)
676 imd->func_btn1 = func;
677 imd->data_btn1 = data;
680 imd->func_btn2 = func;
681 imd->data_btn2 = data;
684 imd->func_btn3 = func;
685 imd->data_btn3 = data;
690 ImageWindow *image_area_new(GtkWidget *top_window)
696 imd = g_new0(ImageWindow, 1);
699 imd->top_window = top_window;
700 imd->title = g_strdup("GQview - ");
701 imd->show_title_zoom = FALSE;
702 imd->new_img = FALSE;
704 imd->eventbox = gtk_event_box_new();
706 gtk_signal_connect(GTK_OBJECT(imd->eventbox),"motion_notify_event",
707 GTK_SIGNAL_FUNC(image_area_mouse_moved), imd);
708 gtk_signal_connect(GTK_OBJECT(imd->eventbox),"button_press_event",
709 GTK_SIGNAL_FUNC(image_area_mouse_pressed), imd);
710 gtk_signal_connect(GTK_OBJECT(imd->eventbox),"button_release_event",
711 GTK_SIGNAL_FUNC(image_area_mouse_released), imd);
712 gtk_widget_set_events(imd->eventbox, GDK_POINTER_MOTION_MASK | GDK_BUTTON_RELEASE_MASK | GDK_BUTTON_PRESS_MASK);
715 h_adj = gtk_adjustment_new(0.0,0.0,0.0,1.0,1.0,1.0);
716 v_adj = gtk_adjustment_new(0.0,0.0,0.0,1.0,1.0,1.0);
718 imd->viewport = gtk_viewport_new (GTK_ADJUSTMENT(h_adj), GTK_ADJUSTMENT(v_adj));
719 gtk_container_add(GTK_CONTAINER(imd->eventbox), imd->viewport);
721 /* table for resize */
722 imd->table = gtk_table_new (1,1,TRUE);
723 gtk_container_add(GTK_CONTAINER (imd->viewport), imd->table);
726 imd->image = gtk_drawing_area_new();
727 gtk_table_attach(GTK_TABLE (imd->table),imd->image,0,1,0,1,GTK_EXPAND,GTK_EXPAND,0,0);
729 gtk_signal_connect(GTK_OBJECT(imd->eventbox),"size_allocate",GTK_SIGNAL_FUNC(image_area_size_cb), imd);
730 gtk_signal_connect(GTK_OBJECT(imd->image),"configure_event",GTK_SIGNAL_FUNC(image_area_update_cb), imd);
732 gtk_signal_connect(GTK_OBJECT(imd->viewport),"drag_begin",
733 GTK_SIGNAL_FUNC(image_area_mouse_drag), imd);
738 void image_area_free(ImageWindow *imd)
740 g_free(imd->image_path);
743 if (imd->image_pixmap) gdk_imlib_free_pixmap(imd->image_pixmap);
744 if (imd->image_data) gdk_imlib_destroy_image(imd->image_data);
749 gint get_default_zoom(ImageWindow *imd)
753 if (zoom_mode == ZOOM_RESET_ORIGINAL)
757 else if (zoom_mode == ZOOM_RESET_FIT_WINDOW)
765 zoom = image_area_get_zoom(imd);
777 *-----------------------------------------------------------------------------
778 * image widget misc utils
779 *-----------------------------------------------------------------------------
782 void image_area_to_root(ImageWindow *imd, gint scaled)
784 GdkVisual *gdkvisual;
785 GdkWindow *rootwindow;
788 if (!imd || !imd->image_data) return;
791 rootwindow = (GdkWindow *) &gdk_root_parent; /* hmm, don't know, correct? */
792 gdkvisual = gdk_window_get_visual(rootwindow);
793 if (gdkvisual != gdk_imlib_get_visual()) return;
797 gdk_imlib_render(imd->image_data, gdk_screen_width(), gdk_screen_height());
801 gdk_imlib_render(imd->image_data, imd->width, imd->height);
804 pixmap = gdk_imlib_move_image(imd->image_data);
805 gdk_window_set_back_pixmap(rootwindow, pixmap, FALSE);
806 gdk_window_clear(rootwindow);
807 gdk_imlib_free_pixmap(pixmap);