LCOV - code coverage report
Current view: top level - borrowed/goffice - go-optionmenu.c (source / functions) Coverage Total Hit
Test: gnucash.info Lines: 0.0 % 153 0
Test Date: 2026-11-02 18:19:43 Functions: 0.0 % 19 0
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /*
       2              :  * go-optionmenu.c
       3              :  *
       4              :  * Copyright (C) 2002 Andreas J. Guelzow <aguelzow@taliesin.ca>
       5              :  * Copyright (C) 2006 Morten Welinder (terra@gnome.org)
       6              :  *
       7              :  * based extensively on:
       8              :  *
       9              :  * GTK - The GIMP Toolkit
      10              :  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
      11              :  *
      12              :  * Modified by the GTK+ Team and others 1997-2000.  See the GTK AUTHORS
      13              :  * file for a list of people on the GTK+ Team.  See the ChangeLog
      14              :  * files for a list of changes.  These files are distributed with
      15              :  * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
      16              :  *
      17              :  *
      18              :  * This library is free software; you can redistribute it and/or
      19              :  * modify it under the terms of the GNU Lesser General Public
      20              :  * License as published by the Free Software Foundation; either
      21              :  * version 2 of the License, or (at your option) any later version.
      22              :  *
      23              :  * This library is distributed in the hope that it will be useful,
      24              :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      25              :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      26              :  * Lesser General Public License for more details.
      27              :  *
      28              :  * You should have received a copy of the GNU Lesser General Public
      29              :  * License along with this library; if not, write to the Free Software
      30              :  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301
      31              :  * USA.
      32              :  */
      33              : 
      34              : #include <config.h>
      35              : #include "go-optionmenu.h"
      36              : 
      37              : #include <gdk/gdkkeysyms.h>
      38              : #include <glib/gi18n-lib.h>
      39              : 
      40              : enum
      41              : {
      42              :     CHANGED, LAST_SIGNAL
      43              : };
      44              : 
      45              : enum
      46              : {
      47              :     PROP_0,
      48              :     PROP_MENU
      49              : };
      50              : 
      51              : static guint signals[LAST_SIGNAL] = { 0 };
      52              : 
      53              : struct _GOOptionMenu
      54              : {
      55              :     GtkButton button;
      56              : 
      57              :     GtkMenuShell *menu;
      58              :     GtkMenuItem *selected;
      59              :     GtkLabel *button_label;
      60              : };
      61              : 
      62            0 : G_DEFINE_TYPE (GOOptionMenu, go_option_menu, GTK_TYPE_BUTTON)
      63              : 
      64              : GtkWidget*
      65            0 : go_option_menu_new(void)
      66              : {
      67            0 :     return g_object_new(GO_TYPE_OPTION_MENU, NULL);
      68              : }
      69              : 
      70            0 : static void go_option_menu_detacher(GtkWidget *widget, GtkMenu *menu)
      71              : {
      72              : #if 0
      73              :     GOOptionMenu *option_menu = GO_OPTION_MENU (widget);
      74              :     /* What?  */
      75              : #endif
      76            0 : }
      77              : 
      78            0 : static void go_option_menu_update_contents(GOOptionMenu *option_menu)
      79              : {
      80              :     const char *text;
      81              :     GtkWidget *w;
      82            0 :     g_return_if_fail(GO_IS_OPTION_MENU(option_menu));
      83              : 
      84            0 :     w = gtk_bin_get_child(GTK_BIN(option_menu->selected));
      85            0 :     text = g_object_get_data(G_OBJECT(w), "option-menu-text");
      86              : 
      87            0 :     if (!text && GTK_IS_LABEL(w))
      88            0 :         text = gtk_label_get_text(GTK_LABEL(w));
      89              : 
      90            0 :     if (!text)
      91            0 :         text = "";
      92              : 
      93              : #if 0
      94              :     g_print ("text = \"%s\"\n", text);
      95              : #endif
      96              : 
      97            0 :     gtk_label_set_text(option_menu->button_label, text);
      98              : }
      99              : 
     100            0 : static void go_option_menu_select_item(GOOptionMenu *option_menu,
     101              :         GtkMenuItem *item)
     102              : {
     103            0 :     if (item == option_menu->selected)
     104            0 :         return;
     105              : 
     106            0 :     if (GTK_IS_CHECK_MENU_ITEM(option_menu->selected))
     107            0 :         gtk_check_menu_item_set_active(
     108            0 :                 GTK_CHECK_MENU_ITEM(option_menu->selected), FALSE);
     109              : 
     110            0 :     option_menu->selected = item;
     111              : 
     112            0 :     if (GTK_IS_CHECK_MENU_ITEM(item))
     113            0 :         gtk_check_menu_item_set_active(
     114            0 :                 GTK_CHECK_MENU_ITEM(option_menu->selected), TRUE);
     115              : 
     116            0 :     go_option_menu_update_contents(option_menu);
     117              : }
     118              : 
     119            0 : static gint go_option_menu_button_press(GtkWidget *widget,
     120              :         GdkEventButton *event)
     121              : {
     122              :     GOOptionMenu *option_menu;
     123              : 
     124            0 :     g_return_val_if_fail(GO_IS_OPTION_MENU(widget), FALSE);
     125            0 :     g_return_val_if_fail(event != NULL, FALSE);
     126              : 
     127            0 :     option_menu = GO_OPTION_MENU(widget);
     128              : 
     129            0 :     if (event->type == GDK_BUTTON_PRESS && event->button == 1)
     130              :     {
     131            0 :         gtk_menu_popup_at_widget (GTK_MENU(option_menu->menu),
     132              :                                   widget,
     133              :                                   GDK_GRAVITY_SOUTH_WEST,
     134              :                                   GDK_GRAVITY_NORTH_WEST,
     135              :                                   (GdkEvent *) event);
     136            0 :         return TRUE;
     137              :     }
     138            0 :     return FALSE;
     139              : }
     140              : 
     141            0 : static gint go_option_menu_key_press(GtkWidget *widget, GdkEventKey *event)
     142              : {
     143            0 :     GOOptionMenu *option_menu = GO_OPTION_MENU(widget);
     144              : 
     145            0 :     switch (event->keyval)
     146              :     {
     147            0 :     case GDK_KEY_KP_Space:
     148              :     case GDK_KEY_space:
     149            0 :         gtk_menu_popup_at_widget (GTK_MENU(option_menu->menu),
     150              :                                   widget,
     151              :                                   GDK_GRAVITY_SOUTH_WEST,
     152              :                                   GDK_GRAVITY_NORTH_WEST,
     153              :                                   (GdkEvent *) event);
     154            0 :         return TRUE;
     155              :     }
     156              : 
     157            0 :     return FALSE;
     158              : }
     159              : 
     160            0 : static void cb_select(GtkMenuItem *item, GOOptionMenu *option_menu)
     161              : {
     162            0 :     go_option_menu_select_item(option_menu, item);
     163            0 :     g_signal_emit(option_menu, signals[CHANGED], 0);
     164            0 : }
     165              : 
     166            0 : static void handle_menu_signals(GOOptionMenu *option_menu, gboolean connect)
     167              : {
     168            0 :     GList *children = gtk_container_get_children(
     169            0 :             GTK_CONTAINER(option_menu->menu));
     170              : 
     171            0 :     while (children)
     172              :     {
     173            0 :         GtkWidget *child = children->data;
     174            0 :         children = g_list_remove(children, child);
     175              : 
     176            0 :         if (GTK_IS_MENU_ITEM(child))
     177              :         {
     178            0 :             GtkWidget *sub = gtk_menu_item_get_submenu(GTK_MENU_ITEM(child));
     179              : 
     180            0 :             if (sub)
     181            0 :                 children = g_list_concat(children,
     182            0 :                         gtk_container_get_children(GTK_CONTAINER(sub)));
     183            0 :             else if (connect)
     184            0 :                 g_signal_connect(child, "activate", G_CALLBACK(cb_select),
     185              :                         option_menu);
     186              : 
     187              :             else
     188            0 :                 g_signal_handlers_disconnect_by_func(child,
     189              :                         G_CALLBACK(cb_select), option_menu);
     190              : 
     191              :         }
     192              :     }
     193              : 
     194            0 :     g_list_free (children);
     195            0 : }
     196              : 
     197            0 : void go_option_menu_set_menu(GOOptionMenu *option_menu, GtkWidget *menu)
     198              : {
     199              :     GtkMenuShell *shell;
     200              : 
     201            0 :     g_return_if_fail(GO_IS_OPTION_MENU(option_menu));
     202            0 :     g_return_if_fail(GTK_IS_MENU_SHELL(menu));
     203              : 
     204            0 :     shell = (GtkMenuShell *) menu;
     205            0 :     if (option_menu->menu == shell)
     206            0 :         return;
     207              : 
     208            0 :     if (option_menu->menu)
     209              :     {
     210            0 :         gtk_menu_shell_cancel(option_menu->menu);
     211              : 
     212            0 :         handle_menu_signals(option_menu, FALSE);
     213              : 
     214            0 :         gtk_menu_detach(GTK_MENU(option_menu->menu));
     215            0 :         g_object_unref(option_menu->menu);
     216              :     }
     217              : 
     218            0 :     option_menu->menu = shell;
     219              : 
     220            0 :     if (shell)
     221              :     {
     222            0 :         g_object_ref(shell);
     223              : 
     224            0 :         gtk_menu_attach_to_widget(GTK_MENU(shell), GTK_WIDGET(option_menu),
     225              :                 go_option_menu_detacher);
     226              : 
     227            0 :         handle_menu_signals(option_menu, TRUE);
     228              : 
     229            0 :         go_option_menu_select_item(option_menu,
     230            0 :                 GTK_MENU_ITEM(gtk_menu_get_active(GTK_MENU(shell))));
     231              :     }
     232              : 
     233            0 :     g_object_notify(G_OBJECT(option_menu), "menu");
     234              : }
     235              : 
     236            0 : void go_option_menu_set_history(GOOptionMenu *option_menu, GSList *selection)
     237              : {
     238            0 :     g_return_if_fail(selection != NULL);
     239            0 :     g_return_if_fail(GO_IS_OPTION_MENU(option_menu));
     240              : 
     241            0 :     if (option_menu->menu)
     242              :     {
     243            0 :         GtkMenuShell *menu = option_menu->menu;
     244              : 
     245              :         while (1)
     246            0 :         {
     247            0 :             int n = GPOINTER_TO_INT(selection->data);
     248            0 :             GList *children = gtk_container_get_children (GTK_CONTAINER(menu));
     249            0 :             GtkMenuItem *item = g_list_nth_data (children, n);
     250            0 :             g_list_free (children);
     251            0 :             selection = selection->next;
     252            0 :             if (selection)
     253            0 :                 menu = GTK_MENU_SHELL(gtk_menu_item_get_submenu(item));
     254              :             else
     255              :             {
     256            0 :                 go_option_menu_select_item(option_menu, item);
     257            0 :                 break;
     258              :             }
     259              :         }
     260              :     }
     261              : }
     262              : 
     263              : /**
     264              :  * go_option_menu_get_history:
     265              :  * @option_menu: a #GOOptionMenu
     266              :  *
     267              :  * Retrieves the currently selected menu item.
     268              :  *
     269              :  * Return value: the selected menu_item
     270              :  **/
     271              : 
     272              : GtkWidget *
     273            0 : go_option_menu_get_history(GOOptionMenu *option_menu)
     274              : {
     275            0 :     return GTK_WIDGET(option_menu->selected);
     276              : }
     277              : 
     278            0 : static void go_option_menu_set_property(GObject *object, guint prop_id,
     279              :         const GValue *value, GParamSpec *pspec)
     280              : {
     281            0 :     GOOptionMenu *option_menu = GO_OPTION_MENU(object);
     282              : 
     283            0 :     switch (prop_id)
     284              :     {
     285            0 :     case PROP_MENU:
     286            0 :         go_option_menu_set_menu(option_menu, g_value_get_object(value));
     287            0 :         break;
     288              : 
     289            0 :     default:
     290            0 :         G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
     291            0 :         break;
     292              :     }
     293            0 : }
     294              : 
     295            0 : static void go_option_menu_get_property(GObject *object, guint prop_id,
     296              :         GValue *value, GParamSpec *pspec)
     297              : {
     298            0 :     GOOptionMenu *option_menu = GO_OPTION_MENU(object);
     299              : 
     300            0 :     switch (prop_id)
     301              :     {
     302            0 :     case PROP_MENU:
     303            0 :         g_value_set_object(value, option_menu->menu);
     304            0 :         break;
     305              : 
     306            0 :     default:
     307            0 :         G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
     308            0 :         break;
     309              :     }
     310            0 : }
     311              : 
     312            0 : static void go_option_menu_destroy(GtkWidget *widget)
     313              : {
     314              :     GOOptionMenu *option_menu;
     315              : 
     316            0 :     g_return_if_fail(GO_IS_OPTION_MENU(widget));
     317              : 
     318            0 :     option_menu = GO_OPTION_MENU(widget);
     319              : 
     320            0 :     if (option_menu->menu)
     321              :     {
     322            0 :         gtk_widget_destroy(GTK_WIDGET(option_menu->menu));
     323            0 :         g_object_unref(option_menu->menu);
     324            0 :         option_menu->menu = NULL;
     325              :     }
     326            0 :     option_menu->selected = NULL;
     327              : 
     328            0 :     GTK_WIDGET_CLASS(go_option_menu_parent_class)->destroy(widget);
     329              : }
     330              : 
     331            0 : static void go_option_menu_class_init(GOOptionMenuClass *class)
     332              : {
     333            0 :     GObjectClass *gobject_class = (GObjectClass*) class;
     334            0 :     GtkWidgetClass *widget_class = (GtkWidgetClass*) class;
     335              : 
     336            0 :     signals[CHANGED] = g_signal_new("changed", G_OBJECT_CLASS_TYPE(class),
     337              :             G_SIGNAL_RUN_LAST, 0,
     338              :             NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
     339              : 
     340            0 :     gobject_class->set_property = go_option_menu_set_property;
     341            0 :     gobject_class->get_property = go_option_menu_get_property;
     342            0 :     widget_class->destroy = go_option_menu_destroy;
     343            0 :     widget_class->button_press_event = go_option_menu_button_press;
     344            0 :     widget_class->key_press_event = go_option_menu_key_press;
     345              : 
     346            0 :     g_object_class_install_property(gobject_class, PROP_MENU,
     347              :             g_param_spec_object("menu", _("Menu"), _("The menu of options"),
     348              :                     GTK_TYPE_MENU, G_PARAM_READABLE | G_PARAM_WRITABLE));
     349            0 : }
     350              : 
     351            0 : static void go_option_menu_init(GOOptionMenu *option_menu)
     352              : {
     353              :     GtkWidget *box;
     354              :     GtkWidget *arrow, *sep;
     355              : 
     356            0 :     gtk_widget_set_can_focus(GTK_WIDGET(option_menu), TRUE);
     357            0 :     gtk_widget_set_can_default(GTK_WIDGET(option_menu), FALSE);
     358            0 :     gtk_widget_set_receives_default(GTK_WIDGET(option_menu), FALSE);
     359              : 
     360            0 :     box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
     361            0 :     gtk_box_set_homogeneous (GTK_BOX (box), FALSE);
     362              : 
     363            0 :     option_menu->menu = NULL;
     364            0 :     option_menu->selected = NULL;
     365              : 
     366            0 :     option_menu->button_label = GTK_LABEL(gtk_label_new(""));
     367            0 :     gtk_box_pack_start(GTK_BOX(box), GTK_WIDGET(option_menu->button_label), FALSE, TRUE, 0);
     368            0 :     arrow = gtk_image_new_from_icon_name ("pan-down-symbolic", GTK_ICON_SIZE_BUTTON);
     369            0 :     gtk_widget_set_margin_start (GTK_WIDGET(arrow), 5);
     370              : 
     371            0 :     gtk_box_pack_end(GTK_BOX(box), arrow, FALSE, FALSE, 0);
     372              : 
     373            0 :     sep = gtk_separator_new (GTK_ORIENTATION_VERTICAL);
     374            0 :     gtk_box_pack_end(GTK_BOX(box), sep, FALSE, FALSE, 0);
     375              : 
     376            0 :     gtk_container_add(GTK_CONTAINER(option_menu), GTK_WIDGET(box));
     377            0 : }
        

Generated by: LCOV version 2.0-1