mirror of
https://gitlab.gnome.org/GNOME/gimp
synced 2024-10-23 04:51:44 +00:00
bfe567c42b
2004-01-17 Sven Neumann <sven@gimp.org> * app/config/gimpguiconfig.[ch] * app/config/gimprc-blurbs.h * app/widgets/gimpdock.c * app/widgets/gimptoolbox.c * app/widgets/gimpwidgets-utils.[ch] * app/widgets/gimpwidgets-utils.[ch] * app/widgets/widgets-enums.[ch]: GTK+-2.4 will allow to request windows to be kept above. This change prepares the code so that we can optionally do this for docks and the toolbox as soon as we depend on GTK+-2.4 (see bug #131672).
837 lines
27 KiB
C
837 lines
27 KiB
C
/* The GIMP -- an image manipulation program
|
|
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include <string.h>
|
|
|
|
#include <gtk/gtk.h>
|
|
|
|
#include "libgimpbase/gimpbase.h"
|
|
#include "libgimpwidgets/gimpwidgets.h"
|
|
|
|
#include "widgets-types.h"
|
|
|
|
#include "config/gimpguiconfig.h"
|
|
|
|
#include "core/gimp.h"
|
|
#include "core/gimpcontext.h"
|
|
#include "core/gimplist.h"
|
|
#include "core/gimptoolinfo.h"
|
|
|
|
#include "gimpdevices.h"
|
|
#include "gimpdialogfactory.h"
|
|
#include "gimphelp-ids.h"
|
|
#include "gimpitemfactory.h"
|
|
#include "gimptoolbox.h"
|
|
#include "gimptoolbox-color-area.h"
|
|
#include "gimptoolbox-dnd.h"
|
|
#include "gimptoolbox-indicator-area.h"
|
|
#include "gimpwidgets-utils.h"
|
|
#include "gtkhwrapbox.h"
|
|
|
|
#include "gimp-intl.h"
|
|
|
|
|
|
#define DEFAULT_TOOL_ICON_SIZE GTK_ICON_SIZE_BUTTON
|
|
#define DEFAULT_BUTTON_RELIEF GTK_RELIEF_NONE
|
|
|
|
#define TOOL_BUTTON_DATA_KEY "gimp-tool-button"
|
|
#define TOOL_INFO_DATA_KEY "gimp-tool-info"
|
|
|
|
|
|
/* local function prototypes */
|
|
|
|
static void gimp_toolbox_class_init (GimpToolboxClass *klass);
|
|
static void gimp_toolbox_init (GimpToolbox *toolbox);
|
|
|
|
static gboolean gimp_toolbox_delete_event (GtkWidget *widget,
|
|
GdkEventAny *event);
|
|
static void gimp_toolbox_size_allocate (GtkWidget *widget,
|
|
GtkAllocation *allocation);
|
|
static void gimp_toolbox_style_set (GtkWidget *widget,
|
|
GtkStyle *previous_style);
|
|
static void gimp_toolbox_book_added (GimpDock *dock,
|
|
GimpDockbook *dockbook);
|
|
static void gimp_toolbox_book_removed (GimpDock *dock,
|
|
GimpDockbook *dockbook);
|
|
static void gimp_toolbox_set_geometry (GimpToolbox *toolbox);
|
|
|
|
static void toolbox_create_tools (GimpToolbox *toolbox,
|
|
GimpContext *context);
|
|
static void toolbox_create_color_area (GimpToolbox *toolbox,
|
|
GimpContext *context);
|
|
static void toolbox_create_indicator_area (GimpToolbox *toolbox,
|
|
GimpContext *context);
|
|
|
|
static void toolbox_tool_changed (GimpContext *context,
|
|
GimpToolInfo *tool_info,
|
|
gpointer data);
|
|
|
|
static void toolbox_tool_button_toggled (GtkWidget *widget,
|
|
GimpToolInfo *tool_info);
|
|
static gboolean toolbox_tool_button_press (GtkWidget *widget,
|
|
GdkEventButton *bevent,
|
|
GimpToolbox *toolbox);
|
|
|
|
static gboolean toolbox_check_device (GtkWidget *widget,
|
|
GdkEvent *event,
|
|
Gimp *gimp);
|
|
|
|
|
|
/* local variables */
|
|
|
|
static GimpDockClass *parent_class = NULL;
|
|
|
|
|
|
GType
|
|
gimp_toolbox_get_type (void)
|
|
{
|
|
static GType type = 0;
|
|
|
|
if (! type)
|
|
{
|
|
static const GTypeInfo type_info =
|
|
{
|
|
sizeof (GimpToolboxClass),
|
|
NULL, /* base_init */
|
|
NULL, /* base_finalize */
|
|
(GClassInitFunc) gimp_toolbox_class_init,
|
|
NULL, /* class_finalize */
|
|
NULL, /* class_data */
|
|
sizeof (GimpToolbox),
|
|
0, /* n_preallocs */
|
|
(GInstanceInitFunc) gimp_toolbox_init,
|
|
};
|
|
|
|
type = g_type_register_static (GIMP_TYPE_DOCK,
|
|
"GimpToolbox",
|
|
&type_info, 0);
|
|
}
|
|
|
|
return type;
|
|
}
|
|
|
|
static void
|
|
gimp_toolbox_class_init (GimpToolboxClass *klass)
|
|
{
|
|
GtkWidgetClass *widget_class;
|
|
GimpDockClass *dock_class;
|
|
|
|
widget_class = GTK_WIDGET_CLASS (klass);
|
|
dock_class = GIMP_DOCK_CLASS (klass);
|
|
|
|
parent_class = g_type_class_peek_parent (klass);
|
|
|
|
widget_class->delete_event = gimp_toolbox_delete_event;
|
|
widget_class->size_allocate = gimp_toolbox_size_allocate;
|
|
widget_class->style_set = gimp_toolbox_style_set;
|
|
|
|
dock_class->book_added = gimp_toolbox_book_added;
|
|
dock_class->book_removed = gimp_toolbox_book_removed;
|
|
|
|
gtk_widget_class_install_style_property
|
|
(widget_class,
|
|
g_param_spec_enum ("tool_icon_size",
|
|
NULL, NULL,
|
|
GTK_TYPE_ICON_SIZE,
|
|
DEFAULT_TOOL_ICON_SIZE,
|
|
G_PARAM_READABLE));
|
|
|
|
gtk_widget_class_install_style_property
|
|
(widget_class,
|
|
g_param_spec_enum ("button_relief",
|
|
NULL, NULL,
|
|
GTK_TYPE_RELIEF_STYLE,
|
|
DEFAULT_BUTTON_RELIEF,
|
|
G_PARAM_READABLE));
|
|
}
|
|
|
|
static void
|
|
gimp_toolbox_init (GimpToolbox *toolbox)
|
|
{
|
|
GimpItemFactory *toolbox_factory;
|
|
GtkWidget *main_vbox;
|
|
GtkWidget *vbox;
|
|
|
|
gtk_window_set_role (GTK_WINDOW (toolbox), "gimp-toolbox");
|
|
|
|
main_vbox = GIMP_DOCK (toolbox)->main_vbox;
|
|
|
|
vbox = gtk_vbox_new (FALSE, 0);
|
|
gtk_box_pack_start (GTK_BOX (main_vbox), vbox, FALSE, FALSE, 0);
|
|
gtk_box_reorder_child (GTK_BOX (main_vbox), vbox, 0);
|
|
gtk_widget_show (vbox);
|
|
|
|
toolbox_factory = gimp_item_factory_from_path ("<Toolbox>");
|
|
|
|
toolbox->menu_bar = GTK_ITEM_FACTORY (toolbox_factory)->widget;
|
|
gtk_box_pack_start (GTK_BOX (vbox), toolbox->menu_bar, FALSE, FALSE, 0);
|
|
gtk_widget_show (toolbox->menu_bar);
|
|
|
|
gtk_window_add_accel_group (GTK_WINDOW (toolbox),
|
|
GTK_ITEM_FACTORY (toolbox_factory)->accel_group);
|
|
|
|
toolbox->wbox = gtk_hwrap_box_new (FALSE);
|
|
gtk_wrap_box_set_justify (GTK_WRAP_BOX (toolbox->wbox), GTK_JUSTIFY_TOP);
|
|
gtk_wrap_box_set_line_justify (GTK_WRAP_BOX (toolbox->wbox),
|
|
GTK_JUSTIFY_LEFT);
|
|
gtk_wrap_box_set_aspect_ratio (GTK_WRAP_BOX (toolbox->wbox), 5.0 / 6.0);
|
|
|
|
gtk_box_pack_start (GTK_BOX (vbox), toolbox->wbox, FALSE, FALSE, 0);
|
|
gtk_widget_show (toolbox->wbox);
|
|
|
|
/* A container that keeps references on the buttons that are not
|
|
* added to the toolbox. Just to make sure they are freed on exit.
|
|
*/
|
|
toolbox->trash = gtk_hbox_new (FALSE, 0);
|
|
gtk_container_add (GTK_CONTAINER (vbox), toolbox->trash);
|
|
}
|
|
|
|
static gboolean
|
|
gimp_toolbox_delete_event (GtkWidget *widget,
|
|
GdkEventAny *event)
|
|
{
|
|
gimp_exit (GIMP_DOCK (widget)->context->gimp, FALSE);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static void
|
|
gimp_toolbox_size_allocate (GtkWidget *widget,
|
|
GtkAllocation *allocation)
|
|
{
|
|
Gimp *gimp;
|
|
GimpToolInfo *tool_info;
|
|
GtkWidget *tool_button;
|
|
|
|
if (GTK_WIDGET_CLASS (parent_class)->size_allocate)
|
|
GTK_WIDGET_CLASS (parent_class)->size_allocate (widget, allocation);
|
|
|
|
if (! GIMP_DOCK (widget)->context)
|
|
return;
|
|
|
|
gimp = GIMP_DOCK (widget)->context->gimp;
|
|
|
|
tool_info = (GimpToolInfo *)
|
|
gimp_container_get_child_by_name (gimp->tool_info_list,
|
|
"gimp-rect-select-tool");
|
|
tool_button = g_object_get_data (G_OBJECT (tool_info), TOOL_BUTTON_DATA_KEY);
|
|
|
|
if (tool_button)
|
|
{
|
|
GimpToolbox *toolbox;
|
|
GtkRequisition button_requisition;
|
|
GtkRequisition color_requisition;
|
|
GtkRequisition indicator_requisition;
|
|
GList *list;
|
|
gint n_tools;
|
|
gint tool_rows;
|
|
gint tool_columns;
|
|
|
|
toolbox = GIMP_TOOLBOX (widget);
|
|
|
|
gtk_widget_size_request (tool_button, &button_requisition);
|
|
gtk_widget_size_request (toolbox->color_area, &color_requisition);
|
|
gtk_widget_size_request (toolbox->indicator_area, &indicator_requisition);
|
|
|
|
for (list = GIMP_LIST (gimp->tool_info_list)->list, n_tools = 0;
|
|
list;
|
|
list = list->next)
|
|
{
|
|
tool_info = (GimpToolInfo *) list->data;
|
|
|
|
if (tool_info->in_toolbox)
|
|
n_tools++;
|
|
}
|
|
|
|
tool_columns = MAX (1, (allocation->width / button_requisition.width));
|
|
tool_rows = n_tools / tool_columns;
|
|
|
|
if (n_tools % tool_columns)
|
|
tool_rows++;
|
|
|
|
if (toolbox->tool_rows != tool_rows ||
|
|
toolbox->tool_columns != tool_columns)
|
|
{
|
|
toolbox->tool_rows = tool_rows;
|
|
toolbox->tool_columns = tool_columns;
|
|
|
|
if ((tool_columns * button_requisition.width) >=
|
|
(color_requisition.width + indicator_requisition.width))
|
|
{
|
|
gtk_widget_set_size_request (toolbox->wbox, -1,
|
|
tool_rows *
|
|
button_requisition.height +
|
|
MAX (color_requisition.height,
|
|
indicator_requisition.height));
|
|
}
|
|
else
|
|
{
|
|
gtk_widget_set_size_request (toolbox->wbox, -1,
|
|
tool_rows *
|
|
button_requisition.height +
|
|
color_requisition.height +
|
|
indicator_requisition.height);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
gimp_toolbox_style_set (GtkWidget *widget,
|
|
GtkStyle *previous_style)
|
|
{
|
|
Gimp *gimp;
|
|
GimpToolInfo *tool_info;
|
|
GtkWidget *tool_button;
|
|
GtkIconSize tool_icon_size;
|
|
GtkReliefStyle relief;
|
|
GList *list;
|
|
|
|
if (GTK_WIDGET_CLASS (parent_class)->style_set)
|
|
GTK_WIDGET_CLASS (parent_class)->style_set (widget, previous_style);
|
|
|
|
if (! GIMP_DOCK (widget)->context)
|
|
return;
|
|
|
|
gimp = GIMP_DOCK (widget)->context->gimp;
|
|
|
|
gtk_widget_style_get (widget,
|
|
"tool_icon_size", &tool_icon_size,
|
|
"button_relief", &relief,
|
|
NULL);
|
|
|
|
for (list = GIMP_LIST (gimp->tool_info_list)->list;
|
|
list;
|
|
list = g_list_next (list))
|
|
{
|
|
tool_info = GIMP_TOOL_INFO (list->data);
|
|
|
|
if (! tool_info->in_toolbox)
|
|
continue;
|
|
|
|
tool_button = g_object_get_data (G_OBJECT (tool_info),
|
|
TOOL_BUTTON_DATA_KEY);
|
|
|
|
if (tool_button)
|
|
{
|
|
GtkImage *image;
|
|
gchar *stock_id;
|
|
|
|
image = GTK_IMAGE (GTK_BIN (tool_button)->child);
|
|
|
|
gtk_image_get_stock (image, &stock_id, NULL);
|
|
gtk_image_set_from_stock (image, stock_id, tool_icon_size);
|
|
|
|
gtk_button_set_relief (GTK_BUTTON (tool_button), relief);
|
|
}
|
|
}
|
|
|
|
gimp_toolbox_set_geometry (GIMP_TOOLBOX (widget));
|
|
}
|
|
|
|
static void
|
|
gimp_toolbox_book_added (GimpDock *dock,
|
|
GimpDockbook *dockbook)
|
|
{
|
|
if (g_list_length (dock->dockbooks) == 1)
|
|
gimp_toolbox_set_geometry (GIMP_TOOLBOX (dock));
|
|
}
|
|
|
|
static void
|
|
gimp_toolbox_book_removed (GimpDock *dock,
|
|
GimpDockbook *dockbook)
|
|
{
|
|
if (dock->dockbooks == NULL &&
|
|
! (GTK_OBJECT_FLAGS (dock) & GTK_IN_DESTRUCTION))
|
|
gimp_toolbox_set_geometry (GIMP_TOOLBOX (dock));
|
|
}
|
|
|
|
static void
|
|
gimp_toolbox_set_geometry (GimpToolbox *toolbox)
|
|
{
|
|
Gimp *gimp;
|
|
GimpToolInfo *tool_info;
|
|
GtkWidget *tool_button;
|
|
|
|
gimp = GIMP_DOCK (toolbox)->context->gimp;
|
|
|
|
tool_info = (GimpToolInfo *)
|
|
gimp_container_get_child_by_name (gimp->tool_info_list,
|
|
"gimp-rect-select-tool");
|
|
tool_button = g_object_get_data (G_OBJECT (tool_info), TOOL_BUTTON_DATA_KEY);
|
|
|
|
if (tool_button)
|
|
{
|
|
GtkWidget *main_vbox;
|
|
GtkRequisition menubar_requisition;
|
|
GtkRequisition button_requisition;
|
|
GtkRequisition color_requisition;
|
|
GtkRequisition indicator_requisition;
|
|
gint border_width;
|
|
gint spacing;
|
|
gint separator_height;
|
|
GdkGeometry geometry;
|
|
|
|
main_vbox = GIMP_DOCK (toolbox)->main_vbox;
|
|
|
|
gtk_widget_size_request (toolbox->menu_bar, &menubar_requisition);
|
|
gtk_widget_size_request (tool_button, &button_requisition);
|
|
gtk_widget_size_request (toolbox->color_area, &color_requisition);
|
|
gtk_widget_size_request (toolbox->indicator_area, &indicator_requisition);
|
|
|
|
border_width = gtk_container_get_border_width (GTK_CONTAINER (main_vbox));
|
|
|
|
spacing = gtk_box_get_spacing (GTK_BOX (main_vbox));
|
|
|
|
gtk_widget_style_get (GTK_WIDGET (toolbox),
|
|
"separator_height", &separator_height,
|
|
NULL);
|
|
|
|
geometry.min_width = (2 * border_width +
|
|
2 * button_requisition.width);
|
|
geometry.min_height = -1;
|
|
geometry.width_inc = button_requisition.width;
|
|
geometry.height_inc = (GIMP_DOCK (toolbox)->dockbooks ?
|
|
1 : button_requisition.height);
|
|
|
|
gtk_window_set_geometry_hints (GTK_WINDOW (toolbox),
|
|
NULL,
|
|
&geometry,
|
|
GDK_HINT_MIN_SIZE |
|
|
GDK_HINT_RESIZE_INC |
|
|
GDK_HINT_USER_POS);
|
|
}
|
|
}
|
|
|
|
GtkWidget *
|
|
gimp_toolbox_new (GimpDialogFactory *dialog_factory,
|
|
Gimp *gimp)
|
|
{
|
|
GimpContext *context;
|
|
GimpToolbox *toolbox;
|
|
GimpGuiConfig *config;
|
|
GdkDisplay *display;
|
|
GList *list;
|
|
|
|
g_return_val_if_fail (GIMP_IS_DIALOG_FACTORY (dialog_factory), NULL);
|
|
g_return_val_if_fail (GIMP_IS_GIMP (gimp), NULL);
|
|
|
|
context = gimp_get_user_context (gimp);
|
|
|
|
toolbox = g_object_new (GIMP_TYPE_TOOLBOX,
|
|
"title", _("The GIMP"),
|
|
"context", context,
|
|
"dialog-factory", dialog_factory,
|
|
NULL);
|
|
|
|
gimp_help_connect (GTK_WIDGET (toolbox), gimp_standard_help_func,
|
|
GIMP_HELP_TOOLBOX, NULL);
|
|
|
|
config = GIMP_GUI_CONFIG (gimp->config);
|
|
|
|
gimp_window_set_hint (GTK_WINDOW (toolbox), config->toolbox_window_hint);
|
|
|
|
/* We need to know when the current device changes, so we can update
|
|
* the correct tool - to do this we connect to motion events.
|
|
* We can't just use EXTENSION_EVENTS_CURSOR though, since that
|
|
* would get us extension events for the mouse pointer, and our
|
|
* device would change to that and not change back. So we check
|
|
* manually that all devices have a cursor, before establishing the check.
|
|
*/
|
|
display = gtk_widget_get_display (GTK_WIDGET (toolbox));
|
|
for (list = gdk_display_list_devices (display); list; list = list->next)
|
|
{
|
|
if (! ((GdkDevice *) (list->data))->has_cursor)
|
|
break;
|
|
}
|
|
|
|
if (! list) /* all devices have cursor */
|
|
{
|
|
g_signal_connect (toolbox, "motion_notify_event",
|
|
G_CALLBACK (toolbox_check_device),
|
|
gimp);
|
|
|
|
gtk_widget_add_events (GTK_WIDGET (toolbox), GDK_POINTER_MOTION_MASK);
|
|
gtk_widget_set_extension_events (GTK_WIDGET (toolbox),
|
|
GDK_EXTENSION_EVENTS_CURSOR);
|
|
}
|
|
|
|
toolbox_create_tools (toolbox, context);
|
|
toolbox_create_color_area (toolbox, context);
|
|
toolbox_create_indicator_area (toolbox, context);
|
|
|
|
g_signal_connect_object (context, "tool_changed",
|
|
G_CALLBACK (toolbox_tool_changed),
|
|
toolbox->wbox,
|
|
0);
|
|
|
|
gimp_toolbox_dnd_init (GIMP_TOOLBOX (toolbox));
|
|
|
|
gimp_toolbox_style_set (GTK_WIDGET (toolbox), GTK_WIDGET (toolbox)->style);
|
|
|
|
return GTK_WIDGET (toolbox);
|
|
}
|
|
|
|
|
|
/* private functions */
|
|
|
|
static gboolean
|
|
gimp_toolbox_button_accel_find_func (GtkAccelKey *key,
|
|
GClosure *closure,
|
|
gpointer data)
|
|
{
|
|
return (GClosure *) data == closure;
|
|
}
|
|
|
|
static void
|
|
gimp_toolbox_button_accel_changed (GtkAccelGroup *accel_group,
|
|
guint unused1,
|
|
GdkModifierType unused2,
|
|
GClosure *accel_closure,
|
|
GtkWidget *tool_button)
|
|
{
|
|
GClosure *button_closure;
|
|
|
|
button_closure = g_object_get_data (G_OBJECT (tool_button),
|
|
"toolbox-accel-closure");
|
|
|
|
if (accel_closure == button_closure)
|
|
{
|
|
GimpToolInfo *tool_info;
|
|
GtkAccelKey *accel_key;
|
|
gchar *tooltip;
|
|
|
|
tool_info = g_object_get_data (G_OBJECT (tool_button), TOOL_INFO_DATA_KEY);
|
|
|
|
accel_key = gtk_accel_group_find (accel_group,
|
|
gimp_toolbox_button_accel_find_func,
|
|
accel_closure);
|
|
|
|
if (accel_key &&
|
|
accel_key->accel_key &&
|
|
accel_key->accel_flags & GTK_ACCEL_VISIBLE)
|
|
{
|
|
/* mostly taken from gtk-2-0/gtk/gtkaccellabel.c:1.46
|
|
*/
|
|
GtkAccelLabelClass *accel_label_class;
|
|
GString *gstring;
|
|
gboolean seen_mod = FALSE;
|
|
gunichar ch;
|
|
|
|
accel_label_class = g_type_class_peek (GTK_TYPE_ACCEL_LABEL);
|
|
|
|
gstring = g_string_new (tool_info->help);
|
|
g_string_append (gstring, " ");
|
|
|
|
if (accel_key->accel_mods & GDK_SHIFT_MASK)
|
|
{
|
|
g_string_append (gstring, accel_label_class->mod_name_shift);
|
|
seen_mod = TRUE;
|
|
}
|
|
if (accel_key->accel_mods & GDK_CONTROL_MASK)
|
|
{
|
|
if (seen_mod)
|
|
g_string_append (gstring, accel_label_class->mod_separator);
|
|
g_string_append (gstring, accel_label_class->mod_name_control);
|
|
seen_mod = TRUE;
|
|
}
|
|
if (accel_key->accel_mods & GDK_MOD1_MASK)
|
|
{
|
|
if (seen_mod)
|
|
g_string_append (gstring, accel_label_class->mod_separator);
|
|
g_string_append (gstring, accel_label_class->mod_name_alt);
|
|
seen_mod = TRUE;
|
|
}
|
|
if (seen_mod)
|
|
g_string_append (gstring, accel_label_class->mod_separator);
|
|
|
|
ch = gdk_keyval_to_unicode (accel_key->accel_key);
|
|
if (ch && (g_unichar_isgraph (ch) || ch == ' ') &&
|
|
(ch < 0x80 || accel_label_class->latin1_to_char))
|
|
{
|
|
switch (ch)
|
|
{
|
|
case ' ':
|
|
g_string_append (gstring, "Space");
|
|
break;
|
|
case '\\':
|
|
g_string_append (gstring, "Backslash");
|
|
break;
|
|
default:
|
|
g_string_append_unichar (gstring, g_unichar_toupper (ch));
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
gchar *tmp;
|
|
|
|
tmp = gtk_accelerator_name (accel_key->accel_key, 0);
|
|
if (tmp[0] != 0 && tmp[1] == 0)
|
|
tmp[0] = g_ascii_toupper (tmp[0]);
|
|
g_string_append (gstring, tmp);
|
|
g_free (tmp);
|
|
}
|
|
|
|
tooltip = g_string_free (gstring, FALSE);
|
|
}
|
|
else
|
|
{
|
|
tooltip = g_strdup (tool_info->help);
|
|
}
|
|
|
|
gimp_help_set_help_data (tool_button, tooltip, tool_info->help_id);
|
|
|
|
g_free (tooltip);
|
|
}
|
|
}
|
|
|
|
static void
|
|
toolbox_create_tools (GimpToolbox *toolbox,
|
|
GimpContext *context)
|
|
{
|
|
GimpItemFactory *item_factory;
|
|
GimpToolInfo *active_tool;
|
|
GList *list;
|
|
GSList *group = NULL;
|
|
|
|
item_factory = gimp_item_factory_from_path ("<Image>");
|
|
|
|
active_tool = gimp_context_get_tool (context);
|
|
|
|
for (list = GIMP_LIST (context->gimp->tool_info_list)->list;
|
|
list;
|
|
list = g_list_next (list))
|
|
{
|
|
GimpToolInfo *tool_info;
|
|
GtkWidget *button;
|
|
GtkWidget *image;
|
|
const gchar *stock_id;
|
|
|
|
tool_info = (GimpToolInfo *) list->data;
|
|
|
|
button = gtk_radio_button_new (group);
|
|
group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (button));
|
|
gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (button), FALSE);
|
|
|
|
if (tool_info->in_toolbox)
|
|
{
|
|
gtk_wrap_box_pack (GTK_WRAP_BOX (toolbox->wbox), button,
|
|
FALSE, FALSE, FALSE, FALSE);
|
|
gtk_widget_show (button);
|
|
|
|
stock_id = gimp_viewable_get_stock_id (GIMP_VIEWABLE (tool_info));
|
|
image = gtk_image_new_from_stock (stock_id, GTK_ICON_SIZE_BUTTON);
|
|
gtk_container_add (GTK_CONTAINER (button), image);
|
|
gtk_widget_show (image);
|
|
}
|
|
else
|
|
{
|
|
gtk_container_add (GTK_CONTAINER (toolbox->trash), button);
|
|
}
|
|
|
|
g_object_set_data (G_OBJECT (tool_info), TOOL_BUTTON_DATA_KEY, button);
|
|
g_object_set_data (G_OBJECT (button), TOOL_INFO_DATA_KEY, tool_info);
|
|
|
|
if (tool_info == active_tool)
|
|
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
|
|
|
|
g_signal_connect (button, "toggled",
|
|
G_CALLBACK (toolbox_tool_button_toggled),
|
|
tool_info);
|
|
|
|
g_signal_connect (button, "button_press_event",
|
|
G_CALLBACK (toolbox_tool_button_press),
|
|
toolbox);
|
|
|
|
if (item_factory)
|
|
{
|
|
GtkWidget *menu_item;
|
|
gchar *menu_path;
|
|
|
|
menu_path = gimp_strip_uline (tool_info->menu_path);
|
|
|
|
menu_item =
|
|
gtk_item_factory_get_widget (GTK_ITEM_FACTORY (item_factory),
|
|
menu_path);
|
|
|
|
g_free (menu_path);
|
|
|
|
if (menu_item)
|
|
{
|
|
GList *accel_closures;
|
|
|
|
accel_closures = gtk_widget_list_accel_closures (menu_item);
|
|
|
|
if (g_list_length (accel_closures) != 1)
|
|
{
|
|
g_warning (G_STRLOC ": FIXME: g_list_length (accel_closures) != 1");
|
|
}
|
|
else
|
|
{
|
|
GClosure *accel_closure;
|
|
GtkAccelGroup *accel_group;
|
|
|
|
accel_closure = (GClosure *) accel_closures->data;
|
|
|
|
g_object_set_data (G_OBJECT (button), "toolbox-accel-closure",
|
|
accel_closure);
|
|
|
|
accel_group = gtk_accel_group_from_accel_closure (accel_closure);
|
|
|
|
g_signal_connect (accel_group, "accel_changed",
|
|
G_CALLBACK (gimp_toolbox_button_accel_changed),
|
|
button);
|
|
|
|
gimp_toolbox_button_accel_changed (accel_group,
|
|
0, 0,
|
|
accel_closure,
|
|
button);
|
|
}
|
|
|
|
g_list_free (accel_closures);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
toolbox_create_color_area (GimpToolbox *toolbox,
|
|
GimpContext *context)
|
|
{
|
|
GtkWidget *frame;
|
|
GtkWidget *alignment;
|
|
GtkWidget *col_area;
|
|
|
|
frame = gtk_frame_new (NULL);
|
|
gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_OUT);
|
|
gtk_wrap_box_pack_wrapped (GTK_WRAP_BOX (toolbox->wbox), frame,
|
|
TRUE, TRUE, FALSE, TRUE, TRUE);
|
|
|
|
alignment = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
|
|
gtk_container_set_border_width (GTK_CONTAINER (alignment), 3);
|
|
gtk_container_add (GTK_CONTAINER (frame), alignment);
|
|
|
|
gimp_help_set_help_data (alignment, NULL, GIMP_HELP_TOOLBOX_COLOR_AREA);
|
|
|
|
col_area = gimp_toolbox_color_area_create (toolbox, 54, 42);
|
|
|
|
gtk_container_add (GTK_CONTAINER (alignment), col_area);
|
|
gimp_help_set_help_data
|
|
(col_area, _("Foreground & background colors. The black and white squares "
|
|
"reset colors. The arrows swap colors. Double click to open "
|
|
"the color selection dialog."), NULL);
|
|
|
|
gtk_widget_show (col_area);
|
|
gtk_widget_show (alignment);
|
|
gtk_widget_show (frame);
|
|
|
|
toolbox->color_area = frame;
|
|
}
|
|
|
|
static void
|
|
toolbox_create_indicator_area (GimpToolbox *toolbox,
|
|
GimpContext *context)
|
|
{
|
|
GtkWidget *frame;
|
|
GtkWidget *alignment;
|
|
GtkWidget *ind_area;
|
|
|
|
frame = gtk_frame_new (NULL);
|
|
gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_OUT);
|
|
gtk_wrap_box_pack (GTK_WRAP_BOX (toolbox->wbox), frame,
|
|
TRUE, TRUE, FALSE, TRUE);
|
|
|
|
alignment = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
|
|
gtk_container_set_border_width (GTK_CONTAINER (alignment), 3);
|
|
gtk_container_add (GTK_CONTAINER (frame), alignment);
|
|
|
|
gimp_help_set_help_data (alignment, NULL, GIMP_HELP_TOOLBOX_INDICATOR_AREA);
|
|
|
|
ind_area = gimp_toolbox_indicator_area_create (toolbox);
|
|
gtk_container_add (GTK_CONTAINER (alignment), ind_area);
|
|
|
|
gtk_widget_show (ind_area);
|
|
gtk_widget_show (alignment);
|
|
gtk_widget_show (frame);
|
|
|
|
toolbox->indicator_area = frame;
|
|
}
|
|
|
|
static void
|
|
toolbox_tool_changed (GimpContext *context,
|
|
GimpToolInfo *tool_info,
|
|
gpointer data)
|
|
{
|
|
if (tool_info)
|
|
{
|
|
GtkWidget *toolbox_button = g_object_get_data (G_OBJECT (tool_info),
|
|
TOOL_BUTTON_DATA_KEY);
|
|
|
|
if (toolbox_button && ! GTK_TOGGLE_BUTTON (toolbox_button)->active)
|
|
{
|
|
g_signal_handlers_block_by_func (toolbox_button,
|
|
toolbox_tool_button_toggled,
|
|
tool_info);
|
|
|
|
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toolbox_button),
|
|
TRUE);
|
|
|
|
g_signal_handlers_unblock_by_func (toolbox_button,
|
|
toolbox_tool_button_toggled,
|
|
tool_info);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
toolbox_tool_button_toggled (GtkWidget *widget,
|
|
GimpToolInfo *tool_info)
|
|
{
|
|
if (GTK_TOGGLE_BUTTON (widget)->active)
|
|
gimp_context_set_tool (gimp_get_user_context (tool_info->gimp), tool_info);
|
|
}
|
|
|
|
static gboolean
|
|
toolbox_tool_button_press (GtkWidget *widget,
|
|
GdkEventButton *event,
|
|
GimpToolbox *toolbox)
|
|
{
|
|
if ((event->type == GDK_2BUTTON_PRESS) && (event->button == 1))
|
|
{
|
|
gimp_dialog_factory_dialog_raise (GIMP_DOCK (toolbox)->dialog_factory,
|
|
gtk_widget_get_screen (widget),
|
|
"gimp-tool-options",
|
|
-1);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static gboolean
|
|
toolbox_check_device (GtkWidget *widget,
|
|
GdkEvent *event,
|
|
Gimp *gimp)
|
|
{
|
|
gimp_devices_check_change (gimp, event);
|
|
|
|
return FALSE;
|
|
}
|