/* This is -*- C -*- */
/* vim: set sw=2: */
/*
* guppi-data-popup.c
*
* Copyright (C) 2000 EMC Capital Management, Inc.
*
* Developed by Jon Trowbridge <trow@gnu.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 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*/
#include <config.h>
#include <gtk/gtkbutton.h>
#include <gtk/gtksignal.h>
#include <gtk/gtkmenuitem.h>
#include <gtk/gtklabel.h>
#include <libgnome/gnome-defs.h>
#include <libgnome/gnome-config.h>
#include <libgnome/gnome-i18n.h>
#include <guppi-convenient.h>
#include "guppi-data-popup.h"
static void popup_cb (GtkWidget * w, GuppiDataPopup * pop);
static GtkMenu *build_popup (GuppiDataPopup * pop, GuppiDataTreeNode * node);
static void popup (GuppiDataPopup * pop);
static void clicked (GtkButton * button);
static GtkObjectClass *parent_class = NULL;
enum {
ARG_0
};
enum {
SELECTED_DATA,
LAST_SIGNAL
};
static guint pop_signals[LAST_SIGNAL] = { 0 };
static void
guppi_data_popup_get_arg (GtkObject * obj, GtkArg * arg, guint arg_id)
{
switch (arg_id) {
default:
break;
};
}
static void
guppi_data_popup_set_arg (GtkObject * obj, GtkArg * arg, guint arg_id)
{
switch (arg_id) {
default:
break;
};
}
static void
guppi_data_popup_destroy (GtkObject * obj)
{
if (parent_class->destroy)
parent_class->destroy (obj);
}
static void
guppi_data_popup_finalize (GtkObject * obj)
{
if (parent_class->finalize)
parent_class->finalize (obj);
}
static void
guppi_data_popup_class_init (GuppiDataPopupClass * klass)
{
GtkObjectClass *object_class = (GtkObjectClass *) klass;
GtkButtonClass *button_class = GTK_BUTTON_CLASS (klass);
parent_class = gtk_type_class (GTK_TYPE_BUTTON);
object_class->get_arg = guppi_data_popup_get_arg;
object_class->set_arg = guppi_data_popup_set_arg;
object_class->destroy = guppi_data_popup_destroy;
object_class->finalize = guppi_data_popup_finalize;
button_class->clicked = clicked;
pop_signals[SELECTED_DATA] =
gtk_signal_new ("selected_data",
GTK_RUN_FIRST,
object_class->type,
GTK_SIGNAL_OFFSET (GuppiDataPopupClass, selected_data),
gtk_marshal_NONE__POINTER,
GTK_TYPE_NONE, 1, GTK_TYPE_POINTER);
gtk_object_class_add_signals (object_class, pop_signals, LAST_SIGNAL);
}
static void
guppi_data_popup_init (GuppiDataPopup * obj)
{
}
GtkType guppi_data_popup_get_type (void)
{
static GtkType guppi_data_popup_type = 0;
if (!guppi_data_popup_type) {
static const GtkTypeInfo guppi_data_popup_info = {
"GuppiDataPopup",
sizeof (GuppiDataPopup),
sizeof (GuppiDataPopupClass),
(GtkClassInitFunc) guppi_data_popup_class_init,
(GtkObjectInitFunc) guppi_data_popup_init,
NULL, NULL, (GtkClassInitFunc) NULL
};
guppi_data_popup_type = gtk_type_unique (GTK_TYPE_BUTTON,
&guppi_data_popup_info);
}
return guppi_data_popup_type;
}
static void
popup_cb (GtkWidget * w, GuppiDataPopup * pop)
{
GuppiDataTreeNode *node;
node = (GuppiDataTreeNode *) gtk_object_get_user_data (GTK_OBJECT (w));
gtk_signal_emit (GTK_OBJECT (pop),
pop_signals[SELECTED_DATA], node ? node->data : NULL);
}
static GtkMenu *
build_popup (GuppiDataPopup * pop, GuppiDataTreeNode * node)
{
GtkMenu *menu = NULL;
GtkWidget *w;
/* Totally convoluted, but it works... */
while (node) {
w = NULL;
if (guppi_data_popup_allowed_data (pop, node->data) || node->child) {
w = gtk_menu_item_new_with_label (guppi_data_get_label (node->data));
gtk_object_set_user_data (GTK_OBJECT (w), node);
}
if (node->child) {
GtkMenu *submenu = build_popup (pop, node->child);
if (submenu) {
gtk_menu_item_set_submenu (GTK_MENU_ITEM (w), GTK_WIDGET (submenu));
} else {
guppi_unref0 (w);
}
} else {
if (w)
gtk_signal_connect (GTK_OBJECT (w),
"activate", GTK_SIGNAL_FUNC (popup_cb), pop);
}
if (w) {
if (menu == NULL)
menu = GTK_MENU (gtk_menu_new ());
gtk_menu_append (menu, w);
gtk_widget_show (w);
}
node = node->sibling_next;
}
return menu;
}
static void
popup (GuppiDataPopup * pop)
{
GtkMenu *menu;
GuppiDataTree *tree;
g_return_if_fail (pop != NULL && GUPPI_IS_DATA_POPUP (pop));
tree = pop->tree;
if (tree == NULL)
tree = guppi_data_tree_main ();
menu = build_popup (pop, tree->root);
if (menu != NULL) {
/* Build "none" menu item */
if (pop->allow_none) {
GtkWidget *w;
w = gtk_menu_item_new_with_label (pop->none_label);
gtk_widget_show (w);
gtk_signal_connect (GTK_OBJECT (w),
"activate", GTK_SIGNAL_FUNC (popup_cb), pop);
gtk_menu_prepend (menu, w);
}
gtk_widget_show (GTK_WIDGET (menu));
gtk_menu_popup (menu, NULL, NULL, NULL, NULL, 1, GDK_CURRENT_TIME);
}
}
static void
clicked (GtkButton * button)
{
popup (GUPPI_DATA_POPUP (button));
}
void
guppi_data_popup_construct (GuppiDataPopup * popup)
{
g_return_if_fail (popup && GUPPI_IS_DATA_POPUP (popup));
if (popup->tree == NULL)
popup->tree = guppi_data_tree_main ();
}
GtkWidget *
guppi_data_popup_new (void)
{
GtkObject *obj;
obj = guppi_type_new (GUPPI_TYPE_DATA_POPUP);
guppi_data_popup_construct (GUPPI_DATA_POPUP (obj));
return GTK_WIDGET (obj);
}
GtkWidget *
guppi_data_popup_new_with_label (const gchar * label)
{
GtkWidget *popup;
popup = guppi_data_popup_new ();
if (label)
gtk_container_add (GTK_CONTAINER (popup), gtk_label_new (label));
return popup;
}
void
guppi_data_popup_disallow_none (GuppiDataPopup * popup)
{
g_return_if_fail (popup && GUPPI_IS_DATA_POPUP (popup));
popup->allow_none = FALSE;
guppi_free (popup->none_label);
popup->none_label = NULL;
}
void
guppi_data_popup_allow_none (GuppiDataPopup * popup, const gchar * str)
{
g_return_if_fail (popup && GUPPI_IS_DATA_POPUP (popup));
popup->allow_none = TRUE;
guppi_free (popup->none_label);
popup->none_label = guppi_strdup (str ? str : _("None"));
}
void
guppi_data_popup_set_allowed_type (GuppiDataPopup * popup, GtkType type)
{
g_return_if_fail (popup && GUPPI_IS_DATA_POPUP (popup));
popup->allowed_type = type;
popup->type_fn = NULL;
popup->user_data = NULL;
}
void
guppi_data_popup_set_allowed_type_fn (GuppiDataPopup * popup,
gboolean (*fn)(GtkType, gpointer),
gpointer user_data)
{
g_return_if_fail (popup && GUPPI_IS_DATA_POPUP (popup));
g_return_if_fail (fn);
popup->allowed_type = 0;
popup->type_fn = fn;
popup->user_data = user_data;
}
void
guppi_data_popup_set_allow_all_types (GuppiDataPopup * popup)
{
g_return_if_fail (popup && GUPPI_IS_DATA_POPUP (popup));
guppi_data_popup_set_allowed_type (popup, (GtkType)0);
}
gboolean
guppi_data_popup_allowed_type (GuppiDataPopup * pop, GtkType type)
{
g_return_val_if_fail (pop && GUPPI_IS_DATA_POPUP (pop), FALSE);
if (pop->type_fn)
return pop->type_fn (type, pop->user_data);
else if (pop->allowed_type == 0)
return TRUE;
else
return gtk_type_is_a (type, pop->allowed_type);
}
gboolean
guppi_data_popup_allowed_data (GuppiDataPopup * popup, GuppiData * data)
{
g_return_val_if_fail (popup && GUPPI_IS_DATA_POPUP (popup), FALSE);
g_return_val_if_fail (data != NULL || GUPPI_IS_DATA (data), FALSE);
return data == NULL
|| guppi_data_popup_allowed_type (popup, GTK_OBJECT_TYPE (data));
}
syntax highlighted by Code2HTML, v. 0.9.1