void scrolled(dt_view_t *self, double x, double y, int up, int state) { const int32_t capwd = darktable.thumbnail_width; const int32_t capht = darktable.thumbnail_height; dt_develop_t *dev = (dt_develop_t *)self->data; const int32_t width_i = self->width; const int32_t height_i = self->height; if(width_i > capwd) x += (capwd-width_i) *.5f; if(height_i > capht) y += (capht-height_i)*.5f; int handled = 0; if(dev->gui_module && dev->gui_module->scrolled) handled = dev->gui_module->scrolled(dev->gui_module, x, y, up, state); if(handled) return; // free zoom dt_dev_zoom_t zoom; int closeup, procw, proch; float zoom_x, zoom_y; DT_CTL_GET_GLOBAL(zoom, dev_zoom); DT_CTL_GET_GLOBAL(closeup, dev_closeup); DT_CTL_GET_GLOBAL(zoom_x, dev_zoom_x); DT_CTL_GET_GLOBAL(zoom_y, dev_zoom_y); dt_dev_get_processed_size(dev, &procw, &proch); float scale = dt_dev_get_zoom_scale(dev, zoom, closeup ? 2.0 : 1.0, 0); const float minscale = dt_dev_get_zoom_scale(dev, DT_ZOOM_FIT, 1.0, 0); // offset from center now (current zoom_{x,y} points there) float mouse_off_x = x - .5*dev->width, mouse_off_y = y - .5*dev->height; zoom_x += mouse_off_x/(procw*scale); zoom_y += mouse_off_y/(proch*scale); zoom = DT_ZOOM_FREE; closeup = 0; if(up) { if (scale == 1.0f) return; else scale += .1f*(1.0f - minscale); } else { if (scale == minscale) return; else scale -= .1f*(1.0f - minscale); } DT_CTL_SET_GLOBAL(dev_zoom_scale, scale); if(scale > 0.99) zoom = DT_ZOOM_1; if(scale < minscale + 0.01) zoom = DT_ZOOM_FIT; if(zoom != DT_ZOOM_1) { zoom_x -= mouse_off_x/(procw*scale); zoom_y -= mouse_off_y/(proch*scale); } dt_dev_check_zoom_bounds(dev, &zoom_x, &zoom_y, zoom, closeup, NULL, NULL); DT_CTL_SET_GLOBAL(dev_zoom, zoom); DT_CTL_SET_GLOBAL(dev_closeup, closeup); if(zoom != DT_ZOOM_1) { DT_CTL_SET_GLOBAL(dev_zoom_x, zoom_x); DT_CTL_SET_GLOBAL(dev_zoom_y, zoom_y); } dt_dev_invalidate(dev); dt_control_queue_redraw(); }
void border_scrolled(dt_view_t *view, double x, double y, int which, int up) { dt_develop_t *dev = (dt_develop_t *)view->data; dt_dev_zoom_t zoom; int closeup; float zoom_x, zoom_y; DT_CTL_GET_GLOBAL(zoom, dev_zoom); DT_CTL_GET_GLOBAL(closeup, dev_closeup); DT_CTL_GET_GLOBAL(zoom_x, dev_zoom_x); DT_CTL_GET_GLOBAL(zoom_y, dev_zoom_y); if(which > 1) { if(up) zoom_x -= 0.02; else zoom_x += 0.02; } else { if(up) zoom_y -= 0.02; else zoom_y += 0.02; } dt_dev_check_zoom_bounds(dev, &zoom_x, &zoom_y, zoom, closeup, NULL, NULL); DT_CTL_SET_GLOBAL(dev_zoom_x, zoom_x); DT_CTL_SET_GLOBAL(dev_zoom_y, zoom_y); dt_dev_invalidate(dev); dt_control_queue_redraw(); }
void _lib_navigation_set_position(dt_lib_module_t *self, double x, double y, int wd, int ht) { dt_lib_navigation_t *d = ( dt_lib_navigation_t *)self->data; dt_dev_zoom_t zoom; int closeup; float zoom_x, zoom_y; DT_CTL_GET_GLOBAL(zoom, dev_zoom); DT_CTL_GET_GLOBAL(closeup, dev_closeup); DT_CTL_GET_GLOBAL(zoom_x, dev_zoom_x); DT_CTL_GET_GLOBAL(zoom_y, dev_zoom_y); if(d->dragging && zoom != DT_ZOOM_FIT) { const int inset = DT_NAVIGATION_INSET; const float width = wd - 2*inset, height = ht - 2*inset; const dt_develop_t *dev = darktable.develop; int iwd, iht; dt_dev_get_processed_size(dev, &iwd, &iht); zoom_x = fmaxf(-.5, fminf(((x-inset)/width - .5f)/(iwd*fminf(wd/(float)iwd, ht/(float)iht)/(float)wd), .5)); zoom_y = fmaxf(-.5, fminf(((y-inset)/height - .5f)/(iht*fminf(wd/(float)iwd, ht/(float)iht)/(float)ht), .5)); dt_dev_check_zoom_bounds(darktable.develop, &zoom_x, &zoom_y, zoom, closeup, NULL, NULL); DT_CTL_SET_GLOBAL(dev_zoom_x, zoom_x); DT_CTL_SET_GLOBAL(dev_zoom_y, zoom_y); /* redraw myself */ gtk_widget_queue_draw(self->widget); /* redraw pipe */ dt_dev_invalidate(darktable.develop); dt_control_queue_redraw_center(); } }
int mouse_moved(struct dt_iop_module_t *self, double x, double y, double pressure, int which) { dt_iop_graduatednd_gui_data_t *g = (dt_iop_graduatednd_gui_data_t *)self->gui_data; int32_t zoom, closeup; DT_CTL_GET_GLOBAL(zoom, dev_zoom); DT_CTL_GET_GLOBAL(closeup, dev_closeup); float zoom_scale = dt_dev_get_zoom_scale(self->dev, zoom, closeup ? 2 : 1, 1); float pzx, pzy; dt_dev_get_pointer_zoom_pos(self->dev, x, y, &pzx, &pzy); pzx += 0.5f; pzy += 0.5f; //are we dragging something ? if (g->dragging > 0) { if (g->dragging == 1) { //we are dragging xa,ya g->xa = pzx; g->ya = pzy; } else if (g->dragging == 2) { //we are dragging xb,yb g->xb = pzx; g->yb = pzy; } else if (g->dragging == 3) { //we are dragging the entire line g->xa += pzx-g->oldx; g->xb += pzx-g->oldx; g->ya += pzy-g->oldy; g->yb += pzy-g->oldy; g->oldx = pzx; g->oldy = pzy; } } else { g->selected = 0; const float ext = 0.02f / zoom_scale; //are we near extermity ? if (pzy>g->ya-ext && pzy<g->ya+ext && pzx>g->xa-ext && pzx<g->xa+ext) { g->selected = 1; } else if (pzy>g->yb-ext && pzy<g->yb+ext && pzx>g->xb-ext && pzx<g->xb+ext) { g->selected = 2; } else if (dist_seg(g->xa,g->ya,g->xb,g->yb,pzx,pzy) < ext*ext*0.5) g->selected = 3; } dt_control_queue_redraw_center(); return 0; }
void gui_post_expose(struct dt_iop_module_t *self, cairo_t *cr, int32_t width, int32_t height, int32_t pointerx, int32_t pointery) { dt_develop_t *dev = self->dev; // dt_iop_graduatednd_gui_data_t *g = (dt_iop_graduatednd_gui_data_t *)self->gui_data; // dt_iop_graduatednd_params_t *p = (dt_iop_graduatednd_params_t *)self->params; // general house keeping. int32_t zoom, closeup; float zoom_x, zoom_y; float wd = dev->preview_pipe->backbuf_width; float ht = dev->preview_pipe->backbuf_height; // Commented out to allow this stub to be compilable with some versions of gcc ... // float bigger_side, smaller_side; // if(wd >= ht) // { // bigger_side = wd; // smaller_side = ht; // } // else // { // bigger_side = ht; // smaller_side = wd; // } DT_CTL_GET_GLOBAL(zoom_y, dev_zoom_y); DT_CTL_GET_GLOBAL(zoom_x, dev_zoom_x); DT_CTL_GET_GLOBAL(zoom, dev_zoom); DT_CTL_GET_GLOBAL(closeup, dev_closeup); float zoom_scale = dt_dev_get_zoom_scale(dev, zoom, closeup ? 2 : 1, 1); float pzx, pzy; dt_dev_get_pointer_zoom_pos(dev, pointerx, pointery, &pzx, &pzy); pzx += 0.5f; pzy += 0.5f; cairo_translate(cr, width/2.0, height/2.0); cairo_scale(cr, zoom_scale, zoom_scale); cairo_translate(cr, -.5f*wd-zoom_x*wd, -.5f*ht-zoom_y*ht); // now top-left is (0,0) and bottom-right is (wd,ht) //TODO calculate values for and execute cairo_translate() and cairo_rotate(). // of course the results can also be passed to draw_overlay() if it's easier to use them there instead. // finally draw the guides. if rotation and translation is done correctly it can be drawn statically in draw_overlay(). // int grab = get_grab(pzx*wd*0.5, pzy*ht*0.5, zoom_scale); //FIXME use the calculated offsets in the 1st and 2nd paramter to get correct mouse positions cairo_set_line_cap(cr,CAIRO_LINE_CAP_ROUND); cairo_set_line_width(cr, 3.0/zoom_scale); cairo_set_source_rgba(cr, .3, .3, .3, .8); // draw_overlay(cr, wd, ht, grab, zoom_scale); //FIXME removed to not annoy users as long as this is just a demo. cairo_set_line_width(cr, 1.0/zoom_scale); cairo_set_source_rgba(cr, .8, .8, .8, .8); // draw_overlay(cr, wd, ht, grab, zoom_scale); //FIXME removed to not annoy users as long as this is just a demo. }
static void _lib_snapshots_add_button_clicked_callback(GtkWidget *widget, gpointer user_data) { dt_lib_module_t *self = (dt_lib_module_t*)user_data; dt_lib_snapshots_t *d = (dt_lib_snapshots_t *)self->data; /* backup last snapshot slot */ dt_lib_snapshot_t last = d->snapshot[d->size-1]; /* rotate slots down to make room for new one on top */ for (int k = d->size-1; k > 0; k--) { GtkWidget *b = d->snapshot[k].button; d->snapshot[k] = d->snapshot[k-1]; d->snapshot[k].button = b; gtk_button_set_label(GTK_BUTTON(d->snapshot[k].button), gtk_button_get_label(GTK_BUTTON(d->snapshot[k-1].button))); } /* update top slot with new snapshot */ char label[64]; GtkWidget *b = d->snapshot[0].button; d->snapshot[0] = last; d->snapshot[0].button = b; const gchar *name = _("original"); if (darktable.develop->history_end > 0) { dt_iop_module_t *module = ((dt_dev_history_item_t *)g_list_nth_data(darktable.develop->history, darktable.develop->history_end-1))->module; if (module) name = module->name(); else name = _("unknown"); } g_snprintf(label,64,"%s (%d)", name, darktable.develop->history_end); gtk_button_set_label(GTK_BUTTON(d->snapshot[0].button), label); dt_lib_snapshot_t *s = d->snapshot + 0; DT_CTL_GET_GLOBAL (s->zoom_y, dev_zoom_y); DT_CTL_GET_GLOBAL (s->zoom_x, dev_zoom_x); DT_CTL_GET_GLOBAL (s->zoom, dev_zoom); DT_CTL_GET_GLOBAL (s->closeup, dev_closeup); DT_CTL_GET_GLOBAL (s->zoom_scale, dev_zoom_scale); /* update slots used */ if (d->num_snapshots != d->size) d->num_snapshots++; /* show active snapshot slots */ for (uint32_t k=0; k < d->num_snapshots; k++) gtk_widget_show(d->snapshot[k].button); /* request a new snapshot for top slot */ dt_dev_snapshot_request(darktable.develop, (const char *)&d->snapshot[0].filename); }
void gui_post_expose(dt_iop_module_t *self, cairo_t *cr, int32_t width, int32_t height, int32_t pointerx, int32_t pointery) { dt_develop_t *dev = self->dev; dt_iop_spots_params_t *p = (dt_iop_spots_params_t *)self->params; dt_iop_spots_gui_data_t *g = (dt_iop_spots_gui_data_t *)self->gui_data; float wd = dev->preview_pipe->backbuf_width; float ht = dev->preview_pipe->backbuf_height; float pzx, pzy; dt_dev_get_pointer_zoom_pos(dev, pointerx, pointery, &pzx, &pzy); pzx += 0.5f; pzy += 0.5f; float zoom_x, zoom_y; int32_t zoom, closeup; DT_CTL_GET_GLOBAL(zoom_y, dev_zoom_y); DT_CTL_GET_GLOBAL(zoom_x, dev_zoom_x); DT_CTL_GET_GLOBAL(zoom, dev_zoom); DT_CTL_GET_GLOBAL(closeup, dev_closeup); float zoom_scale = dt_dev_get_zoom_scale(dev, zoom, closeup ? 2 : 1, 1); cairo_set_source_rgb(cr, .3, .3, .3); cairo_translate(cr, width/2.0, height/2.0f); cairo_scale(cr, zoom_scale, zoom_scale); cairo_translate(cr, -.5f*wd-zoom_x*wd, -.5f*ht-zoom_y*ht); for(int i=0; i<p->num_spots; i++) { const float rad = MIN(wd, ht)*p->spot[i].radius; const float dx = p->spot[i].xc - p->spot[i].x; float dy = p->spot[i].yc - p->spot[i].y; if(dx == 0.0 && dy == 0.0) dy = EPSILON; // otherwise we'll have ol = 1.0/0.0 ==> xr = yr = -nan const float ol = 1.0f/sqrtf(dx*dx*wd*wd + dy*dy*ht*ht); const float d = rad * ol; const float x = p->spot[i].x*wd, y = p->spot[i].y*ht; const float xc = p->spot[i].xc*wd, yc = p->spot[i].yc*ht; const float xr = (p->spot[i].x + d*dx)*wd, yr = (p->spot[i].y + d*dy)*ht; cairo_set_line_cap(cr,CAIRO_LINE_CAP_ROUND); if(i == g->selected || i == g->dragging) cairo_set_line_width(cr, 5.0/zoom_scale); else cairo_set_line_width(cr, 3.0/zoom_scale); cairo_set_source_rgba(cr, .3, .3, .3, .8); draw_overlay(cr, rad, x, y, xc, yc, xr, yr); if(i == g->selected || i == g->dragging) cairo_set_line_width(cr, 2.0/zoom_scale); else cairo_set_line_width(cr, 1.0/zoom_scale); cairo_set_source_rgba(cr, .8, .8, .8, .8); draw_overlay(cr, rad, x, y, xc, yc, xr, yr); } }
static int dt_circle_events_mouse_moved(struct dt_iop_module_t *module,float pzx, float pzy, int which, dt_masks_form_t *form, int parentid, dt_masks_form_gui_t *gui, int index) { if (gui->form_dragging || gui->source_dragging) { gui->posx = pzx*darktable.develop->preview_pipe->backbuf_width; gui->posy = pzy*darktable.develop->preview_pipe->backbuf_height; dt_control_queue_redraw_center(); return 1; } else if (!gui->creation) { int32_t zoom, closeup; DT_CTL_GET_GLOBAL(zoom, dev_zoom); DT_CTL_GET_GLOBAL(closeup, dev_closeup); float zoom_scale = dt_dev_get_zoom_scale(darktable.develop, zoom, closeup ? 2 : 1, 1); float as = 0.005f/zoom_scale*darktable.develop->preview_pipe->backbuf_width; int in,inb,near,ins; dt_circle_get_distance(pzx*darktable.develop->preview_pipe->backbuf_width,pzy*darktable.develop->preview_pipe->backbuf_height,as,gui,index,&in,&inb,&near,&ins); if (ins) { gui->form_selected = TRUE; gui->source_selected = TRUE; gui->border_selected = FALSE; } else if (inb) { gui->form_selected = TRUE; gui->border_selected = TRUE; gui->source_selected = FALSE; } else if (in) { gui->form_selected = TRUE; gui->border_selected = FALSE; gui->source_selected = FALSE; } else { gui->form_selected = FALSE; gui->border_selected = FALSE; gui->source_selected = FALSE; } dt_control_queue_redraw_center(); if (!gui->form_selected && !gui->border_selected) return 0; if (gui->edit_mode != DT_MASKS_EDIT_FULL) return 0; return 1; } return 0; }
static gboolean star_key_accel_callback(GtkAccelGroup *accel_group, GObject *acceleratable, guint keyval, GdkModifierType modifier, gpointer data) { long int num = (long int)data; switch (num) { case DT_VIEW_REJECT: case DT_VIEW_DESERT: case DT_VIEW_STAR_1: case DT_VIEW_STAR_2: case DT_VIEW_STAR_3: case DT_VIEW_STAR_4: case DT_VIEW_STAR_5: case 666: { int32_t mouse_over_id; DT_CTL_GET_GLOBAL(mouse_over_id, lib_image_mouse_over_id); if(mouse_over_id <= 0) { sqlite3_stmt *stmt; DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "select imgid from selected_images", -1, &stmt, NULL); while(sqlite3_step(stmt) == SQLITE_ROW) { const dt_image_t *cimg = dt_image_cache_read_get(darktable.image_cache, sqlite3_column_int(stmt, 0)); dt_image_t *image = dt_image_cache_write_get(darktable.image_cache, cimg); if(num == 666 || num == DT_VIEW_DESERT) image->flags &= ~0xf; else if(num == DT_VIEW_STAR_1 && ((image->flags & 0x7) == 1)) image->flags &= ~0x7; else { image->flags &= ~0x7; image->flags |= num; } dt_image_cache_write_release(darktable.image_cache, image, DT_IMAGE_CACHE_SAFE); dt_image_cache_read_release(darktable.image_cache, cimg); } sqlite3_finalize(stmt); } else { const dt_image_t *cimg = dt_image_cache_read_get(darktable.image_cache, mouse_over_id); dt_image_t *image = dt_image_cache_write_get(darktable.image_cache, cimg); if(num == 666 || num == DT_VIEW_DESERT) image->flags &= ~0xf; else if(num == DT_VIEW_STAR_1 && ((image->flags & 0x7) == 1)) image->flags &= ~0x7; else { image->flags &= ~0x7; image->flags |= num; } dt_image_cache_write_release(darktable.image_cache, image, DT_IMAGE_CACHE_SAFE); dt_image_cache_read_release(darktable.image_cache, cimg); } dt_control_queue_redraw_center(); break; } default: break; } return TRUE; }
float dt_dev_get_zoom_scale(dt_develop_t *dev, dt_dev_zoom_t zoom, int closeup_factor, int preview) { float zoom_scale; // set processed width to something useful while image is not there yet: int procw, proch; dt_dev_get_processed_size(dev, &procw, &proch); const float w = preview ? dev->preview_pipe->backbuf_width : procw; const float h = preview ? dev->preview_pipe->backbuf_height : proch; switch(zoom) { case DT_ZOOM_FIT: zoom_scale = fminf(dev->width/w, dev->height/h); break; case DT_ZOOM_FILL: zoom_scale = fmaxf(dev->width/w, dev->height/h); break; case DT_ZOOM_1: zoom_scale = closeup_factor; if(preview) zoom_scale *= dev->preview_pipe->iscale / dev->preview_downsampling; break; default: // DT_ZOOM_FREE DT_CTL_GET_GLOBAL(zoom_scale, dev_zoom_scale); if(preview) zoom_scale *= dev->preview_pipe->iscale / dev->preview_downsampling; break; } return zoom_scale; }
static void _jump_to() { int32_t imgid = -1; DT_CTL_GET_GLOBAL(imgid, lib_image_mouse_over_id); if(imgid == -1) { sqlite3_stmt *stmt; DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "select imgid from selected_images", -1, &stmt, NULL); if(sqlite3_step(stmt) == SQLITE_ROW) imgid = sqlite3_column_int(stmt, 0); sqlite3_finalize(stmt); } if(imgid != -1) { const int len = 512; char path[len]; const dt_image_t *img = dt_image_cache_read_get(darktable.image_cache, imgid); dt_image_film_roll_directory(img, path, len); dt_image_cache_read_release(darktable.image_cache, img); char collect[1024]; snprintf(collect, 1024, "1:0:0:%s$", path); dt_collection_deserialize(collect); } }
float dt_dev_get_zoom_scale(dt_develop_t *dev, dt_dev_zoom_t zoom, int closeup_factor, int preview) { float zoom_scale; const float w = preview ? dev->preview_pipe->processed_width : dev->pipe->processed_width; const float h = preview ? dev->preview_pipe->processed_height : dev->pipe->processed_height; const float ps = dev->pipe->backbuf_width ? dev->pipe->processed_width/(float)dev->preview_pipe->processed_width : dev->preview_pipe->iscale / dev->preview_downsampling; switch(zoom) { case DT_ZOOM_FIT: zoom_scale = fminf(dev->width/w, dev->height/h); break; case DT_ZOOM_FILL: zoom_scale = fmaxf(dev->width/w, dev->height/h); break; case DT_ZOOM_1: zoom_scale = closeup_factor; if(preview) zoom_scale *= ps; break; default: // DT_ZOOM_FREE DT_CTL_GET_GLOBAL(zoom_scale, dev_zoom_scale); if(preview) zoom_scale *= ps; break; } return zoom_scale; }
void expose(dt_view_t *self, cairo_t *cr, int32_t width, int32_t height, int32_t pointerx, int32_t pointery) { const int i = dt_conf_get_int("plugins/lighttable/layout"); const double start = dt_get_wtime(); // Let's show full preview if in that state... dt_library_t *lib = (dt_library_t *)self->data; int32_t mouse_over_id; DT_CTL_GET_GLOBAL(mouse_over_id, lib_image_mouse_over_id); if( lib->full_preview_id!=-1 ) { lib->image_over = DT_VIEW_DESERT; cairo_set_source_rgb (cr, .1, .1, .1); cairo_paint(cr); dt_view_image_expose(&(lib->image_over),mouse_over_id, cr, width, height, 1, pointerx, pointery); } else // we do pass on expose to manager or zoomable { switch(i) { case 1: // file manager expose_filemanager(self, cr, width, height, pointerx, pointery); break; default: // zoomable expose_zoomable(self, cr, width, height, pointerx, pointery); break; } } const double end = dt_get_wtime(); dt_print(DT_DEBUG_PERF, "[lighttable] expose took %0.04f sec\n", end-start); }
static gboolean _lib_filmstrip_ratings_key_accel_callback(GtkAccelGroup *accel_group, GObject *aceeleratable, guint keyval, GdkModifierType modifier, gpointer data) { int num = GPOINTER_TO_INT(data); switch (num) { case DT_VIEW_DESERT: case DT_VIEW_REJECT: case DT_VIEW_STAR_1: case DT_VIEW_STAR_2: case DT_VIEW_STAR_3: case DT_VIEW_STAR_4: case DT_VIEW_STAR_5: case 666: { int32_t mouse_over_id; DT_CTL_GET_GLOBAL(mouse_over_id, lib_image_mouse_over_id); if (mouse_over_id <= 0) return FALSE; /* get image from cache */ int32_t activated_image = -1; activated_image = darktable.view_manager->proxy.filmstrip.activated_image(darktable.view_manager->proxy.filmstrip.module); int offset = 0; if(mouse_over_id == activated_image) offset = dt_collection_image_offset(mouse_over_id); const dt_image_t *cimg = dt_image_cache_read_get(darktable.image_cache, mouse_over_id); dt_image_t *image = dt_image_cache_write_get(darktable.image_cache, cimg); if (num == 666) image->flags &= ~0xf; else if (num == DT_VIEW_STAR_1 && ((image->flags & 0x7) == 1)) image->flags &= ~0x7; else if(num == DT_VIEW_REJECT && ((image->flags & 0x7) == 6)) image->flags &= ~0x7; else { image->flags &= ~0x7; image->flags |= num; } dt_image_cache_write_release(darktable.image_cache, image, DT_IMAGE_CACHE_SAFE); dt_image_cache_read_release(darktable.image_cache, image); dt_collection_hint_message(darktable.collection); // More than this, we need to redraw all if(mouse_over_id == activated_image) if(_lib_filmstrip_imgid_in_collection(darktable.collection, mouse_over_id) == 0) dt_view_filmstrip_scroll_relative(0, offset); /* redraw all */ dt_control_queue_redraw(); break; } default: break; } return TRUE; }
static void _lib_tagging_redraw_callback(gpointer instance, gpointer user_data) { dt_lib_module_t *self = (dt_lib_module_t *)user_data; dt_lib_tagging_t *d = (dt_lib_tagging_t *)self->data; int imgsel = -1; DT_CTL_GET_GLOBAL(imgsel, lib_image_mouse_over_id); if(imgsel != d->imgsel) update (self, 0); }
static void _zoom_preset_change(int val) { //dt_lib_module_t *self = (dt_lib_module_t *)user_data; dt_develop_t *dev = darktable.develop; if (!dev) return; dt_dev_zoom_t zoom; int closeup, procw, proch; float zoom_x, zoom_y; DT_CTL_GET_GLOBAL(zoom, dev_zoom); DT_CTL_GET_GLOBAL(closeup, dev_closeup); DT_CTL_GET_GLOBAL(zoom_x, dev_zoom_x); DT_CTL_GET_GLOBAL(zoom_y, dev_zoom_y); dt_dev_get_processed_size(dev, &procw, &proch); float scale = 0; zoom_x = 0.0f; //+= (1.0/scale)*(x - .5f*dev->width )/procw; zoom_y = 0.0f; //+= (1.0/scale)*(y - .5f*dev->height)/proch; if (val == 0) { scale = 0.5*dt_dev_get_zoom_scale(dev, DT_ZOOM_FIT, 1.0, 0); zoom = DT_ZOOM_FREE; } else if (val ==1) { zoom = DT_ZOOM_FIT; scale = dt_dev_get_zoom_scale(dev, DT_ZOOM_FIT, 1.0, 0); } else if (val == 2) { scale = dt_dev_get_zoom_scale(dev, DT_ZOOM_1, 1.0, 0); zoom = DT_ZOOM_1; } else if (val == 3) { scale = 2.0f; zoom = DT_ZOOM_FREE; } dt_dev_check_zoom_bounds(dev, &zoom_x, &zoom_y, zoom, closeup, NULL, NULL); DT_CTL_SET_GLOBAL(dev_zoom_scale, scale); DT_CTL_SET_GLOBAL(dev_zoom, zoom); DT_CTL_SET_GLOBAL(dev_closeup, closeup); DT_CTL_SET_GLOBAL(dev_zoom_x, zoom_x); DT_CTL_SET_GLOBAL(dev_zoom_y, zoom_y); dt_dev_invalidate(dev); }
void dt_dev_get_pointer_zoom_pos(dt_develop_t *dev, const float px, const float py, float *zoom_x, float *zoom_y) { dt_dev_zoom_t zoom; int closeup, procw, proch; float zoom2_x, zoom2_y; DT_CTL_GET_GLOBAL(zoom, dev_zoom); DT_CTL_GET_GLOBAL(closeup, dev_closeup); DT_CTL_GET_GLOBAL(zoom2_x, dev_zoom_x); DT_CTL_GET_GLOBAL(zoom2_y, dev_zoom_y); dt_dev_get_processed_size(dev, &procw, &proch); const float scale = dt_dev_get_zoom_scale(dev, zoom, closeup ? 2.0 : 1.0, 0); // offset from center now (current zoom_{x,y} points there) const float mouse_off_x = px - .5*dev->width, mouse_off_y = py - .5*dev->height; zoom2_x += mouse_off_x/(procw*scale); zoom2_y += mouse_off_y/(proch*scale); *zoom_x = zoom2_x; *zoom_y = zoom2_y; }
static gboolean _lib_filmstrip_discard_history_key_accel_callback(GtkAccelGroup *accel_group, GObject *aceeleratable, guint keyval, GdkModifierType modifier, gpointer data) { int32_t mouse_over_id; DT_CTL_GET_GLOBAL(mouse_over_id, lib_image_mouse_over_id); if(mouse_over_id <= 0) return FALSE; dt_history_delete_on_image(mouse_over_id); dt_control_queue_redraw_center(); return TRUE; }
static gboolean zoom_key_accel(GtkAccelGroup *accel_group, GObject *acceleratable, guint keyval, GdkModifierType modifier, gpointer data) { dt_develop_t *dev = darktable.develop; int zoom, closeup; float zoom_x, zoom_y; switch ((long int)data) { case 1: DT_CTL_GET_GLOBAL(zoom, dev_zoom); DT_CTL_GET_GLOBAL(closeup, dev_closeup); if(zoom == DT_ZOOM_1) closeup ^= 1; DT_CTL_SET_GLOBAL(dev_closeup, closeup); DT_CTL_SET_GLOBAL(dev_zoom, DT_ZOOM_1); dt_dev_invalidate(dev); break; case 2: DT_CTL_SET_GLOBAL(dev_zoom, DT_ZOOM_FILL); dt_dev_check_zoom_bounds(dev, &zoom_x, &zoom_y, DT_ZOOM_FILL, 0, NULL, NULL); DT_CTL_SET_GLOBAL(dev_zoom_x, zoom_x); DT_CTL_SET_GLOBAL(dev_zoom_y, zoom_y); DT_CTL_SET_GLOBAL(dev_closeup, 0); dt_dev_invalidate(dev); break; case 3: DT_CTL_SET_GLOBAL(dev_zoom, DT_ZOOM_FIT); DT_CTL_SET_GLOBAL(dev_zoom_x, 0); DT_CTL_SET_GLOBAL(dev_zoom_y, 0); DT_CTL_SET_GLOBAL(dev_closeup, 0); dt_dev_invalidate(dev); break; default: break; } dt_control_queue_redraw_center(); return TRUE; }
static gboolean _lib_filmstrip_copy_history_key_accel_callback(GtkAccelGroup *accel_group, GObject *aceeleratable, guint keyval, GdkModifierType modifier, gpointer data) { dt_lib_filmstrip_t *strip = (dt_lib_filmstrip_t *)data; int32_t mouse_over_id; DT_CTL_GET_GLOBAL(mouse_over_id, lib_image_mouse_over_id); if(mouse_over_id <= 0) return FALSE; strip->history_copy_imgid = mouse_over_id; /* check if images is currently loaded in darkroom */ if (dt_dev_is_current_image(darktable.develop, mouse_over_id)) dt_dev_write_history(darktable.develop); return TRUE; }
static void update (dt_lib_module_t *self, int which) { dt_lib_tagging_t *d = (dt_lib_tagging_t *)self->data; GList *tags=NULL; uint32_t count; if(which == 0) // tags of selected images { int imgsel = -1; DT_CTL_GET_GLOBAL(imgsel, lib_image_mouse_over_id); d->imgsel = imgsel; count = dt_tag_get_attached(imgsel,&tags); } else // related tags of typed text count = dt_tag_get_suggestions(d->keyword,&tags); GtkTreeIter iter; GtkTreeView *view; if(which == 0) view = d->current; else view = d->related; GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(view)); g_object_ref(model); gtk_tree_view_set_model(GTK_TREE_VIEW(view), NULL); gtk_list_store_clear(GTK_LIST_STORE(model)); if( count >0 && tags ) { do { gtk_list_store_append(GTK_LIST_STORE(model), &iter); gtk_list_store_set (GTK_LIST_STORE(model), &iter, DT_LIB_TAGGING_COL_TAG, ((dt_tag_t*)tags->data)->tag, DT_LIB_TAGGING_COL_ID, ((dt_tag_t*)tags->data)->id, -1); } while( (tags=g_list_next(tags)) !=NULL ); // Free result... dt_tag_free_result(&tags); } gtk_tree_view_set_model(GTK_TREE_VIEW(view), model); g_object_unref(model); }
void dt_colorlabels_key_accel_callback(GtkAccelGroup *accel_group, GObject *acceleratable, guint keyval, GdkModifierType modifier, gpointer data) { const long int mode = (long int)data; int selected; DT_CTL_GET_GLOBAL(selected, lib_image_mouse_over_id); if(selected <= 0) { switch(mode) { case 0: case 1: case 2: case 3: case 4: // colors red, yellow, green, blue, purple dt_colorlabels_toggle_label_selection(mode); break; case 5: default: // remove all selected dt_colorlabels_remove_labels_selection(); break; } } else { switch(mode) { case 0: case 1: case 2: case 3: case 4: // colors red, yellow, green, blue, purple dt_colorlabels_toggle_label(selected, mode); break; case 5: default: // remove all selected dt_colorlabels_remove_labels(selected); break; } } // synch to file: // TODO: move color labels to image_t cache and sync via write_get! dt_image_synch_xmp(selected); dt_control_queue_redraw_center(); }
static gboolean _lib_filmstrip_paste_history_key_accel_callback(GtkAccelGroup *accel_group, GObject *aceeleratable, guint keyval, GdkModifierType modifier, gpointer data) { dt_lib_filmstrip_t *strip = (dt_lib_filmstrip_t *)data; if (strip->history_copy_imgid==-1) return FALSE; int32_t mouse_over_id; DT_CTL_GET_GLOBAL(mouse_over_id, lib_image_mouse_over_id); if(mouse_over_id <= 0) return FALSE; int mode = dt_conf_get_int("plugins/lighttable/copy_history/pastemode"); dt_history_copy_and_paste_on_image(strip->history_copy_imgid, mouse_over_id, (mode == 0)?TRUE:FALSE); dt_control_queue_redraw_center(); return TRUE; }
int try_enter(dt_view_t *self) { int selected; DT_CTL_GET_GLOBAL(selected, lib_image_mouse_over_id); if(selected < 0) { // try last selected sqlite3_stmt *stmt; DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "select * from selected_images", -1, &stmt, NULL); if(sqlite3_step(stmt) == SQLITE_ROW) selected = sqlite3_column_int(stmt, 0); sqlite3_finalize(stmt); // Leave as selected only the image being edited DT_DEBUG_SQLITE3_EXEC(dt_database_get(darktable.db), "delete from selected_images", NULL, NULL, NULL); DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "insert or ignore into selected_images values (?1)", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, selected); sqlite3_step(stmt); sqlite3_finalize(stmt); } if(selected < 0) { // fail :( dt_control_log(_("no image selected!")); return 1; } // this loads the image from db if needed: const dt_image_t *img = dt_image_cache_read_get(darktable.image_cache, selected); // get image and check if it has been deleted from disk first! char imgfilename[DT_MAX_PATH_LEN]; dt_image_full_path(img->id, imgfilename, DT_MAX_PATH_LEN); if(!g_file_test(imgfilename, G_FILE_TEST_IS_REGULAR)) { dt_control_log(_("image `%s' is currently unavailable"), img->filename); // dt_image_remove(selected); dt_image_cache_read_release(darktable.image_cache, img); return 1; } // and drop the lock again. dt_image_cache_read_release(darktable.image_cache, img); darktable.develop->image_storage.id = selected; return 0; }
static gboolean _lib_filmstrip_duplicate_image_key_accel_callback(GtkAccelGroup *accel_group, GObject *aceeleratable, guint keyval, GdkModifierType modifier, gpointer data) { int32_t mouse_over_id; DT_CTL_GET_GLOBAL(mouse_over_id, lib_image_mouse_over_id); if(mouse_over_id <= 0) return FALSE; /* check if images is currently loaded in darkroom */ if(dt_dev_is_current_image(darktable.develop, mouse_over_id)) dt_dev_write_history(darktable.develop); int32_t newimgid = dt_image_duplicate(mouse_over_id); if(newimgid != -1) dt_history_copy_and_paste_on_image(mouse_over_id, newimgid, FALSE, NULL); dt_control_queue_redraw_center(); return TRUE; }
static gboolean _lib_filmstrip_ratings_key_accel_callback(GtkAccelGroup *accel_group, GObject *aceeleratable, guint keyval, GdkModifierType modifier, gpointer data) { long int num = (long int)data; switch (num) { case DT_VIEW_DESERT: case DT_VIEW_REJECT: case DT_VIEW_STAR_1: case DT_VIEW_STAR_2: case DT_VIEW_STAR_3: case DT_VIEW_STAR_4: case DT_VIEW_STAR_5: case 666: { int32_t mouse_over_id; DT_CTL_GET_GLOBAL(mouse_over_id, lib_image_mouse_over_id); if (mouse_over_id <= 0) return FALSE; /* get image from cache */ const dt_image_t *cimg = dt_image_cache_read_get(darktable.image_cache, mouse_over_id); dt_image_t *image = dt_image_cache_write_get(darktable.image_cache, cimg); if (num == 666) image->flags &= ~0xf; else if (num == DT_VIEW_STAR_1 && ((image->flags & 0x7) == 1)) image->flags &= ~0x7; else { image->flags &= ~0x7; image->flags |= num; } dt_image_cache_write_release(darktable.image_cache, image, DT_IMAGE_CACHE_SAFE); dt_image_cache_read_release(darktable.image_cache, image); /* redraw all */ dt_control_queue_redraw(); break; } default: break; } return TRUE; }
static void detach_selected_tag(dt_lib_module_t *self, dt_lib_tagging_t *d) { GtkTreeIter iter; GtkTreeModel *model = NULL; GtkTreeView *view = d->current; GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(view)); if(!gtk_tree_selection_get_selected(selection, &model, &iter)) return; guint tagid; gtk_tree_model_get (model, &iter, DT_LIB_TAGGING_COL_ID, &tagid, -1); int imgsel = -1; if(tagid <= 0) return; DT_CTL_GET_GLOBAL(imgsel, lib_image_mouse_over_id); dt_tag_detach(tagid,imgsel); dt_image_synch_xmp(imgsel); }
static gboolean _lib_filmstrip_paste_history_parts_key_accel_callback(GtkAccelGroup *accel_group, GObject *aceeleratable, guint keyval, GdkModifierType modifier, gpointer data) { dt_lib_filmstrip_t *strip = (dt_lib_filmstrip_t *)data; int mode = dt_conf_get_int("plugins/lighttable/copy_history/pastemode"); // get mouse over before launching the dialog int32_t mouse_over_id; DT_CTL_GET_GLOBAL(mouse_over_id, lib_image_mouse_over_id); dt_gui_hist_dialog_new (&(strip->dg), strip->history_copy_imgid, FALSE); if (dt_history_copy_and_paste_on_selection (strip->history_copy_imgid, (mode==0)?TRUE:FALSE, strip->dg.selops)!=0) { if(mouse_over_id <= 0) return FALSE; dt_history_copy_and_paste_on_image(strip->history_copy_imgid, mouse_over_id, (mode == 0)?TRUE:FALSE,strip->dg.selops); } dt_control_queue_redraw_center(); return TRUE; }
static gboolean _lib_navigation_expose_callback(GtkWidget *widget, GdkEventExpose *event, gpointer user_data) { const int inset = DT_NAVIGATION_INSET; int width = widget->allocation.width, height = widget->allocation.height; dt_develop_t *dev = darktable.develop; if (dev->preview_dirty) return FALSE; /* get the current style */ GtkStyle *style=gtk_rc_get_style_by_paths(gtk_settings_get_default(), NULL,"GtkWidget", GTK_TYPE_WIDGET); if(!style) style = gtk_rc_get_style(widget); cairo_surface_t *cst = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height); cairo_t *cr = cairo_create(cst); /* fill background */ cairo_set_source_rgb(cr, style->bg[0].red/65535.0, style->bg[0].green/65535.0, style->bg[0].blue/65535.0); cairo_paint(cr); width -= 2*inset; height -= 2*inset; cairo_translate(cr, inset, inset); /* draw navigation image if available */ if(dev->preview_pipe->backbuf && !dev->preview_dirty) { dt_pthread_mutex_t *mutex = &dev->preview_pipe->backbuf_mutex; dt_pthread_mutex_lock(mutex); const int wd = dev->preview_pipe->backbuf_width; const int ht = dev->preview_pipe->backbuf_height; const float scale = fminf(width/(float)wd, height/(float)ht); const int stride = cairo_format_stride_for_width (CAIRO_FORMAT_RGB24, wd); cairo_surface_t *surface = cairo_image_surface_create_for_data (dev->preview_pipe->backbuf, CAIRO_FORMAT_RGB24, wd, ht, stride); cairo_translate(cr, width/2.0, height/2.0f); cairo_scale(cr, scale, scale); cairo_translate(cr, -.5f*wd, -.5f*ht); // draw shadow around float alpha = 1.0f; for(int k=0; k<4; k++) { cairo_rectangle(cr, -k/scale, -k/scale, wd + 2*k/scale, ht + 2*k/scale); cairo_set_source_rgba(cr, 0, 0, 0, alpha); alpha *= 0.6f; cairo_fill(cr); } cairo_rectangle(cr, 0, 0, wd-2, ht-1); cairo_set_source_surface (cr, surface, 0, 0); cairo_pattern_set_filter(cairo_get_source(cr), CAIRO_FILTER_FAST); cairo_fill(cr); cairo_surface_destroy (surface); dt_pthread_mutex_unlock(mutex); // draw box where we are dt_dev_zoom_t zoom; int closeup; float zoom_x, zoom_y; DT_CTL_GET_GLOBAL(zoom, dev_zoom); DT_CTL_GET_GLOBAL(closeup, dev_closeup); DT_CTL_GET_GLOBAL(zoom_x, dev_zoom_x); DT_CTL_GET_GLOBAL(zoom_y, dev_zoom_y); const float min_scale = dt_dev_get_zoom_scale(dev, DT_ZOOM_FIT, closeup ? 2.0 : 1.0, 0); const float cur_scale = dt_dev_get_zoom_scale(dev, zoom, closeup ? 2.0 : 1.0, 0); // avoid numerical instability for small resolutions: if(cur_scale > min_scale+0.001) { float boxw = 1, boxh = 1; dt_dev_check_zoom_bounds(darktable.develop, &zoom_x, &zoom_y, zoom, closeup, &boxw, &boxh); cairo_translate(cr, wd*(.5f+zoom_x), ht*(.5f+zoom_y)); cairo_set_source_rgb(cr, 0., 0., 0.); cairo_set_line_width(cr, 1.f/scale); boxw *= wd; boxh *= ht; cairo_rectangle(cr, -boxw/2-1, -boxh/2-1, boxw+2, boxh+2); cairo_stroke(cr); cairo_set_source_rgb(cr, 1., 1., 1.); cairo_rectangle(cr, -boxw/2, -boxh/2, boxw, boxh); cairo_stroke(cr); } } /* blit memsurface into widget */ cairo_destroy(cr); cairo_t *cr_pixmap = gdk_cairo_create(gtk_widget_get_window(widget)); cairo_set_source_surface (cr_pixmap, cst, 0, 0); cairo_paint(cr_pixmap); cairo_destroy(cr_pixmap); cairo_surface_destroy(cst); return TRUE; }
static gboolean _lib_tagging_tag_show(GtkAccelGroup *accel_group, GObject *acceleratable, guint keyval, GdkModifierType modifier, dt_lib_module_t* self) { int mouse_over_id = -1; int zoom = dt_conf_get_int("plugins/lighttable/images_in_row"); // the order is: // if(zoom == 1) => currently shown image // else if(selection not empty) => selected images // else if(cursor over image) => hovered image // else => return if(zoom == 1 || dt_collection_get_selected_count(darktable.collection) == 0) { DT_CTL_GET_GLOBAL(mouse_over_id, lib_image_mouse_over_id); if(mouse_over_id < 0) return TRUE; } dt_lib_tagging_t *d = (dt_lib_tagging_t*)self->data; d->floating_tag_imgid = mouse_over_id; gint x, y; gint px, py, w, h; GtkWidget *window = dt_ui_main_window(darktable.gui->ui); GtkWidget *center = dt_ui_center(darktable.gui->ui); gdk_window_get_origin(gtk_widget_get_window(center), &px, &py); w = gdk_window_get_width(gtk_widget_get_window(center)); h = gdk_window_get_height(gtk_widget_get_window(center)); x = px + 0.5*(w-FLOATING_ENTRY_WIDTH); y = py + h - 50; /* put the floating box at the mouse pointer */ // gint pointerx, pointery; // gtk_widget_get_pointer(center, &pointerx, &pointery); // x = px + pointerx + 1; // y = py + pointery + 1; d->floating_tag_window = gtk_window_new(GTK_WINDOW_TOPLEVEL); /* stackoverflow.com/questions/1925568/how-to-give-keyboard-focus-to-a-pop-up-gtk-window */ gtk_widget_set_can_focus(d->floating_tag_window, TRUE); gtk_window_set_decorated(GTK_WINDOW(d->floating_tag_window), FALSE); gtk_window_set_type_hint(GTK_WINDOW(d->floating_tag_window), GDK_WINDOW_TYPE_HINT_POPUP_MENU); gtk_window_set_transient_for(GTK_WINDOW(d->floating_tag_window), GTK_WINDOW(window)); gtk_window_set_opacity(GTK_WINDOW(d->floating_tag_window), 0.8); gtk_window_move(GTK_WINDOW(d->floating_tag_window), x, y); GtkWidget *entry = gtk_entry_new(); gtk_widget_set_size_request(entry, FLOATING_ENTRY_WIDTH, -1); gtk_widget_add_events(entry, GDK_FOCUS_CHANGE_MASK); GtkEntryCompletion *completion = gtk_entry_completion_new(); gtk_entry_completion_set_model(completion, gtk_tree_view_get_model(GTK_TREE_VIEW(d->related))); gtk_entry_completion_set_text_column(completion, 0); gtk_entry_completion_set_inline_completion(completion, TRUE); gtk_entry_completion_set_popup_set_width(completion, FALSE); gtk_entry_set_completion(GTK_ENTRY(entry), completion); gtk_editable_select_region(GTK_EDITABLE(entry), 0, -1); gtk_container_add(GTK_CONTAINER(d->floating_tag_window), entry); g_signal_connect_swapped(entry, "focus-out-event", G_CALLBACK(gtk_widget_destroy), d->floating_tag_window); g_signal_connect(entry, "key-press-event", G_CALLBACK(_lib_tagging_tag_key_press), self); gtk_widget_show_all(d->floating_tag_window); gtk_widget_grab_focus(entry); gtk_window_present(GTK_WINDOW(d->floating_tag_window)); return TRUE; }