diff src/image-overlay.c @ 118:ac0f7f942c4d

Wed Nov 29 22:53:03 2006 John Ellis <johne@verizon.net> * image-overlay.[ch]: Prepare for icon notification display, and fix info overlay image index when on last image of slideshow. * img-view.c: Fix image index when on last image of slideshow.
author gqview
date Thu, 30 Nov 2006 03:56:25 +0000
parents 0c2e1f0a001b
children e2a8b7f2165b
line wrap: on
line diff
--- a/src/image-overlay.c	Wed Nov 29 19:38:25 2006 +0000
+++ b/src/image-overlay.c	Thu Nov 30 03:56:25 2006 +0000
@@ -36,20 +36,43 @@
 	gint show_status;
 
 	gint ovl_info;
-	gint ovl_color;
-	gint ovl_rotate;
-	gint ovl_end;
+
+	gint icon_time[IMAGE_OSD_COUNT];
+	gint icon_id[IMAGE_OSD_COUNT];
 
 	gint idle_id;
 	gint timer_id;
 	gulong destroy_id;
 };
 
+
+typedef struct _OSDIcon OSDIcon;
+struct _OSDIcon {
+	gint x;
+	gint y;
+	gchar *key;
+};
+
+static OSDIcon osd_icons[] = {
+	{ 0, -10, PIXBUF_INLINE_ICON },
+	{ -10, -10, "IMAGE_OSD_ROTATE_USER" },
+	{ -10, -10, "IMAGE_OSD_ROTATE_AUTO" },
+	{ -40, -10, "IMAGE_OSD_COLOR" },
+	{ -70, -10, "IMAGE_OSD_FIRST" },
+	{ -70, -10, "IMAGE_OSD_LAST" },
+	{ 0, 0, NULL }
+};
+
 #define OSD_DATA "overlay-data"
 
 #define OSD_INFO_X 10
 #define OSD_INFO_Y -10
 
+#define IMAGE_OSD_DEFAULT_DURATION 30
+
+
+static void image_osd_timer_schedule(OverlayStateData *osd);
+
 
 static GdkPixbuf *image_osd_info_render(ImageWindow *imd)
 {
@@ -97,6 +120,7 @@
 				{
 				n = g_list_length(lw->slideshow->list_done);
 				t = n + g_list_length(lw->slideshow->list);
+				if (n == 0) n = t;
 				}
 			else
 				{
@@ -182,12 +206,65 @@
 	return pixbuf;
 }
 
-static void image_osd_ovl_reset(OverlayStateData *osd, gint *id)
+static GdkPixbuf *image_osd_icon_pixbuf(ImageOSDFlag flag)
 {
-	if (*id)
+	static GdkPixbuf **icons = NULL;
+	GdkPixbuf *icon = NULL;
+
+	if (!icons) icons = g_new0(GdkPixbuf *, IMAGE_OSD_COUNT);
+	if (icons[flag]) return icons[flag];
+
+	icon = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, 24, 24);
+	pixbuf_set_rect_fill(icon, 1, 1, 22, 22, 255, 255, 255, 200);
+	pixbuf_set_rect(icon, 0, 0, 24, 24, 0, 0, 0, 128, 1, 1, 1, 1);
+	switch (flag)
 		{
-		image_overlay_remove(osd->imd, *id);
-		*id = 0;
+		case IMAGE_OSD_COLOR:
+			pixbuf_set_rect_fill(icon, 3, 3, 18, 6, 200, 0, 0, 255);
+			pixbuf_set_rect_fill(icon, 3, 9, 18, 6, 0, 200, 0, 255);
+			pixbuf_set_rect_fill(icon, 3, 15, 18, 6, 0, 0, 200, 255);
+			break;
+		case IMAGE_OSD_FIRST:
+			pixbuf_set_rect(icon, 3, 3, 18, 18, 0, 0, 0, 200, 3, 3, 3, 0);
+			pixbuf_draw_triangle(icon, 6, 5, 12, 6,
+					     12, 5, 18, 11, 6, 11,
+					     0, 0, 0, 255);
+			break;
+		case IMAGE_OSD_LAST:
+			pixbuf_set_rect(icon, 3, 3, 18, 18, 0, 0, 0, 200, 3, 3, 0, 3);
+			pixbuf_draw_triangle(icon, 6, 12, 12, 6,
+					     12, 18, 6, 12, 18, 12,
+					     0, 0, 0, 255);
+			break;
+		default:
+			break;
+		}
+
+	icons[flag] = icon;
+
+	return icon;
+}
+
+static void image_osd_icon_show(OverlayStateData *osd, ImageOSDFlag flag)
+{
+	GdkPixbuf *pixbuf;
+
+	if (osd->icon_id[flag]) return;
+
+	pixbuf = image_osd_icon_pixbuf(flag);
+	if (!pixbuf) return;
+
+	osd->icon_id[flag] = image_overlay_add(osd->imd, pixbuf,
+					       osd_icons[flag].x, osd_icons[flag].y,
+					       TRUE, FALSE);
+}
+
+static void image_osd_icon_hide(OverlayStateData *osd, ImageOSDFlag flag)
+{
+	if (osd->icon_id[flag])
+		{
+		image_overlay_remove(osd->imd, osd->icon_id[flag]);
+		osd->icon_id[flag] = 0;
 		}
 }
 
