Improve Foreground Select tool's GUI

* Add a dialog with Preview, Apply, and Reset buttons instead of
  depending only on hidden keyboard shortcuts.
* Change default paint mode to Unknown.
* Disable engine list when there is only one engine available.
* Hide useless Anti-Alias toggle.
* Write to selection instead of the layer mask.
This commit is contained in:
Daniel Sabo 2013-12-08 21:22:34 -08:00
parent 33b7c897de
commit e9d3bf8f19
5 changed files with 146 additions and 35 deletions

View File

@ -228,6 +228,7 @@ static const GimpDialogFactoryEntry entries[] =
FOREIGN ("gimp-crop-tool-dialog", TRUE, FALSE),
FOREIGN ("gimp-curves-tool-dialog", TRUE, TRUE),
FOREIGN ("gimp-desaturate-tool-dialog", TRUE, FALSE),
FOREIGN ("gimp-foreground-select-tool-dialog", TRUE, FALSE),
FOREIGN ("gimp-gegl-tool-dialog", TRUE, FALSE),
FOREIGN ("gimp-hue-saturation-tool-dialog", TRUE, FALSE),
FOREIGN ("gimp-levels-tool-dialog", TRUE, TRUE),

View File

@ -84,7 +84,7 @@ gimp_foreground_select_options_class_init (GimpForegroundSelectOptionsClass *kla
N_("Paint over areas to mark color values for "
"inclusion or exclusion from selection"),
GIMP_TYPE_MATTING_DRAW_MODE,
GIMP_MATTING_DRAW_MODE_FOREGROUND,
GIMP_MATTING_DRAW_MODE_UNKNOWN,
GIMP_PARAM_STATIC_STRINGS);
GIMP_CONFIG_INSTALL_PROP_INT (object_class, PROP_STROKE_WIDTH,
@ -155,6 +155,11 @@ gimp_foreground_select_options_set_property (GObject *object,
case PROP_ENGINE:
options->engine = g_value_get_enum (value);
if ((options->engine == GIMP_MATTING_ENGINE_LEVIN) &&
!(gegl_has_operation ("gegl:matting-levin")))
{
options->engine = GIMP_MATTING_ENGINE_GLOBAL;
}
break;
case PROP_LEVELS:
@ -251,6 +256,10 @@ gimp_foreground_select_options_gui (GimpToolOptions *tool_options)
GtkWidget *scale;
GtkWidget *combo;
GtkWidget *inner_vbox;
GtkWidget *antialias_toggle;
antialias_toggle = GIMP_SELECTION_OPTIONS (tool_options)->antialias_toggle;
gtk_widget_hide (antialias_toggle);
frame = gimp_prop_enum_radio_frame_new (config, "draw-mode", _("Draw Mode"),
0,0);
@ -301,6 +310,9 @@ gimp_foreground_select_options_gui (GimpToolOptions *tool_options)
gimp_int_combo_box_set_label (GIMP_INT_COMBO_BOX (combo), _("Engine"));
g_object_set (combo, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
gtk_frame_set_label_widget (GTK_FRAME (frame), combo);
if (!gegl_has_operation ("gegl:matting-levin"))
gtk_widget_set_sensitive (combo, FALSE);
gtk_widget_show (combo);
inner_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 2);
@ -350,25 +362,6 @@ gimp_foreground_select_options_gui (GimpToolOptions *tool_options)
return vbox;
}
gdouble
gimp_foreground_select_options_get_opacity (GimpForegroundSelectOptions *options)
{
g_return_val_if_fail (GIMP_IS_FOREGROUND_SELECT_OPTIONS (options), 0.0);
switch (options->draw_mode)
{
case GIMP_MATTING_DRAW_MODE_FOREGROUND:
return 1.0;
case GIMP_MATTING_DRAW_MODE_BACKGROUND:
return 0.0;
case GIMP_MATTING_DRAW_MODE_UNKNOWN:
default:
return 0.5;
}
}
void
gimp_foreground_select_options_get_mask_color (GimpForegroundSelectOptions *options,
GimpRGB *color)

View File

@ -59,7 +59,6 @@ GtkWidget * gimp_foreground_select_options_gui (GimpToolOptions
void gimp_foreground_select_options_get_mask_color (GimpForegroundSelectOptions *options,
GimpRGB *color);
gdouble gimp_foreground_select_options_get_opacity (GimpForegroundSelectOptions *options);
#endif /* __GIMP_FOREGROUND_SELECT_OPTIONS_H__ */

View File

@ -35,6 +35,7 @@
#include "gegl/gimp-gegl-mask.h"
#include "core/gimp.h"
#include "core/gimpchannel-select.h"
#include "core/gimpdrawable-foreground-extract.h"
#include "core/gimpimage.h"
#include "core/gimplayer.h"
@ -47,6 +48,7 @@
#include "display/gimpdisplay.h"
#include "display/gimpdisplayshell.h"
#include "display/gimptoolgui.h"
#include "gimpforegroundselecttool.h"
#include "gimpforegroundselectoptions.h"
@ -54,6 +56,9 @@
#include "gimp-intl.h"
#define RESPONSE_RESET 1
#define RESPONSE_PREVIEW 2
#define RESPONSE_APPLY 3
typedef struct
{
@ -130,6 +135,13 @@ static void gimp_foreground_select_tool_stroke_paint (GimpForegroundSelectTo
GimpDisplay *display,
GimpForegroundSelectOptions *options);
static void gimp_foreground_select_tool_update_gui (GimpForegroundSelectTool *fg_select);
static void gimp_foreground_select_tool_response (GimpToolGui *gui,
gint response_id,
GimpForegroundSelectTool *fg_select);
G_DEFINE_TYPE (GimpForegroundSelectTool, gimp_foreground_select_tool,
GIMP_TYPE_FREE_SELECT_TOOL)
@ -203,6 +215,7 @@ gimp_foreground_select_tool_init (GimpForegroundSelectTool *fg_select)
fg_select->mask = NULL;
fg_select->trimap = NULL;
fg_select->state = MATTING_STATE_FREE_SELECT;
fg_select->gui = NULL;
}
static void
@ -222,6 +235,12 @@ gimp_foreground_select_tool_finalize (GObject *object)
{
GimpForegroundSelectTool *fg_select = GIMP_FOREGROUND_SELECT_TOOL (object);
if (fg_select->gui)
{
g_object_unref (fg_select->gui);
fg_select->gui = NULL;
}
if (fg_select->stroke)
g_warning ("%s: stroke should be NULL at this point", G_STRLOC);
@ -251,6 +270,9 @@ gimp_foreground_select_tool_control (GimpTool *tool,
{
gimp_foreground_select_tool_drop_masks (fg_select, display);
tool->display = NULL;
if (fg_select->gui)
gimp_tool_gui_hide (fg_select->gui);
}
break;
}
@ -268,6 +290,9 @@ gimp_foreground_select_tool_oper_update (GimpTool *tool,
GimpForegroundSelectTool *fg_select = GIMP_FOREGROUND_SELECT_TOOL (tool);
const gchar *status = NULL;
GimpDisplayShell *shell = gimp_display_get_shell (display);
GimpImage *image = gimp_display_get_image (display);
GIMP_TOOL_CLASS (parent_class)->oper_update (tool, coords, state, proximity,
display);
@ -294,6 +319,13 @@ gimp_foreground_select_tool_oper_update (GimpTool *tool,
if (proximity && status)
gimp_tool_replace_status (tool, display, "%s", status);
gimp_foreground_select_tool_update_gui (fg_select);
gimp_tool_gui_set_shell (fg_select->gui, shell);
gimp_tool_gui_set_viewable (fg_select->gui, GIMP_VIEWABLE (image));
gimp_tool_gui_show (fg_select->gui);
}
static void
@ -359,11 +391,11 @@ gimp_foreground_select_tool_key_press (GimpTool *tool,
case GDK_KEY_Return:
case GDK_KEY_KP_Enter:
case GDK_KEY_ISO_Enter:
gimp_foreground_select_tool_preview (fg_select, display);
gimp_foreground_select_tool_response (fg_select->gui, RESPONSE_PREVIEW, fg_select);
return TRUE;
case GDK_KEY_Escape:
gimp_tool_control (tool, GIMP_TOOL_ACTION_HALT, display);
gimp_foreground_select_tool_response (fg_select->gui, RESPONSE_RESET, fg_select);
return TRUE;
default:
@ -377,11 +409,11 @@ gimp_foreground_select_tool_key_press (GimpTool *tool,
case GDK_KEY_Return:
case GDK_KEY_KP_Enter:
case GDK_KEY_ISO_Enter:
gimp_foreground_select_tool_apply (fg_select, display);
gimp_foreground_select_tool_response (fg_select->gui, RESPONSE_APPLY, fg_select);
return TRUE;
case GDK_KEY_Escape:
gimp_foreground_select_tool_set_trimap (fg_select, display);
gimp_foreground_select_tool_response (fg_select->gui, RESPONSE_PREVIEW, fg_select);
return TRUE;
default:
@ -474,6 +506,80 @@ gimp_foreground_select_tool_button_release (GimpTool *tool,
}
}
static void
gimp_foreground_select_tool_response (GimpToolGui *gui,
gint response_id,
GimpForegroundSelectTool *fg_select)
{
GimpTool *tool = GIMP_TOOL (fg_select);
GimpDisplay *display = tool->display;
if (response_id == RESPONSE_PREVIEW)
{
if (fg_select->state == MATTING_STATE_PREVIEW_MASK)
gimp_foreground_select_tool_set_trimap (fg_select, display);
else
gimp_foreground_select_tool_preview (fg_select, display);
}
else if (response_id == RESPONSE_APPLY)
{
if (fg_select->state != MATTING_STATE_PREVIEW_MASK)
gimp_foreground_select_tool_preview (fg_select, display);
gimp_foreground_select_tool_apply (fg_select, display);
}
else if (response_id == RESPONSE_RESET)
{
gimp_tool_control (tool, GIMP_TOOL_ACTION_HALT, display);
}
gimp_foreground_select_tool_update_gui (fg_select);
}
static void
gimp_foreground_select_tool_update_gui (GimpForegroundSelectTool *fg_select)
{
GimpTool *tool = GIMP_TOOL (fg_select);
if (!fg_select->gui)
{
fg_select->gui = gimp_tool_gui_new (tool->tool_info,
_("Dialog for foreground select"),
FALSE,
_("Toggle Preview"), RESPONSE_PREVIEW,
_("Apply"), RESPONSE_APPLY,
GIMP_STOCK_RESET, RESPONSE_RESET,
NULL);
g_signal_connect (fg_select->gui, "response",
G_CALLBACK (gimp_foreground_select_tool_response),
fg_select);
}
if (fg_select->state == MATTING_STATE_FREE_SELECT)
{
gimp_tool_gui_set_description (fg_select->gui, _("Select foreground pixels"));
}
else if (fg_select->state == MATTING_STATE_PAINT_TRIMAP)
{
gimp_tool_gui_set_description (fg_select->gui, _("Paint mask"));
}
else if (fg_select->state == MATTING_STATE_PREVIEW_MASK)
{
gimp_tool_gui_set_description (fg_select->gui, _("Preview"));
}
if (fg_select->state == MATTING_STATE_FREE_SELECT)
{
gimp_tool_gui_set_response_sensitive (fg_select->gui, RESPONSE_PREVIEW, FALSE);
gimp_tool_gui_set_response_sensitive (fg_select->gui, RESPONSE_APPLY, FALSE);
}
else
{
gimp_tool_gui_set_response_sensitive (fg_select->gui, RESPONSE_PREVIEW, TRUE);
gimp_tool_gui_set_response_sensitive (fg_select->gui, RESPONSE_APPLY, TRUE);
}
}
static void
gimp_foreground_select_tool_motion (GimpTool *tool,
const GimpCoords *coords,
@ -814,18 +920,21 @@ static void
gimp_foreground_select_tool_apply (GimpForegroundSelectTool *fg_select,
GimpDisplay *display)
{
GimpTool *tool = GIMP_TOOL (fg_select);
GimpImage *image = gimp_display_get_image (display);
GimpLayer *layer = gimp_image_get_active_layer (image);
GimpLayerMask *layer_mask;
GimpRGB color = { 0.0, 0.0, 0.0, GIMP_OPACITY_OPAQUE };
GimpTool *tool = GIMP_TOOL (fg_select);
GimpSelectionOptions *options = GIMP_SELECTION_TOOL_GET_OPTIONS (fg_select);
GimpImage *image = gimp_display_get_image (display);
g_return_if_fail (fg_select->mask != NULL);
layer_mask = gimp_layer_mask_new_from_buffer (fg_select->mask, image,
"mask", &color);
gimp_layer_add_mask (layer, layer_mask, TRUE, NULL);
gimp_channel_select_buffer (gimp_image_get_mask (image),
C_("command", "Foreground Select"),
fg_select->mask,
0, /* x offset */
0, /* y offset */
options->operation,
options->feather,
options->feather_radius,
options->feather_radius);
gimp_tool_control (tool, GIMP_TOOL_ACTION_HALT, display);
@ -839,6 +948,7 @@ gimp_foreground_select_tool_stroke_paint (GimpForegroundSelectTool *fg_select
{
GimpScanConvert *scan_convert;
gint width;
gdouble opacity;
g_return_if_fail (fg_select->stroke != NULL);
@ -870,9 +980,16 @@ gimp_foreground_select_tool_stroke_paint (GimpForegroundSelectTool *fg_select
GIMP_JOIN_ROUND, GIMP_CAP_ROUND, 10.0,
0.0, NULL);
if (options->draw_mode == GIMP_MATTING_DRAW_MODE_FOREGROUND)
opacity = 1.0;
else if (options->draw_mode == GIMP_MATTING_DRAW_MODE_BACKGROUND)
opacity = 0.0;
else
opacity = 0.5;
gimp_scan_convert_compose_value (scan_convert, fg_select->trimap,
0, 0,
gimp_foreground_select_options_get_opacity (options));
opacity);
gimp_scan_convert_free (scan_convert);

View File

@ -52,6 +52,7 @@ struct _GimpForegroundSelectTool
GeglBuffer *trimap;
GeglBuffer *mask;
MattingState state;
GimpToolGui *gui;
};
struct _GimpForegroundSelectToolClass