empathy-search-bar.c 8.04 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
 * Copyright (C) 2010 Thomas Meire <blackskad@gmail.com>
 *
 * The code contained in this file is free software; you can redistribute
 * it and/or modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either version
 * 2.1 of the License, or (at your option) any later version.
 *
 * This file 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 General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this code; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

20
#include "config.h"
21
#include "empathy-search-bar.h"
22 23

#include <glib/gi18n-lib.h>
24
#include <tp-account-widgets/tpaw-builder.h>
25
#include <tp-account-widgets/tpaw-utils.h>
26 27

#include "empathy-ui-utils.h"
28
#include "empathy-utils.h"
29 30 31

#define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathySearchBar)

32
G_DEFINE_TYPE (EmpathySearchBar, empathy_search_bar, GTK_TYPE_BOX);
33 34 35 36

typedef struct _EmpathySearchBarPriv EmpathySearchBarPriv;
struct _EmpathySearchBarPriv
{
37
  EmpathyThemeAdium *chat_view;
38 39 40

  GtkWidget *search_entry;

41 42
  GtkWidget *search_match_case;

43 44
  GtkWidget *search_match_case_toolitem;

45 46 47 48 49 50 51
  GtkWidget *search_close;
  GtkWidget *search_previous;
  GtkWidget *search_next;
  GtkWidget *search_not_found;
};

GtkWidget *
52
empathy_search_bar_new (EmpathyThemeAdium *view)
53 54 55 56 57 58 59 60 61
{
  EmpathySearchBar *self = g_object_new (EMPATHY_TYPE_SEARCH_BAR, NULL);

  GET_PRIV (self)->chat_view = view;

  return GTK_WIDGET (self);
}

static void
62
empathy_search_bar_update_buttons (EmpathySearchBar *self,
63 64
    gchar *search,
    gboolean match_case)
65 66 67 68 69 70 71
{
  gboolean can_go_forward = FALSE;
  gboolean can_go_backward = FALSE;

  EmpathySearchBarPriv* priv = GET_PRIV (self);

  /* update previous / next buttons */
72
  empathy_theme_adium_find_abilities (priv->chat_view, search, match_case,
73
      &can_go_backward, &can_go_forward);
74 75

  gtk_widget_set_sensitive (priv->search_previous,
76
      can_go_backward && !TPAW_STR_EMPTY (search));
77
  gtk_widget_set_sensitive (priv->search_next,
78
      can_go_forward && !TPAW_STR_EMPTY (search));
79 80
}

81
static void
82 83 84
empathy_search_bar_search (EmpathySearchBar *self,
    gboolean next,
    gboolean new_search)
85
{
86
  gchar *search;
87
  gboolean found;
88
  gboolean match_case;
89 90 91
  EmpathySearchBarPriv *priv;

  priv = GET_PRIV (self);
92

93 94 95 96 97
  search = gtk_editable_get_chars (GTK_EDITABLE(priv->search_entry), 0, -1);
  match_case = gtk_toggle_button_get_active (
      GTK_TOGGLE_BUTTON (priv->search_match_case));

  /* highlight & search */
98 99 100 101 102 103 104 105 106 107 108 109 110 111
  if (new_search)
    empathy_theme_adium_search (priv->chat_view, search, match_case);
  else if (next)
    empathy_theme_adium_find_next (priv->chat_view);
  else
    empathy_theme_adium_find_previous (priv->chat_view);

  /* FIXME: We should connect to failed-to-find-text of WebKitFindController, but this
   * doesn't seem to work in any case.
   */
  found = TRUE;
  /* (don't) display the not found label */
  gtk_widget_set_visible (priv->search_not_found,
      !(found || TPAW_STR_EMPTY (search)));
112 113

  /* update the buttons */
114
  empathy_search_bar_update_buttons (self, search, match_case);
115

116 117 118 119 120 121 122 123 124
  g_free (search);
}

void
empathy_search_bar_show (EmpathySearchBar *self)
{
  EmpathySearchBarPriv *priv = GET_PRIV (self);

  /* update the highlighting and buttons */
125
  empathy_search_bar_search (self, FALSE, TRUE);
126

127 128 129 130 131 132
  /* grab the focus to the search entry */
  gtk_widget_grab_focus (priv->search_entry);

  gtk_widget_show (GTK_WIDGET (self));
}

133 134
void
empathy_search_bar_hide (EmpathySearchBar *self)
135
{
136
  EmpathySearchBarPriv *priv = GET_PRIV (self);
137

138
  empathy_theme_adium_search (priv->chat_view, "", FALSE);
139
  gtk_widget_hide (GTK_WIDGET (self));
140 141 142 143 144

  /* give the focus back to the focus-chain with the chat view */
  gtk_widget_grab_focus (GTK_WIDGET (priv->chat_view));
}

145 146 147 148 149 150 151
static void
empathy_search_bar_close_cb (GtkButton *button,
    gpointer user_data)
{
  empathy_search_bar_hide (EMPATHY_SEARCH_BAR (user_data));
}

152 153 154 155 156
static void
empathy_search_bar_entry_changed (GtkEditable *entry,
    gpointer user_data)
{
  empathy_search_bar_search (EMPATHY_SEARCH_BAR (user_data), FALSE, TRUE);
157 158
}

