📄 gtkmenu.c
字号:
/* GTK - The GIMP Toolkit * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library 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 * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. *//* * Modified by the GTK+ Team and others 1997-1999. See the AUTHORS * file for a list of people on the GTK+ Team. See the ChangeLog * files for a list of changes. These files are distributed with * GTK+ at ftp://ftp.gtk.org/pub/gtk/. */#include <ctype.h>#include "gdk/gdkkeysyms.h"#include "gtkbindings.h"#include "gtklabel.h"#include "gtkmain.h"#include "gtkmenu.h"#include "gtkmenuitem.h"#include "gtksignal.h"#include "gtkwindow.h"#define MENU_ITEM_CLASS(w) GTK_MENU_ITEM_CLASS (GTK_OBJECT (w)->klass)#define MENU_NEEDS_RESIZE(m) GTK_MENU_SHELL (m)->menu_flagtypedef struct _GtkMenuAttachData GtkMenuAttachData;struct _GtkMenuAttachData{ GtkWidget *attach_widget; GtkMenuDetachFunc detacher;};static void gtk_menu_class_init (GtkMenuClass *klass);static void gtk_menu_init (GtkMenu *menu);static void gtk_menu_destroy (GtkObject *object);static void gtk_menu_realize (GtkWidget *widget);static void gtk_menu_size_request (GtkWidget *widget, GtkRequisition *requisition);static void gtk_menu_size_allocate (GtkWidget *widget, GtkAllocation *allocation);static void gtk_menu_paint (GtkWidget *widget);static void gtk_menu_draw (GtkWidget *widget, GdkRectangle *area);static gint gtk_menu_expose (GtkWidget *widget, GdkEventExpose *event);static gint gtk_menu_key_press (GtkWidget *widget, GdkEventKey *event);static gint gtk_menu_motion_notify (GtkWidget *widget, GdkEventMotion *event);static void gtk_menu_deactivate (GtkMenuShell *menu_shell);static void gtk_menu_show_all (GtkWidget *widget);static void gtk_menu_hide_all (GtkWidget *widget);static void gtk_menu_position (GtkMenu *menu);static void gtk_menu_reparent (GtkMenu *menu, GtkWidget *new_parent, gboolean unrealize);static GtkMenuShellClass *parent_class = NULL;static const gchar *attach_data_key = "gtk-menu-attach-data";static GQuark quark_uline_accel_group = 0;GtkTypegtk_menu_get_type (void){ static GtkType menu_type = 0; if (!menu_type) { static const GtkTypeInfo menu_info = { "GtkMenu", sizeof (GtkMenu), sizeof (GtkMenuClass), (GtkClassInitFunc) gtk_menu_class_init, (GtkObjectInitFunc) gtk_menu_init, /* reserved_1 */ NULL, /* reserved_2 */ NULL, (GtkClassInitFunc) NULL, }; menu_type = gtk_type_unique (gtk_menu_shell_get_type (), &menu_info); } return menu_type;}static voidgtk_menu_class_init (GtkMenuClass *class){ GtkObjectClass *object_class; GtkWidgetClass *widget_class; GtkContainerClass *container_class; GtkMenuShellClass *menu_shell_class; GtkBindingSet *binding_set; object_class = (GtkObjectClass*) class; widget_class = (GtkWidgetClass*) class; container_class = (GtkContainerClass*) class; menu_shell_class = (GtkMenuShellClass*) class; parent_class = gtk_type_class (gtk_menu_shell_get_type ()); object_class->destroy = gtk_menu_destroy; widget_class->realize = gtk_menu_realize; widget_class->draw = gtk_menu_draw; widget_class->size_request = gtk_menu_size_request; widget_class->size_allocate = gtk_menu_size_allocate; widget_class->expose_event = gtk_menu_expose; widget_class->key_press_event = gtk_menu_key_press; widget_class->motion_notify_event = gtk_menu_motion_notify; widget_class->show_all = gtk_menu_show_all; widget_class->hide_all = gtk_menu_hide_all; menu_shell_class->submenu_placement = GTK_LEFT_RIGHT; menu_shell_class->deactivate = gtk_menu_deactivate; binding_set = gtk_binding_set_by_class (class); gtk_binding_entry_add_signal (binding_set, GDK_Up, 0, "move_current", 1, GTK_TYPE_MENU_DIRECTION_TYPE, GTK_MENU_DIR_PREV); gtk_binding_entry_add_signal (binding_set, GDK_Down, 0, "move_current", 1, GTK_TYPE_MENU_DIRECTION_TYPE, GTK_MENU_DIR_NEXT); gtk_binding_entry_add_signal (binding_set, GDK_Left, 0, "move_current", 1, GTK_TYPE_MENU_DIRECTION_TYPE, GTK_MENU_DIR_PARENT); gtk_binding_entry_add_signal (binding_set, GDK_Right, 0, "move_current", 1, GTK_TYPE_MENU_DIRECTION_TYPE, GTK_MENU_DIR_CHILD);}static gintgtk_menu_window_event (GtkWidget *window, GdkEvent *event, GtkWidget *menu){ gboolean handled = FALSE; gtk_widget_ref (window); gtk_widget_ref (menu); switch (event->type) { case GDK_KEY_PRESS: case GDK_KEY_RELEASE: gtk_widget_event (menu, event); handled = TRUE; break; default: break; } gtk_widget_unref (window); gtk_widget_unref (menu); return handled;}static voidgtk_menu_init (GtkMenu *menu){ menu->parent_menu_item = NULL; menu->old_active_menu_item = NULL; menu->accel_group = NULL; menu->position_func = NULL; menu->position_func_data = NULL; menu->toplevel = gtk_window_new (GTK_WINDOW_POPUP); gtk_signal_connect (GTK_OBJECT (menu->toplevel), "event", GTK_SIGNAL_FUNC (gtk_menu_window_event), GTK_OBJECT (menu)); gtk_window_set_policy (GTK_WINDOW (menu->toplevel), FALSE, FALSE, TRUE); gtk_container_add (GTK_CONTAINER (menu->toplevel), GTK_WIDGET (menu)); /* Refloat the menu, so that reference counting for the menu isn't * affected by it being a child of the toplevel */ GTK_WIDGET_SET_FLAGS (menu, GTK_FLOATING); menu->tearoff_window = NULL; menu->torn_off = FALSE; MENU_NEEDS_RESIZE (menu) = TRUE;}static voidgtk_menu_destroy (GtkObject *object){ GtkMenu *menu; GtkMenuAttachData *data; g_return_if_fail (object != NULL); g_return_if_fail (GTK_IS_MENU (object)); menu = GTK_MENU (object); gtk_object_ref (object); data = gtk_object_get_data (object, attach_data_key); if (data) gtk_menu_detach (menu); gtk_menu_set_accel_group (menu, NULL); if (menu->old_active_menu_item) { gtk_widget_unref (menu->old_active_menu_item); menu->old_active_menu_item = NULL; } /* Add back the reference count for being a child */ gtk_object_ref (object); gtk_widget_destroy (menu->toplevel); if (menu->tearoff_window) gtk_widget_destroy (menu->tearoff_window); if (GTK_OBJECT_CLASS (parent_class)->destroy) (* GTK_OBJECT_CLASS (parent_class)->destroy) (object); gtk_object_unref (object);}voidgtk_menu_attach_to_widget (GtkMenu *menu, GtkWidget *attach_widget, GtkMenuDetachFunc detacher){ GtkMenuAttachData *data; g_return_if_fail (menu != NULL); g_return_if_fail (GTK_IS_MENU (menu)); g_return_if_fail (attach_widget != NULL); g_return_if_fail (GTK_IS_WIDGET (attach_widget)); g_return_if_fail (detacher != NULL); /* keep this function in sync with gtk_widget_set_parent() */ data = gtk_object_get_data (GTK_OBJECT (menu), attach_data_key); if (data) { g_warning ("gtk_menu_attach_to_widget(): menu already attached to %s", gtk_type_name (GTK_OBJECT_TYPE (data->attach_widget))); return; } gtk_object_ref (GTK_OBJECT (menu)); gtk_object_sink (GTK_OBJECT (menu)); data = g_new (GtkMenuAttachData, 1); data->attach_widget = attach_widget; data->detacher = detacher; gtk_object_set_data (GTK_OBJECT (menu), attach_data_key, data); if (GTK_WIDGET_STATE (menu) != GTK_STATE_NORMAL) gtk_widget_set_state (GTK_WIDGET (menu), GTK_STATE_NORMAL); /* we don't need to set the style here, since * we are a toplevel widget. */}GtkWidget*gtk_menu_get_attach_widget (GtkMenu *menu){ GtkMenuAttachData *data; g_return_val_if_fail (menu != NULL, NULL); g_return_val_if_fail (GTK_IS_MENU (menu), NULL); data = gtk_object_get_data (GTK_OBJECT (menu), attach_data_key); if (data) return data->attach_widget; return NULL;}voidgtk_menu_detach (GtkMenu *menu){ GtkMenuAttachData *data; g_return_if_fail (menu != NULL); g_return_if_fail (GTK_IS_MENU (menu)); /* keep this function in sync with gtk_widget_unparent() */ data = gtk_object_get_data (GTK_OBJECT (menu), attach_data_key); if (!data) { g_warning ("gtk_menu_detach(): menu is not attached"); return; } gtk_object_remove_data (GTK_OBJECT (menu), attach_data_key); data->detacher (data->attach_widget, menu); if (GTK_WIDGET_REALIZED (menu)) gtk_widget_unrealize (GTK_WIDGET (menu)); g_free (data); gtk_widget_unref (GTK_WIDGET (menu));}GtkWidget*gtk_menu_new (void){ return GTK_WIDGET (gtk_type_new (gtk_menu_get_type ()));}voidgtk_menu_append (GtkMenu *menu, GtkWidget *child){ gtk_menu_shell_append (GTK_MENU_SHELL (menu), child);}voidgtk_menu_prepend (GtkMenu *menu, GtkWidget *child){ gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), child);}voidgtk_menu_insert (GtkMenu *menu, GtkWidget *child, gint position){ gtk_menu_shell_insert (GTK_MENU_SHELL (menu), child, position);}static voidgtk_menu_tearoff_bg_copy (GtkMenu *menu){ GtkWidget *widget; widget = GTK_WIDGET (menu); if (menu->torn_off) { GdkPixmap *pixmap; GdkGC *gc; GdkGCValues gc_values; gc_values.subwindow_mode = GDK_INCLUDE_INFERIORS; gc = gdk_gc_new_with_values (widget->window, &gc_values, GDK_GC_SUBWINDOW); pixmap = gdk_pixmap_new (widget->window, widget->requisition.width, widget->requisition.height, -1); gdk_draw_pixmap (pixmap, gc, widget->window, 0, 0, 0, 0, -1, -1); gdk_gc_unref (gc); gtk_widget_set_usize (menu->tearoff_window, widget->requisition.width, widget->requisition.height); gdk_window_set_back_pixmap (menu->tearoff_window->window, pixmap, FALSE); gdk_pixmap_unref (pixmap); }}voidgtk_menu_popup (GtkMenu *menu, GtkWidget *parent_menu_shell, GtkWidget *parent_menu_item, GtkMenuPositionFunc func, gpointer data, guint button, guint32 activate_time){ GtkWidget *widget; GtkWidget *xgrab_shell; GtkWidget *parent; GdkEvent *current_event; GtkMenuShell *menu_shell; g_return_if_fail (menu != NULL);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -