static void gimp_region_select_tool_button_press (GimpTool *tool, GimpCoords *coords, guint32 time, GdkModifierType state, GimpDisplay *display) { GimpRegionSelectTool *region_sel = GIMP_REGION_SELECT_TOOL (tool); GimpRegionSelectOptions *options = GIMP_REGION_SELECT_TOOL_GET_OPTIONS (tool); region_sel->x = coords->x; region_sel->y = coords->y; region_sel->saved_threshold = options->threshold; gimp_tool_control_activate (tool->control); tool->display = display; if (gimp_selection_tool_start_edit (GIMP_SELECTION_TOOL (region_sel), coords)) return; gimp_tool_push_status (tool, display, _("Move the mouse to change threshold")); /* calculate the region boundary */ region_sel->segs = gimp_region_select_tool_calculate (region_sel, display, ®ion_sel->num_segs); gimp_draw_tool_start (GIMP_DRAW_TOOL (tool), display); }
static void gimp_foreground_select_tool_cursor_update (GimpTool *tool, const GimpCoords *coords, GdkModifierType state, GimpDisplay *display) { GimpForegroundSelectTool *fg_select = GIMP_FOREGROUND_SELECT_TOOL (tool); if (fg_select->mask) { GimpForegroundSelectOptions *options; options = GIMP_FOREGROUND_SELECT_TOOL_GET_OPTIONS (tool); gimp_tool_control_set_toggled (tool->control, options->background); switch (GIMP_SELECTION_TOOL (tool)->function) { case SELECTION_MOVE_MASK: case SELECTION_MOVE: case SELECTION_MOVE_COPY: case SELECTION_ANCHOR: return; default: break; } } GIMP_TOOL_CLASS (parent_class)->cursor_update (tool, coords, state, display); }
static void gimp_foreground_select_tool_oper_update (GimpTool *tool, const GimpCoords *coords, GdkModifierType state, gboolean proximity, GimpDisplay *display) { GimpForegroundSelectTool *fg_select = GIMP_FOREGROUND_SELECT_TOOL (tool); const gchar *status = NULL; GIMP_TOOL_CLASS (parent_class)->oper_update (tool, coords, state, proximity, display); if (fg_select->mask && display == tool->display) { GimpDrawTool *draw_tool = GIMP_DRAW_TOOL (tool); gimp_draw_tool_pause (draw_tool); fg_select->last_coords = *coords; gimp_draw_tool_resume (draw_tool); if (fg_select->strokes) status = _("Add more strokes or press Enter to accept the selection"); else status = _("Mark foreground by painting on the object to extract"); } else { if (GIMP_SELECTION_TOOL (tool)->function == SELECTION_SELECT) status = _("Roughly outline the object to extract"); } if (proximity && status) gimp_tool_replace_status (tool, display, "%s", status); }
static void gimp_foreground_select_tool_cursor_update (GimpTool *tool, const GimpCoords *coords, GdkModifierType state, GimpDisplay *display) { GimpForegroundSelectTool *fg_select = GIMP_FOREGROUND_SELECT_TOOL (tool); if (fg_select->state == MATTING_STATE_PAINT_TRIMAP) { switch (GIMP_SELECTION_TOOL (tool)->function) { case SELECTION_MOVE_MASK: case SELECTION_MOVE: case SELECTION_MOVE_COPY: case SELECTION_ANCHOR: return; default: break; } } GIMP_TOOL_CLASS (parent_class)->cursor_update (tool, coords, state, display); }
static void gimp_rectangle_select_tool_button_press (GimpTool *tool, const GimpCoords *coords, guint32 time, GdkModifierType state, GimpButtonPressType press_type, GimpDisplay *display) { GimpRectangleTool *rectangle; GimpRectangleSelectTool *rect_sel_tool; GimpDisplayShell *shell; GimpRectangleSelectToolPrivate *priv; GimpRectangleFunction function; rectangle = GIMP_RECTANGLE_TOOL (tool); rect_sel_tool = GIMP_RECTANGLE_SELECT_TOOL (tool); shell = gimp_display_get_shell (display); priv = GIMP_RECTANGLE_SELECT_TOOL_GET_PRIVATE (rect_sel_tool); if (tool->display && display != tool->display) { gimp_rectangle_tool_cancel (GIMP_RECTANGLE_TOOL (tool)); } if (gimp_selection_tool_start_edit (GIMP_SELECTION_TOOL (tool), display, coords)) { /* In some cases we want to finish the rectangle select tool * and hand over responsability to the selection tool */ gimp_rectangle_tool_execute (rectangle); gimp_rectangle_tool_control (tool, GIMP_TOOL_ACTION_HALT, display); gimp_rectangle_select_tool_update_option_defaults (rect_sel_tool, TRUE); return; } gimp_tool_control_activate (tool->control); priv->saved_show_selection = gimp_display_shell_get_show_selection (shell); /* if the shift or ctrl keys are down, we don't want to adjust, we * want to create a new rectangle, regardless of pointer loc */ if (state & (gimp_get_extend_selection_mask () | gimp_get_modify_selection_mask ())) { gimp_rectangle_tool_set_function (rectangle, GIMP_RECTANGLE_TOOL_CREATING); } gimp_rectangle_tool_button_press (tool, coords, time, state, display); priv->press_x = coords->x; priv->press_y = coords->y; /* if we have an existing rectangle in the current display, then * we have already "executed", and need to undo at this point, * unless the user has done something in the meantime */ function = gimp_rectangle_tool_get_function (rectangle); if (function == GIMP_RECTANGLE_TOOL_CREATING) { priv->use_saved_op = FALSE; } else { GimpImage *image = gimp_display_get_image (tool->display); GimpUndoStack *undo_stack = gimp_image_get_undo_stack (image); GimpUndoStack *redo_stack = gimp_image_get_redo_stack (image); GimpUndo *undo; GimpChannelOps operation; undo = gimp_undo_stack_peek (undo_stack); if (undo && priv->undo == undo) { /* prevent this change from halting the tool */ gimp_tool_control_push_preserve (tool->control, TRUE); gimp_image_undo (image); gimp_tool_control_pop_preserve (tool->control); /* we will need to redo if the user cancels or executes */ priv->redo = gimp_undo_stack_peek (redo_stack); } /* if the operation is "Replace", turn off the marching ants, because they are confusing */ operation = gimp_rectangle_select_tool_get_operation (rect_sel_tool); if (operation == GIMP_CHANNEL_OP_REPLACE) gimp_display_shell_set_show_selection (shell, FALSE); } priv->undo = NULL; }
static void gimp_selection_tool_modifier_key (GimpTool *tool, GdkModifierType key, gboolean press, GdkModifierType state, GimpDisplay *display) { GimpSelectionTool *selection_tool = GIMP_SELECTION_TOOL (tool); GimpSelectionOptions *options = GIMP_SELECTION_TOOL_GET_OPTIONS (tool); GdkModifierType extend_mask; GdkModifierType modify_mask; extend_mask = gimp_get_extend_selection_mask (); modify_mask = gimp_get_modify_selection_mask (); if (key == extend_mask || key == modify_mask || key == GDK_MOD1_MASK) { GimpChannelOps button_op = options->operation; if (press) { if (key == (state & (extend_mask | modify_mask | GDK_MOD1_MASK))) { /* first modifier pressed */ selection_tool->saved_operation = options->operation; } } else { if (! (state & (extend_mask | modify_mask | GDK_MOD1_MASK))) { /* last modifier released */ button_op = selection_tool->saved_operation; } } if (state & GDK_MOD1_MASK) { /* if alt is down, pretend that neither * shift nor control are down */ button_op = selection_tool->saved_operation; } else if (state & (extend_mask | modify_mask)) { /* else get the operation from the modifier state, but only * if there is actually a modifier pressed, so we don't * override the "last modifier released" assignment above */ button_op = gimp_modifiers_to_channel_op (state); } if (button_op != options->operation) { g_object_set (options, "operation", button_op, NULL); } } }
static void gimp_selection_tool_cursor_update (GimpTool *tool, const GimpCoords *coords, GdkModifierType state, GimpDisplay *display) { GimpSelectionTool *selection_tool = GIMP_SELECTION_TOOL (tool); GimpSelectionOptions *options; GimpToolCursorType tool_cursor; GimpCursorModifier modifier; options = GIMP_SELECTION_TOOL_GET_OPTIONS (tool); tool_cursor = gimp_tool_control_get_tool_cursor (tool->control); modifier = GIMP_CURSOR_MODIFIER_NONE; switch (selection_tool->function) { case SELECTION_SELECT: switch (options->operation) { case GIMP_CHANNEL_OP_REPLACE: break; case GIMP_CHANNEL_OP_ADD: modifier = GIMP_CURSOR_MODIFIER_PLUS; break; case GIMP_CHANNEL_OP_SUBTRACT: modifier = GIMP_CURSOR_MODIFIER_MINUS; break; case GIMP_CHANNEL_OP_INTERSECT: modifier = GIMP_CURSOR_MODIFIER_INTERSECT; break; } break; case SELECTION_MOVE_MASK: modifier = GIMP_CURSOR_MODIFIER_MOVE; break; case SELECTION_MOVE: case SELECTION_MOVE_COPY: tool_cursor = GIMP_TOOL_CURSOR_MOVE; break; case SELECTION_ANCHOR: modifier = GIMP_CURSOR_MODIFIER_ANCHOR; break; } /* we don't set the bad modifier ourselves, so a subclass has set * it, always leave it there since it's more important than what we * have to say. */ if (gimp_tool_control_get_cursor_modifier (tool->control) == GIMP_CURSOR_MODIFIER_BAD) { modifier = GIMP_CURSOR_MODIFIER_BAD; } gimp_tool_set_cursor (tool, display, gimp_tool_control_get_cursor (tool->control), tool_cursor, modifier); }
static void gimp_selection_tool_oper_update (GimpTool *tool, const GimpCoords *coords, GdkModifierType state, gboolean proximity, GimpDisplay *display) { GimpSelectionTool *selection_tool = GIMP_SELECTION_TOOL (tool); GimpSelectionOptions *options = GIMP_SELECTION_TOOL_GET_OPTIONS (tool); GimpImage *image; GimpChannel *selection; GimpDrawable *drawable; GimpLayer *layer; GimpLayer *floating_sel; GdkModifierType extend_mask; GdkModifierType modify_mask; gboolean move_layer = FALSE; gboolean move_floating_sel = FALSE; gboolean selection_empty; image = gimp_display_get_image (display); selection = gimp_image_get_mask (image); drawable = gimp_image_get_active_drawable (image); layer = gimp_image_pick_layer (image, coords->x, coords->y); floating_sel = gimp_image_get_floating_selection (image); extend_mask = gimp_get_extend_selection_mask (); modify_mask = gimp_get_modify_selection_mask (); if (drawable) { if (floating_sel) { if (layer == floating_sel) move_floating_sel = TRUE; } else if (gimp_item_mask_intersect (GIMP_ITEM (drawable), NULL, NULL, NULL, NULL)) { move_layer = TRUE; } } selection_empty = gimp_channel_is_empty (selection); selection_tool->function = SELECTION_SELECT; if (selection_tool->allow_move && (state & GDK_MOD1_MASK) && (state & modify_mask) && move_layer) { /* move the selection */ selection_tool->function = SELECTION_MOVE; } else if (selection_tool->allow_move && (state & GDK_MOD1_MASK) && (state & extend_mask) && move_layer) { /* move a copy of the selection */ selection_tool->function = SELECTION_MOVE_COPY; } else if (selection_tool->allow_move && (state & GDK_MOD1_MASK) && ! selection_empty) { /* move the selection mask */ selection_tool->function = SELECTION_MOVE_MASK; } else if (selection_tool->allow_move && ! (state & (extend_mask | modify_mask)) && move_floating_sel) { /* move the selection */ selection_tool->function = SELECTION_MOVE; } else if ((state & modify_mask) || (state & extend_mask)) { /* select */ selection_tool->function = SELECTION_SELECT; } else if (floating_sel) { /* anchor the selection */ selection_tool->function = SELECTION_ANCHOR; } gimp_tool_pop_status (tool, display); if (proximity) { const gchar *status = NULL; gboolean free_status = FALSE; GdkModifierType modifiers = (extend_mask | modify_mask); if (! selection_empty) modifiers |= GDK_MOD1_MASK; switch (selection_tool->function) { case SELECTION_SELECT: switch (options->operation) { case GIMP_CHANNEL_OP_REPLACE: if (! selection_empty) { status = gimp_suggest_modifiers (_("Click-Drag to replace the " "current selection"), modifiers & ~state, NULL, NULL, NULL); free_status = TRUE; } else { status = _("Click-Drag to create a new selection"); } break; case GIMP_CHANNEL_OP_ADD: status = gimp_suggest_modifiers (_("Click-Drag to add to the " "current selection"), modifiers & ~(state | extend_mask), NULL, NULL, NULL); free_status = TRUE; break; case GIMP_CHANNEL_OP_SUBTRACT: status = gimp_suggest_modifiers (_("Click-Drag to subtract from the " "current selection"), modifiers & ~(state | modify_mask), NULL, NULL, NULL); free_status = TRUE; break; case GIMP_CHANNEL_OP_INTERSECT: status = gimp_suggest_modifiers (_("Click-Drag to intersect with " "the current selection"), modifiers & ~state, NULL, NULL, NULL); free_status = TRUE; break; } break; case SELECTION_MOVE_MASK: status = gimp_suggest_modifiers (_("Click-Drag to move the " "selection mask"), modifiers & ~state, NULL, NULL, NULL); free_status = TRUE; break; case SELECTION_MOVE: status = _("Click-Drag to move the selected pixels"); break; case SELECTION_MOVE_COPY: status = _("Click-Drag to move a copy of the selected pixels"); break; case SELECTION_ANCHOR: status = _("Click to anchor the floating selection"); break; default: g_return_if_reached (); } if (status) gimp_tool_push_status (tool, display, "%s", status); if (free_status) g_free ((gchar *) status); } }
static void gimp_region_select_tool_button_release (GimpTool *tool, GimpCoords *coords, guint32 time, GdkModifierType state, GimpButtonReleaseType release_type, GimpDisplay *display) { GimpRegionSelectTool *region_sel = GIMP_REGION_SELECT_TOOL (tool); GimpSelectionOptions *sel_options = GIMP_SELECTION_TOOL_GET_OPTIONS (tool); GimpRegionSelectOptions *options = GIMP_REGION_SELECT_TOOL_GET_OPTIONS (tool); gimp_tool_pop_status (tool, display); gimp_draw_tool_stop (GIMP_DRAW_TOOL (tool)); gimp_tool_control_halt (tool->control); if (release_type != GIMP_BUTTON_RELEASE_CANCEL) { gint off_x, off_y; if (GIMP_SELECTION_TOOL (tool)->function == SELECTION_ANCHOR) { if (gimp_image_floating_sel (display->image)) { /* If there is a floating selection, anchor it */ floating_sel_anchor (gimp_image_floating_sel (display->image)); } else { /* Otherwise, clear the selection mask */ gimp_channel_clear (gimp_image_get_mask (display->image), NULL, TRUE); } gimp_image_flush (display->image); } else if (region_sel->region_mask) { if (options->sample_merged) { off_x = 0; off_y = 0; } else { GimpDrawable *drawable; drawable = gimp_image_get_active_drawable (display->image); gimp_item_offsets (GIMP_ITEM (drawable), &off_x, &off_y); } gimp_channel_select_channel (gimp_image_get_mask (display->image), GIMP_REGION_SELECT_TOOL_GET_CLASS (tool)->undo_desc, region_sel->region_mask, off_x, off_y, sel_options->operation, sel_options->feather, sel_options->feather_radius, sel_options->feather_radius); gimp_image_flush (display->image); } } if (region_sel->region_mask) { g_object_unref (region_sel->region_mask); region_sel->region_mask = NULL; } if (region_sel->segs) { g_free (region_sel->segs); region_sel->segs = NULL; region_sel->num_segs = 0; } /* Restore the original threshold */ g_object_set (options, "threshold", region_sel->saved_threshold, NULL); }
static void gimp_selection_tool_modifier_key (GimpTool *tool, GdkModifierType key, gboolean press, GdkModifierType state, GimpDisplay *display) { GimpSelectionTool *selection_tool = GIMP_SELECTION_TOOL (tool); GimpSelectionOptions *options; options = GIMP_SELECTION_TOOL_GET_OPTIONS (tool); if (key == GDK_SHIFT_MASK || key == GDK_CONTROL_MASK || key == GDK_MOD1_MASK) { GimpChannelOps button_op = options->operation; if (press) { if (key == (state & (GDK_SHIFT_MASK | GDK_CONTROL_MASK | GDK_MOD1_MASK))) { /* first modifier pressed */ selection_tool->saved_operation = options->operation; } } else { if (! (state & (GDK_SHIFT_MASK | GDK_CONTROL_MASK | GDK_MOD1_MASK))) { /* last modifier released */ button_op = selection_tool->saved_operation; } } if (state & GDK_MOD1_MASK) { /* if alt is down, pretend that neither * shift nor control are down */ button_op = selection_tool->saved_operation; } else if ((state & GDK_CONTROL_MASK) && (state & GDK_SHIFT_MASK)) { button_op = GIMP_CHANNEL_OP_INTERSECT; } else if (state & GDK_SHIFT_MASK) { button_op = GIMP_CHANNEL_OP_ADD; } else if (state & GDK_CONTROL_MASK) { button_op = GIMP_CHANNEL_OP_SUBTRACT; } if (button_op != options->operation) { g_object_set (options, "operation", button_op, NULL); } } }
static void gimp_foreground_select_tool_oper_update (GimpTool *tool, const GimpCoords *coords, GdkModifierType state, gboolean proximity, GimpDisplay *display) { GimpForegroundSelectTool *fg_select = GIMP_FOREGROUND_SELECT_TOOL (tool); GimpForegroundSelectOptions *options = GIMP_FOREGROUND_SELECT_TOOL_GET_OPTIONS (fg_select); const gchar *status_stage = NULL; const gchar *status_mode = 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); if (fg_select->state == MATTING_STATE_FREE_SELECT) { if (GIMP_SELECTION_TOOL (tool)->function == SELECTION_SELECT) status_stage = _("Roughly outline the object to extract"); } else { GimpDrawTool *draw_tool = GIMP_DRAW_TOOL (tool); gimp_draw_tool_pause (draw_tool); fg_select->last_coords = *coords; gimp_draw_tool_resume (draw_tool); if (options->draw_mode == GIMP_MATTING_DRAW_MODE_FOREGROUND) status_mode = _("Selecting foreground, "); else if (options->draw_mode == GIMP_MATTING_DRAW_MODE_BACKGROUND) status_mode = _("Selecting background, "); else status_mode = _("Selecting unknown, "); if (fg_select->state == MATTING_STATE_PAINT_TRIMAP) status_stage = _("press Enter to preview."); else status_stage = _("press Escape to exit preview or Enter to apply."); } if (proximity && status_stage) { if (status_mode) gimp_tool_replace_status (tool, display, "%s%s", status_mode, status_stage); else gimp_tool_replace_status (tool, display, "%s", status_stage); } 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); }