@@ -216,19 +293,51 @@
 		}
 	else
 		{
-		image_osd_ovl_reset(osd, & osd->ovl_info);
+		if (osd->ovl_info)
+			{
+			image_overlay_remove(osd->imd, osd->ovl_info);
+			osd->ovl_info = 0;
+			}
 		}
 
 	if (osd->show_status)
 		{
+		gint i;
+
+		if (osd->changed_states & IMAGE_STATE_IMAGE)
+			{
+			for (i = 0; i < IMAGE_OSD_COUNT; i++) osd->icon_time[i] = 0;
+			}
+
+		if (osd->changed_states & IMAGE_STATE_COLOR_ADJ)
+			{
+			osd->icon_time[IMAGE_OSD_COLOR] = IMAGE_OSD_DEFAULT_DURATION + 1;
+			image_osd_timer_schedule(osd);
+			}
+
+		for (i = 0; i < IMAGE_OSD_COUNT; i++)
+			{
+			if (osd->icon_time[i] > 0)
+				{
+				image_osd_icon_show(osd, i);
+				}
+			else
+				{
+				image_osd_icon_hide(osd, i);
+				}
+			}
 		}
 	else
 		{
-		image_osd_ovl_reset(osd, & osd->ovl_color);
-		image_osd_ovl_reset(osd, & osd->ovl_rotate);
-		image_osd_ovl_reset(osd, & osd->ovl_end);
+		gint i;
+
+		for (i = 0; i < IMAGE_OSD_COUNT; i++)
+			{
+			image_osd_icon_hide(osd, i);
+			}
 		}
 
+	osd->changed_states = IMAGE_STATE_NONE;
 	osd->idle_id = -1;
 	return FALSE;
 }
@@ -255,6 +364,49 @@
 	image_osd_update_schedule(osd, TRUE);
 }
 
+static gint image_osd_timer_cb(gpointer data)
+{
+	OverlayStateData *osd = data;
+	gint done = TRUE;
+	gint changed = FALSE;
+	gint i;
+
+	for (i = 0; i < IMAGE_OSD_COUNT; i++)
+		{
+		if (osd->icon_time[i] > 1)
+			{
+			osd->icon_time[i]--;
+			if (osd->icon_time[i] < 2)
+				{
+				osd->icon_time[i] = 0;
+				changed = TRUE;
+				}
+			else
+				{
+				done = FALSE;
+				}
+			}
+		}
+
+	if (changed) image_osd_update_schedule(osd, FALSE);
+
+	if (done)
+		{
+		osd->timer_id = -1;
+		return FALSE;
+		}
+
+	return TRUE;
+}
+
+static void image_osd_timer_schedule(OverlayStateData *osd)
+{
+	if (osd->timer_id == -1)
+		{
+		osd->timer_id = g_timeout_add(100, image_osd_timer_cb, osd);
+		}
+}
+
 static void image_osd_state_cb(ImageWindow *imd, ImageState state, gpointer data)
 {
 	OverlayStateData *osd = data;
@@ -268,14 +420,22 @@
 	if (!osd) return;
 
 	if (osd->idle_id != -1) g_source_remove(osd->idle_id);
+	if (osd->timer_id != -1) g_source_remove(osd->timer_id);
 
 	if (osd->imd)
 		{
+		gint i;
+
 		g_object_set_data(G_OBJECT(osd->imd->pr), "IMAGE_OVERLAY_DATA", NULL);
 		g_signal_handler_disconnect(osd->imd->pr, osd->destroy_id);
 
 		image_set_state_func(osd->imd, NULL, NULL);
 		image_overlay_remove(osd->imd, osd->ovl_info);
+
+		for (i = 0; i < IMAGE_OSD_COUNT; i++)
+			{
+			image_osd_icon_hide(osd, i);
+			}
 		}
 
 	g_free(osd);
@@ -354,3 +514,28 @@
 	return TRUE;
 }
 
+/* duration:
+    0 = hide
+    1 = show
+   2+ = show for duration tenths of a second
+   -1 = use default duration
+ */
+void image_osd_icon(ImageWindow *imd, ImageOSDFlag flag, gint duration)
+{
+	OverlayStateData *osd;
+
+	if (!imd) return;
+
+	osd = g_object_get_data(G_OBJECT(imd->pr), "IMAGE_OVERLAY_DATA");
+	if (!osd) return;
+
+	if (flag < IMAGE_OSD_NONE || flag >= IMAGE_OSD_COUNT) return;
+	if (duration < 0) duration = IMAGE_OSD_DEFAULT_DURATION;
+	if (duration > 1) duration += 1;
+
+	osd->icon_time[flag] = duration;
+
+	image_osd_update_schedule(osd, FALSE);
+	image_osd_timer_schedule(osd);
+}
+