Merge branch 'wip/gabrybare/dnd-text-style-editor' into 'master'

implement drag-and-drop feature for the text on-canvas editor

See merge request GNOME/gimp!2315
This commit is contained in:
Gabriele 2025-07-02 22:33:49 +02:00
commit 7f74b6b556
17 changed files with 432 additions and 19 deletions

View file

@ -89,7 +89,12 @@ static const GimpActionEntry text_tool_actions[] =
NC_("text-tool-action", NC_("text-tool-action",
"Bend the text along the currently active path"), "Bend the text along the currently active path"),
text_tool_text_along_path_cmd_callback, text_tool_text_along_path_cmd_callback,
GIMP_HELP_TEXT_TOOL_TEXT_ALONG_PATH } GIMP_HELP_TEXT_TOOL_TEXT_ALONG_PATH },
{ "text-tool-restore-on-canvas-editor-position", NULL,
NC_("text-tool-action", "Restore On-Canvas Editor Position"), NULL, { NULL }, NULL,
text_tool_restore_on_canvas_editor_position_cmd_callback,
NULL }
}; };
static const GimpRadioActionEntry text_tool_direction_actions[] = static const GimpRadioActionEntry text_tool_direction_actions[] =
@ -166,6 +171,7 @@ text_tool_actions_update (GimpActionGroup *group,
gboolean clip = FALSE; /* clipboard has text available */ gboolean clip = FALSE; /* clipboard has text available */
GimpTextDirection direction; GimpTextDirection direction;
gint i; gint i;
gdouble x, y;
layers = gimp_image_get_selected_layers (image); layers = gimp_image_get_selected_layers (image);
@ -197,6 +203,9 @@ text_tool_actions_update (GimpActionGroup *group,
SET_SENSITIVE ("text-tool-load", image); SET_SENSITIVE ("text-tool-load", image);
SET_SENSITIVE ("text-tool-text-to-path", text_layer); SET_SENSITIVE ("text-tool-text-to-path", text_layer);
SET_SENSITIVE ("text-tool-text-along-path", text_layer && g_list_length (paths) == 1); SET_SENSITIVE ("text-tool-text-along-path", text_layer && g_list_length (paths) == 1);
SET_SENSITIVE ("text-tool-restore-on-canvas-editor-position",
text_layer &&
gimp_text_layer_get_style_overlay_position (text_tool->layer, &x, &y));
direction = gimp_text_tool_get_direction (text_tool); direction = gimp_text_tool_get_direction (text_tool);
for (i = 0; i < G_N_ELEMENTS (text_tool_direction_actions); i++) for (i = 0; i < G_N_ELEMENTS (text_tool_direction_actions); i++)

View file

@ -36,7 +36,10 @@
#include "display/gimpdisplay.h" #include "display/gimpdisplay.h"
#include "text/gimptextlayer.h"
#include "tools/gimptexttool.h" #include "tools/gimptexttool.h"
#include "tools/gimptexttool-editor.h"
#include "dialogs/dialogs.h" #include "dialogs/dialogs.h"
@ -206,6 +209,17 @@ text_tool_direction_cmd_callback (GimpAction *action,
NULL); NULL);
} }
void
text_tool_restore_on_canvas_editor_position_cmd_callback (GimpAction *action,
GVariant *value,
gpointer data)
{
GimpTextTool *text_tool = GIMP_TEXT_TOOL (data);
gimp_text_tool_restore_on_canvas_editor_position (text_tool);
}
/* private functions */ /* private functions */

View file

@ -46,6 +46,10 @@ void text_tool_text_along_path_cmd_callback (GimpAction *action,
void text_tool_direction_cmd_callback (GimpAction *action, void text_tool_direction_cmd_callback (GimpAction *action,
GVariant *value, GVariant *value,
gpointer data); gpointer data);
void text_tool_restore_on_canvas_editor_position_cmd_callback
(GimpAction *action,
GVariant *value,
gpointer data);
#endif /* __TEXT_TOOL_COMMANDS_H__ */ #endif /* __TEXT_TOOL_COMMANDS_H__ */

View file

@ -1365,6 +1365,11 @@ gimp_display_shell_transform_overlay (GimpDisplayShell *shell,
*x -= requisition.width + overlay->spacing_x; *x -= requisition.width + overlay->spacing_x;
*y -= requisition.height / 2; *y -= requisition.height / 2;
break; break;
default:
*x -= overlay->spacing_x;
*y -= overlay->spacing_y;
break;
} }
} }

View file

@ -70,6 +70,13 @@ enum
struct _GimpTextLayerPrivate struct _GimpTextLayerPrivate
{ {
GimpTextDirection base_dir; GimpTextDirection base_dir;
/* on-canvas editor position */
gboolean style_overlay_positioned;
gdouble style_overlay_x;
gdouble style_overlay_y;
gdouble style_overlay_offset_x;
gdouble style_overlay_offset_y;
}; };
static void gimp_text_layer_finalize (GObject *object); static void gimp_text_layer_finalize (GObject *object);
@ -596,6 +603,81 @@ gimp_item_is_text_layer (GimpItem *item)
} }
void
gimp_text_layer_set_style_overlay_position (GimpTextLayer *layer,
gboolean positioned,
gdouble x,
gdouble y)
{
GimpTextLayerPrivate *priv;
g_return_if_fail (GIMP_IS_TEXT_LAYER (layer));
priv = layer->private;
priv->style_overlay_positioned = positioned;
/* We want to set "style_overlay_x" and "style_overlay_y" only
* when "positioned" is TRUE. Otherwhise, we only want to set
* "style_overlay_positioned" to FALSE */
if (positioned)
{
priv->style_overlay_x = x;
priv->style_overlay_y = y;
}
}
gboolean
gimp_text_layer_get_style_overlay_position (GimpTextLayer *layer,
gdouble *x,
gdouble *y)
{
GimpTextLayerPrivate *priv;
g_return_val_if_fail (GIMP_IS_TEXT_LAYER (layer), FALSE);
priv = layer->private;
if (! priv->style_overlay_positioned)
return FALSE;
*x = priv->style_overlay_x;
*y = priv->style_overlay_y;
return TRUE;
}
void
gimp_text_layer_set_style_overlay_offset (GimpTextLayer *layer,
gdouble offset_x,
gdouble offset_y)
{
GimpTextLayerPrivate *priv;
g_return_if_fail (GIMP_IS_TEXT_LAYER (layer));
priv = layer->private;
priv->style_overlay_offset_x = offset_x;
priv->style_overlay_offset_y = offset_y;
}
void
gimp_text_layer_get_style_overlay_offset (GimpTextLayer *layer,
gdouble *offset_x,
gdouble *offset_y)
{
GimpTextLayerPrivate *priv;
g_return_if_fail (GIMP_IS_TEXT_LAYER (layer));
priv = layer->private;
*offset_x = priv->style_overlay_offset_x;
*offset_y = priv->style_overlay_offset_y;
}
/* private functions */ /* private functions */
static const Babl * static const Babl *

View file

@ -75,5 +75,22 @@ void gimp_text_layer_set (GimpTextLayer *layer,
gboolean gimp_item_is_text_layer (GimpItem *item); gboolean gimp_item_is_text_layer (GimpItem *item);
void gimp_text_layer_set_style_overlay_position
(GimpTextLayer *layer,
gboolean positioned,
gdouble x,
gdouble y);
gboolean gimp_text_layer_get_style_overlay_position
(GimpTextLayer *layer,
gdouble *x,
gdouble *y);
void gimp_text_layer_set_style_overlay_offset
(GimpTextLayer *layer,
gdouble offset_x,
gdouble offset_y);
void gimp_text_layer_get_style_overlay_offset
(GimpTextLayer *layer,
gdouble *offset_x,
gdouble *offset_y);
#endif /* __GIMP_TEXT_LAYER_H__ */ #endif /* __GIMP_TEXT_LAYER_H__ */

View file

@ -38,11 +38,13 @@
#include "menus/menus.h" #include "menus/menus.h"
#include "text/gimptext.h" #include "text/gimptext.h"
#include "text/gimptextlayer.h"
#include "text/gimptextlayout.h" #include "text/gimptextlayout.h"
#include "widgets/gimpdialogfactory.h" #include "widgets/gimpdialogfactory.h"
#include "widgets/gimpdockcontainer.h" #include "widgets/gimpdockcontainer.h"
#include "widgets/gimpoverlaybox.h" #include "widgets/gimpoverlaybox.h"
#include "widgets/gimpoverlaychild.h"
#include "widgets/gimpoverlayframe.h" #include "widgets/gimpoverlayframe.h"
#include "widgets/gimptextbuffer.h" #include "widgets/gimptextbuffer.h"
#include "widgets/gimptexteditor.h" #include "widgets/gimptexteditor.h"
@ -128,6 +130,20 @@ static void gimp_text_tool_fix_position (GimpTextTool *text_tool,
static void gimp_text_tool_convert_gdkkeyevent (GimpTextTool *text_tool, static void gimp_text_tool_convert_gdkkeyevent (GimpTextTool *text_tool,
GdkEventKey *kevent); GdkEventKey *kevent);
static gboolean gimp_text_tool_style_overlay_button_press
(GtkWidget *widget,
GdkEventButton *event,
gpointer user_data);
static gboolean gimp_text_tool_style_overlay_button_release
(GtkWidget *widget,
GdkEventButton *event,
gpointer user_data);
static gboolean gimp_text_tool_style_overlay_button_motion
(GtkWidget *widget,
GdkEventMotion *event,
gpointer user_data);
#define DEFAULT_DRAG_OFFSET 25
/* public functions */ /* public functions */
@ -205,8 +221,6 @@ gimp_text_tool_editor_start (GimpTextTool *text_tool)
gdouble yres = 1.0; gdouble yres = 1.0;
text_tool->style_overlay = gimp_overlay_frame_new (); text_tool->style_overlay = gimp_overlay_frame_new ();
gtk_container_set_border_width (GTK_CONTAINER (text_tool->style_overlay),
4);
gimp_display_shell_add_overlay (shell, gimp_display_shell_add_overlay (shell,
text_tool->style_overlay, text_tool->style_overlay,
0, 0, 0, 0,
@ -214,6 +228,23 @@ gimp_text_tool_editor_start (GimpTextTool *text_tool)
gimp_overlay_box_set_child_opacity (GIMP_OVERLAY_BOX (shell->canvas), gimp_overlay_box_set_child_opacity (GIMP_OVERLAY_BOX (shell->canvas),
text_tool->style_overlay, 0.85); text_tool->style_overlay, 0.85);
gtk_widget_add_events (text_tool->style_overlay,
(GDK_BUTTON_PRESS_MASK |
GDK_BUTTON_RELEASE_MASK |
GDK_BUTTON_MOTION_MASK));
g_signal_connect_object (text_tool->style_overlay, "button-press-event",
G_CALLBACK (gimp_text_tool_style_overlay_button_press),
text_tool, 0);
g_signal_connect_object (text_tool->style_overlay, "button-release-event",
G_CALLBACK (gimp_text_tool_style_overlay_button_release),
text_tool, 0);
g_signal_connect_object (text_tool->style_overlay, "motion-notify-event",
G_CALLBACK (gimp_text_tool_style_overlay_button_motion),
text_tool, 0);
text_tool->overlay_dragging = FALSE;
if (text_tool->image) if (text_tool->image)
gimp_image_get_resolution (text_tool->image, &xres, &yres); gimp_image_get_resolution (text_tool->image, &xres, &yres);
@ -254,10 +285,41 @@ gimp_text_tool_editor_position (GimpTextTool *text_tool)
"y1", &y, "y1", &y,
NULL); NULL);
gimp_display_shell_move_overlay (shell, if (text_tool->layer &&
text_tool->style_overlay, gimp_text_layer_get_style_overlay_position (text_tool->layer, &x, &y))
x, y, {
GIMP_HANDLE_ANCHOR_SOUTH_WEST, 4, 12); gdouble offset_x, offset_y;
gimp_text_layer_get_style_overlay_offset (text_tool->layer,
&offset_x, &offset_y);
gimp_display_shell_move_overlay (shell,
text_tool->style_overlay,
x, y, -1,
offset_x + DEFAULT_DRAG_OFFSET,
offset_y + DEFAULT_DRAG_OFFSET);
gimp_text_style_show_restore_position_button (GIMP_TEXT_STYLE_EDITOR (text_tool->style_editor),
TRUE);
}
else
{
GimpOverlayChild *child_overlay;
/*
* Set 'relative_to_shell' to FALSE to allow the overlay to be positioned
* independently from the shell. This enables the overlay to be moved freely
* and later restored to its original position on screen.
*/
child_overlay = gimp_overlay_child_find (GIMP_OVERLAY_BOX (shell->canvas),
text_tool->style_overlay);
gimp_overlay_child_set_relative_to_shell (child_overlay, FALSE);
gimp_display_shell_move_overlay (shell,
text_tool->style_overlay,
x, y, GIMP_HANDLE_ANCHOR_SOUTH_WEST,
4, 12);
}
if (text_tool->image) if (text_tool->image)
{ {
@ -1893,3 +1955,118 @@ gimp_text_tool_convert_gdkkeyevent (GimpTextTool *text_tool,
break; break;
} }
} }
static gboolean
gimp_text_tool_style_overlay_button_press (GtkWidget *widget,
GdkEventButton *event,
gpointer user_data)
{
GimpTextTool *text_tool = GIMP_TEXT_TOOL (user_data);
GtkWidget *event_widget = gtk_get_event_widget ((GdkEvent*) event);
GimpTool *tool = GIMP_TOOL (text_tool);
GimpDisplayShell *shell = gimp_display_get_shell (tool->display);
GimpOverlayChild *child_overlay = NULL;
if (event_widget != GTK_WIDGET (text_tool->style_overlay) &&
gtk_widget_is_ancestor (event_widget, GTK_WIDGET (text_tool->style_editor)))
{
return FALSE;
}
/* Prevent moving the overlay
* if no text layer has been created
*/
if (! text_tool->layer)
return FALSE;
if (gtk_widget_get_window (GTK_WIDGET (text_tool->style_overlay)))
{
GdkCursor *cursor = gdk_cursor_new_for_display (gtk_widget_get_display (GTK_WIDGET (text_tool->style_overlay)),
GDK_FLEUR);
if (cursor)
{
gdk_window_set_cursor (gtk_widget_get_window (GTK_WIDGET (text_tool->style_overlay)),
cursor);
g_object_unref (cursor);
}
}
text_tool->overlay_dragging = TRUE;
gimp_text_layer_set_style_overlay_offset (text_tool->layer, event->x, event->y);
child_overlay = gimp_overlay_child_find (GIMP_OVERLAY_BOX (shell->canvas),
text_tool->style_overlay);
gimp_overlay_child_set_relative_to_shell (child_overlay, FALSE);
return TRUE;
}
static gboolean
gimp_text_tool_style_overlay_button_release (GtkWidget *widget,
GdkEventButton *event,
gpointer user_data)
{
GimpTextTool *text_tool = GIMP_TEXT_TOOL (user_data);
GtkWidget *event_widget = gtk_get_event_widget ((GdkEvent*) event);
GimpTool *tool = GIMP_TOOL (text_tool);
GimpDisplayShell *shell = gimp_display_get_shell (tool->display);
GimpOverlayChild *child_overlay = NULL;
if (event_widget != GTK_WIDGET (text_tool->style_overlay) &&
gtk_widget_is_ancestor (event_widget, GTK_WIDGET (text_tool->style_editor)))
{
return FALSE;
}
text_tool->overlay_dragging = FALSE;
child_overlay = gimp_overlay_child_find (GIMP_OVERLAY_BOX (shell->canvas),
text_tool->style_overlay);
gimp_overlay_child_set_relative_to_shell (child_overlay, TRUE);
if (gtk_widget_get_window (GTK_WIDGET (text_tool->style_overlay)))
gdk_window_set_cursor (gtk_widget_get_window (GTK_WIDGET (text_tool->style_overlay)), NULL);
return TRUE;
}
static gboolean
gimp_text_tool_style_overlay_button_motion (GtkWidget *widget,
GdkEventMotion *event,
gpointer user_data)
{
GimpTextTool *text_tool = GIMP_TEXT_TOOL (user_data);
if (text_tool->overlay_dragging)
{
GimpTool *tool = GIMP_TOOL (text_tool);
GimpDisplayShell *shell = gimp_display_get_shell (tool->display);
GimpTextStyleEditor *style_editor;
gdouble x, y;
gdouble x_off, y_off;
gimp_text_layer_get_style_overlay_offset (text_tool->layer, &x_off, &y_off);
gdk_window_get_device_position_double (gtk_widget_get_window (GTK_WIDGET (shell)),
event->device,
&x, &y, NULL);
gimp_display_shell_untransform_xy_f (shell,
x, y,
&x, &y);
gimp_display_shell_move_overlay (shell,
text_tool->style_overlay,
x, y, -1,
x_off + DEFAULT_DRAG_OFFSET,
y_off + DEFAULT_DRAG_OFFSET);
gimp_text_layer_set_style_overlay_position (text_tool->layer, TRUE,
x, y);
style_editor = GIMP_TEXT_STYLE_EDITOR (text_tool->style_editor);
gimp_text_style_show_restore_position_button (style_editor, TRUE);
}
return TRUE;
}

View file

@ -65,6 +65,7 @@
#include "widgets/gimphelp-ids.h" #include "widgets/gimphelp-ids.h"
#include "widgets/gimpmenufactory.h" #include "widgets/gimpmenufactory.h"
#include "widgets/gimptextbuffer.h" #include "widgets/gimptextbuffer.h"
#include "widgets/gimptextstyleeditor.h"
#include "widgets/gimpuimanager.h" #include "widgets/gimpuimanager.h"
#include "widgets/gimpviewabledialog.h" #include "widgets/gimpviewabledialog.h"
@ -2418,3 +2419,15 @@ gimp_text_tool_get_direction (GimpTextTool *text_tool)
GimpTextOptions *options = GIMP_TEXT_TOOL_GET_OPTIONS (text_tool); GimpTextOptions *options = GIMP_TEXT_TOOL_GET_OPTIONS (text_tool);
return options->base_dir; return options->base_dir;
} }
void
gimp_text_tool_restore_on_canvas_editor_position (GimpTextTool *text_tool)
{
GimpTextStyleEditor *editor = GIMP_TEXT_STYLE_EDITOR (text_tool->style_editor);
if (text_tool->layer)
gimp_text_layer_set_style_overlay_position (text_tool->layer, FALSE, 0, 0);
gimp_text_tool_editor_position (text_tool);
gimp_text_style_show_restore_position_button (editor, FALSE);
}

