void reset(dt_view_t *self) { 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); }
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 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 _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(); } }
static void _lib_filmstrip_scroll_to_image(dt_lib_module_t *self, gint imgid, gboolean activate) { dt_lib_filmstrip_t *strip = (dt_lib_filmstrip_t *)self->data; /* if no imgid just bail out */ if(imgid <= 0) return; strip->activated_image = imgid; strip->offset = dt_collection_image_offset(imgid); DT_CTL_SET_GLOBAL(lib_image_mouse_over_id, strip->activated_image); /* activate the image if requested */ if (activate) { strip->activated_image = imgid; dt_control_signal_raise(darktable.signals, DT_SIGNAL_VIEWMANAGER_FILMSTRIP_ACTIVATE); } /* redraw filmstrip */ gboolean owns_lock = dt_control_gdk_lock(); gtk_widget_queue_draw(self->widget); if(owns_lock) dt_control_gdk_unlock(); }
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 mouse_leave(dt_view_t *self) { dt_library_t *lib = (dt_library_t *)self->data; if(!lib->pan && dt_conf_get_int("plugins/lighttable/images_in_row") != 1) { DT_CTL_SET_GLOBAL(lib_image_mouse_over_id, -1); dt_control_queue_redraw_center(); } }
void mouse_leave(dt_view_t *self) { // if we are not hovering over a thumbnail in the filmstrip -> show metadata of opened image. dt_develop_t *dev = (dt_develop_t *)self->data; int32_t mouse_over_id = dev->image_storage.id; DT_CTL_SET_GLOBAL(lib_image_mouse_over_id, mouse_over_id); // reset any changes the selected plugin might have made. dt_control_change_cursor(GDK_LEFT_PTR); }
void reset(dt_view_t *self) { dt_library_t *lib = (dt_library_t *)self->data; lib->center = 1; lib->track = lib->pan = 0; lib->offset = 0x7fffffff; lib->first_visible_zoomable = -1; lib->first_visible_filemanager = -1; DT_CTL_SET_GLOBAL(lib_image_mouse_over_id, -1); }
static void _lib_snapshots_toggled_callback(GtkToggleButton *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; /* get current snapshot index */ long which = (long)g_object_get_data(G_OBJECT(widget),"snapshot"); /* free current snapshot image if exists */ if (d->snapshot_image) { cairo_surface_destroy(d->snapshot_image); d->snapshot_image = NULL; } /* check if snapshot is activated */ if (gtk_toggle_button_get_active(widget)) { /* lets inactivate all togglebuttons except for self */ for(uint32_t k=0; k<d->size; k++) if(GTK_WIDGET(widget) != d->snapshot[k].button) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(d->snapshot[k].button), FALSE); /* setup snapshot */ d->selected = which; dt_lib_snapshot_t *s = d->snapshot + (which-1); DT_CTL_SET_GLOBAL(dev_zoom_y, s->zoom_y); DT_CTL_SET_GLOBAL(dev_zoom_x, s->zoom_x); DT_CTL_SET_GLOBAL(dev_zoom, s->zoom); DT_CTL_SET_GLOBAL(dev_closeup, s->closeup); DT_CTL_SET_GLOBAL(dev_zoom_scale, s->zoom_scale); dt_dev_invalidate(darktable.develop); d->snapshot_image = cairo_image_surface_create_from_png(s->filename); } /* redraw center view */ dt_control_queue_redraw_center(); }
static gboolean _lib_filmstrip_mouse_leave_callback(GtkWidget *w, GdkEventCrossing *e, gpointer user_data) { dt_lib_module_t *self = (dt_lib_module_t *)user_data; dt_lib_filmstrip_t *strip = (dt_lib_filmstrip_t *)self->data; DT_CTL_SET_GLOBAL(lib_image_mouse_over_id, strip->activated_image); /* suppress mouse over highlight upon leave */ strip->pointery = -1; gtk_widget_queue_draw(self->widget); 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 _view_map_button_press_callback(GtkWidget *w, GdkEventButton *e, dt_view_t *self) { dt_map_t *lib = (dt_map_t*)self->data; if(e->button == 1) { // check if the click was on an image or just some random position lib->selected_image = _view_map_get_img_at_pos(self, e->x, e->y); if(e->type == GDK_BUTTON_PRESS && lib->selected_image > 0) { lib->start_drag = TRUE; return TRUE; } if(e->type == GDK_2BUTTON_PRESS) { if(lib->selected_image > 0) { // open the image in darkroom DT_CTL_SET_GLOBAL(lib_image_mouse_over_id, lib->selected_image); dt_ctl_switch_mode_to(DT_DEVELOP); return TRUE; } else { // zoom into that position float longitude, latitude; OsmGpsMapPoint *pt = osm_gps_map_point_new_degrees(0.0, 0.0); osm_gps_map_convert_screen_to_geographic(lib->map, e->x, e->y, pt); osm_gps_map_point_get_degrees(pt, &latitude, &longitude); osm_gps_map_point_free(pt); int zoom, max_zoom; g_object_get(G_OBJECT(lib->map), "zoom", &zoom, "max-zoom", &max_zoom, NULL); zoom = MIN(zoom+1, max_zoom); _view_map_center_on_location(self, longitude, latitude, zoom); } return TRUE; } } return FALSE; }
int button_pressed(dt_view_t *self, double x, double y, int which, int type, uint32_t 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->request_color_pick && which == 1) { float zoom_x, zoom_y; dt_dev_get_pointer_zoom_pos(dev, x, y, &zoom_x, &zoom_y); if(darktable.lib->proxy.colorpicker.size) { dev->gui_module->color_picker_box[0] = .5f+zoom_x; dev->gui_module->color_picker_box[1] = .5f+zoom_y; dev->gui_module->color_picker_box[2] = .5f+zoom_x; dev->gui_module->color_picker_box[3] = .5f+zoom_y; } else { dev->gui_module->color_picker_point[0] = .5f+zoom_x; dev->gui_module->color_picker_point[1] = .5f+zoom_y; dev->preview_pipe->changed |= DT_DEV_PIPE_SYNCH; dt_dev_invalidate_all(dev); } dt_control_queue_redraw(); return 1; } if(dev->gui_module && dev->gui_module->button_pressed) handled = dev->gui_module->button_pressed(dev->gui_module, x, y, which, type, state); if(handled) return handled; if(which == 1 && type == GDK_2BUTTON_PRESS) return 0; if(which == 1) { dt_control_change_cursor(GDK_HAND1); return 1; } if(which == 2) { // zoom to 1:1 2:1 and back 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); const float scale = dt_dev_get_zoom_scale(dev, zoom, closeup ? 2 : 1, 0); zoom_x += (1.0/scale)*(x - .5f*dev->width )/procw; zoom_y += (1.0/scale)*(y - .5f*dev->height)/proch; if(zoom == DT_ZOOM_1) { if(!closeup) closeup = 1; else { zoom = DT_ZOOM_FIT; zoom_x = zoom_y = 0.0f; closeup = 0; } } else zoom = DT_ZOOM_1; 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); DT_CTL_SET_GLOBAL(dev_zoom_x, zoom_x); DT_CTL_SET_GLOBAL(dev_zoom_y, zoom_y); dt_dev_invalidate(dev); return 1; } return 0; }
static gboolean _lib_filmstrip_expose_callback(GtkWidget *widget, GdkEventExpose *event, gpointer user_data) { dt_lib_module_t *self = (dt_lib_module_t *)user_data; dt_lib_filmstrip_t *strip = (dt_lib_filmstrip_t *)self->data; GtkAllocation allocation; gtk_widget_get_allocation(widget, &allocation); int32_t width = allocation.width; int32_t height = allocation.height; gdouble pointerx = strip->pointerx; gdouble pointery = strip->pointery; if(darktable.gui->center_tooltip == 1) darktable.gui->center_tooltip++; strip->image_over = DT_VIEW_DESERT; DT_CTL_SET_GLOBAL(lib_image_mouse_over_id, -1); /* create cairo surface */ cairo_t *cr = gdk_cairo_create(gtk_widget_get_window(widget)); /* fill background */ cairo_set_source_rgb (cr, .2, .2, .2); cairo_paint(cr); int offset = strip->offset; const float wd = height; const float ht = height; int max_cols = (int)(width/(float)wd) + 2; if (max_cols%2 == 0) max_cols += 1; const int col_start = max_cols/2 - strip->offset; const int empty_edge = (width - (max_cols * wd))/2; int step_res = SQLITE_ROW; sqlite3_stmt *stmt = NULL; /* mouse over image position in filmstrip */ pointerx -= empty_edge; const int seli = (pointery > 0 && pointery <= ht) ? pointerx / (float)wd : -1; const int img_pointerx = (int)fmodf(pointerx, wd); const int img_pointery = (int)pointery; /* get the count of current collection */ strip->collection_count = dt_collection_get_count (darktable.collection); /* get the collection query */ const gchar *query=dt_collection_get_query (darktable.collection); if(!query) return FALSE; if(offset < 0) strip->offset = offset = 0; if(offset > strip->collection_count-1) strip->offset = offset = strip->collection_count-1; // dt_view_set_scrollbar(self, offset, count, max_cols, 0, 1, 1); DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), query, -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, offset - max_cols/2); DT_DEBUG_SQLITE3_BIND_INT(stmt, 2, max_cols); cairo_save(cr); cairo_translate(cr, empty_edge, 0.0f); for(int col = 0; col < max_cols; col++) { if(col < col_start) { cairo_translate(cr, wd, 0.0f); continue; } if(step_res != SQLITE_DONE) { step_res = sqlite3_step(stmt); } if(step_res == SQLITE_ROW) { int id = sqlite3_column_int(stmt, 0); // set mouse over id if(seli == col) { strip->mouse_over_id = id; DT_CTL_SET_GLOBAL(lib_image_mouse_over_id, strip->mouse_over_id); } cairo_save(cr); // FIXME find out where the y translation is done, how big the value is and use it directly instead of getting it from the matrix ... cairo_matrix_t m; cairo_get_matrix(cr, &m); dt_view_image_expose(&(strip->image_over), id, cr, wd, ht, max_cols, img_pointerx, img_pointery, FALSE); cairo_restore(cr); } else if (step_res == SQLITE_DONE) { /* do nothing, just add some empty thumb frames */ } else goto failure; cairo_translate(cr, wd, 0.0f); } failure: cairo_restore(cr); sqlite3_finalize(stmt); if(darktable.gui->center_tooltip == 1) // set in this round { char* tooltip = dt_history_get_items_as_string(strip->mouse_over_id); if(tooltip != NULL) { g_object_set(G_OBJECT(strip->filmstrip), "tooltip-text", tooltip, (char *)NULL); g_free(tooltip); } } else if(darktable.gui->center_tooltip == 2) // not set in this round { darktable.gui->center_tooltip = 0; g_object_set(G_OBJECT(strip->filmstrip), "tooltip-text", "", (char *)NULL); } #ifdef _DEBUG if(darktable.unmuted & DT_DEBUG_CACHE) dt_mipmap_cache_print(darktable.mipmap_cache); #endif /* cleanup */ cairo_destroy(cr); return TRUE; }
static void expose_zoomable (dt_view_t *self, cairo_t *cr, int32_t width, int32_t height, int32_t pointerx, int32_t pointery) { dt_library_t *lib = (dt_library_t *)self->data; float zoom, zoom_x, zoom_y; int32_t mouse_over_id, pan, track, center; /* query new collection count */ lib->collection_count = dt_collection_get_count (darktable.collection); DT_CTL_GET_GLOBAL(mouse_over_id, lib_image_mouse_over_id); zoom = dt_conf_get_int("plugins/lighttable/images_in_row"); zoom_x = lib->zoom_x; zoom_y = lib->zoom_y; pan = lib->pan; center = lib->center; track = lib->track; lib->image_over = DT_VIEW_DESERT; cairo_set_source_rgb (cr, .2, .2, .2); cairo_paint(cr); const float wd = width/zoom; const float ht = width/zoom; static int oldpan = 0; static float oldzoom = -1; if(oldzoom < 0) oldzoom = zoom; // TODO: exaggerate mouse gestures to pan when zoom == 1 if(pan)// && mouse_over_id >= 0) { zoom_x = lib->select_offset_x - /* (zoom == 1 ? 2. : 1.)*/pointerx; zoom_y = lib->select_offset_y - /* (zoom == 1 ? 2. : 1.)*/pointery; } if(!lib->statements.main_query) return; if (track == 0); else if(track > 1) zoom_y += ht; else if(track > 0) zoom_x += wd; else if(track > -2) zoom_x -= wd; else zoom_y -= ht; if(zoom > DT_LIBRARY_MAX_ZOOM) { // double speed. if (track == 0); else if(track > 1) zoom_y += ht; else if(track > 0) zoom_x += wd; else if(track > -2) zoom_x -= wd; else zoom_y -= ht; if(zoom > 1.5*DT_LIBRARY_MAX_ZOOM) { // quad speed. if (track == 0); else if(track > 1) zoom_y += ht; else if(track > 0) zoom_x += wd; else if(track > -2) zoom_x -= wd; else zoom_y -= ht; } } if(oldzoom != zoom) { float oldx = (pointerx + zoom_x)*oldzoom/width; float oldy = (pointery + zoom_y)*oldzoom/width; if(zoom == 1) { zoom_x = (int)oldx*wd; zoom_y = (int)oldy*ht; lib->offset = 0x7fffffff; } else { zoom_x = oldx*wd - pointerx; zoom_y = oldy*ht - pointery; } } oldzoom = zoom; // TODO: replace this with center on top of selected/developed image if(center) { if(mouse_over_id >= 0) { zoom_x = wd*((int)(zoom_x)/(int)wd); zoom_y = ht*((int)(zoom_y)/(int)ht); } else zoom_x = zoom_y = 0.0; center = 0; } // mouse left the area, but we leave mouse over as it was, especially during panning // if(!pan && pointerx > 0 && pointerx < width && pointery > 0 && pointery < height) DT_CTL_SET_GLOBAL(lib_image_mouse_over_id, -1); if(!pan && zoom != 1) DT_CTL_SET_GLOBAL(lib_image_mouse_over_id, -1); // set scrollbar positions, clamp zoom positions if(lib->collection_count == 0) { zoom_x = zoom_y = 0.0f; } else if(zoom < 1.01) { if(zoom_x < 0) zoom_x = 0; if(zoom_x > wd*DT_LIBRARY_MAX_ZOOM-wd) zoom_x = wd*DT_LIBRARY_MAX_ZOOM-wd; if(zoom_y < 0) zoom_y = 0; if(zoom_y > ht*lib->collection_count/MIN(DT_LIBRARY_MAX_ZOOM, zoom)-ht) zoom_y = ht*lib->collection_count/MIN(DT_LIBRARY_MAX_ZOOM, zoom)-ht; } else { if(zoom_x < -wd*DT_LIBRARY_MAX_ZOOM/2) zoom_x = -wd*DT_LIBRARY_MAX_ZOOM/2; if(zoom_x > wd*DT_LIBRARY_MAX_ZOOM-wd) zoom_x = wd*DT_LIBRARY_MAX_ZOOM-wd; if(zoom_y < -height+ht) zoom_y = -height+ht; if(zoom_y > ht*lib->collection_count/MIN(DT_LIBRARY_MAX_ZOOM, zoom)-ht) zoom_y = ht*lib->collection_count/MIN(DT_LIBRARY_MAX_ZOOM, zoom)-ht; } int offset_i = (int)(zoom_x/wd); int offset_j = (int)(zoom_y/ht); if(lib->first_visible_filemanager >= 0) { offset_i = lib->first_visible_filemanager % DT_LIBRARY_MAX_ZOOM; offset_j = lib->first_visible_filemanager / DT_LIBRARY_MAX_ZOOM; } lib->first_visible_filemanager = -1; lib->first_visible_zoomable = offset_i + DT_LIBRARY_MAX_ZOOM*offset_j; // arbitrary 1000 to avoid bug due to round towards zero using (int) int seli = zoom == 1 ? 0 : ((int)(1000 + (pointerx + zoom_x)/wd) - MAX(offset_i, 0) - 1000); int selj = zoom == 1 ? 0 : ((int)(1000 + (pointery + zoom_y)/ht) - offset_j - 1000); float offset_x = (zoom == 1) ? 0.0 : (zoom_x/wd - (int)(zoom_x/wd)); float offset_y = (zoom == 1) ? 0.0 : (zoom_y/ht - (int)(zoom_y/ht)); const int max_rows = (zoom == 1) ? 1 : (2 + (int)((height)/ht + .5)); const int max_cols = (zoom == 1) ? 1 : (MIN(DT_LIBRARY_MAX_ZOOM - MAX(0, offset_i), 1 + (int)(zoom+.5))); int offset = MAX(0, offset_i) + DT_LIBRARY_MAX_ZOOM*offset_j; int img_pointerx = zoom == 1 ? pointerx : fmodf(pointerx + zoom_x, wd); int img_pointery = zoom == 1 ? pointery : fmodf(pointery + zoom_y, ht); // assure 1:1 is not switching images on resize/tab events: if(!track && lib->offset != 0x7fffffff && zoom == 1) { offset = lib->offset; zoom_x = wd*(offset % DT_LIBRARY_MAX_ZOOM); zoom_y = ht*(offset / DT_LIBRARY_MAX_ZOOM); } else lib->offset = offset; int id, clicked1, last_seli = 1<<30, last_selj = 1<<30; clicked1 = (oldpan == 0 && pan == 1 && lib->button == 1); dt_view_set_scrollbar(self, MAX(0, offset_i), DT_LIBRARY_MAX_ZOOM, zoom, DT_LIBRARY_MAX_ZOOM*offset_j, lib->collection_count, DT_LIBRARY_MAX_ZOOM*max_cols); cairo_translate(cr, -offset_x*wd, -offset_y*ht); cairo_translate(cr, -MIN(offset_i*wd, 0.0), 0.0); for(int row = 0; row < max_rows; row++) { if(offset < 0) { cairo_translate(cr, 0, ht); offset += DT_LIBRARY_MAX_ZOOM; continue; } /* clear and reset main query */ DT_DEBUG_SQLITE3_CLEAR_BINDINGS(lib->statements.main_query); DT_DEBUG_SQLITE3_RESET(lib->statements.main_query); DT_DEBUG_SQLITE3_BIND_INT(lib->statements.main_query, 1, offset); DT_DEBUG_SQLITE3_BIND_INT(lib->statements.main_query, 2, max_cols); for(int col = 0; col < max_cols; col++) { if(sqlite3_step(lib->statements.main_query) == SQLITE_ROW) { id = sqlite3_column_int(lib->statements.main_query, 0); // set mouse over id if((zoom == 1 && mouse_over_id < 0) || ((!pan || track) && seli == col && selj == row)) { mouse_over_id = id; DT_CTL_SET_GLOBAL(lib_image_mouse_over_id, mouse_over_id); } // add clicked image to selected table if(clicked1) { if((lib->modifiers & GDK_SHIFT_MASK) == 0 && (lib->modifiers & GDK_CONTROL_MASK) == 0 && seli == col && selj == row) { /* clear selection except id */ /* clear and resest statement */ DT_DEBUG_SQLITE3_CLEAR_BINDINGS(lib->statements.delete_except_arg); DT_DEBUG_SQLITE3_RESET(lib->statements.delete_except_arg); /* reuse statment */ DT_DEBUG_SQLITE3_BIND_INT(lib->statements.delete_except_arg, 1, id); sqlite3_step(lib->statements.delete_except_arg); } // FIXME: whatever comes first assumtion is broken! // if((lib->modifiers & GDK_SHIFT_MASK) && (last_seli == (1<<30)) && // (image->id == lib->last_selected_id || image->id == mouse_over_id)) { last_seli = col; last_selj = row; } // if(last_seli < (1<<30) && ((lib->modifiers & GDK_SHIFT_MASK) && (col >= MIN(last_seli,seli) && row >= MIN(last_selj,selj) && // col <= MAX(last_seli,seli) && row <= MAX(last_selj,selj)) && (col != last_seli || row != last_selj)) || if((lib->modifiers & GDK_SHIFT_MASK) && id == lib->last_selected_idx) { last_seli = col; last_selj = row; } if((last_seli < (1<<30) && ((lib->modifiers & GDK_SHIFT_MASK) && (col >= last_seli && row >= last_selj && col <= seli && row <= selj) && (col != last_seli || row != last_selj))) || (seli == col && selj == row)) { // insert all in range if shift, or only the one the mouse is over for ctrl or plain click. dt_view_toggle_selection(id); lib->last_selected_idx = id; } } cairo_save(cr); // if(zoom == 1) dt_image_prefetch(image, DT_IMAGE_MIPF); dt_view_image_expose(&(lib->image_over), id, cr, wd, zoom == 1 ? height : ht, zoom, img_pointerx, img_pointery); cairo_restore(cr); } else goto failure; cairo_translate(cr, wd, 0.0f); } cairo_translate(cr, -max_cols*wd, ht); offset += DT_LIBRARY_MAX_ZOOM; } failure: oldpan = pan; lib->zoom_x = zoom_x; lib->zoom_y = zoom_y; lib->track = 0; lib->center = center; if(darktable.unmuted & DT_DEBUG_CACHE) dt_mipmap_cache_print(darktable.mipmap_cache); }
static void expose_filemanager (dt_view_t *self, cairo_t *cr, int32_t width, int32_t height, int32_t pointerx, int32_t pointery) { dt_library_t *lib = (dt_library_t *)self->data; gboolean offset_changed = FALSE; /* query new collection count */ lib->collection_count = dt_collection_get_count (darktable.collection); if(darktable.gui->center_tooltip == 1) darktable.gui->center_tooltip = 2; /* get grid stride */ const int iir = dt_conf_get_int("plugins/lighttable/images_in_row"); /* get image over id */ lib->image_over = DT_VIEW_DESERT; int32_t mouse_over_id, mouse_over_group = -1; DT_CTL_GET_GLOBAL(mouse_over_id, lib_image_mouse_over_id); /* fill background */ cairo_set_source_rgb (cr, .2, .2, .2); cairo_paint(cr); if(lib->first_visible_zoomable >= 0) { lib->offset = lib->first_visible_zoomable; } lib->first_visible_zoomable = -1; /* check if offset has been changed */ if(lib->track > 2) lib->offset += iir; if(lib->track < -2) lib->offset -= iir; lib->track = 0; if(lib->center) lib->offset = 0; lib->center = 0; int offset = lib->offset; /* if offset differs then flag as changed */ if (offset != lib->first_visible_filemanager) offset_changed = TRUE; lib->first_visible_filemanager = offset; static int oldpan = 0; const int pan = lib->pan; const float wd = width/(float)iir; const float ht = width/(float)iir; int pi = pointerx / (float)wd; int pj = pointery / (float)ht; if(pointerx < 0 || pointery < 0) pi = pj = -1; //const int pidx = grid_to_index(pj, pi, iir, offset); const int img_pointerx = iir == 1 ? pointerx : fmodf(pointerx, wd); const int img_pointery = iir == 1 ? pointery : fmodf(pointery, ht); const int max_rows = 1 + (int)((height)/ht + .5); const int max_cols = iir; int id; int clicked1 = (oldpan == 0 && pan == 1 && lib->button == 1); /* get the count of current collection */ if(lib->collection_count == 0) { const float fs = 15.0f; const float ls = 1.5f*fs; const float offy = height*0.2f; const float offx = 60; const float at = 0.3f; cairo_set_font_size(cr, fs); cairo_set_source_rgba(cr, .7, .7, .7, 1.0f); cairo_select_font_face (cr, "sans-serif", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); cairo_move_to(cr, offx, offy); cairo_show_text(cr, _("there are no images in this collection")); cairo_move_to(cr, offx, offy + 2*ls); cairo_show_text(cr, _("if you have not imported any images yet")); cairo_move_to(cr, offx, offy + 3*ls); cairo_show_text(cr, _("you can do so in the import module")); cairo_move_to(cr, offx - 10.0f, offy + 3*ls - ls*.25f); cairo_line_to(cr, 0.0f, 10.0f); cairo_set_source_rgba(cr, .7, .7, .7, at); cairo_stroke(cr); cairo_move_to(cr, offx, offy + 5*ls); cairo_set_source_rgba(cr, .7, .7, .7, 1.0f); cairo_show_text(cr, _("try to relax the filter settings in the top panel")); cairo_rel_move_to(cr, 10.0f, -ls*.25f); cairo_line_to(cr, width*0.5f, 0.0f); cairo_set_source_rgba(cr, .7, .7, .7, at); cairo_stroke(cr); cairo_move_to(cr, offx, offy + 6*ls); cairo_set_source_rgba(cr, .7, .7, .7, 1.0f); cairo_show_text(cr, _("or add images in the collection module in the left panel")); cairo_move_to(cr, offx - 10.0f, offy + 6*ls - ls*0.25f); cairo_rel_line_to(cr, - offx + 10.0f, 0.0f); cairo_set_source_rgba(cr, .7, .7, .7, at); cairo_stroke(cr); return; } /* do we have a main query collection statement */ if(!lib->statements.main_query) return; if(offset < 0) lib->offset = offset = 0; while(offset >= lib->collection_count) lib->offset = (offset -= iir); /* update scroll borders */ dt_view_set_scrollbar(self, 0, 1, 1, offset, lib->collection_count, max_rows*iir); /* let's reset and reuse the main_query statement */ DT_DEBUG_SQLITE3_CLEAR_BINDINGS(lib->statements.main_query); DT_DEBUG_SQLITE3_RESET(lib->statements.main_query); /* setup offset and row for the main query */ DT_DEBUG_SQLITE3_BIND_INT(lib->statements.main_query, 1, offset); DT_DEBUG_SQLITE3_BIND_INT(lib->statements.main_query, 2, max_rows*iir); if(mouse_over_id != -1) { const dt_image_t *mouse_over_image = dt_image_cache_read_get(darktable.image_cache, mouse_over_id); mouse_over_group = mouse_over_image->group_id; dt_image_cache_read_release(darktable.image_cache, mouse_over_image); DT_DEBUG_SQLITE3_CLEAR_BINDINGS(lib->statements.is_grouped); DT_DEBUG_SQLITE3_RESET(lib->statements.is_grouped); DT_DEBUG_SQLITE3_BIND_INT(lib->statements.is_grouped, 1, mouse_over_group); DT_DEBUG_SQLITE3_BIND_INT(lib->statements.is_grouped, 2, mouse_over_id); if(sqlite3_step(lib->statements.is_grouped) != SQLITE_ROW) mouse_over_group = -1; } // prefetch the ids so that we can peek into the future to see if there are adjacent images in the same group. int *query_ids = g_malloc0(max_rows*max_cols*sizeof(int)); for(int row = 0; row < max_rows; row++) { for(int col = 0; col < max_cols; col++) { if(sqlite3_step(lib->statements.main_query) == SQLITE_ROW) query_ids[row*iir+col] = sqlite3_column_int(lib->statements.main_query, 0); else goto end_query_cache; } } end_query_cache: cairo_save(cr); for(int row = 0; row < max_rows; row++) { for(int col = 0; col < max_cols; col++) { //curidx = grid_to_index(row, col, iir, offset); id = query_ids[row*iir+col]; if(id > 0) { if (iir == 1 && row) continue; /* set mouse over id if pointer is in current row / col */ if(pi == col && pj == row) { mouse_over_id = id; DT_CTL_SET_GLOBAL(lib_image_mouse_over_id, mouse_over_id); } /* handle mouse click on current row / col this could easily and preferable be moved to button_pressed() */ if (clicked1 && (pi == col && pj == row)) { if ((lib->modifiers & (GDK_SHIFT_MASK|GDK_CONTROL_MASK)) == 0) dt_selection_select_single(darktable.selection, id); else if ((lib->modifiers & (GDK_CONTROL_MASK)) == GDK_CONTROL_MASK) dt_selection_toggle(darktable.selection, id); else if ((lib->modifiers & (GDK_SHIFT_MASK)) == GDK_SHIFT_MASK) dt_selection_select_range(darktable.selection, id); } cairo_save(cr); // if(iir == 1) dt_image_prefetch(image, DT_IMAGE_MIPF); dt_view_image_expose(&(lib->image_over), id, cr, wd, iir == 1 ? height : ht, iir, img_pointerx, img_pointery); cairo_restore(cr); } else goto failure; cairo_translate(cr, wd, 0.0f); } cairo_translate(cr, -max_cols*wd, ht); } cairo_restore(cr); // and now the group borders for(int row = 0; row < max_rows; row++) { for(int col = 0; col < max_cols; col++) { id = query_ids[row*iir+col]; if(id > 0) { const dt_image_t *image = dt_image_cache_read_get(darktable.image_cache, id); int group_id = -1; if(image) group_id = image->group_id; dt_image_cache_read_release(darktable.image_cache, image); if (iir == 1 && row) continue; cairo_save(cr); gboolean paint_border = FALSE; // regular highlight border if(group_id != -1) { if(mouse_over_group == group_id && iir > 1 && ((!darktable.gui->grouping && dt_conf_get_bool("plugins/lighttable/draw_group_borders")) || group_id == darktable.gui->expanded_group_id)) { cairo_set_source_rgb(cr, 1, 0.8, 0); paint_border = TRUE; } // border of expanded group else if(darktable.gui->grouping && group_id == darktable.gui->expanded_group_id && iir > 1) { cairo_set_source_rgb(cr, 0, 0, 1); paint_border = TRUE; } } if(paint_border) { int neighbour_group = -1; // top border if(row > 0) { int _id = query_ids[(row-1)*iir+col]; if(_id > 0) { const dt_image_t *_img = dt_image_cache_read_get(darktable.image_cache, _id); neighbour_group = _img->group_id; dt_image_cache_read_release(darktable.image_cache, _img); } } if(neighbour_group != group_id) { cairo_move_to(cr, 0, 0); cairo_line_to(cr, wd, 0); } // left border neighbour_group = -1; if(col > 0) { int _id = query_ids[row*iir+(col-1)]; if(_id > 0) { const dt_image_t *_img = dt_image_cache_read_get(darktable.image_cache, _id); neighbour_group = _img->group_id; dt_image_cache_read_release(darktable.image_cache, _img); } } if(neighbour_group != group_id) { cairo_move_to(cr, 0, 0); cairo_line_to(cr, 0, ht); } // bottom border neighbour_group = -1; if(row < max_rows-1) { int _id = query_ids[(row+1)*iir+col]; if(_id > 0) { const dt_image_t *_img = dt_image_cache_read_get(darktable.image_cache, _id); neighbour_group = _img->group_id; dt_image_cache_read_release(darktable.image_cache, _img); } } if(neighbour_group != group_id) { cairo_move_to(cr, 0, ht); cairo_line_to(cr, wd, ht); } // right border neighbour_group = -1; if(col < max_cols-1) { int _id = query_ids[row*iir+(col+1)]; if(_id > 0) { const dt_image_t *_img = dt_image_cache_read_get(darktable.image_cache, _id); neighbour_group = _img->group_id; dt_image_cache_read_release(darktable.image_cache, _img); } } if(neighbour_group != group_id) { cairo_move_to(cr, wd, 0); cairo_line_to(cr, wd, ht); } cairo_set_line_width(cr, 0.01*wd); cairo_stroke(cr); } cairo_restore(cr); } else goto failure; cairo_translate(cr, wd, 0.0f); } cairo_translate(cr, -max_cols*wd, ht); } /* check if offset was changed and we need to prefetch thumbs */ if (offset_changed) { int32_t imgids_num = 0; const int prefetchrows = .5*max_rows+1; int32_t imgids[prefetchrows*iir]; /* clear and reset main query */ DT_DEBUG_SQLITE3_CLEAR_BINDINGS(lib->statements.main_query); DT_DEBUG_SQLITE3_RESET(lib->statements.main_query); /* setup offest and row for prefetch */ DT_DEBUG_SQLITE3_BIND_INT(lib->statements.main_query, 1, offset + max_rows*iir); DT_DEBUG_SQLITE3_BIND_INT(lib->statements.main_query, 2, prefetchrows*iir); // prefetch jobs in inverse order: supersede previous jobs: most important last while(sqlite3_step(lib->statements.main_query) == SQLITE_ROW && imgids_num < prefetchrows*iir) imgids[imgids_num++] = sqlite3_column_int(lib->statements.main_query, 0); float imgwd = iir == 1 ? 0.97 : 0.8; dt_mipmap_size_t mip = dt_mipmap_cache_get_matching_size( darktable.mipmap_cache, imgwd*wd, imgwd*(iir==1?height:ht)); while(imgids_num > 0) { imgids_num --; dt_mipmap_buffer_t buf; dt_mipmap_cache_read_get( darktable.mipmap_cache, &buf, imgids[imgids_num], mip, DT_MIPMAP_PREFETCH); } } failure: g_free(query_ids); oldpan = pan; if(darktable.unmuted & DT_DEBUG_CACHE) dt_mipmap_cache_print(darktable.mipmap_cache); if(darktable.gui->center_tooltip == 1) // set in this round { char* tooltip = dt_history_get_items_as_string(mouse_over_id); if(tooltip != NULL) { g_object_set(G_OBJECT(dt_ui_center(darktable.gui->ui)), "tooltip-text", tooltip, (char *)NULL); g_free(tooltip); } } else if(darktable.gui->center_tooltip == 2) // not set in this round { darktable.gui->center_tooltip = 0; g_object_set(G_OBJECT(dt_ui_center(darktable.gui->ui)), "tooltip-text", "", (char *)NULL); } }
int dt_load_from_string(const gchar* input, gboolean open_image_in_dr) { int id = 0; if(input == NULL || input[0] == '\0') return 0; char* filename = dt_make_path_absolute(input); if(filename == NULL) { dt_control_log(_("found strange path `%s'"), input); return 0; } if(g_file_test(filename, G_FILE_TEST_IS_DIR)) { // import a directory into a film roll unsigned int last_char = strlen(filename)-1; if(filename[last_char] == '/') filename[last_char] = '\0'; id = dt_film_import(filename); if(id) { dt_film_open(id); dt_ctl_switch_mode_to(DT_LIBRARY); } else { dt_control_log(_("error loading directory `%s'"), filename); } } else { // import a single image gchar *directory = g_path_get_dirname((const gchar *)filename); dt_film_t film; const int filmid = dt_film_new(&film, directory); id = dt_image_import(filmid, filename, TRUE); g_free (directory); if(id) { dt_film_open(filmid); // make sure buffers are loaded (load full for testing) dt_mipmap_buffer_t buf; dt_mipmap_cache_read_get(darktable.mipmap_cache, &buf, id, DT_MIPMAP_FULL, DT_MIPMAP_BLOCKING); if(!buf.buf) { id = 0; dt_control_log(_("file `%s' has unknown format!"), filename); } else { dt_mipmap_cache_read_release(darktable.mipmap_cache, &buf); if(open_image_in_dr) { DT_CTL_SET_GLOBAL(lib_image_mouse_over_id, id); dt_ctl_switch_mode_to(DT_DEVELOP); } } } else { dt_control_log(_("error loading file `%s'"), filename); } } g_free(filename); return id; }
static void _lib_import_single_image_callback(GtkWidget *widget,gpointer user_data) { GtkWidget *win = dt_ui_main_window(darktable.gui->ui); GtkWidget *filechooser = gtk_file_chooser_dialog_new (_("import image"), GTK_WINDOW (win), GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, (char *)NULL); gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(filechooser), TRUE); char *last_directory = dt_conf_get_string("ui_last/import_last_directory"); if(last_directory != NULL) gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER (filechooser), last_directory); char *cp, **extensions, ext[1024]; GtkFileFilter *filter; filter = GTK_FILE_FILTER(gtk_file_filter_new()); extensions = g_strsplit(dt_supported_extensions, ",", 100); for(char **i=extensions; *i!=NULL; i++) { snprintf(ext, 1024, "*.%s", *i); gtk_file_filter_add_pattern(filter, ext); gtk_file_filter_add_pattern(filter, cp=g_ascii_strup(ext, -1)); g_free(cp); } g_strfreev(extensions); gtk_file_filter_set_name(filter, _("supported images")); gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(filechooser), filter); filter = GTK_FILE_FILTER(gtk_file_filter_new()); gtk_file_filter_add_pattern(filter, "*"); gtk_file_filter_set_name(filter, _("all files")); gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(filechooser), filter); GtkWidget *preview = gtk_image_new(); gtk_file_chooser_set_preview_widget(GTK_FILE_CHOOSER(filechooser), preview); g_signal_connect(filechooser, "update-preview", G_CALLBACK (_lib_import_update_preview), preview); dt_lib_import_metadata_t metadata; gtk_file_chooser_set_extra_widget (GTK_FILE_CHOOSER (filechooser), _lib_import_get_extra_widget(&metadata, FALSE)); if (gtk_dialog_run (GTK_DIALOG (filechooser)) == GTK_RESPONSE_ACCEPT) { dt_conf_set_string("ui_last/import_last_directory", gtk_file_chooser_get_current_folder(GTK_FILE_CHOOSER (filechooser))); _lib_import_evaluate_extra_widget(&metadata, FALSE); char *filename = NULL; dt_film_t film; GSList *list = gtk_file_chooser_get_filenames (GTK_FILE_CHOOSER (filechooser)); GSList *it = list; int id = 0; int filmid = 0; /* reset filter to display all images, otherwise view may remain empty */ dt_view_filter_reset_to_show_all(darktable.view_manager); while(it) { filename = (char *)it->data; gchar *directory = g_path_get_dirname((const gchar *)filename); filmid = dt_film_new(&film, directory); id = dt_image_import(filmid, filename, TRUE); if(!id) dt_control_log(_("error loading file `%s'"), filename); g_free (filename); g_free (directory); it = g_slist_next(it); } if(id) { dt_film_open(filmid); // make sure buffers are loaded (load full for testing) dt_mipmap_buffer_t buf; dt_mipmap_cache_read_get(darktable.mipmap_cache, &buf, id, DT_MIPMAP_FULL, DT_MIPMAP_BLOCKING); if(!buf.buf) { dt_control_log(_("file has unknown format!")); } else { dt_mipmap_cache_read_release(darktable.mipmap_cache, &buf); DT_CTL_SET_GLOBAL(lib_image_mouse_over_id, id); dt_ctl_switch_mode_to(DT_DEVELOP); } } } gtk_widget_destroy(metadata.frame); gtk_widget_destroy (filechooser); gtk_widget_queue_draw(dt_ui_center(darktable.gui->ui)); }
void mouse_moved(dt_view_t *self, double x, double y, int which) { const int32_t capwd = darktable.thumbnail_width; const int32_t capht = darktable.thumbnail_height; dt_develop_t *dev = (dt_develop_t *)self->data; // if we are not hovering over a thumbnail in the filmstrip -> show metadata of opened image. int32_t mouse_over_id = -1; DT_CTL_GET_GLOBAL(mouse_over_id, lib_image_mouse_over_id); if(mouse_over_id == -1) { mouse_over_id = dev->image_storage.id; DT_CTL_SET_GLOBAL(lib_image_mouse_over_id, mouse_over_id); } dt_control_t *ctl = darktable.control; const int32_t width_i = self->width; const int32_t height_i = self->height; int32_t offx = 0.0f, offy = 0.0f; if(width_i > capwd) offx = (capwd-width_i) *.5f; if(height_i > capht) offy = (capht-height_i)*.5f; int handled = 0; x += offx; y += offy; if(dev->gui_module && dev->gui_module->request_color_pick && ctl->button_down && ctl->button_down_which == 1) { // module requested a color box float zoom_x, zoom_y, bzoom_x, bzoom_y; dt_dev_get_pointer_zoom_pos(dev, x, y, &zoom_x, &zoom_y); dt_dev_get_pointer_zoom_pos(dev, ctl->button_x + offx, ctl->button_y + offy, &bzoom_x, &bzoom_y); if(darktable.lib->proxy.colorpicker.size) { dev->gui_module->color_picker_box[0] = fmaxf(0.0, fminf(.5f+bzoom_x, .5f+zoom_x)); dev->gui_module->color_picker_box[1] = fmaxf(0.0, fminf(.5f+bzoom_y, .5f+zoom_y)); dev->gui_module->color_picker_box[2] = fminf(1.0, fmaxf(.5f+bzoom_x, .5f+zoom_x)); dev->gui_module->color_picker_box[3] = fminf(1.0, fmaxf(.5f+bzoom_y, .5f+zoom_y)); } else { dev->gui_module->color_picker_point[0] = .5f + zoom_x; dev->gui_module->color_picker_point[1] = .5f + zoom_y; } dev->preview_pipe->changed |= DT_DEV_PIPE_SYNCH; dt_dev_invalidate_all(dev); dt_control_queue_redraw(); return; } if(dev->gui_module && dev->gui_module->mouse_moved) handled = dev->gui_module->mouse_moved(dev->gui_module, x, y, which); if(handled) return; if(darktable.control->button_down && darktable.control->button_down_which == 1) { // depending on dev_zoom, adjust dev_zoom_x/y. dt_dev_zoom_t zoom; int closeup; DT_CTL_GET_GLOBAL(zoom, dev_zoom); DT_CTL_GET_GLOBAL(closeup, dev_closeup); int procw, proch; dt_dev_get_processed_size(dev, &procw, &proch); const float scale = dt_dev_get_zoom_scale(dev, zoom, closeup ? 2 : 1, 0); float old_zoom_x, old_zoom_y; DT_CTL_GET_GLOBAL(old_zoom_x, dev_zoom_x); DT_CTL_GET_GLOBAL(old_zoom_y, dev_zoom_y); float zx = old_zoom_x - (1.0/scale)*(x - ctl->button_x - offx)/procw; float zy = old_zoom_y - (1.0/scale)*(y - ctl->button_y - offy)/proch; dt_dev_check_zoom_bounds(dev, &zx, &zy, zoom, closeup, NULL, NULL); DT_CTL_SET_GLOBAL(dev_zoom_x, zx); DT_CTL_SET_GLOBAL(dev_zoom_y, zy); ctl->button_x = x - offx; ctl->button_y = y - offy; dt_dev_invalidate(dev); dt_control_queue_redraw(); } }
void enter(dt_view_t *self) { /* connect to ui pipe finished signal for redraw */ dt_control_signal_connect(darktable.signals, DT_SIGNAL_DEVELOP_UI_PIPE_FINISHED,G_CALLBACK(_darkroom_ui_pipe_finish_signal_callback), (gpointer)self); dt_print(DT_DEBUG_CONTROL, "[run_job+] 11 %f in darkroom mode\n", dt_get_wtime()); dt_develop_t *dev = (dt_develop_t *)self->data; dev->gui_leaving = 0; dev->gui_module = NULL; select_this_image(dev->image_storage.id); 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); // take a copy of the image struct for convenience. dt_dev_load_image(darktable.develop, dev->image_storage.id); /* * Add view specific tool buttons */ /* create favorite plugin preset popup tool */ GtkWidget *favorite_presets = dtgtk_button_new(dtgtk_cairo_paint_presets, CPF_STYLE_FLAT|CPF_DO_NOT_USE_BORDER); g_object_set(G_OBJECT(favorite_presets), "tooltip-text", _("quick access to presets of your favorites"), (char *)NULL); g_signal_connect (G_OBJECT (favorite_presets), "clicked", G_CALLBACK (_darkroom_ui_favorite_presets_popupmenu), NULL); dt_view_manager_view_toolbox_add(darktable.view_manager, favorite_presets); /* add IOP modules to plugin list */ /* create quick styles popup menu tool */ GtkWidget *styles = dtgtk_button_new (dtgtk_cairo_paint_styles,CPF_STYLE_FLAT|CPF_DO_NOT_USE_BORDER); g_signal_connect (G_OBJECT (styles), "clicked", G_CALLBACK (_darkroom_ui_apply_style_popupmenu), NULL); g_object_set (G_OBJECT (styles), "tooltip-text", _("quick access for applying any of your styles"), (char *)NULL); dt_view_manager_view_toolbox_add(darktable.view_manager, styles); /* * add IOP modules to plugin list */ // avoid triggering of events before plugin is ready: darktable.gui->reset = 1; char option[1024]; GList *modules = g_list_last(dev->iop); while(modules) { dt_iop_module_t *module = (dt_iop_module_t *)(modules->data); /* initialize gui if iop have one defined */ if (!dt_iop_is_hidden(module)) { module->gui_init(module); dt_iop_reload_defaults(module); /* add module to right panel */ GtkWidget *expander = dt_iop_gui_get_expander(module); dt_ui_container_add_widget(darktable.gui->ui, DT_UI_CONTAINER_PANEL_RIGHT_CENTER, expander); snprintf(option, 1024, "plugins/darkroom/%s/expanded", module->op); dt_iop_gui_set_expanded(module, dt_conf_get_bool(option)); } /* setup key accelerators */ module->accel_closures = NULL; if(module->connect_key_accels) module->connect_key_accels(module); dt_iop_connect_common_accels(module); modules = g_list_previous(modules); } darktable.gui->reset = 0; /* signal that darktable.develop is initialized and ready to be used */ dt_control_signal_raise(darktable.signals,DT_SIGNAL_DEVELOP_INITIALIZE); // synch gui and flag gegl pipe as dirty // this is done here and not in dt_read_history, as it would else be triggered before module->gui_init. dt_dev_pop_history_items(dev, dev->history_end); /* ensure that filmstrip shows current image */ dt_view_filmstrip_scroll_to_image(darktable.view_manager, dev->image_storage.id, FALSE); // switch on groups as they where last time: dt_dev_modulegroups_set(dev, dt_conf_get_int("plugins/darkroom/groups")); // make signals work again: darktable.gui->reset = 0; // get last active plugin: gchar *active_plugin = dt_conf_get_string("plugins/darkroom/active"); if(active_plugin) { GList *modules = dev->iop; while(modules) { dt_iop_module_t *module = (dt_iop_module_t *)(modules->data); if(!strcmp(module->op, active_plugin)) dt_iop_request_focus(module); modules = g_list_next(modules); } g_free(active_plugin); } // image should be there now. float zoom_x, zoom_y; dt_dev_check_zoom_bounds(dev, &zoom_x, &zoom_y, DT_ZOOM_FIT, 0, NULL, NULL); DT_CTL_SET_GLOBAL(dev_zoom_x, zoom_x); DT_CTL_SET_GLOBAL(dev_zoom_y, zoom_y); /* connect signal for filmstrip image activate */ dt_control_signal_connect(darktable.signals, DT_SIGNAL_VIEWMANAGER_FILMSTRIP_ACTIVATE, G_CALLBACK(_view_darkroom_filmstrip_activate_callback), self); // prefetch next few from first selected image on. dt_view_filmstrip_prefetch(); }