159 160 161 162 163
static gboolean
empathy_search_bar_key_pressed (GtkWidget   *widget,
    GdkEventKey *event,
    gpointer user_data)
{
164
  if (event->keyval == GDK_KEY_Escape)
165 166 167 168 169 170 171
    {
      empathy_search_bar_hide (EMPATHY_SEARCH_BAR (widget));
      return TRUE;
    }
  return FALSE;
}

172 173 174 175
static void
empathy_search_bar_next_cb (GtkButton *button,
    gpointer user_data)
{
176
  empathy_search_bar_search (EMPATHY_SEARCH_BAR (user_data), TRUE, FALSE);
177 178 179 180 181 182
}

static void
empathy_search_bar_previous_cb (GtkButton *button,
    gpointer user_data)
{
183
  empathy_search_bar_search (EMPATHY_SEARCH_BAR (user_data), FALSE, FALSE);
184 185
}

Thomas Meire's avatar
Thomas Meire committed
186 187 188 189
static void
empathy_search_bar_match_case_toggled (GtkButton *button,
    gpointer user_data)
{
190
  empathy_search_bar_search (EMPATHY_SEARCH_BAR (user_data), FALSE, TRUE);
Thomas Meire's avatar
Thomas Meire committed
191 192
}

193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228
static void
empathy_search_bar_match_case_menu_toggled (GtkWidget *check,
    gpointer user_data)
{
  EmpathySearchBarPriv* priv = GET_PRIV ( EMPATHY_SEARCH_BAR (user_data));
  gboolean match_case;

  match_case = gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (check));

  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->search_match_case),
      match_case);
}

static gboolean
empathy_searchbar_create_menu_proxy_cb (GtkToolItem *toolitem,
    gpointer user_data)
{
  EmpathySearchBarPriv* priv = GET_PRIV ( EMPATHY_SEARCH_BAR (user_data));
  GtkWidget *checkbox_menu;
  gboolean match_case;

  checkbox_menu = gtk_check_menu_item_new_with_mnemonic (_("_Match case"));
  match_case = gtk_toggle_button_get_active (
      GTK_TOGGLE_BUTTON (priv->search_match_case));
  gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (checkbox_menu),
      match_case);

  g_signal_connect (checkbox_menu, "toggled",
      G_CALLBACK (empathy_search_bar_match_case_menu_toggled), user_data);

  gtk_tool_item_set_proxy_menu_item (toolitem, "menu-proxy",
      checkbox_menu);

  return TRUE;
}

229 230 231 232 233 234 235 236 237 238 239 240 241 242
static void
empathy_search_bar_init (EmpathySearchBar * self)
{
  gchar *filename;
  GtkBuilder *gui;
  GtkWidget *internal;
  EmpathySearchBarPriv *priv;

  priv = G_TYPE_INSTANCE_GET_PRIVATE (self, EMPATHY_TYPE_SEARCH_BAR,
      EmpathySearchBarPriv);

  self->priv = priv;

  filename = empathy_file_lookup ("empathy-search-bar.ui", "libempathy-gtk");
243
  gui = tpaw_builder_get_file (filename,
244 245 246 247 248 249
      "search_widget", &internal,
      "search_close", &priv->search_close,
      "search_entry", &priv->search_entry,
      "search_previous", &priv->search_previous,
      "search_next", &priv->search_next,
      "search_not_found", &priv->search_not_found,
250
      "search_match_case", &priv->search_match_case,
251 252 253 254
      NULL);
  g_free (filename);

  /* Add the signals */
255
  tpaw_builder_connect (gui, self,
256 257 258 259
      "search_close", "clicked", empathy_search_bar_close_cb,
      "search_entry", "changed", empathy_search_bar_entry_changed,
      "search_previous", "clicked", empathy_search_bar_previous_cb,
      "search_next", "clicked", empathy_search_bar_next_cb,
Thomas Meire's avatar
Thomas Meire committed
260
      "search_match_case", "toggled", empathy_search_bar_match_case_toggled,
261
      "search_match_case_toolitem", "create-menu-proxy", empathy_searchbar_create_menu_proxy_cb,
262 263
      NULL);

264 265 266
  g_signal_connect (G_OBJECT (self), "key-press-event",
      G_CALLBACK (empathy_search_bar_key_pressed), NULL);

267
  gtk_box_pack_start (GTK_BOX (self), internal, TRUE, TRUE, 0);
268 269 270 271 272 273 274 275 276 277 278 279 280
  gtk_widget_show_all (internal);
  gtk_widget_hide (priv->search_not_found);
  g_object_unref (gui);
}

static void
empathy_search_bar_class_init (EmpathySearchBarClass *class)
{
  GObjectClass *gobject_class = G_OBJECT_CLASS (class);

  g_type_class_add_private (gobject_class, sizeof (EmpathySearchBarPriv));
}

281 282 283 284 285 286 287
void
empathy_search_bar_paste_clipboard (EmpathySearchBar *self)
{
  EmpathySearchBarPriv *priv = GET_PRIV (self);

  gtk_editable_paste_clipboard (GTK_EDITABLE (priv->search_entry));
}