View file

@ -71,6 +71,9 @@ struct _GimpTextTool
GtkWidget *style_overlay; GtkWidget *style_overlay;
GtkWidget *style_editor; GtkWidget *style_editor;
/* style overlay dragging: */
gboolean overlay_dragging;
gboolean selecting; gboolean selecting;
GtkTextIter select_start_iter; GtkTextIter select_start_iter;
gboolean select_words; gboolean select_words;
@ -128,5 +131,8 @@ gboolean gimp_text_tool_ensure_layout (GimpTextTool *text_tool);
void gimp_text_tool_apply (GimpTextTool *text_tool, void gimp_text_tool_apply (GimpTextTool *text_tool,
gboolean push_undo); gboolean push_undo);
void gimp_text_tool_restore_on_canvas_editor_position
(GimpTextTool *text_tool);
#endif /* __GIMP_TEXT_TOOL_H__ */ #endif /* __GIMP_TEXT_TOOL_H__ */

View file

@ -430,7 +430,7 @@ gimp_overlay_box_set_child_position (GimpOverlayBox *box,
{ {
GimpOverlayChild *child = gimp_overlay_child_find (box, widget); GimpOverlayChild *child = gimp_overlay_child_find (box, widget);
if (child) if (child && ! child->relative_to_shell)
{ {
if (! child->has_position || if (! child->has_position ||
child->x != x || child->x != x ||

View file

@ -70,14 +70,15 @@ gimp_overlay_child_new (GimpOverlayBox *box,
child = g_slice_new0 (GimpOverlayChild); child = g_slice_new0 (GimpOverlayChild);
child->widget = widget; child->widget = widget;
child->xalign = CLAMP (xalign, 0.0, 1.0); child->xalign = CLAMP (xalign, 0.0, 1.0);
child->yalign = CLAMP (yalign, 0.0, 1.0); child->yalign = CLAMP (yalign, 0.0, 1.0);
child->x = 0.0; child->x = 0.0;
child->y = 0.0; child->y = 0.0;
child->has_position = FALSE; child->relative_to_shell = FALSE;
child->angle = angle; child->has_position = FALSE;
child->opacity = CLAMP (opacity, 0.0, 1.0); child->angle = angle;
child->opacity = CLAMP (opacity, 0.0, 1.0);
cairo_matrix_init_identity (&child->matrix); cairo_matrix_init_identity (&child->matrix);
@ -509,6 +510,16 @@ gimp_overlay_child_pick (GimpOverlayBox *box,
return FALSE; return FALSE;
} }
void
gimp_overlay_child_set_relative_to_shell (GimpOverlayChild *child,
gboolean relative_to_shell)
{
g_return_if_fail (child != NULL);
child->relative_to_shell = relative_to_shell;
}
/* private functions */ /* private functions */

View file

@ -29,6 +29,7 @@ struct _GimpOverlayChild
GtkWidget *widget; GtkWidget *widget;
GdkWindow *window; GdkWindow *window;
gboolean relative_to_shell;
gboolean has_position; gboolean has_position;
gdouble xalign; gdouble xalign;
gdouble yalign; gdouble yalign;
@ -82,6 +83,8 @@ gboolean gimp_overlay_child_pick (GimpOverlayBox *bo
GimpOverlayChild *child, GimpOverlayChild *child,
gdouble box_x, gdouble box_x,
gdouble box_y); gdouble box_y);
void gimp_overlay_child_set_relative_to_shell (GimpOverlayChild *child,
gboolean relative_to_shell);
#endif /* __GIMP_OVERLAY_CHILD_H__ */ #endif /* __GIMP_OVERLAY_CHILD_H__ */

View file

@ -36,7 +36,7 @@ static gboolean gimp_overlay_frame_draw (GtkWidget *widget,
cairo_t *cr); cairo_t *cr);
G_DEFINE_TYPE (GimpOverlayFrame, gimp_overlay_frame, GTK_TYPE_BIN) G_DEFINE_TYPE (GimpOverlayFrame, gimp_overlay_frame, GTK_TYPE_EVENT_BOX)
#define parent_class gimp_overlay_frame_parent_class #define parent_class gimp_overlay_frame_parent_class

View file

@ -35,12 +35,12 @@ typedef struct _GimpOverlayFrameClass GimpOverlayFrameClass;
struct _GimpOverlayFrame struct _GimpOverlayFrame
{ {
GtkBin parent_instance; GtkEventBox parent_instance;
}; };
struct _GimpOverlayFrameClass struct _GimpOverlayFrameClass
{ {
GtkBinClass parent_class; GtkEventBoxClass parent_class;
}; };

View file

@ -33,6 +33,10 @@
#include "core/gimpcontainer.h" #include "core/gimpcontainer.h"
#include "core/gimpcontext.h" #include "core/gimpcontext.h"
#include "tools/tools-types.h"
#include "tools/tool_manager.h"
#include "tools/gimptexttool.h"
#include "text/gimptext.h" #include "text/gimptext.h"
#include "text/gimpfont.h" #include "text/gimpfont.h"
@ -42,6 +46,7 @@
#include "gimptextbuffer.h" #include "gimptextbuffer.h"
#include "gimptextstyleeditor.h" #include "gimptextstyleeditor.h"
#include "gimptexttag.h" #include "gimptexttag.h"
#include "gimpwidgets-constructors.h"
#include "gimpwidgets-utils.h" #include "gimpwidgets-utils.h"
#include "gimp-intl.h" #include "gimp-intl.h"
@ -120,6 +125,10 @@ static void gimp_text_style_editor_set_kerning (GimpTextStyleEditor *
static void gimp_text_style_editor_update (GimpTextStyleEditor *editor); static void gimp_text_style_editor_update (GimpTextStyleEditor *editor);
static gboolean gimp_text_style_editor_update_idle (GimpTextStyleEditor *editor); static gboolean gimp_text_style_editor_update_idle (GimpTextStyleEditor *editor);
static void gimp_text_style_editor_restore_position_callback
(GtkWidget *button,
GimpTextStyleEditor *editor);
G_DEFINE_TYPE (GimpTextStyleEditor, gimp_text_style_editor, G_DEFINE_TYPE (GimpTextStyleEditor, gimp_text_style_editor,
GTK_TYPE_BOX) GTK_TYPE_BOX)
@ -193,6 +202,7 @@ gimp_text_style_editor_init (GimpTextStyleEditor *editor)
{ {
GtkWidget *image; GtkWidget *image;
GeglColor *color; GeglColor *color;
GtkWidget *move_icon;
gtk_orientable_set_orientation (GTK_ORIENTABLE (editor), gtk_orientable_set_orientation (GTK_ORIENTABLE (editor),
GTK_ORIENTATION_VERTICAL); GTK_ORIENTATION_VERTICAL);
@ -227,6 +237,30 @@ gimp_text_style_editor_init (GimpTextStyleEditor *editor)
G_CALLBACK (gimp_text_style_editor_size_changed), G_CALLBACK (gimp_text_style_editor_size_changed),
editor); editor);
/* Icon that indicates that the overlay can be moved */
move_icon = gtk_image_new_from_icon_name (GIMP_ICON_TOOL_MOVE,
GTK_ICON_SIZE_MENU);
gtk_widget_set_sensitive (move_icon, FALSE);
gtk_widget_show (move_icon);
/* Restore position button */
editor->restore_position_button = gimp_icon_button_new (GIMP_ICON_RESET, NULL);
gtk_button_set_relief (GTK_BUTTON (editor->restore_position_button),
GTK_RELIEF_NONE);
gtk_image_set_from_icon_name (GTK_IMAGE (gtk_bin_get_child (GTK_BIN (editor->restore_position_button))),
GIMP_ICON_RESET, GTK_ICON_SIZE_MENU);
gimp_help_set_help_data (editor->restore_position_button,
_("Restore On-Canvas Editor Position"), NULL);
g_signal_connect (editor->restore_position_button, "clicked",
G_CALLBACK (gimp_text_style_editor_restore_position_callback),
editor);
gtk_box_pack_end (GTK_BOX (editor->upper_hbox), move_icon, FALSE, FALSE, 0);
gtk_box_pack_end (GTK_BOX (editor->upper_hbox), editor->restore_position_button,
FALSE, FALSE, 0);
/* lower row */ /* lower row */
editor->lower_hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 2); editor->lower_hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 2);
@ -299,6 +333,16 @@ gimp_text_style_editor_init (GimpTextStyleEditor *editor)
g_signal_connect (editor->baseline_adjustment, "value-changed", g_signal_connect (editor->baseline_adjustment, "value-changed",
G_CALLBACK (gimp_text_style_editor_baseline_changed), G_CALLBACK (gimp_text_style_editor_baseline_changed),
editor); editor);
/* Add external spacing to the upper and lower boxes */
gtk_widget_set_margin_top (editor->upper_hbox, 8);
gtk_widget_set_margin_start (editor->upper_hbox, 6);
gtk_widget_set_margin_end (editor->upper_hbox, 6);
gtk_widget_set_margin_start (editor->lower_hbox, 6);
gtk_widget_set_margin_end (editor->lower_hbox, 6);
gtk_widget_set_margin_bottom (editor->lower_hbox, 6);
} }
static void static void
@ -623,6 +667,16 @@ gimp_text_style_editor_list_tags (GimpTextStyleEditor *editor,
return g_list_reverse (tags); return g_list_reverse (tags);
} }
void
gimp_text_style_show_restore_position_button (GimpTextStyleEditor *editor,
gboolean show)
{
if (show)
gtk_widget_show (editor->restore_position_button);
else
gtk_widget_hide (editor->restore_position_button);
}
/* private functions */ /* private functions */
@ -1329,3 +1383,13 @@ gimp_text_style_editor_update_idle (GimpTextStyleEditor *editor)
return FALSE; return FALSE;
} }
static void
gimp_text_style_editor_restore_position_callback (GtkWidget *button,
GimpTextStyleEditor *editor)
{
GimpTool *tool = tool_manager_get_active (editor->gimp);
GimpTextTool *text_tool = GIMP_TEXT_TOOL (tool);
gimp_text_tool_restore_on_canvas_editor_position (text_tool);
}

