/* * libmokoui -- OpenMoko Application Framework UI Library * * Authored by Chris Lord * * Copyright (C) 2006-2007 OpenMoko Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser Public License as published by * the Free Software Foundation; version 2 of the license. * * 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 Lesser Public License for more details. * * Current Version: $Rev$ ($Date$) [$Author$] */ /** * SECTION: moko-search-bar * @short_description: An implementation of the OpenMoko "Search Bar" * user interface * @see_also: #GtkEntry, #GtkComboBox * * The #MokoSearchBar is a composite widget that implements the "Search Bar" * user interface from OpenMoko. It comprises of a #GtkEntry, a #GtkComboBox * and a #GtkToggleButton that toggles the visibility of the entry and combo box. * */ #include "moko-search-bar.h" G_DEFINE_TYPE (MokoSearchBar, moko_search_bar, GTK_TYPE_HBOX) #define SEARCH_BAR_PRIVATE(o) \ (G_TYPE_INSTANCE_GET_PRIVATE ((o), MOKO_TYPE_SEARCH_BAR, \ MokoSearchBarPrivate)) typedef struct _MokoSearchBarPrivate MokoSearchBarPrivate; struct _MokoSearchBarPrivate { GtkWidget *toggle; GtkWidget *entry; GtkWidget *combo; }; enum { PROP_COMBO = 1, PROP_ENTRY, }; enum { TOGGLED, TEXT_CHANGED, COMBO_CHANGED, LAST_SIGNAL }; static guint signals[LAST_SIGNAL] = { 0 }; static void combo_changed_cb (GtkComboBox *combo, MokoSearchBar *self) { g_signal_emit (self, signals[COMBO_CHANGED], 0, combo); } static void moko_search_bar_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { MokoSearchBarPrivate *priv = SEARCH_BAR_PRIVATE (object); switch (property_id) { case PROP_COMBO : g_value_set_object (value, priv->combo); break; case PROP_ENTRY : g_value_set_object (value, priv->entry); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } } static void moko_search_bar_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { MokoSearchBarPrivate *priv = SEARCH_BAR_PRIVATE (object); switch (property_id) { case PROP_COMBO : priv->combo = g_value_get_object (value); gtk_box_pack_start (GTK_BOX (object), priv->combo, TRUE, TRUE, 0); gtk_widget_show (priv->combo); g_signal_connect (G_OBJECT (priv->combo), "changed", G_CALLBACK (combo_changed_cb), object); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } } static void moko_search_bar_dispose (GObject *object) { if (G_OBJECT_CLASS (moko_search_bar_parent_class)->dispose) G_OBJECT_CLASS (moko_search_bar_parent_class)->dispose (object); } static void moko_search_bar_finalize (GObject *object) { G_OBJECT_CLASS (moko_search_bar_parent_class)->finalize (object); } static void moko_search_bar_class_init (MokoSearchBarClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); g_type_class_add_private (klass, sizeof (MokoSearchBarPrivate)); object_class->get_property = moko_search_bar_get_property; object_class->set_property = moko_search_bar_set_property; object_class->dispose = moko_search_bar_dispose; object_class->finalize = moko_search_bar_finalize; g_object_class_install_property ( object_class, PROP_COMBO, g_param_spec_object ( "combo", "GtkComboBox *", "The GtkComboBox to place inside the widget.", GTK_TYPE_COMBO_BOX, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); g_object_class_install_property ( object_class, PROP_ENTRY, g_param_spec_object ( "entry", "GtkEntry *", "The GtkEntry created for this widget.", GTK_TYPE_ENTRY, G_PARAM_READABLE)); /** * MokoSearchBar::toggled: * @searchbar: The #MokoSearchBar that received the signal * @search_visible: %TRUE if the search entry is visible, %FALSE * otherwise * @user_data: User data set when the signal handler was connected. * * The ::toggled signal is emitted each time the search button is * pressed. */ signals[TOGGLED] = g_signal_new ("toggled", G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (MokoSearchBarClass, toggled), NULL, NULL, g_cclosure_marshal_VOID__BOOLEAN, G_TYPE_NONE, 1, G_TYPE_BOOLEAN); /** * MokoSearchBar::text-changed: * @searchbar: The #MokoSearchBar that received the signal * @editable: The underlying #GtkEditable that received the ::changed * signal. * @user_data: User data set when the signal handler was connected. * * The ::text-changed signal is emitted each time the underlying * #GtkEditable receives its ::changed signal. */ signals[TEXT_CHANGED] = g_signal_new ("text-changed", G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (MokoSearchBarClass, text_changed), NULL, NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER); /** * MokoSearchBar::combo-changed: * @searchbar: The #MokoSearchBar that received the signal * @combo: The underlying #GtkComboBox that received the ::changed * signal. * @user_data: User data set when the signal handler was connected. * * The ::combo-changed signal is emitted each time the underlying * #GtkComboBox receives its ::changed signal. */ signals[COMBO_CHANGED] = g_signal_new ("combo-changed", G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (MokoSearchBarClass, combo_changed), NULL, NULL, g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, GTK_TYPE_COMBO_BOX); } static void toggled_cb (GtkWidget *button, MokoSearchBar *self) { MokoSearchBarPrivate *priv = SEARCH_BAR_PRIVATE (self); g_object_set (G_OBJECT (priv->entry), "visible", !GTK_WIDGET_VISIBLE (priv->entry), NULL); g_object_set (G_OBJECT (priv->combo), "visible", !GTK_WIDGET_VISIBLE (priv->combo), NULL); if (GTK_WIDGET_VISIBLE (priv->entry)) gtk_widget_grab_focus (priv->entry); g_signal_emit (self, signals[TOGGLED], 0, GTK_WIDGET_VISIBLE (priv->entry)); } static void entry_changed_cb (GtkEditable *editable, MokoSearchBar *self) { g_signal_emit (self, signals[TEXT_CHANGED], 0, editable); } static void moko_search_bar_init (MokoSearchBar *self) { MokoSearchBarPrivate *priv = SEARCH_BAR_PRIVATE (self); /* Create toggle button */ priv->toggle = gtk_toggle_button_new (); gtk_widget_set_name (priv->toggle, "mokosearchbutton"); gtk_button_set_image (GTK_BUTTON (priv->toggle), gtk_image_new_from_stock (GTK_STOCK_FIND, GTK_ICON_SIZE_SMALL_TOOLBAR)); gtk_box_pack_start (GTK_BOX (self), priv->toggle, FALSE, FALSE, 0); gtk_widget_show_all (priv->toggle); /* Create entry */ priv->entry = gtk_entry_new (); gtk_widget_set_name (priv->entry, "mokosearchentry"); g_object_set (G_OBJECT (priv->entry), "no-show-all", TRUE, NULL); gtk_box_pack_start (GTK_BOX (self), priv->entry, TRUE, TRUE, 0); /* Connect up signals */ g_signal_connect (G_OBJECT (priv->toggle), "toggled", G_CALLBACK (toggled_cb), self); g_signal_connect (G_OBJECT (priv->entry), "changed", G_CALLBACK (entry_changed_cb), self); } /** * moko_search_bar_new: * * Create a new MokoSearBar widget * * returns: The newly created MokoSearchBar */ GtkWidget * moko_search_bar_new (void) { return GTK_WIDGET (g_object_new (MOKO_TYPE_SEARCH_BAR, "combo", gtk_combo_box_new (), NULL)); } /** * moko_search_bar_new_with_combo: * @combo: a GtkComboBox to use as the combobox * * Creates a MokoSearchBar with the specified combo box * * returns: the newly created MokoSearchBar */ GtkWidget * moko_search_bar_new_with_combo (GtkComboBox *combo) { return GTK_WIDGET (g_object_new (MOKO_TYPE_SEARCH_BAR, "combo", combo, NULL)); } /** * moko_search_bar_get_combo_box: * @self: a MokoSearchBar * * Get a pointer to the GtkComboBox being used in the MokoSearchBar * * returns: the GtkComboBox */ GtkComboBox * moko_search_bar_get_combo_box (MokoSearchBar *self) { GtkComboBox *combo; g_object_get (G_OBJECT (self), "combo", &combo, NULL); return combo; } /** * moko_search_bar_get_entry: * @self: a MokoSearchBar * * Retrieve the GtkEntry widget being used in the MokoSearchBar * * returns: the GtkEntry */ GtkEntry * moko_search_bar_get_entry (MokoSearchBar *self) { GtkEntry *entry; g_object_get (G_OBJECT (self), "entry", &entry, NULL); return entry; } /** * moko_search_bar_search_visible: * @self: a MokoSaerchBar * * Determine the visibility of the search entry. * * returns: TRUE if the search entry is visible */ gboolean moko_search_bar_search_visible (MokoSearchBar *self) { MokoSearchBarPrivate *priv = SEARCH_BAR_PRIVATE (self); return GTK_WIDGET_VISIBLE (priv->entry); } /** * moko_search_bar_toggle: * @self: a MokoSearchBar * * Toggle the search button on the MokoSearchBar. * This toggles the visibility of the combo box and entry widgets. */ void moko_search_bar_toggle (MokoSearchBar *self) { MokoSearchBarPrivate *priv = SEARCH_BAR_PRIVATE (self); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->toggle), !gtk_toggle_button_get_active ( GTK_TOGGLE_BUTTON (priv->toggle))); }