mirror of https://github.com/GNOME/gimp.git
app: Popup menu at rect in GimpEditor
Rather than trying to fix up our own heuristics using a `GtkMenuPositionFunc`, use whatever GTK provides to position given a specific rectangle, which also has the benefit of nicely integrating with GDK backends such as Wayland. Another advantage is that we can use GdkGravity to center the popup. Since GTK 3, GtkWidget also gained a "popup-menu" signal, which we can/should use instead of rolling our own context signals.
This commit is contained in:
parent
67fd1f0c52
commit
eed28c0941
|
@ -58,7 +58,11 @@ static void gimp_colormap_editor_color_update (GimpColorDialog *dialog
|
|||
GimpColorDialogState state,
|
||||
GimpColormapEditor *editor);
|
||||
|
||||
static void gimp_colormap_editor_entry_popup (GimpEditor *editor);
|
||||
static gboolean gimp_colormap_editor_entry_button_press (GtkWidget *widget,
|
||||
GdkEvent *event,
|
||||
gpointer user_data);
|
||||
static gboolean gimp_colormap_editor_entry_popup (GtkWidget *widget,
|
||||
gpointer user_data);
|
||||
static void gimp_colormap_editor_color_clicked (GimpColormapEditor *editor,
|
||||
GimpPaletteEntry *entry,
|
||||
GdkModifierType state);
|
||||
|
@ -177,15 +181,18 @@ gimp_colormap_editor_set_context (GimpDocked *docked,
|
|||
gtk_box_pack_start (GTK_BOX (editor), editor->selection, TRUE, TRUE, 0);
|
||||
gtk_widget_show (editor->selection);
|
||||
|
||||
g_signal_connect_swapped (editor->selection, "color-context",
|
||||
G_CALLBACK (gimp_colormap_editor_entry_popup),
|
||||
editor);
|
||||
g_signal_connect_swapped (editor->selection, "color-clicked",
|
||||
G_CALLBACK (gimp_colormap_editor_color_clicked),
|
||||
editor);
|
||||
g_signal_connect_swapped (editor->selection, "color-activated",
|
||||
G_CALLBACK (gimp_colormap_editor_edit_color),
|
||||
editor);
|
||||
g_signal_connect (editor->selection, "button-press-event",
|
||||
G_CALLBACK (gimp_colormap_editor_entry_button_press),
|
||||
editor);
|
||||
g_signal_connect (editor->selection, "popup-menu",
|
||||
G_CALLBACK (gimp_colormap_editor_entry_popup),
|
||||
editor);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -361,10 +368,38 @@ gimp_colormap_editor_color_update (GimpColorDialog *dialog,
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gimp_colormap_editor_entry_popup (GimpEditor *editor)
|
||||
static gboolean
|
||||
gimp_colormap_editor_entry_button_press (GtkWidget *widget,
|
||||
GdkEvent *event,
|
||||
gpointer user_data)
|
||||
{
|
||||
gimp_editor_popup_menu (editor, NULL, NULL);
|
||||
if (gdk_event_triggers_context_menu (event))
|
||||
{
|
||||
gimp_editor_popup_menu_at_pointer (GIMP_EDITOR (user_data), event);
|
||||
return GDK_EVENT_STOP;
|
||||
}
|
||||
|
||||
return GDK_EVENT_PROPAGATE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gimp_colormap_editor_entry_popup (GtkWidget *widget,
|
||||
gpointer user_data)
|
||||
{
|
||||
GimpColormapEditor *editor = GIMP_COLORMAP_EDITOR (user_data);
|
||||
GimpColormapSelection *selection = GIMP_COLORMAP_SELECTION (widget);
|
||||
GimpPaletteEntry *selected;
|
||||
GdkRectangle rect;
|
||||
|
||||
selected = gimp_colormap_selection_get_selected_entry (selection);
|
||||
if (!selected)
|
||||
return GDK_EVENT_PROPAGATE;
|
||||
|
||||
gimp_colormap_selection_get_entry_rect (selection, selected, &rect);
|
||||
return gimp_editor_popup_menu_at_rect (GIMP_EDITOR (editor),
|
||||
gtk_widget_get_window (widget),
|
||||
&rect, GDK_GRAVITY_CENTER, GDK_GRAVITY_NORTH_WEST,
|
||||
NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
@ -58,7 +58,6 @@ enum
|
|||
|
||||
enum
|
||||
{
|
||||
COLOR_CONTEXT,
|
||||
COLOR_CLICKED,
|
||||
COLOR_ACTIVATED,
|
||||
LAST_SIGNAL
|
||||
|
@ -106,9 +105,6 @@ static void gimp_colormap_selection_entry_selected (GimpPaletteView *vi
|
|||
static void gimp_colormap_selection_entry_activated (GimpPaletteView *view,
|
||||
GimpPaletteEntry *entry,
|
||||
GimpColormapSelection *selection);
|
||||
static void gimp_colormap_selection_entry_context (GimpPaletteView *view,
|
||||
GimpPaletteEntry *entry,
|
||||
GimpColormapSelection *selection);
|
||||
static void gimp_colormap_selection_color_dropped (GimpPaletteView *view,
|
||||
GimpPaletteEntry *entry,
|
||||
const GimpRGB *color,
|
||||
|
@ -137,14 +133,6 @@ gimp_colormap_selection_class_init (GimpColormapSelectionClass* klass)
|
|||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
|
||||
|
||||
signals[COLOR_CONTEXT] =
|
||||
g_signal_new ("color-context",
|
||||
G_TYPE_FROM_CLASS (klass),
|
||||
G_SIGNAL_RUN_FIRST,
|
||||
G_STRUCT_OFFSET (GimpColormapSelectionClass, color_context),
|
||||
NULL, NULL, NULL,
|
||||
G_TYPE_NONE, 1,
|
||||
G_TYPE_POINTER);
|
||||
signals[COLOR_CLICKED] =
|
||||
g_signal_new ("color-clicked",
|
||||
G_TYPE_FROM_CLASS (klass),
|
||||
|
@ -215,9 +203,6 @@ gimp_colormap_selection_init (GimpColormapSelection *selection)
|
|||
g_signal_connect (selection->view, "entry-activated",
|
||||
G_CALLBACK (gimp_colormap_selection_entry_activated),
|
||||
selection);
|
||||
g_signal_connect (selection->view, "entry-context",
|
||||
G_CALLBACK (gimp_colormap_selection_entry_context),
|
||||
selection);
|
||||
g_signal_connect (selection->view, "color-dropped",
|
||||
G_CALLBACK (gimp_colormap_selection_color_dropped),
|
||||
selection);
|
||||
|
@ -471,6 +456,32 @@ gimp_colormap_selection_max_index (GimpColormapSelection *selection)
|
|||
return MAX (0, gimp_image_get_colormap_size (image) - 1);
|
||||
}
|
||||
|
||||
GimpPaletteEntry *
|
||||
gimp_colormap_selection_get_selected_entry (GimpColormapSelection *selection)
|
||||
{
|
||||
g_return_val_if_fail (GIMP_IS_COLORMAP_SELECTION (selection), NULL);
|
||||
|
||||
return gimp_palette_view_get_selected_entry (GIMP_PALETTE_VIEW (selection->view));
|
||||
}
|
||||
|
||||
void
|
||||
gimp_colormap_selection_get_entry_rect (GimpColormapSelection *selection,
|
||||
GimpPaletteEntry *entry,
|
||||
GdkRectangle *rect)
|
||||
{
|
||||
GtkAllocation allocation;
|
||||
|
||||
g_return_if_fail (GIMP_IS_COLORMAP_SELECTION (selection));
|
||||
g_return_if_fail (entry);
|
||||
g_return_if_fail (rect);
|
||||
|
||||
gimp_palette_view_get_entry_rect (GIMP_PALETTE_VIEW (selection->view),
|
||||
entry, rect);
|
||||
gtk_widget_get_allocation (GTK_WIDGET (selection), &allocation);
|
||||
/* rect->x += allocation.x; */
|
||||
/* rect->y += allocation.y; */
|
||||
}
|
||||
|
||||
|
||||
/* private functions */
|
||||
|
||||
|
@ -603,16 +614,6 @@ gimp_colormap_selection_entry_activated (GimpPaletteView *view,
|
|||
g_signal_emit (selection, signals[COLOR_ACTIVATED], 0, entry);
|
||||
}
|
||||
|
||||
static void
|
||||
gimp_colormap_selection_entry_context (GimpPaletteView *view,
|
||||
GimpPaletteEntry *entry,
|
||||
GimpColormapSelection *selection)
|
||||
{
|
||||
gimp_colormap_selection_set_index (selection, entry->position, NULL);
|
||||
|
||||
g_signal_emit (selection, signals[COLOR_CONTEXT], 0, entry);
|
||||
}
|
||||
|
||||
static void
|
||||
gimp_colormap_selection_color_dropped (GimpPaletteView *view,
|
||||
GimpPaletteEntry *entry,
|
||||
|
|
|
@ -54,8 +54,6 @@ struct _GimpColormapSelectionClass
|
|||
{
|
||||
GtkBoxClass parent_class;
|
||||
|
||||
void (* color_context) (GimpColormapSelection *selection,
|
||||
GimpPaletteEntry *entry);
|
||||
void (* color_clicked) (GimpColormapSelection *selection,
|
||||
GimpPaletteEntry *entry,
|
||||
GdkModifierType state);
|
||||
|
@ -76,6 +74,11 @@ gboolean gimp_colormap_selection_set_index (GimpColormapSelection *selection
|
|||
|
||||
gint gimp_colormap_selection_max_index (GimpColormapSelection *selection);
|
||||
|
||||
GimpPaletteEntry * gimp_colormap_selection_get_selected_entry (GimpColormapSelection *selection);
|
||||
|
||||
void gimp_colormap_selection_get_entry_rect (GimpColormapSelection *selection,
|
||||
GimpPaletteEntry *entry,
|
||||
GdkRectangle *rect);
|
||||
|
||||
#endif /* __GIMP_COLORMAP_SELECTION_H__ */
|
||||
|
||||
|
|
|
@ -93,12 +93,6 @@ static void gimp_container_editor_activate_item (GtkWidget *widge
|
|||
GimpViewable *viewable,
|
||||
gpointer insert_data,
|
||||
GimpContainerEditor *editor);
|
||||
static void gimp_container_editor_context_item (GtkWidget *widget,
|
||||
GimpViewable *viewable,
|
||||
gpointer insert_data,
|
||||
GimpContainerEditor *editor);
|
||||
static void gimp_container_editor_real_context_item(GimpContainerEditor *editor,
|
||||
GimpViewable *viewable);
|
||||
|
||||
static GtkWidget * gimp_container_editor_get_preview (GimpDocked *docked,
|
||||
GimpContext *context,
|
||||
|
@ -136,7 +130,6 @@ gimp_container_editor_class_init (GimpContainerEditorClass *klass)
|
|||
|
||||
klass->select_item = NULL;
|
||||
klass->activate_item = NULL;
|
||||
klass->context_item = gimp_container_editor_real_context_item;
|
||||
|
||||
g_object_class_install_property (object_class, PROP_VIEW_TYPE,
|
||||
g_param_spec_enum ("view-type",
|
||||
|
@ -288,9 +281,9 @@ gimp_container_editor_constructed (GObject *object)
|
|||
g_signal_connect_object (editor->view, "activate-item",
|
||||
G_CALLBACK (gimp_container_editor_activate_item),
|
||||
editor, 0);
|
||||
g_signal_connect_object (editor->view, "context-item",
|
||||
G_CALLBACK (gimp_container_editor_context_item),
|
||||
editor, 0);
|
||||
/* g_signal_connect_object (editor->view, "context-item", XXX maybe listen to popup-menu? */
|
||||
/* G_CALLBACK (gimp_container_editor_context_item), */
|
||||
/* editor, 0); */
|
||||
|
||||
{
|
||||
GimpObject *object = gimp_context_get_by_type (editor->priv->context,
|
||||
|
@ -461,30 +454,6 @@ gimp_container_editor_activate_item (GtkWidget *widget,
|
|||
klass->activate_item (editor, viewable);
|
||||
}
|
||||
|
||||
static void
|
||||
gimp_container_editor_context_item (GtkWidget *widget,
|
||||
GimpViewable *viewable,
|
||||
gpointer insert_data,
|
||||
GimpContainerEditor *editor)
|
||||
{
|
||||
GimpContainerEditorClass *klass = GIMP_CONTAINER_EDITOR_GET_CLASS (editor);
|
||||
|
||||
if (klass->context_item)
|
||||
klass->context_item (editor, viewable);
|
||||
}
|
||||
|
||||
static void
|
||||
gimp_container_editor_real_context_item (GimpContainerEditor *editor,
|
||||
GimpViewable *viewable)
|
||||
{
|
||||
GimpContainer *container = gimp_container_view_get_container (editor->view);
|
||||
|
||||
if (viewable && gimp_container_have (container, GIMP_OBJECT (viewable)))
|
||||
{
|
||||
gimp_editor_popup_menu (GIMP_EDITOR (editor->view), NULL, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static GtkWidget *
|
||||
gimp_container_editor_get_preview (GimpDocked *docked,
|
||||
GimpContext *context,
|
||||
|
|
|
@ -50,8 +50,6 @@ struct _GimpContainerEditorClass
|
|||
GimpViewable *object);
|
||||
void (* activate_item) (GimpContainerEditor *editor,
|
||||
GimpViewable *object);
|
||||
void (* context_item) (GimpContainerEditor *editor,
|
||||
GimpViewable *object);
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -241,68 +241,25 @@ gimp_container_icon_view_unmap (GtkWidget *widget)
|
|||
GTK_WIDGET_CLASS (parent_class)->unmap (widget);
|
||||
}
|
||||
|
||||
static void
|
||||
gimp_container_icon_view_menu_position (GtkMenu *menu,
|
||||
gint *x,
|
||||
gint *y,
|
||||
gpointer data)
|
||||
{
|
||||
GimpContainerIconView *icon_view = GIMP_CONTAINER_ICON_VIEW (data);
|
||||
GtkWidget *widget = GTK_WIDGET (icon_view->view);
|
||||
GtkAllocation allocation;
|
||||
#if 0
|
||||
GtkTreeIter selected_iter;
|
||||
#endif
|
||||
|
||||
gtk_widget_get_allocation (widget, &allocation);
|
||||
|
||||
gdk_window_get_origin (gtk_widget_get_window (widget), x, y);
|
||||
|
||||
if (! gtk_widget_get_has_window (widget))
|
||||
{
|
||||
*x += allocation.x;
|
||||
*y += allocation.y;
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (gimp_container_icon_view_get_selected_single (icon_view, &selected_iter))
|
||||
{
|
||||
GtkTreePath *path;
|
||||
GdkRectangle cell_rect;
|
||||
gint center;
|
||||
|
||||
path = gtk_tree_model_get_path (icon_view->model, &selected_iter);
|
||||
gtk_icon_view_get_cell_area (icon_view->view, path,
|
||||
icon_view->main_column, &cell_rect);
|
||||
gtk_tree_path_free (path);
|
||||
|
||||
center = cell_rect.y + cell_rect.height / 2;
|
||||
center = CLAMP (center, 0, allocation.height);
|
||||
|
||||
*x += allocation.width / 2;
|
||||
*y += center;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
GtkStyleContext *style = gtk_widget_get_style_context (widget);
|
||||
GtkBorder border;
|
||||
|
||||
gtk_style_context_get_border (style, 0, &border);
|
||||
|
||||
*x += border.left;
|
||||
*y += border.top;
|
||||
}
|
||||
|
||||
gimp_menu_position (menu, x, y);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gimp_container_icon_view_popup_menu (GtkWidget *widget)
|
||||
{
|
||||
return gimp_editor_popup_menu (GIMP_EDITOR (widget),
|
||||
gimp_container_icon_view_menu_position,
|
||||
widget);
|
||||
GimpContainerIconView *icon_view = GIMP_CONTAINER_ICON_VIEW (widget);
|
||||
GtkTreeIter iter;
|
||||
GtkTreePath *path;
|
||||
GdkRectangle rect;
|
||||
|
||||
if (!gimp_container_icon_view_get_selected_single (icon_view, &iter))
|
||||
return FALSE;
|
||||
|
||||
path = gtk_tree_model_get_path (icon_view->model, &iter);
|
||||
gtk_icon_view_get_cell_rect (icon_view->view, path, NULL, &rect);
|
||||
gtk_tree_path_free (path);
|
||||
|
||||
return gimp_editor_popup_menu_at_rect (GIMP_EDITOR (widget),
|
||||
gtk_widget_get_window (GTK_WIDGET (icon_view->view)),
|
||||
&rect, GDK_GRAVITY_CENTER, GDK_GRAVITY_NORTH_WEST,
|
||||
NULL);
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
|
@ -638,6 +595,7 @@ gimp_container_icon_view_button_press (GtkWidget *widget,
|
|||
GdkEventButton *bevent,
|
||||
GimpContainerIconView *icon_view)
|
||||
{
|
||||
GimpContainerView *container_view = GIMP_CONTAINER_VIEW (icon_view);
|
||||
GtkTreePath *path;
|
||||
|
||||
icon_view->priv->dnd_renderer = NULL;
|
||||
|
@ -658,10 +616,32 @@ gimp_container_icon_view_button_press (GtkWidget *widget,
|
|||
|
||||
icon_view->priv->dnd_renderer = renderer;
|
||||
|
||||
if (gdk_event_triggers_context_menu ((GdkEvent *) bevent))
|
||||
{
|
||||
/* If the clicked item is not selected, it becomes the new
|
||||
* selection. Otherwise, we use the current selection. This
|
||||
* allows to not break multiple selection when right-clicking.
|
||||
*/
|
||||
if (! gimp_container_view_is_item_selected (container_view, renderer->viewable))
|
||||
gimp_container_view_item_selected (container_view, renderer->viewable);
|
||||
/* Show the context menu. */
|
||||
if (gimp_container_view_get_container (container_view))
|
||||
gimp_editor_popup_menu_at_pointer (GIMP_EDITOR (icon_view), (GdkEvent *) bevent);
|
||||
}
|
||||
|
||||
g_object_unref (renderer);
|
||||
|
||||
gtk_tree_path_free (path);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (gdk_event_triggers_context_menu ((GdkEvent *) bevent))
|
||||
{
|
||||
gimp_editor_popup_menu_at_pointer (GIMP_EDITOR (icon_view), (GdkEvent *) bevent);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
|
|
@ -420,64 +420,26 @@ gimp_container_tree_view_unmap (GtkWidget *widget)
|
|||
GTK_WIDGET_CLASS (parent_class)->unmap (widget);
|
||||
}
|
||||
|
||||
static void
|
||||
gimp_container_tree_view_menu_position (GtkMenu *menu,
|
||||
gint *x,
|
||||
gint *y,
|
||||
gpointer data)
|
||||
{
|
||||
GimpContainerTreeView *tree_view = GIMP_CONTAINER_TREE_VIEW (data);
|
||||
GtkWidget *widget = GTK_WIDGET (tree_view->view);
|
||||
GtkAllocation allocation;
|
||||
GtkTreeIter selected_iter;
|
||||
|
||||
gtk_widget_get_allocation (widget, &allocation);
|
||||
|
||||
gdk_window_get_origin (gtk_widget_get_window (widget), x, y);
|
||||
|
||||
if (! gtk_widget_get_has_window (widget))
|
||||
{
|
||||
*x += allocation.x;
|
||||
*y += allocation.y;
|
||||
}
|
||||
|
||||
if (gimp_container_tree_view_get_selected_single (tree_view, &selected_iter))
|
||||
{
|
||||
GtkTreePath *path;
|
||||
GdkRectangle cell_rect;
|
||||
gint center;
|
||||
|
||||
path = gtk_tree_model_get_path (tree_view->model, &selected_iter);
|
||||
gtk_tree_view_get_cell_area (tree_view->view, path,
|
||||
tree_view->main_column, &cell_rect);
|
||||
gtk_tree_path_free (path);
|
||||
|
||||
center = cell_rect.y + cell_rect.height / 2;
|
||||
center = CLAMP (center, 0, allocation.height);
|
||||
|
||||
*x += allocation.width / 2;
|
||||
*y += center;
|
||||
}
|
||||
else
|
||||
{
|
||||
GtkStyleContext *style = gtk_widget_get_style_context (widget);
|
||||
GtkBorder border;
|
||||
|
||||
gtk_style_context_get_border (style, 0, &border);
|
||||
|
||||
*x += border.left;
|
||||
*y += border.top;
|
||||
}
|
||||
|
||||
gimp_menu_position (menu, x, y);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gimp_container_tree_view_popup_menu (GtkWidget *widget)
|
||||
{
|
||||
return gimp_editor_popup_menu (GIMP_EDITOR (widget),
|
||||
gimp_container_tree_view_menu_position,
|
||||
widget);
|
||||
GimpContainerTreeView *tree_view = GIMP_CONTAINER_TREE_VIEW (widget);
|
||||
GtkTreeIter iter;
|
||||
GtkTreePath *path;
|
||||
GdkRectangle rect;
|
||||
|
||||
if (!gimp_container_tree_view_get_selected_single (tree_view, &iter))
|
||||
return FALSE;
|
||||
|
||||
path = gtk_tree_model_get_path (tree_view->model, &iter);
|
||||
gtk_tree_view_get_cell_area (tree_view->view, path,
|
||||
tree_view->main_column, &rect);
|
||||
gtk_tree_path_free (path);
|
||||
|
||||
return gimp_editor_popup_menu_at_rect (GIMP_EDITOR (widget),
|
||||
gtk_tree_view_get_bin_window (tree_view->view),
|
||||
&rect, GDK_GRAVITY_CENTER, GDK_GRAVITY_NORTH_WEST,
|
||||
NULL);
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
|
@ -1484,7 +1446,7 @@ gimp_container_tree_view_button (GtkWidget *widget,
|
|||
gimp_container_view_item_selected (container_view, renderer->viewable);
|
||||
/* Show the context menu. */
|
||||
if (gimp_container_view_get_container (container_view))
|
||||
gimp_container_view_item_context (container_view, renderer->viewable);
|
||||
gimp_editor_popup_menu_at_pointer (GIMP_EDITOR (tree_view), (GdkEvent *) bevent);
|
||||
}
|
||||
else if (bevent->button == 1)
|
||||
{
|
||||
|
|
|
@ -48,7 +48,6 @@ enum
|
|||
SELECT_ITEM,
|
||||
SELECT_ITEMS,
|
||||
ACTIVATE_ITEM,
|
||||
CONTEXT_ITEM,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
|
@ -191,21 +190,9 @@ gimp_container_view_default_init (GimpContainerViewInterface *iface)
|
|||
GIMP_TYPE_OBJECT,
|
||||
G_TYPE_POINTER);
|
||||
|
||||
view_signals[CONTEXT_ITEM] =
|
||||
g_signal_new ("context-item",
|
||||
G_TYPE_FROM_INTERFACE (iface),
|
||||
G_SIGNAL_RUN_FIRST,
|
||||
G_STRUCT_OFFSET (GimpContainerViewInterface, context_item),
|
||||
NULL, NULL,
|
||||
gimp_marshal_VOID__OBJECT_POINTER,
|
||||
G_TYPE_NONE, 2,
|
||||
GIMP_TYPE_OBJECT,
|
||||
G_TYPE_POINTER);
|
||||
|
||||
iface->select_item = NULL;
|
||||
iface->select_items = NULL;
|
||||
iface->activate_item = NULL;
|
||||
iface->context_item = NULL;
|
||||
|
||||
iface->set_container = gimp_container_view_real_set_container;
|
||||
iface->set_context = gimp_container_view_real_set_context;
|
||||
|
@ -709,27 +696,6 @@ gimp_container_view_activate_item (GimpContainerView *view,
|
|||
viewable, insert_data);
|
||||
}
|
||||
|
||||
void
|
||||
gimp_container_view_context_item (GimpContainerView *view,
|
||||
GimpViewable *viewable)
|
||||
{
|
||||
GimpContainerViewPrivate *private;
|
||||
gpointer insert_data;
|
||||
|
||||
g_return_if_fail (GIMP_IS_CONTAINER_VIEW (view));
|
||||
g_return_if_fail (GIMP_IS_VIEWABLE (viewable));
|
||||
|
||||
private = GIMP_CONTAINER_VIEW_GET_PRIVATE (view);
|
||||
|
||||
if (gimp_container_frozen (private->container))
|
||||
return;
|
||||
|
||||
insert_data = g_hash_table_lookup (private->item_hash, viewable);
|
||||
|
||||
g_signal_emit (view, view_signals[CONTEXT_ITEM], 0,
|
||||
viewable, insert_data);
|
||||
}
|
||||
|
||||
gpointer
|
||||
gimp_container_view_lookup (GimpContainerView *view,
|
||||
GimpViewable *viewable)
|
||||
|
@ -975,16 +941,6 @@ gimp_container_view_item_activated (GimpContainerView *view,
|
|||
gimp_container_view_activate_item (view, viewable);
|
||||
}
|
||||
|
||||
void
|
||||
gimp_container_view_item_context (GimpContainerView *view,
|
||||
GimpViewable *viewable)
|
||||
{
|
||||
g_return_if_fail (GIMP_IS_CONTAINER_VIEW (view));
|
||||
g_return_if_fail (GIMP_IS_VIEWABLE (viewable));
|
||||
|
||||
gimp_container_view_context_item (view, viewable);
|
||||
}
|
||||
|
||||
void
|
||||
gimp_container_view_set_property (GObject *object,
|
||||
guint property_id,
|
||||
|
|
|
@ -54,9 +54,6 @@ struct _GimpContainerViewInterface
|
|||
void (* activate_item) (GimpContainerView *view,
|
||||
GimpViewable *object,
|
||||
gpointer insert_data);
|
||||
void (* context_item) (GimpContainerView *view,
|
||||
GimpViewable *object,
|
||||
gpointer insert_data);
|
||||
|
||||
/* virtual functions */
|
||||
void (* set_container) (GimpContainerView *view,
|
||||
|
@ -133,8 +130,6 @@ gboolean gimp_container_view_select_item (GimpContainerView *v
|
|||
GimpViewable *viewable);
|
||||
void gimp_container_view_activate_item (GimpContainerView *view,
|
||||
GimpViewable *viewable);
|
||||
void gimp_container_view_context_item (GimpContainerView *view,
|
||||
GimpViewable *viewable);
|
||||
gint gimp_container_view_get_selected (GimpContainerView *view,
|
||||
GList **items,
|
||||
GList **items_data);
|
||||
|
@ -156,8 +151,6 @@ gboolean gimp_container_view_multi_selected (GimpContainerView *v
|
|||
GList *paths);
|
||||
void gimp_container_view_item_activated (GimpContainerView *view,
|
||||
GimpViewable *item);
|
||||
void gimp_container_view_item_context (GimpContainerView *view,
|
||||
GimpViewable *item);
|
||||
|
||||
/* convenience functions */
|
||||
|
||||
|
|
|
@ -482,6 +482,28 @@ gimp_editor_popup_menu_at_pointer (GimpEditor *editor,
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gimp_editor_popup_menu_at_rect (GimpEditor *editor,
|
||||
GdkWindow *window,
|
||||
const GdkRectangle *rect,
|
||||
GdkGravity rect_anchor,
|
||||
GdkGravity menu_anchor,
|
||||
const GdkEvent *trigger_event)
|
||||
{
|
||||
g_return_val_if_fail (GIMP_IS_EDITOR (editor), FALSE);
|
||||
|
||||
if (editor->priv->ui_manager && editor->priv->ui_path)
|
||||
{
|
||||
gimp_ui_manager_update (editor->priv->ui_manager, editor->priv->popup_data);
|
||||
gimp_ui_manager_ui_popup_at_rect (editor->priv->ui_manager, editor->priv->ui_path,
|
||||
window, rect, rect_anchor, menu_anchor,
|
||||
trigger_event, NULL, NULL);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
gimp_editor_add_button (GimpEditor *editor,
|
||||
const gchar *icon_name,
|
||||
|
|
|
@ -61,6 +61,12 @@ gboolean gimp_editor_popup_menu (GimpEditor *editor,
|
|||
gboolean gimp_editor_popup_menu_at_pointer
|
||||
(GimpEditor *editor,
|
||||
const GdkEvent *trigger_event);
|
||||
gboolean gimp_editor_popup_menu_at_rect (GimpEditor *editor,
|
||||
GdkWindow *window,
|
||||
const GdkRectangle *rect,
|
||||
GdkGravity rect_anchor,
|
||||
GdkGravity menu_anchor,
|
||||
const GdkEvent *trigger_event);
|
||||
|
||||
GtkWidget * gimp_editor_add_button (GimpEditor *editor,
|
||||
const gchar *icon_name,
|
||||
|
|
|
@ -134,9 +134,6 @@ static gboolean gimp_item_tree_view_select_items (GimpContainerView *view,
|
|||
static void gimp_item_tree_view_activate_item (GimpContainerView *view,
|
||||
GimpViewable *item,
|
||||
gpointer insert_data);
|
||||
static void gimp_item_tree_view_context_item (GimpContainerView *view,
|
||||
GimpViewable *item,
|
||||
gpointer insert_data);
|
||||
|
||||
static gboolean gimp_item_tree_view_drop_possible (GimpContainerTreeView *view,
|
||||
GimpDndType src_type,
|
||||
|
@ -307,7 +304,6 @@ gimp_item_tree_view_view_iface_init (GimpContainerViewInterface *iface)
|
|||
iface->select_item = gimp_item_tree_view_select_item;
|
||||
iface->select_items = gimp_item_tree_view_select_items;
|
||||
iface->activate_item = gimp_item_tree_view_activate_item;
|
||||
iface->context_item = gimp_item_tree_view_context_item;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1182,17 +1178,6 @@ gimp_item_tree_view_activate_item (GimpContainerView *view,
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gimp_item_tree_view_context_item (GimpContainerView *view,
|
||||
GimpViewable *item,
|
||||
gpointer insert_data)
|
||||
{
|
||||
if (parent_view_iface->context_item)
|
||||
parent_view_iface->context_item (view, item, insert_data);
|
||||
|
||||
gimp_editor_popup_menu (GIMP_EDITOR (view), NULL, NULL);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gimp_item_tree_view_drop_possible (GimpContainerTreeView *tree_view,
|
||||
GimpDndType src_type,
|
||||
|
|
|
@ -106,9 +106,11 @@ static void palette_editor_entry_selected (GimpPaletteView *view,
|
|||
static void palette_editor_entry_activated (GimpPaletteView *view,
|
||||
GimpPaletteEntry *entry,
|
||||
GimpPaletteEditor *editor);
|
||||
static void palette_editor_entry_context (GimpPaletteView *view,
|
||||
GimpPaletteEntry *entry,
|
||||
GimpPaletteEditor *editor);
|
||||
static gboolean palette_editor_button_press_event (GtkWidget *widget,
|
||||
GdkEvent *event,
|
||||
gpointer user_data);
|
||||
static gboolean palette_editor_popup_menu (GtkWidget *widget,
|
||||
gpointer user_data);
|
||||
static void palette_editor_color_dropped (GimpPaletteView *view,
|
||||
GimpPaletteEntry *entry,
|
||||
const GimpRGB *color,
|
||||
|
@ -219,12 +221,15 @@ gimp_palette_editor_init (GimpPaletteEditor *editor)
|
|||
g_signal_connect (editor->view, "entry-activated",
|
||||
G_CALLBACK (palette_editor_entry_activated),
|
||||
editor);
|
||||
g_signal_connect (editor->view, "entry-context",
|
||||
G_CALLBACK (palette_editor_entry_context),
|
||||
editor);
|
||||
g_signal_connect (editor->view, "color-dropped",
|
||||
G_CALLBACK (palette_editor_color_dropped),
|
||||
editor);
|
||||
g_signal_connect (editor->view, "button-press-event",
|
||||
G_CALLBACK (palette_editor_button_press_event),
|
||||
editor);
|
||||
g_signal_connect (editor->view, "popup-menu",
|
||||
G_CALLBACK (palette_editor_popup_menu),
|
||||
editor);
|
||||
|
||||
gimp_dnd_viewable_dest_add (editor->view,
|
||||
GIMP_TYPE_PALETTE,
|
||||
|
@ -825,12 +830,39 @@ palette_editor_entry_activated (GimpPaletteView *view,
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
palette_editor_entry_context (GimpPaletteView *view,
|
||||
GimpPaletteEntry *entry,
|
||||
GimpPaletteEditor *editor)
|
||||
static gboolean
|
||||
palette_editor_button_press_event (GtkWidget *widget,
|
||||
GdkEvent *event,
|
||||
gpointer user_data)
|
||||
{
|
||||
gimp_editor_popup_menu (GIMP_EDITOR (editor), NULL, NULL);
|
||||
GimpPaletteEditor *editor = GIMP_PALETTE_EDITOR (user_data);
|
||||
|
||||
if (gdk_event_triggers_context_menu (event))
|
||||
{
|
||||
gimp_editor_popup_menu_at_pointer (GIMP_EDITOR (editor), event);
|
||||
return GDK_EVENT_STOP;
|
||||
}
|
||||
|
||||
return GDK_EVENT_PROPAGATE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
palette_editor_popup_menu (GtkWidget *widget,
|
||||
gpointer user_data)
|
||||
{
|
||||
GimpPaletteEditor *editor = GIMP_PALETTE_EDITOR (user_data);
|
||||
GimpPaletteEntry *selected;
|
||||
GdkRectangle rect;
|
||||
|
||||
selected = gimp_palette_view_get_selected_entry (GIMP_PALETTE_VIEW (editor->view));
|
||||
if (!selected)
|
||||
return GDK_EVENT_PROPAGATE;
|
||||
|
||||
gimp_palette_view_get_entry_rect (GIMP_PALETTE_VIEW (editor->view), selected, &rect);
|
||||
return gimp_editor_popup_menu_at_rect (GIMP_EDITOR (editor),
|
||||
gtk_widget_get_window (GTK_WIDGET (editor->view)),
|
||||
&rect, GDK_GRAVITY_CENTER, GDK_GRAVITY_NORTH_WEST,
|
||||
NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
@ -42,7 +42,6 @@ enum
|
|||
ENTRY_CLICKED,
|
||||
ENTRY_SELECTED,
|
||||
ENTRY_ACTIVATED,
|
||||
ENTRY_CONTEXT,
|
||||
COLOR_DROPPED,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
@ -119,15 +118,6 @@ gimp_palette_view_class_init (GimpPaletteViewClass *klass)
|
|||
G_TYPE_NONE, 1,
|
||||
G_TYPE_POINTER);
|
||||
|
||||
view_signals[ENTRY_CONTEXT] =
|
||||
g_signal_new ("entry-context",
|
||||
G_TYPE_FROM_CLASS (klass),
|
||||
G_SIGNAL_RUN_FIRST,
|
||||
G_STRUCT_OFFSET (GimpPaletteViewClass, entry_context),
|
||||
NULL, NULL, NULL,
|
||||
G_TYPE_NONE, 1,
|
||||
G_TYPE_POINTER);
|
||||
|
||||
view_signals[COLOR_DROPPED] =
|
||||
g_signal_new ("color-dropped",
|
||||
G_TYPE_FROM_CLASS (klass),
|
||||
|
@ -226,7 +216,9 @@ gimp_palette_view_button_press (GtkWidget *widget,
|
|||
if (entry != view->selected)
|
||||
gimp_palette_view_select_entry (view, entry);
|
||||
|
||||
g_signal_emit (view, view_signals[ENTRY_CONTEXT], 0, entry);
|
||||
/* Usually the menu is provided by a GimpEditor.
|
||||
* Make sure it's also run by returning FALSE here */
|
||||
return FALSE;
|
||||
}
|
||||
else if (bevent->button == 1)
|
||||
{
|
||||
|
@ -404,6 +396,39 @@ gimp_palette_view_select_entry (GimpPaletteView *view,
|
|||
g_signal_emit (view, view_signals[ENTRY_SELECTED], 0, view->selected);
|
||||
}
|
||||
|
||||
GimpPaletteEntry *
|
||||
gimp_palette_view_get_selected_entry (GimpPaletteView *view)
|
||||
{
|
||||
g_return_val_if_fail (GIMP_IS_PALETTE_VIEW (view), NULL);
|
||||
|
||||
return view->selected;
|
||||
}
|
||||
|
||||
void
|
||||
gimp_palette_view_get_entry_rect (GimpPaletteView *view,
|
||||
GimpPaletteEntry *entry,
|
||||
GdkRectangle *rect)
|
||||
{
|
||||
GimpViewRendererPalette *renderer;
|
||||
GtkAllocation allocation;
|
||||
gint row, col;
|
||||
|
||||
g_return_if_fail (GIMP_IS_PALETTE_VIEW (view));
|
||||
g_return_if_fail (entry);
|
||||
g_return_if_fail (rect);
|
||||
|
||||
gtk_widget_get_allocation (GTK_WIDGET (view), &allocation);
|
||||
|
||||
renderer = GIMP_VIEW_RENDERER_PALETTE (GIMP_VIEW (view)->renderer);
|
||||
row = entry->position / renderer->columns;
|
||||
col = entry->position % renderer->columns;
|
||||
|
||||
rect->x = allocation.x + col * renderer->cell_width;
|
||||
rect->y = allocation.y + row * renderer->cell_height;
|
||||
rect->width = renderer->cell_width;
|
||||
rect->height = renderer->cell_height;
|
||||
}
|
||||
|
||||
|
||||
/* private functions */
|
||||
|
||||
|
|
|
@ -66,5 +66,11 @@ GType gimp_palette_view_get_type (void) G_GNUC_CONST;
|
|||
void gimp_palette_view_select_entry (GimpPaletteView *view,
|
||||
GimpPaletteEntry *entry);
|
||||
|
||||
GimpPaletteEntry * gimp_palette_view_get_selected_entry (GimpPaletteView *view);
|
||||
|
||||
void gimp_palette_view_get_entry_rect (GimpPaletteView *view,
|
||||
GimpPaletteEntry *entry,
|
||||
GdkRectangle *rect);
|
||||
|
||||
|
||||
#endif /* __GIMP_PALETTE_VIEW_H__ */
|
||||
|
|
|
@ -801,6 +801,46 @@ gimp_ui_manager_ui_popup_at_pointer (GimpUIManager *manager,
|
|||
gtk_menu_popup_at_pointer (GTK_MENU (menu), trigger_event);
|
||||
}
|
||||
|
||||
void
|
||||
gimp_ui_manager_ui_popup_at_rect (GimpUIManager *manager,
|
||||
const gchar *ui_path,
|
||||
GdkWindow *window,
|
||||
const GdkRectangle *rect,
|
||||
GdkGravity rect_anchor,
|
||||
GdkGravity menu_anchor,
|
||||
const GdkEvent *trigger_event,
|
||||
GDestroyNotify popdown_func,
|
||||
gpointer popdown_data)
|
||||
{
|
||||
GtkWidget *menu;
|
||||
|
||||
g_return_if_fail (GIMP_IS_UI_MANAGER (manager));
|
||||
g_return_if_fail (ui_path != NULL);
|
||||
|
||||
menu = gimp_ui_manager_get_widget (manager, ui_path);
|
||||
|
||||
if (GTK_IS_MENU_ITEM (menu))
|
||||
menu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (menu));
|
||||
|
||||
if (! menu)
|
||||
return;
|
||||
|
||||
g_return_if_fail (GTK_IS_MENU (menu));
|
||||
|
||||
if (popdown_func && popdown_data)
|
||||
{
|
||||
g_object_set_data_full (G_OBJECT (manager), "popdown-data",
|
||||
popdown_data, popdown_func);
|
||||
g_signal_connect (menu, "selection-done",
|
||||
G_CALLBACK (gimp_ui_manager_delete_popdown_data),
|
||||
manager);
|
||||
}
|
||||
|
||||
gtk_menu_popup_at_rect (GTK_MENU (menu), window,
|
||||
rect, rect_anchor, menu_anchor,
|
||||
trigger_event);
|
||||
}
|
||||
|
||||
|
||||
/* private functions */
|
||||
|
||||
|
|
|
@ -148,6 +148,16 @@ void gimp_ui_manager_ui_popup_at_pointer
|
|||
const GdkEvent *trigger_event,
|
||||
GDestroyNotify popdown_func,
|
||||
gpointer popdown_data);
|
||||
void gimp_ui_manager_ui_popup_at_rect
|
||||
(GimpUIManager *manager,
|
||||
const gchar *ui_path,
|
||||
GdkWindow *window,
|
||||
const GdkRectangle *rect,
|
||||
GdkGravity rect_anchor,
|
||||
GdkGravity menu_anchor,
|
||||
const GdkEvent *trigger_event,
|
||||
GDestroyNotify popdown_func,
|
||||
gpointer popdown_data);
|
||||
|
||||
|
||||
#endif /* __GIMP_UI_MANAGER_H__ */
|
||||
|
|
Loading…
Reference in New Issue