View file

@ -48,6 +48,7 @@ struct _GimpTextStyleEditor
GtkWidget *upper_hbox; GtkWidget *upper_hbox;
GtkWidget *lower_hbox; GtkWidget *lower_hbox;
GtkWidget *restore_position_button;
GtkWidget *font_entry; GtkWidget *font_entry;
GtkWidget *size_entry; GtkWidget *size_entry;
@ -85,5 +86,9 @@ GtkWidget * gimp_text_style_editor_new (Gimp *gimp,
GList * gimp_text_style_editor_list_tags (GimpTextStyleEditor *editor, GList * gimp_text_style_editor_list_tags (GimpTextStyleEditor *editor,
GList **remove_tags); GList **remove_tags);
void gimp_text_style_show_restore_position_button
(GimpTextStyleEditor *editor,
gboolean show);
#endif /* __GIMP_TEXT_STYLE_EDITOR_H__ */ #endif /* __GIMP_TEXT_STYLE_EDITOR_H__ */

View file

@ -9,6 +9,9 @@
<item><attribute name="action">text-tool.text-tool-copy</attribute></item> <item><attribute name="action">text-tool.text-tool-copy</attribute></item>
<item><attribute name="action">text-tool.text-tool-paste</attribute></item> <item><attribute name="action">text-tool.text-tool-paste</attribute></item>
<item><attribute name="action">text-tool.text-tool-delete</attribute></item> <item><attribute name="action">text-tool.text-tool-delete</attribute></item>
<section>
<item><attribute name="action">text-tool.text-tool-restore-on-canvas-editor-position</attribute></item>
</section>
<section> <section>
<item><attribute name="action">text-tool.text-tool-load</attribute></item> <item><attribute name="action">text-tool.text-tool-load</attribute></item>
<item><attribute name="action">text-tool.text-tool-clear</attribute></item> <item><attribute name="action">text-tool.text-tool-clear</attribute></item>