static void gimp_source_tool_button_press (GimpTool *tool, const GimpCoords *coords, guint32 time, GdkModifierType state, GimpButtonPressType press_type, GimpDisplay *display) { GimpPaintTool *paint_tool = GIMP_PAINT_TOOL (tool); GimpSourceTool *source_tool = GIMP_SOURCE_TOOL (tool); GimpSourceCore *source = GIMP_SOURCE_CORE (paint_tool->core); GdkModifierType extend_mask = gimp_get_extend_selection_mask (); GdkModifierType toggle_mask = gimp_get_toggle_behavior_mask (); gimp_draw_tool_pause (GIMP_DRAW_TOOL (tool)); if ((state & (toggle_mask | extend_mask)) == toggle_mask) { source->set_source = TRUE; gimp_source_tool_set_src_display (source_tool, display); } else { source->set_source = FALSE; } GIMP_TOOL_CLASS (parent_class)->button_press (tool, coords, time, state, press_type, display); source_tool->src_x = source->src_x; source_tool->src_y = source->src_y; gimp_draw_tool_resume (GIMP_DRAW_TOOL (tool)); }
static void gimp_bucket_fill_tool_modifier_key (GimpTool *tool, GdkModifierType key, gboolean press, GdkModifierType state, GimpDisplay *display) { GimpBucketFillOptions *options = GIMP_BUCKET_FILL_TOOL_GET_OPTIONS (tool); if (key == gimp_get_toggle_behavior_mask ()) { switch (options->fill_mode) { case GIMP_BUCKET_FILL_FG: g_object_set (options, "fill-mode", GIMP_BUCKET_FILL_BG, NULL); break; case GIMP_BUCKET_FILL_BG: g_object_set (options, "fill-mode", GIMP_BUCKET_FILL_FG, NULL); break; default: break; } } else if (key == gimp_get_extend_selection_mask ()) { g_object_set (options, "fill-selection", ! options->fill_selection, NULL); } }
static void gimp_source_tool_cursor_update (GimpTool *tool, const GimpCoords *coords, GdkModifierType state, GimpDisplay *display) { GimpPaintTool *paint_tool = GIMP_PAINT_TOOL (tool); GimpSourceOptions *options = GIMP_SOURCE_TOOL_GET_OPTIONS (tool); GimpCursorType cursor = GIMP_CURSOR_MOUSE; GimpCursorModifier modifier = GIMP_CURSOR_MODIFIER_NONE; if (gimp_source_core_use_source (GIMP_SOURCE_CORE (paint_tool->core), options)) { GdkModifierType extend_mask = gimp_get_extend_selection_mask (); GdkModifierType toggle_mask = gimp_get_toggle_behavior_mask (); if ((state & (toggle_mask | extend_mask)) == toggle_mask) { cursor = GIMP_CURSOR_CROSSHAIR_SMALL; } else if (! GIMP_SOURCE_CORE (GIMP_PAINT_TOOL (tool)->core)->src_drawable) { modifier = GIMP_CURSOR_MODIFIER_BAD; } } gimp_tool_control_set_cursor (tool->control, cursor); gimp_tool_control_set_cursor_modifier (tool->control, modifier); GIMP_TOOL_CLASS (parent_class)->cursor_update (tool, coords, state, display); }
static void gimp_align_tool_oper_update (GimpTool *tool, const GimpCoords *coords, GdkModifierType state, gboolean proximity, GimpDisplay *display) { GimpAlignTool *align_tool = GIMP_ALIGN_TOOL (tool); GimpDisplayShell *shell = gimp_display_get_shell (display); GimpImage *image = gimp_display_get_image (display); gint snap_distance = display->config->snap_distance; gboolean add; add = ((state & gimp_get_extend_selection_mask ()) && align_tool->selected_objects); if (gimp_draw_tool_on_vectors (GIMP_DRAW_TOOL (tool), display, coords, snap_distance, snap_distance, NULL, NULL, NULL, NULL, NULL, NULL)) { if (add) align_tool->function = ALIGN_TOOL_ADD_PATH; else align_tool->function = ALIGN_TOOL_PICK_PATH; } else if (gimp_display_shell_get_show_guides (shell) && gimp_image_find_guide (image, coords->x, coords->y, FUNSCALEX (shell, snap_distance), FUNSCALEY (shell, snap_distance))) { if (add) align_tool->function = ALIGN_TOOL_ADD_GUIDE; else align_tool->function = ALIGN_TOOL_PICK_GUIDE; } else { GimpLayer *layer; layer = gimp_image_pick_layer_by_bounds (image, coords->x, coords->y); if (layer) { if (add) align_tool->function = ALIGN_TOOL_ADD_LAYER; else align_tool->function = ALIGN_TOOL_PICK_LAYER; } else { align_tool->function = ALIGN_TOOL_IDLE; } } gimp_align_tool_status_update (tool, display, state, proximity); }
static void gimp_curves_tool_button_release (GimpTool *tool, const GimpCoords *coords, guint32 time, GdkModifierType state, GimpButtonReleaseType release_type, GimpDisplay *display) { GimpCurvesTool *c_tool = GIMP_CURVES_TOOL (tool); GimpImageMapTool *im_tool = GIMP_IMAGE_MAP_TOOL (tool); GimpCurvesConfig *config = GIMP_CURVES_CONFIG (im_tool->config); if (state & gimp_get_extend_selection_mask ()) { GimpCurve *curve = config->curve[config->channel]; gdouble value = c_tool->picked_color[config->channel]; gint closest; closest = gimp_curve_get_closest_point (curve, value); gimp_curve_view_set_selected (GIMP_CURVE_VIEW (c_tool->graph), closest); gimp_curve_set_point (curve, closest, value, gimp_curve_map_value (curve, value)); } else if (state & gimp_get_toggle_behavior_mask ()) { GimpHistogramChannel channel; for (channel = GIMP_HISTOGRAM_VALUE; channel <= GIMP_HISTOGRAM_ALPHA; channel++) { GimpCurve *curve = config->curve[channel]; gdouble value = c_tool->picked_color[channel]; gint closest; if (value != -1) { closest = gimp_curve_get_closest_point (curve, value); gimp_curve_view_set_selected (GIMP_CURVE_VIEW (c_tool->graph), closest); gimp_curve_set_point (curve, closest, value, gimp_curve_map_value (curve, value)); } } } /* chain up to halt the tool */ GIMP_TOOL_CLASS (parent_class)->button_release (tool, coords, time, state, release_type, display); }
static void gimp_curves_tool_oper_update (GimpTool *tool, const GimpCoords *coords, GdkModifierType state, gboolean proximity, GimpDisplay *display) { if (gimp_image_map_tool_on_guide (GIMP_IMAGE_MAP_TOOL (tool), coords, display)) { GIMP_TOOL_CLASS (parent_class)->oper_update (tool, coords, state, proximity, display); } else { GimpColorPickMode mode; gchar *status = NULL; GdkModifierType extend_mask = gimp_get_extend_selection_mask (); GdkModifierType toggle_mask = gimp_get_toggle_behavior_mask (); gimp_tool_pop_status (tool, display); if (state & extend_mask) { mode = GIMP_COLOR_PICK_MODE_PALETTE; status = g_strdup (_("Click to add a control point")); } else if (state & toggle_mask) { mode = GIMP_COLOR_PICK_MODE_PALETTE; status = g_strdup (_("Click to add control points to all channels")); } else { mode = GIMP_COLOR_PICK_MODE_NONE; status = gimp_suggest_modifiers (_("Click to locate on curve"), (extend_mask | toggle_mask) & ~state, _("%s: add control point"), _("%s: add control points to all channels"), NULL); } GIMP_COLOR_TOOL (tool)->pick_mode = mode; if (proximity) gimp_tool_push_status (tool, display, "%s", status); g_free (status); } }
static void gimp_image_map_tool_oper_update (GimpTool *tool, const GimpCoords *coords, GdkModifierType state, gboolean proximity, GimpDisplay *display) { GimpImageMapTool *im_tool = GIMP_IMAGE_MAP_TOOL (tool); gimp_tool_pop_status (tool, display); if (! gimp_image_map_tool_on_guide (im_tool, coords, display)) { GIMP_TOOL_CLASS (parent_class)->oper_update (tool, coords, state, proximity, display); } else { GdkModifierType extend_mask = gimp_get_extend_selection_mask (); GdkModifierType toggle_mask = gimp_get_toggle_behavior_mask (); gchar *status = NULL; if (state & extend_mask) { status = g_strdup (_("Click to switch the original and filtered sides")); } else if (state & toggle_mask) { status = g_strdup (_("Click to switch between vertical and horizontal")); } else { status = gimp_suggest_modifiers (_("Click to move the split guide"), (extend_mask | toggle_mask) & ~state, _("%s: switch original and filtered"), _("%s: switch horizontal and vertical"), NULL); } if (proximity) gimp_tool_push_status (tool, display, "%s", status); g_free (status); } }
static void gimp_align_tool_cursor_update (GimpTool *tool, const GimpCoords *coords, GdkModifierType state, GimpDisplay *display) { GimpAlignTool *align_tool = GIMP_ALIGN_TOOL (tool); GimpToolCursorType tool_cursor = GIMP_TOOL_CURSOR_NONE; GimpCursorModifier modifier = GIMP_CURSOR_MODIFIER_NONE; /* always add '+' when Shift is pressed, even if nothing is selected */ if (state & gimp_get_extend_selection_mask ()) modifier = GIMP_CURSOR_MODIFIER_PLUS; switch (align_tool->function) { case ALIGN_TOOL_IDLE: tool_cursor = GIMP_TOOL_CURSOR_RECT_SELECT; break; case ALIGN_TOOL_PICK_LAYER: case ALIGN_TOOL_ADD_LAYER: tool_cursor = GIMP_TOOL_CURSOR_HAND; break; case ALIGN_TOOL_PICK_GUIDE: case ALIGN_TOOL_ADD_GUIDE: tool_cursor = GIMP_TOOL_CURSOR_MOVE; break; case ALIGN_TOOL_PICK_PATH: case ALIGN_TOOL_ADD_PATH: tool_cursor = GIMP_TOOL_CURSOR_PATHS; break; case ALIGN_TOOL_DRAG_BOX: break; } gimp_tool_control_set_cursor (tool->control, GIMP_CURSOR_MOUSE); gimp_tool_control_set_tool_cursor (tool->control, tool_cursor); gimp_tool_control_set_cursor_modifier (tool->control, modifier); GIMP_TOOL_CLASS (parent_class)->cursor_update (tool, coords, state, display); }
static void gimp_rectangle_select_tool_cursor_update (GimpTool *tool, const GimpCoords *coords, GdkModifierType state, GimpDisplay *display) { gimp_rectangle_tool_cursor_update (tool, coords, state, display); /* override the previous if shift or ctrl are down */ if (state & (gimp_get_extend_selection_mask () | gimp_get_modify_selection_mask ())) { gimp_tool_control_set_cursor (tool->control, GIMP_CURSOR_CROSSHAIR_SMALL); } 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; }
GtkWidget * gimp_bucket_fill_options_gui (GimpToolOptions *tool_options) { GObject *config = G_OBJECT (tool_options); GtkWidget *vbox = gimp_paint_options_gui (tool_options); GtkWidget *vbox2; GtkWidget *frame; GtkWidget *hbox; GtkWidget *button; GtkWidget *scale; GtkWidget *combo; gchar *str; GdkModifierType extend_mask = gimp_get_extend_selection_mask (); GdkModifierType toggle_mask = gimp_get_toggle_behavior_mask (); /* fill type */ str = g_strdup_printf (_("Fill Type (%s)"), gimp_get_mod_string (toggle_mask)), frame = gimp_prop_enum_radio_frame_new (config, "fill-mode", str, 0, 0); g_free (str); gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0); gtk_widget_show (frame); hbox = gimp_prop_pattern_box_new (NULL, GIMP_CONTEXT (tool_options), NULL, 2, "pattern-view-type", "pattern-view-size"); gimp_enum_radio_frame_add (GTK_FRAME (frame), hbox, GIMP_BUCKET_FILL_PATTERN, TRUE); /* fill selection */ str = g_strdup_printf (_("Affected Area (%s)"), gimp_get_mod_string (extend_mask)); frame = gimp_prop_boolean_radio_frame_new (config, "fill-selection", str, _("Fill whole selection"), _("Fill similar colors")); g_free (str); gtk_box_reorder_child (GTK_BOX (gtk_bin_get_child (GTK_BIN (frame))), g_object_get_data (G_OBJECT (frame), "radio-button"), 1); gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0); gtk_widget_show (frame); frame = gimp_frame_new (_("Finding Similar Colors")); gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0); gtk_widget_show (frame); g_object_bind_property (config, "fill-selection", frame, "sensitive", G_BINDING_SYNC_CREATE | G_BINDING_INVERT_BOOLEAN); vbox2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0); gtk_container_add (GTK_CONTAINER (frame), vbox2); gtk_widget_show (vbox2); /* the fill transparent areas toggle */ button = gimp_prop_check_button_new (config, "fill-transparent", NULL); gtk_box_pack_start (GTK_BOX (vbox2), button, FALSE, FALSE, 0); gtk_widget_show (button); /* the sample merged toggle */ button = gimp_prop_check_button_new (config, "sample-merged", NULL); gtk_box_pack_start (GTK_BOX (vbox2), button, FALSE, FALSE, 0); gtk_widget_show (button); /* the diagonal neighbors toggle */ button = gimp_prop_check_button_new (config, "diagonal-neighbors", NULL); gtk_box_pack_start (GTK_BOX (vbox2), button, FALSE, FALSE, 0); gtk_widget_show (button); /* the threshold scale */ scale = gimp_prop_spin_scale_new (config, "threshold", NULL, 1.0, 16.0, 1); gtk_box_pack_start (GTK_BOX (vbox2), scale, FALSE, FALSE, 0); gtk_widget_show (scale); /* the fill criterion combo */ combo = gimp_prop_enum_combo_box_new (config, "fill-criterion", 0, 0); gimp_int_combo_box_set_label (GIMP_INT_COMBO_BOX (combo), _("Fill by")); gtk_box_pack_start (GTK_BOX (vbox2), combo, FALSE, FALSE, 0); gtk_widget_show (combo); return vbox; }
static void gimp_n_point_deformation_tool_button_press (GimpTool *tool, const GimpCoords *coords, guint32 time, GdkModifierType state, GimpButtonPressType press_type, GimpDisplay *display) { GimpNPointDeformationTool *npd_tool = GIMP_N_POINT_DEFORMATION_TOOL (tool); if (display != tool->display) { /* this is the first click on the drawable - just start the tool */ gimp_n_point_deformation_tool_start (npd_tool, display); } npd_tool->selected_cp = NULL; if (press_type == GIMP_BUTTON_PRESS_NORMAL) { NPDControlPoint *cp = npd_tool->hovering_cp; if (cp) { /* there is a control point at cursor's position */ npd_tool->selected_cp = cp; if (! g_list_find (npd_tool->selected_cps, cp)) { /* control point isn't selected, so we can add it to the * list of selected control points */ if (! (state & gimp_get_extend_selection_mask ())) { /* <SHIFT> isn't pressed, so this isn't a * multiselection - clear the list of selected * control points */ gimp_n_point_deformation_tool_clear_selected_points_list (npd_tool); } gimp_n_point_deformation_tool_add_cp_to_selection (npd_tool, cp); } else if (state & gimp_get_extend_selection_mask ()) { /* control point is selected and <SHIFT> is pressed - * remove control point from selected points */ gimp_n_point_deformation_tool_remove_cp_from_selection (npd_tool, cp); } } npd_tool->start_x = coords->x; npd_tool->start_y = coords->y; npd_tool->last_x = coords->x; npd_tool->last_y = coords->y; } gimp_tool_control_activate (tool->control); }
static void gimp_n_point_deformation_tool_button_release (GimpTool *tool, const GimpCoords *coords, guint32 time, GdkModifierType state, GimpButtonReleaseType release_type, GimpDisplay *display) { GimpNPointDeformationTool *npd_tool = GIMP_N_POINT_DEFORMATION_TOOL (tool); gimp_tool_control_halt (tool->control); gimp_draw_tool_pause (GIMP_DRAW_TOOL (npd_tool)); if (release_type == GIMP_BUTTON_RELEASE_CLICK) { if (! npd_tool->hovering_cp) { NPDPoint p; gimp_npd_debug (("cp doesn't exist, adding\n")); p.x = coords->x - npd_tool->offset_x; p.y = coords->y - npd_tool->offset_y; npd_add_control_point (npd_tool->model, &p); } } else if (release_type == GIMP_BUTTON_RELEASE_NORMAL) { if (npd_tool->rubber_band) { GArray *cps = npd_tool->model->control_points; gint x0 = MIN (npd_tool->start_x, npd_tool->cursor_x); gint y0 = MIN (npd_tool->start_y, npd_tool->cursor_y); gint x1 = MAX (npd_tool->start_x, npd_tool->cursor_x); gint y1 = MAX (npd_tool->start_y, npd_tool->cursor_y); gint i; if (! (state & gimp_get_extend_selection_mask ())) { /* <SHIFT> isn't pressed, so we want a clear selection */ gimp_n_point_deformation_tool_clear_selected_points_list (npd_tool); } for (i = 0; i < cps->len; i++) { NPDControlPoint *cp = &g_array_index (cps, NPDControlPoint, i); if (gimp_n_point_deformation_tool_is_cp_in_area (cp, x0, y0, x1, y1, npd_tool->offset_x, npd_tool->offset_y, npd_tool->cp_scaled_radius)) { /* control point is situated in an area defined by * rubber band */ gimp_n_point_deformation_tool_add_cp_to_selection (npd_tool, cp); gimp_npd_debug (("%p selected\n", cp)); } } } } else if (release_type == GIMP_BUTTON_RELEASE_CANCEL) { gimp_npd_debug (("gimp_button_release_cancel\n")); } npd_tool->rubber_band = FALSE; gimp_draw_tool_resume (GIMP_DRAW_TOOL (npd_tool)); }
static void gimp_perspective_clone_tool_button_press (GimpTool *tool, const GimpCoords *coords, guint32 time, GdkModifierType state, GimpButtonPressType press_type, GimpDisplay *display) { GimpPaintTool *paint_tool = GIMP_PAINT_TOOL (tool); GimpPerspectiveCloneTool *clone_tool = GIMP_PERSPECTIVE_CLONE_TOOL (tool); GimpPerspectiveClone *clone = GIMP_PERSPECTIVE_CLONE (paint_tool->core); GimpSourceCore *source_core = GIMP_SOURCE_CORE (clone); GimpPerspectiveCloneOptions *options; options = GIMP_PERSPECTIVE_CLONE_TOOL_GET_OPTIONS (tool); if (options->clone_mode == GIMP_PERSPECTIVE_CLONE_MODE_ADJUST) { if (clone_tool->widget) { gimp_tool_widget_hover (clone_tool->widget, coords, state, TRUE); if (gimp_tool_widget_button_press (clone_tool->widget, coords, time, state, press_type)) { clone_tool->grab_widget = clone_tool->widget; } } gimp_tool_control_activate (tool->control); } else { GdkModifierType extend_mask = gimp_get_extend_selection_mask (); GdkModifierType toggle_mask = gimp_get_toggle_behavior_mask (); gdouble nnx, nny; gimp_draw_tool_pause (GIMP_DRAW_TOOL (tool)); if ((state & (toggle_mask | extend_mask)) == toggle_mask) { source_core->set_source = TRUE; clone_tool->src_display = display; } else { source_core->set_source = FALSE; } GIMP_TOOL_CLASS (parent_class)->button_press (tool, coords, time, state, press_type, display); /* Set the coordinates for the reference cross */ gimp_perspective_clone_get_source_point (clone, coords->x, coords->y, &nnx, &nny); clone_tool->src_x = floor (nnx); clone_tool->src_y = floor (nny); gimp_draw_tool_resume (GIMP_DRAW_TOOL (tool)); } }
static void gimp_align_tool_status_update (GimpTool *tool, GimpDisplay *display, GdkModifierType state, gboolean proximity) { GimpAlignTool *align_tool = GIMP_ALIGN_TOOL (tool); GdkModifierType extend_mask; extend_mask = gimp_get_extend_selection_mask (); gimp_tool_pop_status (tool, display); if (proximity) { gchar *status = NULL; if (! align_tool->selected_objects) { /* no need to suggest Shift if nothing is selected */ state |= extend_mask; } switch (align_tool->function) { case ALIGN_TOOL_IDLE: status = gimp_suggest_modifiers (_("Click on a layer, path or guide, " "or Click-Drag to pick several " "layers"), extend_mask & ~state, NULL, NULL, NULL); break; case ALIGN_TOOL_PICK_LAYER: status = gimp_suggest_modifiers (_("Click to pick this layer as " "first item"), extend_mask & ~state, NULL, NULL, NULL); break; case ALIGN_TOOL_ADD_LAYER: status = g_strdup (_("Click to add this layer to the list")); break; case ALIGN_TOOL_PICK_GUIDE: status = gimp_suggest_modifiers (_("Click to pick this guide as " "first item"), extend_mask & ~state, NULL, NULL, NULL); break; case ALIGN_TOOL_ADD_GUIDE: status = g_strdup (_("Click to add this guide to the list")); break; case ALIGN_TOOL_PICK_PATH: status = gimp_suggest_modifiers (_("Click to pick this path as " "first item"), extend_mask & ~state, NULL, NULL, NULL); break; case ALIGN_TOOL_ADD_PATH: status = g_strdup (_("Click to add this path to the list")); break; case ALIGN_TOOL_DRAG_BOX: break; } if (status) { gimp_tool_push_status (tool, display, "%s", status); g_free (status); } } }
/* some rather complex logic here. If the user clicks without modifiers, * then we start a new list, and use the first object in it as reference. * If the user clicks using Shift, or draws a rubber-band box, then * we add objects to the list, but do not specify which one should * be used as reference. */ static void gimp_align_tool_button_release (GimpTool *tool, const GimpCoords *coords, guint32 time, GdkModifierType state, GimpButtonReleaseType release_type, GimpDisplay *display) { GimpAlignTool *align_tool = GIMP_ALIGN_TOOL (tool); GimpAlignOptions *options = GIMP_ALIGN_TOOL_GET_OPTIONS (tool); GimpDisplayShell *shell = gimp_display_get_shell (display); GObject *object = NULL; GimpImage *image = gimp_display_get_image (display); GdkModifierType extend_mask; gint i; extend_mask = gimp_get_extend_selection_mask (); gimp_draw_tool_pause (GIMP_DRAW_TOOL (tool)); gimp_tool_control_halt (tool->control); if (release_type == GIMP_BUTTON_RELEASE_CANCEL) { align_tool->x2 = align_tool->x1; align_tool->y2 = align_tool->y1; gimp_draw_tool_resume (GIMP_DRAW_TOOL (tool)); return; } if (! (state & extend_mask)) /* start a new list */ { gimp_align_tool_clear_selected (align_tool); align_tool->set_reference = FALSE; } /* if mouse has moved less than EPSILON pixels since button press, * select the nearest thing, otherwise make a rubber-band rectangle */ if (hypot (coords->x - align_tool->x1, coords->y - align_tool->y1) < EPSILON) { GimpVectors *vectors; GimpGuide *guide; GimpLayer *layer; gint snap_distance = display->config->snap_distance; if (gimp_draw_tool_on_vectors (GIMP_DRAW_TOOL (tool), display, coords, snap_distance, snap_distance, NULL, NULL, NULL, NULL, NULL, &vectors)) { object = G_OBJECT (vectors); } else if (gimp_display_shell_get_show_guides (shell) && (guide = gimp_image_find_guide (image, coords->x, coords->y, FUNSCALEX (shell, snap_distance), FUNSCALEY (shell, snap_distance)))) { object = G_OBJECT (guide); } else { if ((layer = gimp_image_pick_layer_by_bounds (image, coords->x, coords->y))) { object = G_OBJECT (layer); } } if (object) { if (! g_list_find (align_tool->selected_objects, object)) { align_tool->selected_objects = g_list_append (align_tool->selected_objects, object); g_signal_connect (object, "removed", G_CALLBACK (gimp_align_tool_object_removed), align_tool); /* if an object has been selected using unmodified click, * it should be used as the reference */ if (! (state & extend_mask)) align_tool->set_reference = TRUE; } } } else /* FIXME: look for vectors too */ { gint X0 = MIN (coords->x, align_tool->x1); gint X1 = MAX (coords->x, align_tool->x1); gint Y0 = MIN (coords->y, align_tool->y1); gint Y1 = MAX (coords->y, align_tool->y1); GList *all_layers; GList *list; all_layers = gimp_image_get_layer_list (image); for (list = all_layers; list; list = g_list_next (list)) { GimpLayer *layer = list->data; gint x0, y0, x1, y1; if (! gimp_item_get_visible (GIMP_ITEM (layer))) continue; gimp_item_get_offset (GIMP_ITEM (layer), &x0, &y0); x1 = x0 + gimp_item_get_width (GIMP_ITEM (layer)); y1 = y0 + gimp_item_get_height (GIMP_ITEM (layer)); if (x0 < X0 || y0 < Y0 || x1 > X1 || y1 > Y1) continue; if (g_list_find (align_tool->selected_objects, layer)) continue; align_tool->selected_objects = g_list_append (align_tool->selected_objects, layer); g_signal_connect (layer, "removed", G_CALLBACK (gimp_align_tool_object_removed), align_tool); } g_list_free (all_layers); } for (i = 0; i < ALIGN_OPTIONS_N_BUTTONS; i++) { if (options->button[i]) gtk_widget_set_sensitive (options->button[i], align_tool->selected_objects != NULL); } align_tool->x2 = align_tool->x1; align_tool->y2 = align_tool->y1; gimp_draw_tool_resume (GIMP_DRAW_TOOL (tool)); }
static void gimp_image_map_tool_button_press (GimpTool *tool, const GimpCoords *coords, guint32 time, GdkModifierType state, GimpButtonPressType press_type, GimpDisplay *display) { GimpImageMapTool *im_tool = GIMP_IMAGE_MAP_TOOL (tool); if (! gimp_image_map_tool_on_guide (im_tool, coords, display)) { GIMP_TOOL_CLASS (parent_class)->button_press (tool, coords, time, state, press_type, display); } else { GimpImageMapOptions *options = GIMP_IMAGE_MAP_TOOL_GET_OPTIONS (tool); if (state & gimp_get_extend_selection_mask ()) { GimpAlignmentType alignment; /* switch side */ switch (options->preview_alignment) { case GIMP_ALIGN_LEFT: alignment = GIMP_ALIGN_RIGHT; break; case GIMP_ALIGN_RIGHT: alignment = GIMP_ALIGN_LEFT; break; case GIMP_ALIGN_TOP: alignment = GIMP_ALIGN_BOTTOM; break; case GIMP_ALIGN_BOTTOM: alignment = GIMP_ALIGN_TOP; break; default: g_return_if_reached (); } g_object_set (options, "preview-alignment", alignment, NULL); } else if (state & gimp_get_toggle_behavior_mask ()) { GimpItem *item = GIMP_ITEM (im_tool->drawable); GimpAlignmentType alignment; gdouble position; /* switch orientation */ switch (options->preview_alignment) { case GIMP_ALIGN_LEFT: alignment = GIMP_ALIGN_TOP; break; case GIMP_ALIGN_RIGHT: alignment = GIMP_ALIGN_BOTTOM; break; case GIMP_ALIGN_TOP: alignment = GIMP_ALIGN_LEFT; break; case GIMP_ALIGN_BOTTOM: alignment = GIMP_ALIGN_RIGHT; break; default: g_return_if_reached (); } if (alignment == GIMP_ALIGN_LEFT || alignment == GIMP_ALIGN_RIGHT) { position = ((coords->x - gimp_item_get_offset_x (item)) / gimp_item_get_width (item)); } else { position = ((coords->y - gimp_item_get_offset_y (item)) / gimp_item_get_height (item)); } g_object_set (options, "preview-alignment", alignment, "preview-position", CLAMP (position, 0.0, 1.0), NULL); } else { gimp_guide_tool_start_edit (tool, display, im_tool->percent_guide); } } }
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_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); } }
/** * gimp_transform_options_gui: * @tool_options: a #GimpToolOptions * * Build the Transform Tool Options. * * Return value: a container holding the transform tool options **/ GtkWidget * gimp_transform_options_gui (GimpToolOptions *tool_options) { GObject *config = G_OBJECT (tool_options); GtkWidget *vbox = gimp_tool_options_gui (tool_options); GtkWidget *hbox; GtkWidget *box; GtkWidget *label; GtkWidget *frame; GtkWidget *combo; GtkWidget *scale; GtkWidget *grid_box; const gchar *constrain_name = NULL; const gchar *constrain_label = NULL; const gchar *constrain_tip = NULL; hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 2); gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); gtk_widget_show (hbox); label = gtk_label_new (_("Transform:")); gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); gtk_widget_show (label); box = gimp_prop_enum_icon_box_new (config, "type", "gimp", 0, 0); gtk_box_pack_start (GTK_BOX (hbox), box, FALSE, FALSE, 0); gtk_widget_show (box); frame = gimp_prop_enum_radio_frame_new (config, "direction", _("Direction"), 0, 0); gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0); gtk_widget_show (frame); /* the interpolation menu */ combo = gimp_prop_enum_combo_box_new (config, "interpolation", 0, 0); gimp_int_combo_box_set_label (GIMP_INT_COMBO_BOX (combo), _("Interpolation")); g_object_set (combo, "ellipsize", PANGO_ELLIPSIZE_END, NULL); gtk_box_pack_start (GTK_BOX (vbox), combo, FALSE, FALSE, 0); gtk_widget_show (combo); /* the clipping menu */ combo = gimp_prop_enum_combo_box_new (config, "clip", 0, 0); gimp_int_combo_box_set_label (GIMP_INT_COMBO_BOX (combo), _("Clipping")); g_object_set (combo, "ellipsize", PANGO_ELLIPSIZE_END, NULL); gtk_box_pack_start (GTK_BOX (vbox), combo, FALSE, FALSE, 0); gtk_widget_show (combo); /* the preview frame */ scale = gimp_prop_spin_scale_new (config, "preview-opacity", _("Image opacity"), 0.01, 0.1, 0); gimp_prop_widget_set_factor (scale, 100.0, 0.0, 0.0, 1); frame = gimp_prop_expanding_frame_new (config, "show-preview", _("Show image preview"), scale, NULL); gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0); gtk_widget_show (frame); /* the guides frame */ frame = gimp_frame_new (NULL); gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0); gtk_widget_show (frame); /* the guides type menu */ combo = gimp_prop_enum_combo_box_new (config, "grid-type", 0, 0); gimp_int_combo_box_set_label (GIMP_INT_COMBO_BOX (combo), _("Guides")); g_object_set (combo, "ellipsize", PANGO_ELLIPSIZE_END, NULL); gtk_frame_set_label_widget (GTK_FRAME (frame), combo); gtk_widget_show (combo); /* the grid density scale */ scale = gimp_prop_spin_scale_new (config, "grid-size", NULL, 1.8, 8.0, 0); gimp_spin_scale_set_label (GIMP_SPIN_SCALE (scale), NULL); gtk_container_add (GTK_CONTAINER (frame), scale); g_object_bind_property_full (config, "grid-type", scale, "visible", G_BINDING_SYNC_CREATE, gimp_transform_options_sync_grid, NULL, NULL, NULL); if (tool_options->tool_info->tool_type == GIMP_TYPE_ROTATE_TOOL) { constrain_name = "constrain-rotate"; constrain_label = _("15 degrees (%s)"); constrain_tip = _("Limit rotation steps to 15 degrees"); } else if (tool_options->tool_info->tool_type == GIMP_TYPE_SCALE_TOOL) { constrain_name = "constrain-scale"; constrain_label = _("Keep aspect (%s)"); constrain_tip = _("Keep the original aspect ratio"); } //TODO: check that the selection tools use the gimp_get_*_mask() functions for constrain/etc or change to what they use else if (tool_options->tool_info->tool_type == GIMP_TYPE_UNIFIED_TRANSFORM_TOOL) { GdkModifierType shift = gimp_get_extend_selection_mask (); GdkModifierType ctrl = gimp_get_constrain_behavior_mask (); struct { GdkModifierType mod; gchar *name; gchar *desc; gchar *tip; } opt_list[] = { { shift, NULL, "Constrain (%s)" }, { shift, "constrain-move", "Move", "Constrain movement to 45 degree angles from center (%s)" }, { shift, "constrain-scale", "Scale", "Maintain aspect ratio when scaling (%s)" }, { shift, "constrain-rotate", "Rotate", "Constrain rotation to 15 degree increments (%s)" }, { shift, "constrain-shear", "Shear", "Shear along edge direction only (%s)" }, { shift, "constrain-perspective", "Perspective", "Constrain perspective handles to move along edges and diagonal (%s)" }, { ctrl, NULL, "From pivot (%s)" }, { ctrl, "frompivot-scale", "Scale", "Scale from pivot point (%s)" }, { ctrl, "frompivot-shear", "Shear", "Shear opposite edge by same amount (%s)" }, { ctrl, "frompivot-perspective", "Perspective", "Maintain position of pivot while changing perspective (%s)" }, { 0, NULL, "Pivot" }, { shift, "cornersnap", "Snap (%s)", "Snap pivot to corners and center (%s)" }, { 0, "fixedpivot", "Lock", "Lock pivot position to canvas" }, }; GtkWidget *button; gchar *label; gint i; frame = NULL; for (i = 0; i < G_N_ELEMENTS (opt_list); i++) { if (!opt_list[i].name && !opt_list[i].desc) { frame = NULL; continue; } label = g_strdup_printf (opt_list[i].desc, gimp_get_mod_string (opt_list[i].mod)); if (opt_list[i].name) { button = gimp_prop_check_button_new (config, opt_list[i].name, label); gtk_box_pack_start (GTK_BOX (frame ? grid_box : vbox), button, FALSE, FALSE, 0); gtk_widget_show (button); g_free (label); label = g_strdup_printf (opt_list[i].tip, gimp_get_mod_string (opt_list[i].mod)); gimp_help_set_help_data (button, label, NULL); } else { frame = gimp_frame_new (label); gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0); gtk_widget_show (frame); grid_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 2); gtk_container_add (GTK_CONTAINER (frame), grid_box); gtk_widget_show (grid_box); } g_free (label); } } if (constrain_label) { GtkWidget *button; gchar *label; GdkModifierType constrain_mask; constrain_mask = gimp_get_extend_selection_mask (); label = g_strdup_printf (constrain_label, gimp_get_mod_string (constrain_mask)); button = gimp_prop_check_button_new (config, constrain_name, label); gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0); gtk_widget_show (button); gimp_help_set_help_data (button, constrain_tip, NULL); g_free (label); } return vbox; }
static void gimp_perspective_clone_tool_button_press (GimpTool *tool, const GimpCoords *coords, guint32 time, GdkModifierType state, GimpButtonPressType press_type, GimpDisplay *display) { GimpPaintTool *paint_tool = GIMP_PAINT_TOOL (tool); GimpPerspectiveCloneTool *clone_tool = GIMP_PERSPECTIVE_CLONE_TOOL (tool); GimpPerspectiveClone *clone = GIMP_PERSPECTIVE_CLONE (paint_tool->core); GimpSourceCore *source_core = GIMP_SOURCE_CORE (clone); GimpPerspectiveCloneOptions *options; options = GIMP_PERSPECTIVE_CLONE_TOOL_GET_OPTIONS (tool); switch (options->clone_mode) { case GIMP_PERSPECTIVE_CLONE_MODE_ADJUST: if (clone_tool->function == TRANSFORM_CREATING) gimp_perspective_clone_tool_oper_update (tool, coords, state, TRUE, display); clone_tool->lastx = coords->x; clone_tool->lasty = coords->y; gimp_tool_control_activate (tool->control); break; case GIMP_PERSPECTIVE_CLONE_MODE_PAINT: { GdkModifierType extend_mask = gimp_get_extend_selection_mask (); GdkModifierType toggle_mask = gimp_get_toggle_behavior_mask (); gdouble nnx, nny; gimp_draw_tool_pause (GIMP_DRAW_TOOL (tool)); if ((state & (toggle_mask | extend_mask)) == toggle_mask) { source_core->set_source = TRUE; clone_tool->src_display = display; } else { source_core->set_source = FALSE; } GIMP_TOOL_CLASS (parent_class)->button_press (tool, coords, time, state, press_type, display); /* Set the coordinates for the reference cross */ gimp_perspective_clone_get_source_point (clone, coords->x, coords->y, &nnx, &nny); clone_tool->src_x = nnx; clone_tool->src_y = nny; gimp_draw_tool_resume (GIMP_DRAW_TOOL (tool)); } break; } }
static void gimp_perspective_clone_tool_cursor_update (GimpTool *tool, const GimpCoords *coords, GdkModifierType state, GimpDisplay *display) { GimpPerspectiveCloneTool *clone_tool = GIMP_PERSPECTIVE_CLONE_TOOL (tool); GimpPerspectiveCloneOptions *options; GimpImage *image; GimpToolClass *tool_class; GimpCursorType cursor = GIMP_CURSOR_MOUSE; GimpCursorModifier modifier = GIMP_CURSOR_MODIFIER_NONE; options = GIMP_PERSPECTIVE_CLONE_TOOL_GET_OPTIONS (tool); image = gimp_display_get_image (display); if (gimp_image_coords_in_active_pickable (image, coords, FALSE, TRUE)) { cursor = GIMP_CURSOR_MOUSE; } if (options->clone_mode == GIMP_PERSPECTIVE_CLONE_MODE_ADJUST) { /* perspective cursors */ cursor = gimp_tool_control_get_cursor (tool->control); switch (clone_tool->function) { case TRANSFORM_HANDLE_NW: cursor = GIMP_CURSOR_CORNER_TOP_LEFT; break; case TRANSFORM_HANDLE_NE: cursor = GIMP_CURSOR_CORNER_TOP_RIGHT; break; case TRANSFORM_HANDLE_SW: cursor = GIMP_CURSOR_CORNER_BOTTOM_LEFT; break; case TRANSFORM_HANDLE_SE: cursor = GIMP_CURSOR_CORNER_BOTTOM_RIGHT; break; default: cursor = GIMP_CURSOR_CROSSHAIR_SMALL; break; } } else { GdkModifierType extend_mask = gimp_get_extend_selection_mask (); GdkModifierType toggle_mask = gimp_get_toggle_behavior_mask (); if ((state & (toggle_mask | extend_mask)) == toggle_mask) { cursor = GIMP_CURSOR_CROSSHAIR_SMALL; } else if (! GIMP_SOURCE_CORE (GIMP_PAINT_TOOL (tool)->core)->src_drawable) { modifier = GIMP_CURSOR_MODIFIER_BAD; } } gimp_tool_control_set_cursor (tool->control, cursor); gimp_tool_control_set_cursor_modifier (tool->control, modifier); /* If we are in adjust mode, skip the GimpBrushClass when chaining up. * This ensures that the cursor will be set regardless of * GimpBrushTool::show_cursor (see bug #354933). */ if (options->clone_mode == GIMP_PERSPECTIVE_CLONE_MODE_ADJUST) tool_class = GIMP_TOOL_CLASS (g_type_class_peek_parent (parent_class)); else tool_class = GIMP_TOOL_CLASS (parent_class); tool_class->cursor_update (tool, coords, state, display); }