[gegl] bin: add a thumbbar as part of overlay image controls
- From: Øyvind "pippin" Kolås <ok src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gegl] bin: add a thumbbar as part of overlay image controls
- Date: Sun, 27 Jan 2019 16:26:46 +0000 (UTC)
commit e525efa8bf9cf4f079579c7c427e0208a3414ac3
Author: Øyvind Kolås <pippin gimp org>
Date: Sun Jan 27 03:20:13 2019 +0100
bin: add a thumbbar as part of overlay image controls
bin/ui.c | 332 +++++++++++++++++++++++++++++++++++++++++++----
operations/common/save.c | 4 +-
2 files changed, 309 insertions(+), 27 deletions(-)
---
diff --git a/bin/ui.c b/bin/ui.c
index c225b4dc9..615078756 100644
--- a/bin/ui.c
+++ b/bin/ui.c
@@ -253,8 +253,6 @@ struct _State {
char new_opname[1024];
int rev;
- int concurrent_thumbnailers;
-
float u, v;
float scale;
float dir_scale;
@@ -266,6 +264,13 @@ struct _State {
int show_graph;
float graph_scale;
+ float thumbbar_pan_x;
+ float thumbbar_pan_y;
+ int show_thumbbar;
+ float thumbbar_scale;
+ float thumbbar_opacity;
+ int thumbbar_timeout;
+
int show_controls;
int controls_timeout;
int frame_no;
@@ -322,23 +327,20 @@ Setting settings[]=
STRING_PROP_RO(save_path, "save path, might be different from path if current path is an immutable source
image itself"),
STRING_PROP_RO(src_path, "source path the immutable source image currently being edited"),
- FLOAT_PROP(u, "horizontal coordinate of top-left in display/scaled by scale factor coordinates"),
- FLOAT_PROP(v, "vertical coordinate of top-left in display/scaled by scale factor coordinates"),
- FLOAT_PROP(render_quality, "1.0 = normal 2.0 = render at 2.0 zoom factor 4.0 render at 25%"),
- FLOAT_PROP(preview_quality, "preview quality for use during some interactions, same scale as
render-quality"),
+// FLOAT_PROP(u, "horizontal coordinate of top-left in display/scaled by scale factor coordinates"),
+// FLOAT_PROP(v, "vertical coordinate of top-left in display/scaled by scale factor coordinates"),
+// FLOAT_PROP(render_quality, "1.0 = normal 2.0 = render at 2.0 zoom factor 4.0 render at 25%"),
+// FLOAT_PROP(preview_quality, "preview quality for use during some interactions, same scale as
render-quality"),
INT_PROP(show_graph, "show the graph (and commandline)"),
+ INT_PROP(show_thumbbar, "show the thumbbar"),
INT_PROP(show_controls, "show image viewer controls (maybe merge with show-graph and give better name)"),
INT_PROP(slide_enabled, "slide show going"),
INT_PROP_RO(is_video, ""),
INT_PROP(color_manage_display, "perform ICC color management and convert output to display ICC profile
instead of passing out sRGB, passing out sRGB is faster."),
INT_PROP(playing, "wheter we are playing or not set to 0 for pause 1 for playing"),
- INT_PROP(concurrent_thumbnailers, "number of child processes spawned at the same time doing thumbnailing"),
INT_PROP(frame_no, "current frame number in video/animation"),
FLOAT_PROP(scale, "display scale factor"),
INT_PROP(show_bindings, "show currently valid keybindings"),
- FLOAT_PROP(graph_pan_x, "vertical scroll offset of graph"),
- FLOAT_PROP(graph_pan_y, "horizontal scroll offset of graph"),
- FLOAT_PROP(graph_scale, "graph scale factor"),
};
@@ -627,13 +629,13 @@ static gboolean renderer_task (gpointer data)
if (thumb_queue)
{
static GPid thumbnailer_pid = 0;
-#define THUMB_BATCH_SIZE 32
+#define THUMB_BATCH_SIZE 10
char *argv[THUMB_BATCH_SIZE]={"gegl","--thumbgen", NULL};
int count = 2;
MrgList *to_remove = NULL;
for (MrgList *iter = thumb_queue;
- iter && count < THUMB_BATCH_SIZE-2;
+ iter && count < THUMB_BATCH_SIZE-3;
iter=iter->next)
{
ThumbQueueItem *item = iter->data;
@@ -695,12 +697,14 @@ static void init_state (State *o)
const char *renderer_env = g_getenv ("GEGL_RENDERER");
o->scale = 1.0;
o->graph_scale = 1.0;
+ o->thumbbar_scale = 1.0;
+ o->thumbbar_opacity = 1.0;
+ o->show_thumbbar = 1.0;
o->render_quality = 1.0;
o->preview_quality = 1.0;
//o->preview_quality = 2.0;
o->slide_pause = 5.0;
o->slide_enabled = 0;
- o->concurrent_thumbnailers = 2;
o->show_bindings = 0;
o->ui_consumer = g_hash_table_new (g_direct_hash, g_direct_equal);
@@ -733,7 +737,7 @@ int mrg_ui_main (int argc, char **argv, char **ops)
State *o = &state;
global_state = o;
-
+ mrg_set_image_cache_mb (mrg, 1024);
mrg_set_title (mrg, "GEGL");
gegl_init (&argc, &argv);
@@ -878,6 +882,14 @@ static int hide_controls_cb (Mrg *mrg, void *data)
return 0;
}
+static int fade_thumbbar_cb (Mrg *mrg, void *data)
+{
+ State *o = data;
+ o->show_thumbbar = 1;
+ mrg_queue_draw (o->mrg, NULL);
+ return 0;
+}
+
static void on_viewer_motion (MrgEvent *e, void *data1, void *data2)
{
State *o = data1;
@@ -892,7 +904,22 @@ static void on_viewer_motion (MrgEvent *e, void *data1, void *data2)
mrg_remove_idle (o->mrg, o->controls_timeout);
o->controls_timeout = 0;
}
- o->controls_timeout = mrg_add_timeout (o->mrg, 1000, hide_controls_cb, o);
+ o->controls_timeout = mrg_add_timeout (o->mrg, 2000, hide_controls_cb, o);
+ }
+}
+
+static void on_thumbbar_motion (MrgEvent *e, void *data1, void *data2)
+{
+ State *o = data1;
+ on_viewer_motion (e, data1, NULL);
+ {
+ o->show_thumbbar = 2;
+ if (o->thumbbar_timeout)
+ {
+ mrg_remove_idle (o->mrg, o->thumbbar_timeout);
+ o->thumbbar_timeout = 0;
+ }
+ o->thumbbar_timeout = mrg_add_timeout (o->mrg, 4000, fade_thumbbar_cb, o);
}
}
@@ -1117,6 +1144,7 @@ static void on_dir_drag (MrgEvent *e, void *data1, void *data2)
if (e->type == MRG_DRAG_RELEASE)
{
zoom_pinch = 0;
+ mrg_queue_draw (e->mrg, NULL);
} else if (e->type == MRG_DRAG_PRESS)
{
if (e->device_no == 5)
@@ -1182,6 +1210,8 @@ static void on_dir_drag (MrgEvent *e, void *data1, void *data2)
}
+
+
static GeglNode *add_output (State *o, GeglNode *active, const char *optype);
static GeglNode *add_aux (State *o, GeglNode *active, const char *optype);
static GeglNode *add_input (State *o, GeglNode *active, const char *optype);
@@ -1372,9 +1402,14 @@ static void entry_select (MrgEvent *event, void *data1, void *data2)
static void entry_load (MrgEvent *event, void *data1, void *data2)
{
State *o = data1;
+
+ if (o->rev)
+ argvs_eval ("save");
+
g_free (o->path);
o->path = g_strdup (data2);
load_path (o);
+ mrg_event_stop_propagate (event);
mrg_queue_draw (event->mrg, NULL);
}
@@ -1414,7 +1449,6 @@ static void ui_dir_viewer (State *o)
mrg_listen (mrg, MRG_MOTION, on_viewer_motion, o, NULL);
cairo_new_path (cr);
-// mrg_set_edge_right (mrg, 4095);
cairo_save (cr);
cairo_translate (cr, 0, -(int)o->v);
{
@@ -1445,7 +1479,7 @@ static void ui_dir_viewer (State *o)
float y = dim * (no/cols);
int is_dir = 0;
- if (y < -dim || y > mrg_height (mrg) + o->v)
+ if (y < -dim + o->v || y > mrg_height (mrg) + o->v)
continue;
lstat (path, &stat_buf);
@@ -1591,6 +1625,165 @@ static void draw_edit (Mrg *mrg, float x, float y, float w, float h)
cairo_new_path (cr);
cairo_arc (cr, x+0.5*w, y+0.5*h, h * .4, 0.0, G_PI * 2);
}
+static void on_thumbbar_drag (MrgEvent *e, void *data1, void *data2);
+
+
+static void on_thumbbar_visible (MrgEvent *event, void *data1, void *data2)
+{
+}
+
+static void on_thumbbar_scroll (MrgEvent *event, void *data1, void *data2)
+{
+ State *o = data1;
+ on_viewer_motion (event, data1, NULL);
+ switch (event->scroll_direction)
+ {
+ case MRG_SCROLL_DIRECTION_DOWN:
+ o->thumbbar_scale /= 1.1;
+ if (o->thumbbar_scale < 0.2)
+ o->thumbbar_scale = 0.2;
+ break;
+ case MRG_SCROLL_DIRECTION_UP:
+ o->thumbbar_scale *= 1.1;
+ if (o->thumbbar_scale > 3)
+ o->thumbbar_scale = 3;
+ break;
+ default:
+ break;
+ }
+ mrg_queue_draw (event->mrg, NULL);
+ mrg_event_stop_propagate (event);
+}
+
+static void draw_thumb_bar (State *o)
+{
+ Mrg *mrg = o->mrg;
+ float width = mrg_width(mrg);
+ float height = mrg_height(mrg);
+ cairo_t *cr = mrg_cr (mrg);
+ GList *curr = g_list_find_custom (o->paths, o->path, (void*)g_strcmp0);
+ float dim = height * 0.15 * o->thumbbar_scale;
+ float padding = .025;
+ float opacity;
+
+ cairo_save (cr);
+
+ if (o->show_thumbbar > 1)
+ {
+ opacity = o->thumbbar_opacity * (1.0 - 0.09) + 0.09 * 1.0;
+ if (opacity < 0.99)
+ mrg_queue_draw (o->mrg, NULL);
+ }
+ else
+ {
+ opacity = o->thumbbar_opacity * (1.0 - 0.09) + 0.09 * 0.05;
+ if (opacity > 0.06)
+ mrg_queue_draw (o->mrg, NULL);
+ }
+ o->thumbbar_opacity = opacity;
+
+ //cairo_translate (mrg_cr (mrg), - o->thumbbar_pan_x, -o->thumbbar_pan_y);
+ //cairo_scale (mrg_cr (mrg), o->thumbbar_scale, o->thumbbar_scale);
+
+ cairo_rectangle (cr, 0, height-dim, width, dim);
+ mrg_listen (mrg, MRG_DRAG, on_thumbbar_drag, o, NULL);
+ mrg_listen (mrg, MRG_SCROLL, on_thumbbar_scroll, o, NULL);
+ mrg_listen (mrg, MRG_DRAG, on_thumbbar_motion, o, NULL);
+ mrg_listen (mrg, MRG_MOTION, on_thumbbar_motion, o, NULL);
+ mrg_listen (mrg, MRG_SCROLL, on_thumbbar_motion, o, NULL);
+ cairo_new_path (cr);
+
+ if (curr && opacity > 0.06)
+ {
+ GList *iter = curr;
+ float x = mrg_width(mrg)/2-dim/2 - o->thumbbar_pan_x;
+
+
+ for (iter = curr; iter && x < width; iter = iter->next)
+ {
+ char *path = suffix_path (iter->data);
+ char *thumbpath = get_thumb_path (path);
+ int w, h;
+
+ if (
+ access (thumbpath, F_OK) == 0 &&
+ mrg_query_image (mrg, thumbpath, &w, &h))
+ {
+
+ float wdim = dim, hdim = dim;
+ if (w > h) hdim = dim / (1.0 * w / h);
+ else wdim = dim * (1.0 * w / h);
+
+ if (w!=0 && h!=0)
+ {
+ cairo_rectangle (mrg_cr (mrg), x, height-dim, wdim, hdim);
+ if (iter == curr)
+ cairo_set_source_rgba (mrg_cr (mrg), 1,1,0,.7 * opacity);
+ else
+ cairo_set_source_rgba (mrg_cr (mrg), 1,1,1,.1 * opacity);
+ mrg_listen (mrg, MRG_TAP, entry_load, o, (void*)g_intern_string (iter->data));
+ cairo_fill (mrg_cr (mrg));
+ mrg_image (mrg, x + dim * padding, height-dim*(1.0-padding),
+ wdim * (1.0-padding*2), hdim *(1.0-padding*2), opacity, thumbpath, NULL, NULL);
+ }
+ }
+ else
+ {
+ if (access (thumbpath, F_OK) != 0) // only queue if does not exist,
+ // mrg/stb_image seem to suffer on some of our pngs
+ {
+ queue_thumb (iter->data, thumbpath);
+ }
+ }
+ x += dim;
+ g_free (thumbpath);
+ g_free (path);
+ }
+ x = mrg_width(mrg)/2-dim/2 - o->thumbbar_pan_x;
+ dim = height * 0.15 * o->thumbbar_scale;
+ x -= dim;
+
+ for (iter = curr->prev; iter && x > -dim; iter = iter->prev)
+ {
+ char *path = suffix_path (iter->data);
+ char *thumbpath = get_thumb_path (path);
+ int w, h;
+
+ if (
+ access (thumbpath, F_OK) == 0 &&
+ mrg_query_image (mrg, thumbpath, &w, &h))
+ {
+
+ float wdim = dim, hdim = dim;
+ if (w > h) hdim = dim / (1.0 * w / h);
+ else wdim = dim * (1.0 * w / h);
+ if (w!=0 && h!=0)
+ {
+ cairo_rectangle (mrg_cr (mrg), x, height-dim, wdim, hdim);
+ cairo_set_source_rgba (mrg_cr (mrg), 1,1,1,.1 * opacity);
+ mrg_listen (mrg, MRG_TAP, entry_load, o, (void*)g_intern_string (iter->data));
+ cairo_fill (mrg_cr (mrg));
+ mrg_image (mrg, x + dim * padding, height-dim*(1.0-padding),
+ wdim * (1.0-padding*2), hdim *(1.0-padding*2), opacity, thumbpath, NULL, NULL);
+ }
+ }
+ else
+ {
+ if (access (thumbpath, F_OK) != 0) // only queue if does not exist,
+ // mrg/stb_image seem to suffer on some of our pngs
+ {
+ queue_thumb (iter->data, thumbpath);
+ }
+ }
+ x -= dim;
+ g_free (thumbpath);
+ g_free (path);
+ }
+
+ }
+
+ cairo_restore (cr);
+}
static void ui_viewer (State *o)
{
@@ -1601,12 +1794,12 @@ static void ui_viewer (State *o)
cairo_save (cr);
cairo_rectangle (cr, 0,0, width, height);
- draw_grid (mrg, height * 0.1/3, height * 0.1/3, height * 0.12, height * 0.12);
+ draw_grid (mrg, height * 0.1/4, height * 0.1/4, height * 0.10, height * 0.10);
if (o->show_controls)
contrasty_stroke (cr);
else
cairo_new_path (cr);
- cairo_rectangle (cr, 0, 0, height * 0.2, height * 0.2);
+ cairo_rectangle (cr, 0, 0, height * 0.15, height * 0.15);
if (o->show_controls)
{
cairo_set_source_rgba (cr, 1,1,1,.1);
@@ -1614,13 +1807,13 @@ static void ui_viewer (State *o)
}
mrg_listen (mrg, MRG_PRESS, run_command, "parent", NULL);
- draw_back (mrg, height * .1 / 3, height * .5, height * .1, height *.1);
+ draw_back (mrg, height * .1 / 4, height * .5, height * .1, height *.1);
cairo_close_path (cr);
if (o->show_controls)
contrasty_stroke (cr);
else
cairo_new_path (cr);
- cairo_rectangle (cr, 0, height * .3, height * .2, height *.7);
+ cairo_rectangle (cr, 0, height * .3, height * .15, height *.7);
if (o->show_controls)
{
cairo_set_source_rgba (cr, 1,1,1,.1);
@@ -1629,13 +1822,13 @@ static void ui_viewer (State *o)
mrg_listen (mrg, MRG_TAP, run_command, "prev", NULL);
cairo_new_path (cr);
- draw_forward (mrg, width - height * .15, height * .5, height * .1, height *.1);
+ draw_forward (mrg, width - height * .12, height * .5, height * .1, height *.1);
cairo_close_path (cr);
if (o->show_controls)
contrasty_stroke (cr);
else
cairo_new_path (cr);
- cairo_rectangle (cr, width - height * .2, height * .3, height * .2, height *.7);
+ cairo_rectangle (cr, width - height * .15, height * .3, height * .15, height *.7);
if (o->show_controls)
{
@@ -1643,13 +1836,13 @@ static void ui_viewer (State *o)
cairo_fill_preserve (cr);
}
mrg_listen (mrg, MRG_TAP, run_command, "next", NULL);
- draw_edit (mrg, width - height * .2, height * .0, height * .2, height *.2);
+ draw_edit (mrg, width - height * .15, height * .0, height * .15, height *.15);
if (o->show_controls)
contrasty_stroke (cr);
else
cairo_new_path (cr);
- cairo_rectangle (cr, width - height * .2, height * .0, height * .2, height *.2);
+ cairo_rectangle (cr, width - height * .15, height * .0, height * .15, height *.15);
if (o->show_controls)
{
cairo_set_source_rgba (cr, 1,1,1,.1);
@@ -1658,6 +1851,8 @@ static void ui_viewer (State *o)
mrg_listen (mrg, MRG_PRESS, run_command, "toggle editing", NULL);
cairo_new_path (cr);
+ if (o->show_thumbbar)
+ draw_thumb_bar (o);
if (o->slide_enabled && o->slide_timeout == 0)
{
@@ -1706,6 +1901,8 @@ static void dir_scroll_cb (MrgEvent *event, void *data1, void *data2)
}
}
+
+
static void dir_touch_handling (Mrg *mrg, State *o)
{
cairo_new_path (mrg_cr (mrg));
@@ -2918,6 +3115,90 @@ static void on_graph_drag (MrgEvent *e, void *data1, void *data2)
drag_preview (e);
}
+
+static void on_thumbbar_drag (MrgEvent *e, void *data1, void *data2)
+{
+ static float pinch_coord[4][2] = {0,};
+ static int pinch = 0;
+ static float orig_zoom = 1.0;
+
+ State *o = data1;
+ //GeglNode *node = data2;
+
+ on_viewer_motion (e, data1, data2);
+ if (e->type == MRG_DRAG_RELEASE)
+ {
+ pinch = 0;
+ } else if (e->type == MRG_DRAG_PRESS)
+ {
+ if (e->device_no == 5) /* 5 is second finger/touch point */
+ {
+ pinch_coord[1][0] = e->device_x;
+ pinch_coord[1][1] = e->device_y;
+ pinch_coord[2][0] = pinch_coord[0][0];
+ pinch_coord[2][1] = pinch_coord[0][1];
+ pinch_coord[3][0] = pinch_coord[1][0];
+ pinch_coord[3][1] = pinch_coord[1][1];
+ pinch = 1;
+ orig_zoom = o->graph_scale;
+ }
+ else if (e->device_no == 1 || e->device_no == 4) /* 1 is mouse pointer 4 is first finger */
+ {
+ pinch_coord[0][0] = e->device_x;
+ pinch_coord[0][1] = e->device_y;
+ }
+ } else if (e->type == MRG_DRAG_MOTION)
+ {
+ if (e->device_no == 1 || e->device_no == 4) /* 1 is mouse pointer 4 is first finger */
+ {
+ pinch_coord[0][0] = e->device_x;
+ pinch_coord[0][1] = e->device_y;
+ }
+ if (e->device_no == 5)
+ {
+ pinch_coord[1][0] = e->device_x;
+ pinch_coord[1][1] = e->device_y;
+ }
+
+ if (pinch)
+ {
+ float orig_dist = hypotf ( pinch_coord[2][0]- pinch_coord[3][0],
+ pinch_coord[2][1]- pinch_coord[3][1]);
+ float dist = hypotf (pinch_coord[0][0] - pinch_coord[1][0],
+ pinch_coord[0][1] - pinch_coord[1][1]);
+ {
+ float x, y;
+ float screen_cx = (pinch_coord[0][0] + pinch_coord[1][0])/2;
+ float screen_cy = (pinch_coord[0][1] + pinch_coord[1][1])/2;
+ //get_coords_graph (o, screen_cx, screen_cy, &x, &y);
+
+ x = (o->thumbbar_pan_x + screen_cx) / o->thumbbar_scale;
+ y = (o->thumbbar_pan_y + screen_cy) / o->thumbbar_scale;
+
+ o->thumbbar_scale = orig_zoom * (dist / orig_dist);
+
+ o->thumbbar_pan_x = x * o->thumbbar_scale - screen_cx;
+ o->thumbbar_pan_y = y * o->thumbbar_scale - screen_cy;
+
+ o->thumbbar_pan_x -= (e->delta_x )/2; /* doing half contribution of motion per finger */
+ o->thumbbar_pan_y -= (e->delta_y )/2; /* is simple and roughly right */
+ }
+
+ }
+ else
+ {
+ if (e->device_no == 1 || e->device_no == 4)
+ {
+ o->thumbbar_pan_x -= (e->delta_x );
+ o->thumbbar_pan_y -= (e->delta_y );
+ }
+ }
+ mrg_queue_draw (e->mrg, NULL);
+ }
+ mrg_event_stop_propagate (e);
+}
+
+
static void on_active_node_drag (MrgEvent *e, void *data1, void *data2, int is_aux)
{
State *o = data1;
@@ -4906,6 +5187,7 @@ static void load_path_inner (State *o,
o->is_video = 0;
o->frame_no = -1;
o->prev_frame_played = 0;
+ o->thumbbar_pan_x = 0;
if (g_str_has_suffix (path, ".gif"))
{
diff --git a/operations/common/save.c b/operations/common/save.c
index 55ea8bf1b..4780c8fa9 100644
--- a/operations/common/save.c
+++ b/operations/common/save.c
@@ -61,9 +61,9 @@ gegl_save_set_saver (GeglOperation *operation)
const gchar *extension, *handler;
/* If prepare has already been invoked, bail out early */
- if (self->cached_path && !strcmp (o->path, self->cached_path))
+ if (self->cached_path && o->path && !strcmp (o->path, self->cached_path))
return;
- if (*o->path == '\0')
+ if (o->path == NULL || *o->path == '\0')
return;
g_free (self->cached_path);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]