gimp/app/widgets/gimpdockbook.c

866 lines
28 KiB
C
Raw Normal View History

/* GIMP - The GNU Image Manipulation Program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* gimpdockbook.c
* Copyright (C) 2001-2007 Michael Natterer <mitch@gimp.org>
*
* 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 3 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, see <https://www.gnu.org/licenses/>.
*/
#include "config.h"
#include <string.h>
#include <gegl.h>
#undef GTK_DISABLE_DEPRECATED
#include <gtk/gtk.h>
#include "libgimpwidgets/gimpwidgets.h"
#include "widgets-types.h"
#include "config/gimpguiconfig.h"
#include "core/gimp.h"
Move away from creating all item_factories statically in menus_init() but 2003-01-10 Michael Natterer <mitch@gimp.org> Move away from creating all item_factories statically in menus_init() but create a new one for each place where one is needed: * app/widgets/Makefile.am * app/widgets/widgets-types.h * app/widgets/gimpmenufactory.[ch]: new factory which creates and configures the GimpItemFactories it knows about on-the-fly. * app/widgets/gimpitemfactory.[ch]: added gimp_item_factory_update() which calls the "update_func". Added "gboolean update_on_popup" so item_factories can be configured to require manual updates (used for the <Image> factory). * app/gui/menus.[ch]: create a "global_menu_factory" and register all menus we have with it. Added various setup functions which do stuff like adding the "Open Recent" menu or reorder plug-in menu entries. Removed the debugging stuff... * app/gui/Makefile.am * app/gui/debug-commands.[ch]: ...and added it here. * app/gui/gui.c: create the <Toolbox>, the popup-<Image> and the <Paths> factories here because they are still global. * app/gui/plug-in-menus.[ch]: changed the "image_factory" parameters to "item_factory" and create/update the entries for the passed item_factory only. Makes the whole stuff much more straightforward. * app/plug-in/plug-ins.c: don't call plug_in_make_menu(). * app/display/gimpdisplay.[ch] * app/display/gimpdisplayshell.[ch]: added "menu_factory" and "popup_factory" parameters to gimp_display_new() and gimp_display_shell_new(). Create the menubar_factory and the qmask_factory dynamically. Pass the shell, not a Gimp to the QMask callbacks. Changed gimp_display_shell_set_menu_sensitivity() to gimp_display_shell_menu_update() and don't call it directly (it's a GimpItemFactory update_func now). Call gimp_item_factory_update() on the resp. factories instead. * app/gui/qmask-commands.c * app/display/gimpdisplayshell-callbacks.c * app/tools/gimpimagemaptool.c: changed accordingly. * app/widgets/gimpbrusheditor.c * app/widgets/gimpbrushfactoryview.[ch] * app/widgets/gimpbufferview.[ch] * app/widgets/gimpcolormapeditor.[ch] * app/widgets/gimpcontainereditor.[ch] * app/widgets/gimpdataeditor.[ch] * app/widgets/gimpdatafactoryview.[ch] * app/widgets/gimpdialogfactory.[ch] * app/widgets/gimpdock.c * app/widgets/gimpdockbook.[ch] * app/widgets/gimpdocumentview.[ch] * app/widgets/gimpgradienteditor.[ch] * app/widgets/gimpimageview.[ch] * app/widgets/gimpitemlistview.[ch] * app/widgets/gimppaletteeditor.[ch]: pass around lots of GimpMenuFactory pointers and menu_identifiers so all views can create their item_factories themselves. Unref the factories when they are no longer needed because they belong to the views now. * app/gui/dialogs-commands.c * app/gui/dialogs-constructors.c * app/gui/dialogs.c * app/gui/brush-select.c * app/gui/gradient-select.c * app/gui/palette-select.c * app/gui/pattern-select.c: changed accordingly. * app/gui/file-dialog-utils.[ch] (file_dialog_new): require menu_factory and menu_identifier parameters. * app/gui/file-open-dialog.[ch] * app/gui/file-save-dialog.[ch]: removed file_*_dialog_menu_init() (they went to menus.c as setup_funcs). Added file_*_dialog_set_type() and moved the <Load> and <Save> factory callbacks to file-commands.c * app/gui/file-commands.[ch]: changed accordingly. * app/gui/view-commands.c: changed the statusbar, menubar, rulers and guides callbacks to do their job only if the setting has actually changed. Don't update whole item factories afterwards. Instead, just change the state of the items that actually need update. Unrelated: * app/core/gimpchannel.c (gimp_channel_init): set "bounds_known" and friends to FALSE since we don't know that the new channel will be empty (fixes QMask and probably other stuff). * app/gui/image-commands.c * app/gui/vectors-commands.c: cleanup.
2003-01-11 01:55:53 +08:00
#include "core/gimpcontext.h"
#include "core/gimpmarshal.h"
Move away from creating all item_factories statically in menus_init() but 2003-01-10 Michael Natterer <mitch@gimp.org> Move away from creating all item_factories statically in menus_init() but create a new one for each place where one is needed: * app/widgets/Makefile.am * app/widgets/widgets-types.h * app/widgets/gimpmenufactory.[ch]: new factory which creates and configures the GimpItemFactories it knows about on-the-fly. * app/widgets/gimpitemfactory.[ch]: added gimp_item_factory_update() which calls the "update_func". Added "gboolean update_on_popup" so item_factories can be configured to require manual updates (used for the <Image> factory). * app/gui/menus.[ch]: create a "global_menu_factory" and register all menus we have with it. Added various setup functions which do stuff like adding the "Open Recent" menu or reorder plug-in menu entries. Removed the debugging stuff... * app/gui/Makefile.am * app/gui/debug-commands.[ch]: ...and added it here. * app/gui/gui.c: create the <Toolbox>, the popup-<Image> and the <Paths> factories here because they are still global. * app/gui/plug-in-menus.[ch]: changed the "image_factory" parameters to "item_factory" and create/update the entries for the passed item_factory only. Makes the whole stuff much more straightforward. * app/plug-in/plug-ins.c: don't call plug_in_make_menu(). * app/display/gimpdisplay.[ch] * app/display/gimpdisplayshell.[ch]: added "menu_factory" and "popup_factory" parameters to gimp_display_new() and gimp_display_shell_new(). Create the menubar_factory and the qmask_factory dynamically. Pass the shell, not a Gimp to the QMask callbacks. Changed gimp_display_shell_set_menu_sensitivity() to gimp_display_shell_menu_update() and don't call it directly (it's a GimpItemFactory update_func now). Call gimp_item_factory_update() on the resp. factories instead. * app/gui/qmask-commands.c * app/display/gimpdisplayshell-callbacks.c * app/tools/gimpimagemaptool.c: changed accordingly. * app/widgets/gimpbrusheditor.c * app/widgets/gimpbrushfactoryview.[ch] * app/widgets/gimpbufferview.[ch] * app/widgets/gimpcolormapeditor.[ch] * app/widgets/gimpcontainereditor.[ch] * app/widgets/gimpdataeditor.[ch] * app/widgets/gimpdatafactoryview.[ch] * app/widgets/gimpdialogfactory.[ch] * app/widgets/gimpdock.c * app/widgets/gimpdockbook.[ch] * app/widgets/gimpdocumentview.[ch] * app/widgets/gimpgradienteditor.[ch] * app/widgets/gimpimageview.[ch] * app/widgets/gimpitemlistview.[ch] * app/widgets/gimppaletteeditor.[ch]: pass around lots of GimpMenuFactory pointers and menu_identifiers so all views can create their item_factories themselves. Unref the factories when they are no longer needed because they belong to the views now. * app/gui/dialogs-commands.c * app/gui/dialogs-constructors.c * app/gui/dialogs.c * app/gui/brush-select.c * app/gui/gradient-select.c * app/gui/palette-select.c * app/gui/pattern-select.c: changed accordingly. * app/gui/file-dialog-utils.[ch] (file_dialog_new): require menu_factory and menu_identifier parameters. * app/gui/file-open-dialog.[ch] * app/gui/file-save-dialog.[ch]: removed file_*_dialog_menu_init() (they went to menus.c as setup_funcs). Added file_*_dialog_set_type() and moved the <Load> and <Save> factory callbacks to file-commands.c * app/gui/file-commands.[ch]: changed accordingly. * app/gui/view-commands.c: changed the statusbar, menubar, rulers and guides callbacks to do their job only if the setting has actually changed. Don't update whole item factories afterwards. Instead, just change the state of the items that actually need update. Unrelated: * app/core/gimpchannel.c (gimp_channel_init): set "bounds_known" and friends to FALSE since we don't know that the new channel will be empty (fixes QMask and probably other stuff). * app/gui/image-commands.c * app/gui/vectors-commands.c: cleanup.
2003-01-11 01:55:53 +08:00
#include "gimpdialogfactory.h"
#include "gimpdnd.h"
#include "gimpdock.h"
#include "gimpdockable.h"
#include "gimpdockbook.h"
#include "gimpdocked.h"
#include "gimpdockcontainer.h"
#include "gimpdockwindow.h"
#include "gimphelp-ids.h"
Move away from creating all item_factories statically in menus_init() but 2003-01-10 Michael Natterer <mitch@gimp.org> Move away from creating all item_factories statically in menus_init() but create a new one for each place where one is needed: * app/widgets/Makefile.am * app/widgets/widgets-types.h * app/widgets/gimpmenufactory.[ch]: new factory which creates and configures the GimpItemFactories it knows about on-the-fly. * app/widgets/gimpitemfactory.[ch]: added gimp_item_factory_update() which calls the "update_func". Added "gboolean update_on_popup" so item_factories can be configured to require manual updates (used for the <Image> factory). * app/gui/menus.[ch]: create a "global_menu_factory" and register all menus we have with it. Added various setup functions which do stuff like adding the "Open Recent" menu or reorder plug-in menu entries. Removed the debugging stuff... * app/gui/Makefile.am * app/gui/debug-commands.[ch]: ...and added it here. * app/gui/gui.c: create the <Toolbox>, the popup-<Image> and the <Paths> factories here because they are still global. * app/gui/plug-in-menus.[ch]: changed the "image_factory" parameters to "item_factory" and create/update the entries for the passed item_factory only. Makes the whole stuff much more straightforward. * app/plug-in/plug-ins.c: don't call plug_in_make_menu(). * app/display/gimpdisplay.[ch] * app/display/gimpdisplayshell.[ch]: added "menu_factory" and "popup_factory" parameters to gimp_display_new() and gimp_display_shell_new(). Create the menubar_factory and the qmask_factory dynamically. Pass the shell, not a Gimp to the QMask callbacks. Changed gimp_display_shell_set_menu_sensitivity() to gimp_display_shell_menu_update() and don't call it directly (it's a GimpItemFactory update_func now). Call gimp_item_factory_update() on the resp. factories instead. * app/gui/qmask-commands.c * app/display/gimpdisplayshell-callbacks.c * app/tools/gimpimagemaptool.c: changed accordingly. * app/widgets/gimpbrusheditor.c * app/widgets/gimpbrushfactoryview.[ch] * app/widgets/gimpbufferview.[ch] * app/widgets/gimpcolormapeditor.[ch] * app/widgets/gimpcontainereditor.[ch] * app/widgets/gimpdataeditor.[ch] * app/widgets/gimpdatafactoryview.[ch] * app/widgets/gimpdialogfactory.[ch] * app/widgets/gimpdock.c * app/widgets/gimpdockbook.[ch] * app/widgets/gimpdocumentview.[ch] * app/widgets/gimpgradienteditor.[ch] * app/widgets/gimpimageview.[ch] * app/widgets/gimpitemlistview.[ch] * app/widgets/gimppaletteeditor.[ch]: pass around lots of GimpMenuFactory pointers and menu_identifiers so all views can create their item_factories themselves. Unref the factories when they are no longer needed because they belong to the views now. * app/gui/dialogs-commands.c * app/gui/dialogs-constructors.c * app/gui/dialogs.c * app/gui/brush-select.c * app/gui/gradient-select.c * app/gui/palette-select.c * app/gui/pattern-select.c: changed accordingly. * app/gui/file-dialog-utils.[ch] (file_dialog_new): require menu_factory and menu_identifier parameters. * app/gui/file-open-dialog.[ch] * app/gui/file-save-dialog.[ch]: removed file_*_dialog_menu_init() (they went to menus.c as setup_funcs). Added file_*_dialog_set_type() and moved the <Load> and <Save> factory callbacks to file-commands.c * app/gui/file-commands.[ch]: changed accordingly. * app/gui/view-commands.c: changed the statusbar, menubar, rulers and guides callbacks to do their job only if the setting has actually changed. Don't update whole item factories afterwards. Instead, just change the state of the items that actually need update. Unrelated: * app/core/gimpchannel.c (gimp_channel_init): set "bounds_known" and friends to FALSE since we don't know that the new channel will be empty (fixes QMask and probably other stuff). * app/gui/image-commands.c * app/gui/vectors-commands.c: cleanup.
2003-01-11 01:55:53 +08:00
#include "gimpmenufactory.h"
#include "gimppanedbox.h"
#include "gimpstringaction.h"
#include "gimpuimanager.h"
#include "gimpview.h"
#include "gimpwidgets-utils.h"
app: Use a GdkWindow instead of GimpDockSeparators for dockable DND Make drag-and-drop rearrangement of dockables happen directly in the existing widget hierarchy so we don't have to use special, ugly widgets (read GimpDockSeparator:s) for that. More specifically, make edges of dockables and dockbooks have the same semantics as the GimpDockSeparators had. We put a highlight colored GdkWindow on top of the widget in question to highlight these special drop areas. This GdkWindow is not taken into consideration in the GTK+ drag-and-drop code, so it does not interupt the DND interaction. To achive this, there is a problem we must solve: Drag events in GTK+ are propagated inwards and out, but we sometimes want ancenstor widgets to take care of drop events. We solve this by introducing the concept of "drag handlers". A drag handler is asked if it will handle a given drag event, and if it will, a client will let the drag event be propagated upwards in the widget hierarchy. Right now, the GimpPanedBox is the only "drag handler". The code could be generalized more but it doesn't feel worth it at this point. The size of the special drop area is 5px, the same size as the default GtkPaned handles. This is because the plan is to later use these handles as drop areas too. Other changes of interest are: * We need to take care of "drag-motion", "drag-drop" and widget highlightning ourselves. We can not use the GtkDestDefaults conveniences with gtk_drag_dest_set() any longer since we need more control. * Make the drop callback pass the insert index directly instead of a GimpDockSeparator * Add some GIMP_LOG() debug output for DND * Disable the GimpDockSeparator code in GimpToolbox
2009-11-30 01:22:12 +08:00
#include "gimp-log.h"
#include "gimp-intl.h"
#define DEFAULT_TAB_ICON_SIZE GTK_ICON_SIZE_BUTTON
#define DND_WIDGET_ICON_SIZE GTK_ICON_SIZE_BUTTON
#define MENU_WIDGET_SPACING 4
#define TAB_HOVER_TIMEOUT 500
#define GIMP_DOCKABLE_DETACH_REF_KEY "gimp-dockable-detach-ref"
added GimpDropMode... ...removed from here. 2001-05-06 Michael Natterer <mitch@gimp.org> * app/appenums.h: added GimpDropMode... * app/gimpdnd.h: ...removed from here. * app/gimpimage.[ch]: - New signal "mode_changed". - removed "const GimpImage*" from gimp_image_colormap_changed() because a signal emission is never "const" for the object which emits the signal. - Fixed gimp_image_[set|get]_component_[active|visible](): ALPHA_CHANNEL maps to ALPHA_PIX only in RGB mode, use ALPHA_G_PIX/ALPHA_I_PIX in GRAY/INDEXED mode. * app/gimpimage-convert.c * app/undo.c: call gimp_image_mode_changed(). * app/gimpviewable.c: added an implementation of "invalidate_preview" which frees the preview temp_buf which may be attached to the viewable. Subclasses need to chain up now. * app/gimpdrawable.c * app/gimpimage.c: chain up in invalidate_preview(). * app/widgets/gimpchannellistview.c: connect to the image's "mode_changed" signal and rebuild the channel list in the callback. * app/widgets/gimpcontainerview.h: indentation. * app/widgets/gimpdockbook.c: set the dockable's context to NULL in gimp_dockbook_remove() * app/widgets/gimpimagedock.c: forgot to actually set the dock's image in gimp_image_dock_new(). * app/gui/dialogs-constructors.c: added a get_name_func() for tool views which returns the tool's "blurb". It's safe to assume now that a dockable's context will exist as long as the dockable exists unless it's explicitely set to NULL, so remove ugly hacks handling context destruction. * app/tools/gimptool.c: removed COMPAT_CRUFT and useless #include's.
2001-05-07 00:14:34 +08:00
enum
{
DOCKABLE_ADDED,
DOCKABLE_REMOVED,
DOCKABLE_REORDERED,
LAST_SIGNAL
};
struct _GimpDockbookPrivate
{
GimpDock *dock;
GimpUIManager *ui_manager;
guint tab_hover_timeout;
GimpDockable *tab_hover_dockable;
app: Use a GdkWindow instead of GimpDockSeparators for dockable DND Make drag-and-drop rearrangement of dockables happen directly in the existing widget hierarchy so we don't have to use special, ugly widgets (read GimpDockSeparator:s) for that. More specifically, make edges of dockables and dockbooks have the same semantics as the GimpDockSeparators had. We put a highlight colored GdkWindow on top of the widget in question to highlight these special drop areas. This GdkWindow is not taken into consideration in the GTK+ drag-and-drop code, so it does not interupt the DND interaction. To achive this, there is a problem we must solve: Drag events in GTK+ are propagated inwards and out, but we sometimes want ancenstor widgets to take care of drop events. We solve this by introducing the concept of "drag handlers". A drag handler is asked if it will handle a given drag event, and if it will, a client will let the drag event be propagated upwards in the widget hierarchy. Right now, the GimpPanedBox is the only "drag handler". The code could be generalized more but it doesn't feel worth it at this point. The size of the special drop area is 5px, the same size as the default GtkPaned handles. This is because the plan is to later use these handles as drop areas too. Other changes of interest are: * We need to take care of "drag-motion", "drag-drop" and widget highlightning ourselves. We can not use the GtkDestDefaults conveniences with gtk_drag_dest_set() any longer since we need more control. * Make the drop callback pass the insert index directly instead of a GimpDockSeparator * Add some GIMP_LOG() debug output for DND * Disable the GimpDockSeparator code in GimpToolbox
2009-11-30 01:22:12 +08:00
GimpPanedBox *drag_handler;
GtkWidget *menu_button;
};
static void gimp_dockbook_finalize (GObject *object);
static gboolean gimp_dockbook_drag_motion (GtkWidget *widget,
GdkDragContext *context,
gint x,
gint y,
guint time);
static gboolean gimp_dockbook_drag_drop (GtkWidget *widget,
GdkDragContext *context,
gint x,
gint y,
guint time);
static gboolean gimp_dockbook_popup_menu (GtkWidget *widget);
static GtkNotebook *gimp_dockbook_create_window (GtkNotebook *notebook,
GtkWidget *page,
gint x,
gint y);
static void gimp_dockbook_page_added (GtkNotebook *notebook,
GtkWidget *child,
guint page_num);
static void gimp_dockbook_page_removed (GtkNotebook *notebook,
GtkWidget *child,
guint page_num);
static void gimp_dockbook_page_reordered (GtkNotebook *notebook,
GtkWidget *child,
guint page_num);
static gboolean gimp_dockbook_menu_button_press (GimpDockbook *dockbook,
GdkEventButton *bevent,
GtkWidget *button);
static gboolean gimp_dockbook_show_menu (GimpDockbook *dockbook);
static void gimp_dockbook_menu_end (GimpDockable *dockable);
static void gimp_dockbook_tab_locked_notify (GimpDockable *dockable,
GParamSpec *pspec,
GimpDockbook *dockbook);
static void gimp_dockbook_help_func (const gchar *help_id,
gpointer help_data);
G_DEFINE_TYPE (GimpDockbook, gimp_dockbook, GTK_TYPE_NOTEBOOK)
#define parent_class gimp_dockbook_parent_class
static guint dockbook_signals[LAST_SIGNAL] = { 0 };
static const GtkTargetEntry dialog_target_table[] = { GIMP_TARGET_NOTEBOOK_TAB };
static void
gimp_dockbook_class_init (GimpDockbookClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
GtkNotebookClass *notebook_class = GTK_NOTEBOOK_CLASS (klass);
dockbook_signals[DOCKABLE_ADDED] =
g_signal_new ("dockable-added",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (GimpDockbookClass, dockable_added),
NULL, NULL,
gimp_marshal_VOID__OBJECT,
G_TYPE_NONE, 1,
GIMP_TYPE_DOCKABLE);
dockbook_signals[DOCKABLE_REMOVED] =
g_signal_new ("dockable-removed",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (GimpDockbookClass, dockable_removed),
NULL, NULL,
gimp_marshal_VOID__OBJECT,
G_TYPE_NONE, 1,
GIMP_TYPE_DOCKABLE);
dockbook_signals[DOCKABLE_REORDERED] =
g_signal_new ("dockable-reordered",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (GimpDockbookClass, dockable_reordered),
NULL, NULL,
gimp_marshal_VOID__OBJECT,
G_TYPE_NONE, 1,
GIMP_TYPE_DOCKABLE);
object_class->finalize = gimp_dockbook_finalize;
widget_class->drag_motion = gimp_dockbook_drag_motion;
widget_class->drag_drop = gimp_dockbook_drag_drop;
widget_class->popup_menu = gimp_dockbook_popup_menu;
notebook_class->create_window = gimp_dockbook_create_window;
notebook_class->page_added = gimp_dockbook_page_added;
notebook_class->page_removed = gimp_dockbook_page_removed;
notebook_class->page_reordered = gimp_dockbook_page_reordered;
klass->dockable_added = NULL;
klass->dockable_removed = NULL;
klass->dockable_reordered = NULL;
gtk_widget_class_install_style_property (widget_class,
g_param_spec_enum ("tab-icon-size",
NULL, NULL,
GTK_TYPE_ICON_SIZE,
DEFAULT_TAB_ICON_SIZE,
GIMP_PARAM_READABLE));
g_type_class_add_private (klass, sizeof (GimpDockbookPrivate));
}
static void
gimp_dockbook_init (GimpDockbook *dockbook)
{
GtkNotebook *notebook = GTK_NOTEBOOK (dockbook);
GtkWidget *image;
dockbook->p = G_TYPE_INSTANCE_GET_PRIVATE (dockbook,
GIMP_TYPE_DOCKBOOK,
GimpDockbookPrivate);
/* Various init */
gtk_notebook_popup_enable (notebook);
gtk_notebook_set_scrollable (notebook, TRUE);
gtk_notebook_set_show_border (notebook, FALSE);
gtk_notebook_set_show_tabs (notebook, TRUE);
gtk_notebook_set_group_name (notebook, "gimp-dockbook");
gtk_drag_dest_set (GTK_WIDGET (dockbook),
app: Use a GdkWindow instead of GimpDockSeparators for dockable DND Make drag-and-drop rearrangement of dockables happen directly in the existing widget hierarchy so we don't have to use special, ugly widgets (read GimpDockSeparator:s) for that. More specifically, make edges of dockables and dockbooks have the same semantics as the GimpDockSeparators had. We put a highlight colored GdkWindow on top of the widget in question to highlight these special drop areas. This GdkWindow is not taken into consideration in the GTK+ drag-and-drop code, so it does not interupt the DND interaction. To achive this, there is a problem we must solve: Drag events in GTK+ are propagated inwards and out, but we sometimes want ancenstor widgets to take care of drop events. We solve this by introducing the concept of "drag handlers". A drag handler is asked if it will handle a given drag event, and if it will, a client will let the drag event be propagated upwards in the widget hierarchy. Right now, the GimpPanedBox is the only "drag handler". The code could be generalized more but it doesn't feel worth it at this point. The size of the special drop area is 5px, the same size as the default GtkPaned handles. This is because the plan is to later use these handles as drop areas too. Other changes of interest are: * We need to take care of "drag-motion", "drag-drop" and widget highlightning ourselves. We can not use the GtkDestDefaults conveniences with gtk_drag_dest_set() any longer since we need more control. * Make the drop callback pass the insert index directly instead of a GimpDockSeparator * Add some GIMP_LOG() debug output for DND * Disable the GimpDockSeparator code in GimpToolbox
2009-11-30 01:22:12 +08:00
0,
app/gimpprogress.[ch] s/GDisplay/GimpDisplay/ 2001-10-16 Michael Natterer <mitch@gimp.org> * app/gimpprogress.[ch] * app/undo.c: s/GDisplay/GimpDisplay/ * app/plug_in.[ch]: removed unused boolean "destroy" field of the PlugIn struct. * app/core/gimpedit.c: don't include "app_procs.h" * app/display/gimpdisplay-callbacks.c: moved the "grab_abd_scroll" stuff from gimpdisplay-scroll.* here (less complicated and easier to cleanup...) * app/display/gimpdisplay-scroll.[ch]: removed here. * app/display/gimpdisplay-render.[ch] * app/display/gimpdisplay-selection.[ch] * app/display/gimpdisplayshell.c: s/GDisplay/GimpDisplay/g * app/display/gimpdisplay.[ch]: ditto, removed gdisplay_active() which was just a wrapper around "gimp_context_get_display (gimp_get_user_context (the_gimp))" (which is more to type but makes the use of the global "the_gimp" variable more obvious). * app/gui/color-area.h * app/gui/edit-commands.c * app/gui/file-commands.c * app/gui/file-dialog-utils.c * app/gui/image-commands.c * app/gui/info-window.h * app/gui/paths-dialog.h * app/gui/select-commands.c * app/gui/tool-options-dialog.c * app/gui/tools-commands.c * app/gui/view-commands.c: s/GDisplay/GimpDisplay/, gdisplay_active() removal, include "app_procs.h" for "the_gimp". * app/tools/gimpbezierselecttool.h * app/tools/gimpbrightnesscontrasttool.[ch] * app/tools/gimpbycolorselecttool.c * app/tools/gimpcolorbalancetool.[ch] * app/tools/gimpcurvestool.[ch] * app/tools/gimpeditselectiontool.h * app/tools/gimphistogramtool.[ch] * app/tools/gimphuesaturationtool.[ch] * app/tools/gimplevelstool.[ch] * app/tools/gimpmovetool.h * app/tools/gimpperspectivetool.h * app/tools/gimpposterizetool.[ch] * app/tools/gimprotatetool.h * app/tools/gimpscaletool.h * app/tools/gimpsheartool.h * app/tools/gimptexttool.h * app/tools/gimpthresholdtool.[ch] * app/tools/gimptool.[ch] * app/tools/gimptransformtool.h * app/tools/tool_manager.[ch]: lots of s/GDisplay/GimpDisplay/, made all *_dialog_hide() functions private, cleanup. * app/widgets/*: removed GtkType and gtk_type_* stuff entirely and use GObject functions, removed lots of empty "destroy" methods and use more type checking class cast macros instead of casting directly. * app/widgets/gimpcontainermenu.c: fixed item insert order. * app/widgets/gimphistogramview.[ch]: cleaned up and renamed all functions. * app/widgets/gimpwidgets-utils.[ch]: removed gimp_dialog_hide() as Gtk+ does the right thing (TM) now. * tools/pdbgen/pdb/color.pdb: implemented "histogram" without digging into tools/ and widgets/ (needs to be done for all color PDB functions). * tools/pdbgen/pdb/gimprc.pdb: no need to use "the_gimp" in a PDB function as a "Gimp" pointer is passed to them all. * tools/pdbgen/pdb/image.pdb: don't include "app_procs.h" * app/pdb/color_cmds.c * app/pdb/gimprc_cmds.c * app/pdb/image_cmds.c: regenerated. * app/pdb/procedural_db.c: don't include "app_procs.h"
2001-10-17 19:33:43 +08:00
dialog_target_table, G_N_ELEMENTS (dialog_target_table),
GDK_ACTION_MOVE);
/* Menu button */
dockbook->p->menu_button = gtk_button_new ();
gtk_widget_set_can_focus (dockbook->p->menu_button, FALSE);
gtk_button_set_relief (GTK_BUTTON (dockbook->p->menu_button),
GTK_RELIEF_NONE);
gtk_notebook_set_action_widget (notebook,
dockbook->p->menu_button,
GTK_PACK_END);
gtk_widget_show (dockbook->p->menu_button);
image = gtk_image_new_from_icon_name (GIMP_ICON_MENU_LEFT,
GTK_ICON_SIZE_MENU);
gtk_image_set_pixel_size (GTK_IMAGE (image), 12);
gtk_image_set_from_icon_name (GTK_IMAGE (image), GIMP_ICON_MENU_LEFT,
GTK_ICON_SIZE_MENU);
gtk_container_add (GTK_CONTAINER (dockbook->p->menu_button), image);
gtk_widget_show (image);
gimp_help_set_help_data (dockbook->p->menu_button, _("Configure this tab"),
GIMP_HELP_DOCK_TAB_MENU);
g_signal_connect_swapped (dockbook->p->menu_button, "button-press-event",
G_CALLBACK (gimp_dockbook_menu_button_press),
dockbook);
}
Move away from creating all item_factories statically in menus_init() but 2003-01-10 Michael Natterer <mitch@gimp.org> Move away from creating all item_factories statically in menus_init() but create a new one for each place where one is needed: * app/widgets/Makefile.am * app/widgets/widgets-types.h * app/widgets/gimpmenufactory.[ch]: new factory which creates and configures the GimpItemFactories it knows about on-the-fly. * app/widgets/gimpitemfactory.[ch]: added gimp_item_factory_update() which calls the "update_func". Added "gboolean update_on_popup" so item_factories can be configured to require manual updates (used for the <Image> factory). * app/gui/menus.[ch]: create a "global_menu_factory" and register all menus we have with it. Added various setup functions which do stuff like adding the "Open Recent" menu or reorder plug-in menu entries. Removed the debugging stuff... * app/gui/Makefile.am * app/gui/debug-commands.[ch]: ...and added it here. * app/gui/gui.c: create the <Toolbox>, the popup-<Image> and the <Paths> factories here because they are still global. * app/gui/plug-in-menus.[ch]: changed the "image_factory" parameters to "item_factory" and create/update the entries for the passed item_factory only. Makes the whole stuff much more straightforward. * app/plug-in/plug-ins.c: don't call plug_in_make_menu(). * app/display/gimpdisplay.[ch] * app/display/gimpdisplayshell.[ch]: added "menu_factory" and "popup_factory" parameters to gimp_display_new() and gimp_display_shell_new(). Create the menubar_factory and the qmask_factory dynamically. Pass the shell, not a Gimp to the QMask callbacks. Changed gimp_display_shell_set_menu_sensitivity() to gimp_display_shell_menu_update() and don't call it directly (it's a GimpItemFactory update_func now). Call gimp_item_factory_update() on the resp. factories instead. * app/gui/qmask-commands.c * app/display/gimpdisplayshell-callbacks.c * app/tools/gimpimagemaptool.c: changed accordingly. * app/widgets/gimpbrusheditor.c * app/widgets/gimpbrushfactoryview.[ch] * app/widgets/gimpbufferview.[ch] * app/widgets/gimpcolormapeditor.[ch] * app/widgets/gimpcontainereditor.[ch] * app/widgets/gimpdataeditor.[ch] * app/widgets/gimpdatafactoryview.[ch] * app/widgets/gimpdialogfactory.[ch] * app/widgets/gimpdock.c * app/widgets/gimpdockbook.[ch] * app/widgets/gimpdocumentview.[ch] * app/widgets/gimpgradienteditor.[ch] * app/widgets/gimpimageview.[ch] * app/widgets/gimpitemlistview.[ch] * app/widgets/gimppaletteeditor.[ch]: pass around lots of GimpMenuFactory pointers and menu_identifiers so all views can create their item_factories themselves. Unref the factories when they are no longer needed because they belong to the views now. * app/gui/dialogs-commands.c * app/gui/dialogs-constructors.c * app/gui/dialogs.c * app/gui/brush-select.c * app/gui/gradient-select.c * app/gui/palette-select.c * app/gui/pattern-select.c: changed accordingly. * app/gui/file-dialog-utils.[ch] (file_dialog_new): require menu_factory and menu_identifier parameters. * app/gui/file-open-dialog.[ch] * app/gui/file-save-dialog.[ch]: removed file_*_dialog_menu_init() (they went to menus.c as setup_funcs). Added file_*_dialog_set_type() and moved the <Load> and <Save> factory callbacks to file-commands.c * app/gui/file-commands.[ch]: changed accordingly. * app/gui/view-commands.c: changed the statusbar, menubar, rulers and guides callbacks to do their job only if the setting has actually changed. Don't update whole item factories afterwards. Instead, just change the state of the items that actually need update. Unrelated: * app/core/gimpchannel.c (gimp_channel_init): set "bounds_known" and friends to FALSE since we don't know that the new channel will be empty (fixes QMask and probably other stuff). * app/gui/image-commands.c * app/gui/vectors-commands.c: cleanup.
2003-01-11 01:55:53 +08:00
static void
gimp_dockbook_finalize (GObject *object)
{
GimpDockbook *dockbook = GIMP_DOCKBOOK (object);
Move away from creating all item_factories statically in menus_init() but 2003-01-10 Michael Natterer <mitch@gimp.org> Move away from creating all item_factories statically in menus_init() but create a new one for each place where one is needed: * app/widgets/Makefile.am * app/widgets/widgets-types.h * app/widgets/gimpmenufactory.[ch]: new factory which creates and configures the GimpItemFactories it knows about on-the-fly. * app/widgets/gimpitemfactory.[ch]: added gimp_item_factory_update() which calls the "update_func". Added "gboolean update_on_popup" so item_factories can be configured to require manual updates (used for the <Image> factory). * app/gui/menus.[ch]: create a "global_menu_factory" and register all menus we have with it. Added various setup functions which do stuff like adding the "Open Recent" menu or reorder plug-in menu entries. Removed the debugging stuff... * app/gui/Makefile.am * app/gui/debug-commands.[ch]: ...and added it here. * app/gui/gui.c: create the <Toolbox>, the popup-<Image> and the <Paths> factories here because they are still global. * app/gui/plug-in-menus.[ch]: changed the "image_factory" parameters to "item_factory" and create/update the entries for the passed item_factory only. Makes the whole stuff much more straightforward. * app/plug-in/plug-ins.c: don't call plug_in_make_menu(). * app/display/gimpdisplay.[ch] * app/display/gimpdisplayshell.[ch]: added "menu_factory" and "popup_factory" parameters to gimp_display_new() and gimp_display_shell_new(). Create the menubar_factory and the qmask_factory dynamically. Pass the shell, not a Gimp to the QMask callbacks. Changed gimp_display_shell_set_menu_sensitivity() to gimp_display_shell_menu_update() and don't call it directly (it's a GimpItemFactory update_func now). Call gimp_item_factory_update() on the resp. factories instead. * app/gui/qmask-commands.c * app/display/gimpdisplayshell-callbacks.c * app/tools/gimpimagemaptool.c: changed accordingly. * app/widgets/gimpbrusheditor.c * app/widgets/gimpbrushfactoryview.[ch] * app/widgets/gimpbufferview.[ch] * app/widgets/gimpcolormapeditor.[ch] * app/widgets/gimpcontainereditor.[ch] * app/widgets/gimpdataeditor.[ch] * app/widgets/gimpdatafactoryview.[ch] * app/widgets/gimpdialogfactory.[ch] * app/widgets/gimpdock.c * app/widgets/gimpdockbook.[ch] * app/widgets/gimpdocumentview.[ch] * app/widgets/gimpgradienteditor.[ch] * app/widgets/gimpimageview.[ch] * app/widgets/gimpitemlistview.[ch] * app/widgets/gimppaletteeditor.[ch]: pass around lots of GimpMenuFactory pointers and menu_identifiers so all views can create their item_factories themselves. Unref the factories when they are no longer needed because they belong to the views now. * app/gui/dialogs-commands.c * app/gui/dialogs-constructors.c * app/gui/dialogs.c * app/gui/brush-select.c * app/gui/gradient-select.c * app/gui/palette-select.c * app/gui/pattern-select.c: changed accordingly. * app/gui/file-dialog-utils.[ch] (file_dialog_new): require menu_factory and menu_identifier parameters. * app/gui/file-open-dialog.[ch] * app/gui/file-save-dialog.[ch]: removed file_*_dialog_menu_init() (they went to menus.c as setup_funcs). Added file_*_dialog_set_type() and moved the <Load> and <Save> factory callbacks to file-commands.c * app/gui/file-commands.[ch]: changed accordingly. * app/gui/view-commands.c: changed the statusbar, menubar, rulers and guides callbacks to do their job only if the setting has actually changed. Don't update whole item factories afterwards. Instead, just change the state of the items that actually need update. Unrelated: * app/core/gimpchannel.c (gimp_channel_init): set "bounds_known" and friends to FALSE since we don't know that the new channel will be empty (fixes QMask and probably other stuff). * app/gui/image-commands.c * app/gui/vectors-commands.c: cleanup.
2003-01-11 01:55:53 +08:00
g_clear_object (&dockbook->p->ui_manager);
Move away from creating all item_factories statically in menus_init() but 2003-01-10 Michael Natterer <mitch@gimp.org> Move away from creating all item_factories statically in menus_init() but create a new one for each place where one is needed: * app/widgets/Makefile.am * app/widgets/widgets-types.h * app/widgets/gimpmenufactory.[ch]: new factory which creates and configures the GimpItemFactories it knows about on-the-fly. * app/widgets/gimpitemfactory.[ch]: added gimp_item_factory_update() which calls the "update_func". Added "gboolean update_on_popup" so item_factories can be configured to require manual updates (used for the <Image> factory). * app/gui/menus.[ch]: create a "global_menu_factory" and register all menus we have with it. Added various setup functions which do stuff like adding the "Open Recent" menu or reorder plug-in menu entries. Removed the debugging stuff... * app/gui/Makefile.am * app/gui/debug-commands.[ch]: ...and added it here. * app/gui/gui.c: create the <Toolbox>, the popup-<Image> and the <Paths> factories here because they are still global. * app/gui/plug-in-menus.[ch]: changed the "image_factory" parameters to "item_factory" and create/update the entries for the passed item_factory only. Makes the whole stuff much more straightforward. * app/plug-in/plug-ins.c: don't call plug_in_make_menu(). * app/display/gimpdisplay.[ch] * app/display/gimpdisplayshell.[ch]: added "menu_factory" and "popup_factory" parameters to gimp_display_new() and gimp_display_shell_new(). Create the menubar_factory and the qmask_factory dynamically. Pass the shell, not a Gimp to the QMask callbacks. Changed gimp_display_shell_set_menu_sensitivity() to gimp_display_shell_menu_update() and don't call it directly (it's a GimpItemFactory update_func now). Call gimp_item_factory_update() on the resp. factories instead. * app/gui/qmask-commands.c * app/display/gimpdisplayshell-callbacks.c * app/tools/gimpimagemaptool.c: changed accordingly. * app/widgets/gimpbrusheditor.c * app/widgets/gimpbrushfactoryview.[ch] * app/widgets/gimpbufferview.[ch] * app/widgets/gimpcolormapeditor.[ch] * app/widgets/gimpcontainereditor.[ch] * app/widgets/gimpdataeditor.[ch] * app/widgets/gimpdatafactoryview.[ch] * app/widgets/gimpdialogfactory.[ch] * app/widgets/gimpdock.c * app/widgets/gimpdockbook.[ch] * app/widgets/gimpdocumentview.[ch] * app/widgets/gimpgradienteditor.[ch] * app/widgets/gimpimageview.[ch] * app/widgets/gimpitemlistview.[ch] * app/widgets/gimppaletteeditor.[ch]: pass around lots of GimpMenuFactory pointers and menu_identifiers so all views can create their item_factories themselves. Unref the factories when they are no longer needed because they belong to the views now. * app/gui/dialogs-commands.c * app/gui/dialogs-constructors.c * app/gui/dialogs.c * app/gui/brush-select.c * app/gui/gradient-select.c * app/gui/palette-select.c * app/gui/pattern-select.c: changed accordingly. * app/gui/file-dialog-utils.[ch] (file_dialog_new): require menu_factory and menu_identifier parameters. * app/gui/file-open-dialog.[ch] * app/gui/file-save-dialog.[ch]: removed file_*_dialog_menu_init() (they went to menus.c as setup_funcs). Added file_*_dialog_set_type() and moved the <Load> and <Save> factory callbacks to file-commands.c * app/gui/file-commands.[ch]: changed accordingly. * app/gui/view-commands.c: changed the statusbar, menubar, rulers and guides callbacks to do their job only if the setting has actually changed. Don't update whole item factories afterwards. Instead, just change the state of the items that actually need update. Unrelated: * app/core/gimpchannel.c (gimp_channel_init): set "bounds_known" and friends to FALSE since we don't know that the new channel will be empty (fixes QMask and probably other stuff). * app/gui/image-commands.c * app/gui/vectors-commands.c: cleanup.
2003-01-11 01:55:53 +08:00
G_OBJECT_CLASS (parent_class)->finalize (object);
}
app: Use a GdkWindow instead of GimpDockSeparators for dockable DND Make drag-and-drop rearrangement of dockables happen directly in the existing widget hierarchy so we don't have to use special, ugly widgets (read GimpDockSeparator:s) for that. More specifically, make edges of dockables and dockbooks have the same semantics as the GimpDockSeparators had. We put a highlight colored GdkWindow on top of the widget in question to highlight these special drop areas. This GdkWindow is not taken into consideration in the GTK+ drag-and-drop code, so it does not interupt the DND interaction. To achive this, there is a problem we must solve: Drag events in GTK+ are propagated inwards and out, but we sometimes want ancenstor widgets to take care of drop events. We solve this by introducing the concept of "drag handlers". A drag handler is asked if it will handle a given drag event, and if it will, a client will let the drag event be propagated upwards in the widget hierarchy. Right now, the GimpPanedBox is the only "drag handler". The code could be generalized more but it doesn't feel worth it at this point. The size of the special drop area is 5px, the same size as the default GtkPaned handles. This is because the plan is to later use these handles as drop areas too. Other changes of interest are: * We need to take care of "drag-motion", "drag-drop" and widget highlightning ourselves. We can not use the GtkDestDefaults conveniences with gtk_drag_dest_set() any longer since we need more control. * Make the drop callback pass the insert index directly instead of a GimpDockSeparator * Add some GIMP_LOG() debug output for DND * Disable the GimpDockSeparator code in GimpToolbox
2009-11-30 01:22:12 +08:00
static gboolean
gimp_dockbook_drag_motion (GtkWidget *widget,
GdkDragContext *context,
gint x,
gint y,
guint time)
{
GimpDockbook *dockbook = GIMP_DOCKBOOK (widget);
if (gimp_paned_box_will_handle_drag (dockbook->p->drag_handler,
widget,
context,
x, y,
time))
{
gdk_drag_status (context, 0, time);
return FALSE;
}
return GTK_WIDGET_CLASS (parent_class)->drag_motion (widget, context,
x, y, time);
app: Use a GdkWindow instead of GimpDockSeparators for dockable DND Make drag-and-drop rearrangement of dockables happen directly in the existing widget hierarchy so we don't have to use special, ugly widgets (read GimpDockSeparator:s) for that. More specifically, make edges of dockables and dockbooks have the same semantics as the GimpDockSeparators had. We put a highlight colored GdkWindow on top of the widget in question to highlight these special drop areas. This GdkWindow is not taken into consideration in the GTK+ drag-and-drop code, so it does not interupt the DND interaction. To achive this, there is a problem we must solve: Drag events in GTK+ are propagated inwards and out, but we sometimes want ancenstor widgets to take care of drop events. We solve this by introducing the concept of "drag handlers". A drag handler is asked if it will handle a given drag event, and if it will, a client will let the drag event be propagated upwards in the widget hierarchy. Right now, the GimpPanedBox is the only "drag handler". The code could be generalized more but it doesn't feel worth it at this point. The size of the special drop area is 5px, the same size as the default GtkPaned handles. This is because the plan is to later use these handles as drop areas too. Other changes of interest are: * We need to take care of "drag-motion", "drag-drop" and widget highlightning ourselves. We can not use the GtkDestDefaults conveniences with gtk_drag_dest_set() any longer since we need more control. * Make the drop callback pass the insert index directly instead of a GimpDockSeparator * Add some GIMP_LOG() debug output for DND * Disable the GimpDockSeparator code in GimpToolbox
2009-11-30 01:22:12 +08:00
}
static gboolean
gimp_dockbook_drag_drop (GtkWidget *widget,
GdkDragContext *context,
gint x,
gint y,
guint time)
{
app: Use a GdkWindow instead of GimpDockSeparators for dockable DND Make drag-and-drop rearrangement of dockables happen directly in the existing widget hierarchy so we don't have to use special, ugly widgets (read GimpDockSeparator:s) for that. More specifically, make edges of dockables and dockbooks have the same semantics as the GimpDockSeparators had. We put a highlight colored GdkWindow on top of the widget in question to highlight these special drop areas. This GdkWindow is not taken into consideration in the GTK+ drag-and-drop code, so it does not interupt the DND interaction. To achive this, there is a problem we must solve: Drag events in GTK+ are propagated inwards and out, but we sometimes want ancenstor widgets to take care of drop events. We solve this by introducing the concept of "drag handlers". A drag handler is asked if it will handle a given drag event, and if it will, a client will let the drag event be propagated upwards in the widget hierarchy. Right now, the GimpPanedBox is the only "drag handler". The code could be generalized more but it doesn't feel worth it at this point. The size of the special drop area is 5px, the same size as the default GtkPaned handles. This is because the plan is to later use these handles as drop areas too. Other changes of interest are: * We need to take care of "drag-motion", "drag-drop" and widget highlightning ourselves. We can not use the GtkDestDefaults conveniences with gtk_drag_dest_set() any longer since we need more control. * Make the drop callback pass the insert index directly instead of a GimpDockSeparator * Add some GIMP_LOG() debug output for DND * Disable the GimpDockSeparator code in GimpToolbox
2009-11-30 01:22:12 +08:00
GimpDockbook *dockbook = GIMP_DOCKBOOK (widget);
if (gimp_paned_box_will_handle_drag (dockbook->p->drag_handler,
widget,
context,
x, y,
time))
{
return FALSE;
app: Use a GdkWindow instead of GimpDockSeparators for dockable DND Make drag-and-drop rearrangement of dockables happen directly in the existing widget hierarchy so we don't have to use special, ugly widgets (read GimpDockSeparator:s) for that. More specifically, make edges of dockables and dockbooks have the same semantics as the GimpDockSeparators had. We put a highlight colored GdkWindow on top of the widget in question to highlight these special drop areas. This GdkWindow is not taken into consideration in the GTK+ drag-and-drop code, so it does not interupt the DND interaction. To achive this, there is a problem we must solve: Drag events in GTK+ are propagated inwards and out, but we sometimes want ancenstor widgets to take care of drop events. We solve this by introducing the concept of "drag handlers". A drag handler is asked if it will handle a given drag event, and if it will, a client will let the drag event be propagated upwards in the widget hierarchy. Right now, the GimpPanedBox is the only "drag handler". The code could be generalized more but it doesn't feel worth it at this point. The size of the special drop area is 5px, the same size as the default GtkPaned handles. This is because the plan is to later use these handles as drop areas too. Other changes of interest are: * We need to take care of "drag-motion", "drag-drop" and widget highlightning ourselves. We can not use the GtkDestDefaults conveniences with gtk_drag_dest_set() any longer since we need more control. * Make the drop callback pass the insert index directly instead of a GimpDockSeparator * Add some GIMP_LOG() debug output for DND * Disable the GimpDockSeparator code in GimpToolbox
2009-11-30 01:22:12 +08:00
}
if (widget == gtk_drag_get_source_widget (context))
{
GList *children = gtk_container_get_children (GTK_CONTAINER (widget));
gint n_children = g_list_length (children);
g_list_free (children);
app: Use a GdkWindow instead of GimpDockSeparators for dockable DND Make drag-and-drop rearrangement of dockables happen directly in the existing widget hierarchy so we don't have to use special, ugly widgets (read GimpDockSeparator:s) for that. More specifically, make edges of dockables and dockbooks have the same semantics as the GimpDockSeparators had. We put a highlight colored GdkWindow on top of the widget in question to highlight these special drop areas. This GdkWindow is not taken into consideration in the GTK+ drag-and-drop code, so it does not interupt the DND interaction. To achive this, there is a problem we must solve: Drag events in GTK+ are propagated inwards and out, but we sometimes want ancenstor widgets to take care of drop events. We solve this by introducing the concept of "drag handlers". A drag handler is asked if it will handle a given drag event, and if it will, a client will let the drag event be propagated upwards in the widget hierarchy. Right now, the GimpPanedBox is the only "drag handler". The code could be generalized more but it doesn't feel worth it at this point. The size of the special drop area is 5px, the same size as the default GtkPaned handles. This is because the plan is to later use these handles as drop areas too. Other changes of interest are: * We need to take care of "drag-motion", "drag-drop" and widget highlightning ourselves. We can not use the GtkDestDefaults conveniences with gtk_drag_dest_set() any longer since we need more control. * Make the drop callback pass the insert index directly instead of a GimpDockSeparator * Add some GIMP_LOG() debug output for DND * Disable the GimpDockSeparator code in GimpToolbox
2009-11-30 01:22:12 +08:00
/* we dragged the only tab, and want to drop it back on the same
* notebook, this would remove and add the page, causing the
* dockbook to be destroyed in the process because it becomes
* empty
*/
if (n_children == 1)
return FALSE;
}
return GTK_WIDGET_CLASS (parent_class)->drag_drop (widget, context,
x, y, time);
}
static gboolean
gimp_dockbook_popup_menu (GtkWidget *widget)
{
return gimp_dockbook_show_menu (GIMP_DOCKBOOK (widget));
}
static GtkNotebook *
gimp_dockbook_create_window (GtkNotebook *notebook,
GtkWidget *page,
gint x,
gint y)
{
GimpDockbook *dockbook = GIMP_DOCKBOOK (notebook);
GimpDockable *dockable = GIMP_DOCKABLE (page);
GimpDialogFactory *dialog_factory;
GimpMenuFactory *menu_factory;
GimpDockWindow *src_dock_window;
GimpDock *src_dock;
GtkWidget *new_dock;
GimpDockWindow *new_dock_window;
GtkWidget *new_dockbook;
src_dock = gimp_dockbook_get_dock (dockbook);
src_dock_window = gimp_dock_window_from_dock (src_dock);
dialog_factory = gimp_dock_get_dialog_factory (src_dock);
menu_factory = gimp_dialog_factory_get_menu_factory (dialog_factory);
new_dock = gimp_dock_with_window_new (dialog_factory,
gimp_widget_get_monitor (page),
FALSE);
new_dock_window = gimp_dock_window_from_dock (GIMP_DOCK (new_dock));
gtk_window_set_position (GTK_WINDOW (new_dock_window), GTK_WIN_POS_MOUSE);
if (src_dock_window)
gimp_dock_window_setup (new_dock_window, src_dock_window);
new_dockbook = gimp_dockbook_new (menu_factory);
gimp_dock_add_book (GIMP_DOCK (new_dock), GIMP_DOCKBOOK (new_dockbook), 0);
gtk_widget_show (GTK_WIDGET (new_dock_window));
gtk_widget_show (new_dock);
return GTK_NOTEBOOK (new_dockbook);
}
static void
gimp_dockbook_page_added (GtkNotebook *notebook,
GtkWidget *child,
guint page_num)
{
GimpDockbook *dockbook = GIMP_DOCKBOOK (notebook);
GimpDockable *dockable = GIMP_DOCKABLE (child);
GtkWidget *tab_widget;
GtkWidget *menu_widget;
GIMP_LOG (DND, "GimpDockable %p added to GimpDockbook %p",
dockable, dockbook);
tab_widget = gimp_dockbook_create_tab_widget (dockbook, dockable);
/* For the notebook right-click menu, always use the icon style */
menu_widget =
gimp_dockable_create_tab_widget (dockable,
gimp_dock_get_context (dockbook->p->dock),
GIMP_TAB_STYLE_ICON_BLURB,
GTK_ICON_SIZE_MENU);
gtk_notebook_set_tab_label (notebook, child, tab_widget);
gtk_notebook_set_menu_label (notebook, child, menu_widget);
if (! gimp_dockable_get_locked (dockable))
{
gtk_notebook_set_tab_reorderable (notebook, child, TRUE);
gtk_notebook_set_tab_detachable (notebook, child, TRUE);
}
gimp_dockable_set_dockbook (dockable, dockbook);
gimp_dockable_set_context (dockable,
gimp_dock_get_context (dockbook->p->dock));
g_signal_connect (dockable, "notify::locked",
G_CALLBACK (gimp_dockbook_tab_locked_notify),
dockbook);
gtk_widget_show (child);
gtk_notebook_set_current_page (notebook, page_num);
g_signal_emit (dockbook, dockbook_signals[DOCKABLE_ADDED], 0, dockable);
}
static void
gimp_dockbook_page_removed (GtkNotebook *notebook,
GtkWidget *child,
guint page_num)
{
GimpDockbook *dockbook = GIMP_DOCKBOOK (notebook);
GimpDockable *dockable = GIMP_DOCKABLE (child);
GIMP_LOG (DND, "GimpDockable removed %p from GimpDockbook %p",
dockable, dockbook);
g_signal_handlers_disconnect_by_func (dockable,
G_CALLBACK (gimp_dockbook_tab_locked_notify),
dockbook);
gimp_dockable_set_dockbook (dockable, NULL);
gimp_dockable_set_context (dockable, NULL);
g_signal_emit (dockbook, dockbook_signals[DOCKABLE_REMOVED], 0, dockable);
if (dockbook->p->dock)
{
GList *children = gtk_container_get_children (GTK_CONTAINER (dockbook));
if (! children)
gimp_dock_remove_book (dockbook->p->dock, dockbook);
g_list_free (children);
}
}
static void
gimp_dockbook_page_reordered (GtkNotebook *notebook,
GtkWidget *child,
guint page_num)
{
}
static gboolean
gimp_dockbook_menu_button_press (GimpDockbook *dockbook,
GdkEventButton *bevent,
GtkWidget *button)
{
gboolean handled = FALSE;
if (bevent->button == 1 && bevent->type == GDK_BUTTON_PRESS)
handled = gimp_dockbook_show_menu (dockbook);
return handled;
}
static gboolean
gimp_dockbook_show_menu (GimpDockbook *dockbook)
{
GimpUIManager *dockbook_ui_manager;
GimpUIManager *dialog_ui_manager;
const gchar *dialog_ui_path;
gpointer dialog_popup_data;
GtkWidget *parent_menu_widget;
GtkAction *parent_menu_action;
GimpDockable *dockable;
gint page_num;
dockbook_ui_manager = gimp_dockbook_get_ui_manager (dockbook);
if (! dockbook_ui_manager)
return FALSE;
parent_menu_widget =
gtk_ui_manager_get_widget (GTK_UI_MANAGER (dockbook_ui_manager),
"/dockable-popup/dockable-menu");
parent_menu_action =
gtk_ui_manager_get_action (GTK_UI_MANAGER (dockbook_ui_manager),
"/dockable-popup/dockable-menu");
if (! parent_menu_widget || ! parent_menu_action)
return FALSE;
page_num = gtk_notebook_get_current_page (GTK_NOTEBOOK (dockbook));
dockable = GIMP_DOCKABLE (gtk_notebook_get_nth_page (GTK_NOTEBOOK (dockbook),
page_num));
if (! dockable)
return FALSE;
dialog_ui_manager = gimp_dockable_get_menu (dockable,
&dialog_ui_path,
&dialog_popup_data);
if (dialog_ui_manager && dialog_ui_path)
{
GtkWidget *child_menu_widget;
GtkAction *child_menu_action;
gchar *label;
child_menu_widget =
gtk_ui_manager_get_widget (GTK_UI_MANAGER (dialog_ui_manager),
dialog_ui_path);
if (! child_menu_widget)
{
g_warning ("%s: UI manager '%s' has no widget at path '%s'",
G_STRFUNC, dialog_ui_manager->name, dialog_ui_path);
return FALSE;
}
child_menu_action =
gtk_ui_manager_get_action (GTK_UI_MANAGER (dialog_ui_manager),
dialog_ui_path);
if (! child_menu_action)
{
g_warning ("%s: UI manager '%s' has no action at path '%s'",
G_STRFUNC, dialog_ui_manager->name, dialog_ui_path);
return FALSE;
}
g_object_get (child_menu_action,
"label", &label,
NULL);
g_object_set (parent_menu_action,
"label", label,
"icon-name", gimp_dockable_get_icon_name (dockable),
"visible", TRUE,
NULL);
g_free (label);
if (! GTK_IS_MENU (child_menu_widget))
{
g_warning ("%s: child_menu_widget (%p) is not a GtkMenu",
G_STRFUNC, child_menu_widget);
return FALSE;
}
{
GtkWidget *image = gimp_dockable_get_icon (dockable,
GTK_ICON_SIZE_MENU);
gimp_menu_item_set_image (GTK_MENU_ITEM (parent_menu_widget), image);
gtk_widget_show (image);
}
gtk_menu_item_set_submenu (GTK_MENU_ITEM (parent_menu_widget),
child_menu_widget);
gimp_ui_manager_update (dialog_ui_manager, dialog_popup_data);
}
else
{
g_object_set (parent_menu_action, "visible", FALSE, NULL);
}
/* an action callback may destroy both dockable and dockbook, so
* reference them for gimp_dockbook_menu_end()
*/
g_object_ref (dockable);
g_object_set_data_full (G_OBJECT (dockable), GIMP_DOCKABLE_DETACH_REF_KEY,
g_object_ref (dockbook),
g_object_unref);
gimp_ui_manager_update (dockbook_ui_manager, dockable);
gimp_ui_manager_ui_popup_at_widget (dockbook_ui_manager,
"/dockable-popup",
dockbook->p->menu_button,
GDK_GRAVITY_WEST,
GDK_GRAVITY_NORTH_EAST,
NULL,
(GDestroyNotify) gimp_dockbook_menu_end,
dockable);
return TRUE;
}
static void
gimp_dockbook_menu_end (GimpDockable *dockable)
{
GimpUIManager *dialog_ui_manager;
const gchar *dialog_ui_path;
gpointer dialog_popup_data;
dialog_ui_manager = gimp_dockable_get_menu (dockable,
&dialog_ui_path,
&dialog_popup_data);
if (dialog_ui_manager && dialog_ui_path)
{
GtkWidget *child_menu_widget =
gtk_ui_manager_get_widget (GTK_UI_MANAGER (dialog_ui_manager),
dialog_ui_path);
if (child_menu_widget)
gtk_menu_detach (GTK_MENU (child_menu_widget));
}
/* release gimp_dockbook_show_menu()'s references */
g_object_set_data (G_OBJECT (dockable), GIMP_DOCKABLE_DETACH_REF_KEY, NULL);
g_object_unref (dockable);
}
/* public functions */
GtkWidget *
gimp_dockbook_new (GimpMenuFactory *menu_factory)
{
GimpDockbook *dockbook;
g_return_val_if_fail (GIMP_IS_MENU_FACTORY (menu_factory), NULL);
dockbook = g_object_new (GIMP_TYPE_DOCKBOOK, NULL);
dockbook->p->ui_manager = gimp_menu_factory_manager_new (menu_factory,
2016-11-23 14:01:41 +08:00
"<Dockable>",
dockbook);
gimp_help_connect (GTK_WIDGET (dockbook), gimp_dockbook_help_func,
GIMP_HELP_DOCK, dockbook);
return GTK_WIDGET (dockbook);
}
GimpDock *
gimp_dockbook_get_dock (GimpDockbook *dockbook)
{
g_return_val_if_fail (GIMP_IS_DOCKBOOK (dockbook), NULL);
return dockbook->p->dock;
}
void
gimp_dockbook_set_dock (GimpDockbook *dockbook,
GimpDock *dock)
{
g_return_if_fail (GIMP_IS_DOCKBOOK (dockbook));
g_return_if_fail (dock == NULL || GIMP_IS_DOCK (dock));
dockbook->p->dock = dock;
}
GimpUIManager *
gimp_dockbook_get_ui_manager (GimpDockbook *dockbook)
{
g_return_val_if_fail (GIMP_IS_DOCKBOOK (dockbook), NULL);
return dockbook->p->ui_manager;
}
/**
* gimp_dockbook_add_from_dialog_factory:
* @dockbook: The #DockBook
* @identifiers: The dockable identifier(s)
*
* Add a dockable from the dialog factory associated with the dockbook.
**/
GtkWidget *
gimp_dockbook_add_from_dialog_factory (GimpDockbook *dockbook,
const gchar *identifiers)
{
GtkWidget *dockable;
GimpDock *dock;
gchar *identifier;
gchar *p;
g_return_val_if_fail (GIMP_IS_DOCKBOOK (dockbook), NULL);
g_return_val_if_fail (identifiers != NULL, NULL);
identifier = g_strdup (identifiers);
p = strchr (identifier, '|');
if (p)
*p = '\0';
dock = gimp_dockbook_get_dock (dockbook);
dockable = gimp_dialog_factory_dockable_new (gimp_dock_get_dialog_factory (dock),
dock,
identifier, -1);
g_free (identifier);
/* Maybe gimp_dialog_factory_dockable_new() returned an already
* existing singleton dockable, so check if it already is
* attached to a dockbook.
*/
if (dockable && ! gimp_dockable_get_dockbook (GIMP_DOCKABLE (dockable)))
gtk_notebook_append_page (GTK_NOTEBOOK (dockbook),
dockable, NULL);
return dockable;
}
/**
* gimp_dockbook_update_with_context:
* @dockbook:
* @context:
*
* Set @context on all dockables in @dockbook.
**/
void
gimp_dockbook_update_with_context (GimpDockbook *dockbook,
GimpContext *context)
{
GList *children = gtk_container_get_children (GTK_CONTAINER (dockbook));
GList *iter;
for (iter = children; iter; iter = g_list_next (iter))
{
GimpDockable *dockable = GIMP_DOCKABLE (iter->data);
gimp_dockable_set_context (dockable, context);
}
g_list_free (children);
}
Added configurable styles for dockable tabs (fixes bug #87376): 2003-07-08 Michael Natterer <mitch@gimp.org> Added configurable styles for dockable tabs (fixes bug #87376): * app/widgets/widgets-enums.[ch]: added new enum GimpTabStyle which can be one on { ICON, NAME, ICON_NAME, ICON_BLURB }. * app/widgets/gimpdockable.[ch]: added a GimpTabStyle member to the GimpDockable struct which defaults to GIMP_TAB_STYLE_ICON. Renamed "short_name" to "name" and "name" to "blurb". Renamed GimpDockableGetTabFunc to GimpDockableGetIconFunc. Implemented all tab styles in gimp_dockable_real_get_tab_widget() and use the "get_icon_func" only for creating the tab's icon, not the entire tab widget. * app/widgets/gimpdockbook.[ch]: changed accordingly. Create the menu widgets and the DND icon using gimp_dockable_get_tab_widget() with tab_style == GIMP_TAB_STYLE_ICON_BLURB instead of duplicating tons of code. Made gimp_dockbook_get_tab_widget() public because it's needed for exchanging tabs on-the-fly. * app/widgets/gimpimagedock.c: changed accordingly. * app/widgets/gimpdialogfactory.c: remember the dockables' tab style in sessionrc. * app/gui/dialogs-menu.c: added a submenu to select the tab style for each dockable. * app/gui/dialogs-commands.[ch]: new callback dialogs_tab_style_cmd_callback(). * app/gui/dialogs-constructors.[ch]: added stock_ids to all dockables, swapped the "name" and "blurb" parameters, reordered functions, cleanup. * app/gui/dialogs-menu.c * app/gui/image-menu.c * app/gui/toolbox-menu.c: use GIMP_STOCK_DEFAULT_COLORS for the color editor dockable and renamed it to "FG/BG Color".
2003-07-08 23:07:56 +08:00
GtkWidget *
gimp_dockbook_create_tab_widget (GimpDockbook *dockbook,
GimpDockable *dockable)
{
GtkWidget *tab_widget;
GimpDockWindow *dock_window;
GtkAction *action = NULL;
GtkIconSize tab_size = DEFAULT_TAB_ICON_SIZE;
gtk_widget_style_get (GTK_WIDGET (dockbook),
"tab-icon-size", &tab_size,
NULL);
tab_widget =
gimp_dockable_create_tab_widget (dockable,
gimp_dock_get_context (dockbook->p->dock),
gimp_dockable_get_tab_style (dockable),
tab_size);
if (GIMP_IS_VIEW (tab_widget))
{
GtkWidget *event_box;
event_box = gtk_event_box_new ();
gtk_event_box_set_visible_window (GTK_EVENT_BOX (event_box), FALSE);
gtk_event_box_set_above_child (GTK_EVENT_BOX (event_box), TRUE);
gtk_container_add (GTK_CONTAINER (event_box), tab_widget);
gtk_widget_show (tab_widget);
tab_widget = event_box;
}
/* EEK */
dock_window = gimp_dock_window_from_dock (dockbook->p->dock);
if (dock_window &&
gimp_dock_container_get_ui_manager (GIMP_DOCK_CONTAINER (dock_window)))
{
const gchar *dialog_id;
dialog_id = g_object_get_data (G_OBJECT (dockable),
"gimp-dialog-identifier");
if (dialog_id)
{
GimpDockContainer *dock_container;
GimpActionGroup *group;
dock_container = GIMP_DOCK_CONTAINER (dock_window);
group = gimp_ui_manager_get_action_group
(gimp_dock_container_get_ui_manager (dock_container), "dialogs");
if (group)
{
GList *actions;
GList *list;
actions = gtk_action_group_list_actions (GTK_ACTION_GROUP (group));
for (list = actions; list; list = g_list_next (list))
{
if (GIMP_IS_STRING_ACTION (list->data) &&
strstr (GIMP_STRING_ACTION (list->data)->value,
dialog_id))
{
action = list->data;
break;
}
}
g_list_free (actions);
}
}
}
if (action)
gimp_widget_set_accel_help (tab_widget, action);
else
gimp_help_set_help_data (tab_widget,
gimp_dockable_get_blurb (dockable),
gimp_dockable_get_help_id (dockable));
return tab_widget;
}
app: Use a GdkWindow instead of GimpDockSeparators for dockable DND Make drag-and-drop rearrangement of dockables happen directly in the existing widget hierarchy so we don't have to use special, ugly widgets (read GimpDockSeparator:s) for that. More specifically, make edges of dockables and dockbooks have the same semantics as the GimpDockSeparators had. We put a highlight colored GdkWindow on top of the widget in question to highlight these special drop areas. This GdkWindow is not taken into consideration in the GTK+ drag-and-drop code, so it does not interupt the DND interaction. To achive this, there is a problem we must solve: Drag events in GTK+ are propagated inwards and out, but we sometimes want ancenstor widgets to take care of drop events. We solve this by introducing the concept of "drag handlers". A drag handler is asked if it will handle a given drag event, and if it will, a client will let the drag event be propagated upwards in the widget hierarchy. Right now, the GimpPanedBox is the only "drag handler". The code could be generalized more but it doesn't feel worth it at this point. The size of the special drop area is 5px, the same size as the default GtkPaned handles. This is because the plan is to later use these handles as drop areas too. Other changes of interest are: * We need to take care of "drag-motion", "drag-drop" and widget highlightning ourselves. We can not use the GtkDestDefaults conveniences with gtk_drag_dest_set() any longer since we need more control. * Make the drop callback pass the insert index directly instead of a GimpDockSeparator * Add some GIMP_LOG() debug output for DND * Disable the GimpDockSeparator code in GimpToolbox
2009-11-30 01:22:12 +08:00
/**
* gimp_dockable_set_drag_handler:
* @dockable:
* @handler:
*
* Set a drag handler that will be asked if it will handle drag events
* before the dockbook handles the event itself.
**/
void
gimp_dockbook_set_drag_handler (GimpDockbook *dockbook,
GimpPanedBox *drag_handler)
{
g_return_if_fail (GIMP_IS_DOCKBOOK (dockbook));
dockbook->p->drag_handler = drag_handler;
}
/* private functions */
static void
gimp_dockbook_tab_locked_notify (GimpDockable *dockable,
GParamSpec *pspec,
GimpDockbook *dockbook)
{
gboolean locked = gimp_dockable_get_locked (dockable);
gtk_notebook_set_tab_reorderable (GTK_NOTEBOOK (dockbook),
GTK_WIDGET (dockable), ! locked);
gtk_notebook_set_tab_detachable (GTK_NOTEBOOK (dockbook),
GTK_WIDGET (dockable), ! locked);
}
static void
gimp_dockbook_help_func (const gchar *help_id,
gpointer help_data)
{
GimpDockbook *dockbook = GIMP_DOCKBOOK (help_data);
GtkWidget *dockable;
gint page_num;
page_num = gtk_notebook_get_current_page (GTK_NOTEBOOK (dockbook));
dockable = gtk_notebook_get_nth_page (GTK_NOTEBOOK (dockbook), page_num);
if (GIMP_IS_DOCKABLE (dockable))
gimp_standard_help_func (gimp_dockable_get_help_id (GIMP_DOCKABLE (dockable)),
NULL);
else
gimp_standard_help_func (GIMP_HELP_DOCK, NULL);
}