bin: add a thumbbar as part of overlay image controls

parent 4d634721
......@@ -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"))
{
......
......@@ -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);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment