summaryrefslogtreecommitdiff
path: root/logview/logview-findbar.c
diff options
context:
space:
mode:
Diffstat (limited to 'logview/logview-findbar.c')
-rw-r--r--logview/logview-findbar.c348
1 files changed, 348 insertions, 0 deletions
diff --git a/logview/logview-findbar.c b/logview/logview-findbar.c
new file mode 100644
index 00000000..bdbda89f
--- /dev/null
+++ b/logview/logview-findbar.c
@@ -0,0 +1,348 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2; -*- */
+/* logview-findbar.c - find toolbar for logview
+ *
+ * Copyright (C) 2005 Vincent Noel <[email protected]>
+ * Copyright (C) 2008 Cosimo Cecchi <[email protected]>
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <gtk/gtk.h>
+#include <glib/gi18n.h>
+#include <gdk/gdkkeysyms.h>
+
+#include "logview-findbar.h"
+
+struct _LogviewFindbarPrivate {
+ GtkWidget *entry;
+ GtkWidget *message;
+
+ GtkToolItem *clear_button;
+ GtkToolItem *back_button;
+ GtkToolItem *forward_button;
+ GtkToolItem *status_item;
+ GtkToolItem *separator;
+
+ char *string;
+
+ guint status_bold_id;
+};
+
+enum {
+ PREVIOUS,
+ NEXT,
+ CLOSE,
+ TEXT_CHANGED,
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+G_DEFINE_TYPE (LogviewFindbar, logview_findbar, GTK_TYPE_TOOLBAR);
+
+#define GET_PRIVATE(o) \
+ (G_TYPE_INSTANCE_GET_PRIVATE ((o), LOGVIEW_TYPE_FINDBAR, LogviewFindbarPrivate))
+
+static void
+back_button_clicked_cb (GtkToolButton *button,
+ gpointer user_data)
+{
+ LogviewFindbar *findbar = user_data;
+
+ g_signal_emit (findbar, signals[PREVIOUS], 0);
+}
+
+static void
+forward_button_clicked_cb (GtkToolButton *button,
+ gpointer user_data)
+{
+ LogviewFindbar *findbar = user_data;
+
+ g_signal_emit (findbar, signals[NEXT], 0);
+}
+
+static void
+clear_button_clicked_cb (GtkToolButton *button,
+ gpointer user_data)
+{
+ LogviewFindbar *findbar = user_data;
+
+ logview_findbar_set_message (findbar, NULL);
+ gtk_entry_set_text (GTK_ENTRY (findbar->priv->entry), "");
+}
+
+static void
+entry_activate_cb (GtkWidget *entry,
+ gpointer user_data)
+{
+ LogviewFindbar *findbar = user_data;
+
+ g_signal_emit (findbar, signals[NEXT], 0);
+}
+
+static void
+entry_changed_cb (GtkEditable *editable,
+ gpointer user_data)
+{
+ LogviewFindbar *findbar = user_data;
+ const char *text;
+
+ text = gtk_entry_get_text (GTK_ENTRY (editable));
+
+ if (g_strcmp0 (text, "") == 0) {
+ return;
+ }
+
+ if (g_strcmp0 (findbar->priv->string, text) != 0) {
+ g_free (findbar->priv->string);
+ findbar->priv->string = g_strdup (text);
+
+ g_signal_emit (findbar, signals[TEXT_CHANGED], 0);
+ }
+}
+
+static gboolean
+entry_key_press_event_cb (GtkWidget *entry,
+ GdkEventKey *event,
+ gpointer user_data)
+{
+ LogviewFindbar *findbar = user_data;
+
+ if (event->keyval == GDK_Escape) {
+ g_signal_emit (findbar, signals[CLOSE], 0);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static gboolean
+unbold_timeout_cb (gpointer user_data)
+{
+ LogviewFindbar *findbar = user_data;
+ PangoFontDescription *desc;
+
+ desc = pango_font_description_new ();
+ gtk_widget_modify_font (findbar->priv->message, desc);
+ pango_font_description_free (desc);
+
+ findbar->priv->status_bold_id = 0;
+
+ return FALSE;
+}
+
+static void
+logview_findbar_init (LogviewFindbar *findbar)
+{
+ GtkWidget *label, *w, *box;
+ GtkToolbar *gtoolbar;
+ GtkToolItem *item;
+ LogviewFindbarPrivate *priv;
+
+ priv = findbar->priv = GET_PRIVATE (findbar);
+
+ gtoolbar = GTK_TOOLBAR (findbar);
+
+ gtk_toolbar_set_style (gtoolbar, GTK_TOOLBAR_BOTH_HORIZ);
+
+ priv->status_bold_id = 0;
+
+ /* Find: |_______| */
+ w = gtk_alignment_new (0.0, 0.5, 1.0, 1.0);
+ gtk_alignment_set_padding (GTK_ALIGNMENT (w), 0, 0, 2, 2);
+
+ box = gtk_hbox_new (FALSE, 12);
+ gtk_container_add (GTK_CONTAINER (w), box);
+
+ label = gtk_label_new_with_mnemonic (_("_Find:"));
+ gtk_box_pack_start (GTK_BOX (box), label, FALSE, FALSE, 0);
+
+ priv->entry = gtk_entry_new ();
+ gtk_entry_set_width_chars (GTK_ENTRY (priv->entry), 32);
+ gtk_label_set_mnemonic_widget (GTK_LABEL (label), priv->entry);
+ gtk_box_pack_start (GTK_BOX (box), priv->entry, TRUE, TRUE, 0);
+
+ item = gtk_tool_item_new ();
+ gtk_container_add (GTK_CONTAINER (item), w);
+ gtk_toolbar_insert (gtoolbar, item, -1);
+ gtk_widget_show_all (GTK_WIDGET (item));
+
+ /* "Previous" and "Next" buttons */
+ w = gtk_arrow_new (GTK_ARROW_LEFT, GTK_SHADOW_NONE);
+ priv->back_button = gtk_tool_button_new (w, _("Find Previous"));
+ gtk_tool_item_set_is_important (priv->back_button, TRUE);
+ gtk_tool_item_set_tooltip_text (priv->back_button,
+ _("Find previous occurrence of the search string"));
+ gtk_toolbar_insert (gtoolbar, priv->back_button, -1);
+ gtk_widget_show_all (GTK_WIDGET (priv->back_button));
+
+ w = gtk_arrow_new (GTK_ARROW_RIGHT, GTK_SHADOW_NONE);
+ priv->forward_button = gtk_tool_button_new (w, _("Find Next"));
+ gtk_tool_item_set_is_important (priv->forward_button, TRUE);
+ gtk_tool_item_set_tooltip_text (priv->forward_button,
+ _("Find next occurrence of the search string"));
+ gtk_toolbar_insert (gtoolbar, priv->forward_button, -1);
+ gtk_widget_show_all (GTK_WIDGET (priv->forward_button));
+
+ /* clear button */
+ priv->clear_button = gtk_tool_button_new_from_stock (GTK_STOCK_CLEAR);
+ gtk_tool_item_set_tooltip_text (priv->clear_button,
+ _("Clear the search string"));
+ gtk_toolbar_insert (gtoolbar, priv->clear_button, -1);
+ gtk_widget_show_all (GTK_WIDGET (priv->clear_button));
+
+ /* separator */
+ priv->separator = gtk_separator_tool_item_new ();
+ gtk_toolbar_insert (gtoolbar, priv->separator, -1);
+
+ /* message */
+ priv->status_item = gtk_tool_item_new ();
+ gtk_tool_item_set_expand (priv->status_item, TRUE);
+ priv->message = gtk_label_new ("");
+ gtk_label_set_use_markup (GTK_LABEL (priv->message), TRUE);
+ gtk_misc_set_alignment (GTK_MISC (priv->message), 0.0, 0.5);
+ gtk_container_add (GTK_CONTAINER (priv->status_item), priv->message);
+ gtk_widget_show (priv->message);
+ gtk_toolbar_insert (gtoolbar, priv->status_item, -1);
+
+ priv->string = NULL;
+
+ /* signal handlers */
+ g_signal_connect (priv->back_button, "clicked",
+ G_CALLBACK (back_button_clicked_cb), findbar);
+ g_signal_connect (priv->forward_button, "clicked",
+ G_CALLBACK (forward_button_clicked_cb), findbar);
+ g_signal_connect (priv->clear_button, "clicked",
+ G_CALLBACK (clear_button_clicked_cb), findbar);
+ g_signal_connect (priv->entry, "activate",
+ G_CALLBACK (entry_activate_cb), findbar);
+ g_signal_connect (priv->entry, "changed",
+ G_CALLBACK (entry_changed_cb), findbar);
+ g_signal_connect (priv->entry, "key-press-event",
+ G_CALLBACK (entry_key_press_event_cb), findbar);
+}
+
+static void
+do_grab_focus (GtkWidget *widget)
+{
+ LogviewFindbar *findbar = LOGVIEW_FINDBAR (widget);
+
+ gtk_widget_grab_focus (findbar->priv->entry);
+}
+
+static void
+do_finalize (GObject *obj)
+{
+ LogviewFindbar *findbar = LOGVIEW_FINDBAR (obj);
+
+ g_free (findbar->priv->string);
+
+ G_OBJECT_CLASS (logview_findbar_parent_class)->finalize (obj);
+}
+
+static void
+logview_findbar_class_init (LogviewFindbarClass *klass)
+{
+ GObjectClass *oclass = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *wclass = GTK_WIDGET_CLASS (klass);
+
+ oclass->finalize = do_finalize;
+
+ wclass->grab_focus = do_grab_focus;
+
+ signals[PREVIOUS] = g_signal_new ("previous",
+ G_OBJECT_CLASS_TYPE (oclass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (LogviewFindbarClass, previous),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+ signals[NEXT] = g_signal_new ("next",
+ G_OBJECT_CLASS_TYPE (oclass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (LogviewFindbarClass, next),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+ signals[CLOSE] = g_signal_new ("close",
+ G_OBJECT_CLASS_TYPE (oclass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (LogviewFindbarClass, close),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+ signals[TEXT_CHANGED] = g_signal_new ("text-changed",
+ G_OBJECT_CLASS_TYPE (oclass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (LogviewFindbarClass, text_changed),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+ g_type_class_add_private (klass, sizeof (LogviewFindbarPrivate));
+}
+
+/* public methods */
+
+GtkWidget *
+logview_findbar_new (void)
+{
+ GtkWidget *widget;
+ widget = g_object_new (LOGVIEW_TYPE_FINDBAR, NULL);
+ return widget;
+}
+
+void
+logview_findbar_open (LogviewFindbar *findbar)
+{
+ g_assert (LOGVIEW_IS_FINDBAR (findbar));
+
+ gtk_widget_show (GTK_WIDGET (findbar));
+ gtk_widget_grab_focus (GTK_WIDGET (findbar));
+}
+
+const char *
+logview_findbar_get_text (LogviewFindbar *findbar)
+{
+ g_assert (LOGVIEW_IS_FINDBAR (findbar));
+
+ return findbar->priv->string;
+}
+
+void
+logview_findbar_set_message (LogviewFindbar *findbar,
+ const char *text)
+{
+ PangoFontDescription *desc;
+
+ g_assert (LOGVIEW_IS_FINDBAR (findbar));
+
+ if (text) {
+ desc = pango_font_description_new ();
+ pango_font_description_set_weight (desc, PANGO_WEIGHT_BOLD);
+ gtk_widget_modify_font (findbar->priv->message, desc);
+ pango_font_description_free (desc);
+
+ findbar->priv->status_bold_id = g_timeout_add (600, unbold_timeout_cb, findbar);
+ }
+
+ gtk_label_set_text (GTK_LABEL (findbar->priv->message),
+ text != NULL ? text : "");
+ g_object_set (findbar->priv->separator, "visible", text != NULL, NULL);
+ g_object_set (findbar->priv->status_item, "visible", text != NULL, NULL);
+}