void dt_iop_gui_init_blending(GtkWidget *iopw, dt_iop_module_t *module) { /* create and add blend mode if module supports it */ if (module->flags()&IOP_FLAGS_SUPPORTS_BLENDING) { module->blend_data = g_malloc(sizeof(dt_iop_gui_blend_data_t)); memset(module->blend_data, 0, sizeof(dt_iop_gui_blend_data_t)); dt_iop_gui_blend_data_t *bd = (dt_iop_gui_blend_data_t*)module->blend_data; dt_iop_gui_blendop_modes_t modes[23]; /* number must fit exactly!!! */ modes[0].mode = DEVELOP_BLEND_DISABLED; modes[0].name = _("off"); modes[1].mode = DEVELOP_BLEND_NORMAL; modes[1].name = _("normal"); modes[2].mode = DEVELOP_BLEND_INVERSE; modes[2].name = _("inverse"); modes[3].mode = DEVELOP_BLEND_LIGHTEN; modes[3].name = _("lighten"); modes[4].mode = DEVELOP_BLEND_DARKEN; modes[4].name = _("darken"); modes[5].mode = DEVELOP_BLEND_MULTIPLY; modes[5].name = _("multiply"); modes[6].mode = DEVELOP_BLEND_AVERAGE; modes[6].name = _("average"); modes[7].mode = DEVELOP_BLEND_ADD; modes[7].name = _("addition"); modes[8].mode = DEVELOP_BLEND_SUBSTRACT; modes[8].name = _("subtract"); modes[9].mode = DEVELOP_BLEND_DIFFERENCE; modes[9].name = _("difference"); modes[10].mode = DEVELOP_BLEND_SCREEN; modes[10].name = _("screen"); modes[11].mode = DEVELOP_BLEND_OVERLAY; modes[11].name = _("overlay"); modes[12].mode = DEVELOP_BLEND_SOFTLIGHT; modes[12].name = _("softlight"); modes[13].mode = DEVELOP_BLEND_HARDLIGHT; modes[13].name = _("hardlight"); modes[14].mode = DEVELOP_BLEND_VIVIDLIGHT; modes[14].name = _("vividlight"); modes[15].mode = DEVELOP_BLEND_LINEARLIGHT; modes[15].name = _("linearlight"); modes[16].mode = DEVELOP_BLEND_PINLIGHT; modes[16].name = _("pinlight"); modes[17].mode = DEVELOP_BLEND_LIGHTNESS; modes[17].name = _("lightness"); modes[18].mode = DEVELOP_BLEND_CHROMA; modes[18].name = _("chroma"); modes[19].mode = DEVELOP_BLEND_HUE; modes[19].name = _("hue"); modes[20].mode = DEVELOP_BLEND_COLOR; modes[20].name = _("color"); modes[21].mode = DEVELOP_BLEND_COLORADJUST; modes[21].name = _("coloradjustment"); modes[22].mode = DEVELOP_BLEND_UNBOUNDED; modes[22].name = _("unbounded"); bd->number_modes = sizeof(modes) / sizeof(dt_iop_gui_blendop_modes_t); memcpy(bd->modes, modes, bd->number_modes * sizeof(dt_iop_gui_blendop_modes_t)); bd->iopw = iopw; bd->module = module; bd->csp = dt_iop_module_colorspace(module); bd->blendif_support = (bd->csp == iop_cs_Lab || bd->csp == iop_cs_rgb); bd->blendif_box = NULL; bd->blend_modes_combo = dt_bauhaus_combobox_new(module); dt_bauhaus_widget_set_label(bd->blend_modes_combo, _("blend mode")); bd->opacity_slider = dt_bauhaus_slider_new_with_range(module, 0.0, 100.0, 1, 100.0, 0); dt_bauhaus_widget_set_label(bd->opacity_slider, _("opacity")); dt_bauhaus_slider_set_format(bd->opacity_slider, "%.0f%%"); module->fusion_slider = bd->opacity_slider; for(int k = 0; k < bd->number_modes; k++) dt_bauhaus_combobox_add(bd->blend_modes_combo, bd->modes[k].name); dt_bauhaus_combobox_set(bd->blend_modes_combo, 0); gtk_object_set(GTK_OBJECT(bd->opacity_slider), "tooltip-text", _("set the opacity of the blending"), (char *)NULL); gtk_object_set(GTK_OBJECT(bd->blend_modes_combo), "tooltip-text", _("choose blending mode"), (char *)NULL); g_signal_connect (G_OBJECT (bd->opacity_slider), "value-changed", G_CALLBACK (_blendop_opacity_callback), bd); g_signal_connect (G_OBJECT (bd->blend_modes_combo), "value-changed", G_CALLBACK (_blendop_mode_callback), bd); gtk_box_pack_start(GTK_BOX(iopw), bd->blend_modes_combo, TRUE, TRUE,0); gtk_box_pack_start(GTK_BOX(iopw), bd->opacity_slider, TRUE, TRUE,0); if(bd->blendif_support) { dt_iop_gui_init_blendif(GTK_VBOX(iopw), module); } bd->blend_inited = 1; gtk_widget_queue_draw(GTK_WIDGET(iopw)); dt_iop_gui_update_blending(module); } }
void dt_dev_reload_history_items(dt_develop_t *dev) { dt_dev_pop_history_items(dev, 0); // remove unused history items: GList *history = g_list_nth(dev->history, dev->history_end); while(history) { GList *next = g_list_next(history); dt_dev_history_item_t *hist = (dt_dev_history_item_t *)(history->data); free(hist->params); free(hist->blend_params); free(history->data); dev->history = g_list_delete_link(dev->history, history); history = next; } dt_dev_read_history(dev); //we have to add new module instances first GList *modules = dev->iop; while(modules) { dt_iop_module_t *module = (dt_iop_module_t *)(modules->data); if (module->multi_priority > 0) { if (!dt_iop_is_hidden(module) && !module->expander) { module->gui_init(module); dt_iop_reload_defaults(module); //we search the base iop corresponding GList *mods = g_list_first(dev->iop); dt_iop_module_t *base = NULL; int pos_module = 0; int pos_base = 0; int pos = 0; while (mods) { dt_iop_module_t *mod = (dt_iop_module_t *)(mods->data); if (mod->multi_priority == 0 && mod->instance == module->instance) { base = mod; pos_base = pos; } else if (mod == module) pos_module = pos; mods = g_list_next(mods); pos++; } if (!base) continue; /* 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); GValue gv = { 0, { { 0 } } }; g_value_init(&gv,G_TYPE_INT); gtk_container_child_get_property(GTK_CONTAINER(dt_ui_get_container(darktable.gui->ui, DT_UI_CONTAINER_PANEL_RIGHT_CENTER)),base->expander,"position",&gv); gtk_box_reorder_child (dt_ui_get_container(darktable.gui->ui, DT_UI_CONTAINER_PANEL_RIGHT_CENTER),expander,g_value_get_int(&gv)+pos_base-pos_module); dt_iop_gui_set_expanded(module, TRUE); dt_iop_gui_update_blending(module); //the pipe need to be reconstruct dev->pipe->changed |= DT_DEV_PIPE_REMOVE; dev->preview_pipe->changed |= DT_DEV_PIPE_REMOVE; } } modules = g_list_next(modules); } dt_dev_pop_history_items(dev, dev->history_end); }
static void dt_dev_change_image(dt_develop_t *dev, const uint32_t imgid) { // stop crazy users from sleeping on key-repeat spacebar: if(dev->image_loading) return; // get last active plugin, make sure focus out is called: gchar *active_plugin = dt_conf_get_string("plugins/darkroom/active"); dt_iop_request_focus(NULL); // store last active group dt_conf_set_int("plugins/darkroom/groups", dt_dev_modulegroups_get(dev)); // store last active plugin: if(darktable.develop->gui_module) dt_conf_set_string("plugins/darkroom/active", darktable.develop->gui_module->op); else dt_conf_set_string("plugins/darkroom/active", ""); g_assert(dev->gui_attached); // commit image ops to db dt_dev_write_history(dev); // be sure light table will update the thumbnail // TODO: only if image changed! // if() { dt_mipmap_cache_remove(darktable.mipmap_cache, dev->image_storage.id); dt_image_synch_xmp(dev->image_storage.id); } select_this_image(imgid); while(dev->history) { // clear history of old image free(((dt_dev_history_item_t *)dev->history->data)->params); free( (dt_dev_history_item_t *)dev->history->data); dev->history = g_list_delete_link(dev->history, dev->history); } // get new image: dt_dev_reload_image(dev, imgid); // make sure no signals propagate here: darktable.gui->reset = 1; GList *modules = g_list_last(dev->iop); int nb_iop = g_list_length(dev->iop); dt_dev_pixelpipe_cleanup_nodes(dev->pipe); dt_dev_pixelpipe_cleanup_nodes(dev->preview_pipe); for (int i=nb_iop-1; i>0; i--) { dt_iop_module_t *module = (dt_iop_module_t *)(g_list_nth_data(dev->iop,i)); if (module->multi_priority == 0) //if the module is the "base" instance, we keep it { dt_iop_reload_defaults(module); dt_iop_gui_update(module); } else //else we delete it and remove it from the panel { if (!dt_iop_is_hidden(module)) { gtk_container_remove (GTK_CONTAINER(dt_ui_get_container(darktable.gui->ui, DT_UI_CONTAINER_PANEL_RIGHT_CENTER)),module->expander); dt_iop_gui_cleanup_module(module); } //we remove the module from the list dev->iop = g_list_remove_link(dev->iop,g_list_nth(dev->iop,i)); //we cleanup the module dt_accel_disconnect_list(module->accel_closures); dt_accel_cleanup_locals_iop(module); module->accel_closures = NULL; dt_iop_cleanup_module(module); free(module); } } dt_dev_pixelpipe_create_nodes(dev->pipe, dev); dt_dev_pixelpipe_create_nodes(dev->preview_pipe, dev); dt_dev_read_history(dev); //we have to init all module instances other than "base" instance modules = dev->iop; while(modules) { dt_iop_module_t *module = (dt_iop_module_t *)(modules->data); if(module->multi_priority > 0) { if (!dt_iop_is_hidden(module)) { module->gui_init(module); dt_iop_reload_defaults(module); //we search the base iop corresponding GList *mods = g_list_first(dev->iop); dt_iop_module_t *base = NULL; int pos_module = 0; int pos_base = 0; int pos = 0; while (mods) { dt_iop_module_t *mod = (dt_iop_module_t *)(mods->data); if (mod->multi_priority == 0 && mod->instance == module->instance) { base = mod; pos_base = pos; } else if (mod == module) pos_module = pos; mods = g_list_next(mods); pos++; } if (!base) continue; /* 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); GValue gv = { 0, { { 0 } } }; g_value_init(&gv,G_TYPE_INT); gtk_container_child_get_property(GTK_CONTAINER(dt_ui_get_container(darktable.gui->ui, DT_UI_CONTAINER_PANEL_RIGHT_CENTER)),base->expander,"position",&gv); gtk_box_reorder_child (dt_ui_get_container(darktable.gui->ui, DT_UI_CONTAINER_PANEL_RIGHT_CENTER),expander,g_value_get_int(&gv)+pos_base-pos_module); dt_iop_gui_set_expanded(module, TRUE); dt_iop_gui_update_blending(module); } /* setup key accelerators */ module->accel_closures = NULL; if(module->connect_key_accels) module->connect_key_accels(module); dt_iop_connect_common_accels(module); //we update show params for multi-instances for each other instances dt_dev_modules_update_multishow(module->dev); } modules = g_list_next(modules); } dt_dev_pop_history_items(dev, dev->history_end); if(active_plugin) { 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); } /* last set the group to update visibility of iop modules for new pipe */ dt_dev_modulegroups_set(dev,dt_conf_get_int("plugins/darkroom/groups")); // make signals work again, but only after focus event, // to avoid crop/rotate for example to add another history item. darktable.gui->reset = 0; // Signal develop initialize dt_control_signal_raise(darktable.signals, DT_SIGNAL_DEVELOP_IMAGE_CHANGED); // prefetch next few from first selected image on. dt_view_filmstrip_prefetch(); }