1 /* Copyright (C) 2004 Red Hat, Inc.
2 
3 This library is free software; you can redistribute it and/or
4 modify it under the terms of the GNU Library General Public License as
5 published by the Free Software Foundation; either version 2 of the
6 License, or (at your option) any later version.
7 
8 This library is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 Library General Public License for more details.
12 
13 You should have received a copy of the GNU Library General Public
14 License along with the Gnome Library; see the file COPYING.LIB.  If not,
15 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
16 Boston, MA 02111-1307, USA.
17 */
18 
19 #include "config.h"
20 
21 #include <string.h>
22 
23 #include <glib/gi18n-lib.h>
24 #include <gtk/gtk.h>
25 #include <gdk/gdkkeysyms.h>
26 
27 #include "eggfindbar.h"
28 
29 struct _EggFindBarPrivate
30 {
31   gchar *search_string;
32 
33   GtkToolItem *next_button;
34   GtkToolItem *previous_button;
35   GtkToolItem *status_separator;
36   GtkToolItem *status_item;
37   GtkToolItem *case_button;
38 
39   GtkWidget *find_entry;
40   GtkWidget *status_label;
41 
42   gulong set_focus_handler;
43   guint case_sensitive : 1;
44 };
45 
46 #define EGG_FIND_BAR_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), EGG_TYPE_FIND_BAR, EggFindBarPrivate))
47 
48 enum {
49     PROP_0,
50     PROP_SEARCH_STRING,
51     PROP_CASE_SENSITIVE
52 };
53 
54 static void egg_find_bar_finalize      (GObject        *object);
55 static void egg_find_bar_get_property  (GObject        *object,
56                                         guint           prop_id,
57                                         GValue         *value,
58                                         GParamSpec     *pspec);
59 static void egg_find_bar_set_property  (GObject        *object,
60                                         guint           prop_id,
61                                         const GValue   *value,
62                                         GParamSpec     *pspec);
63 static void egg_find_bar_show          (GtkWidget *widget);
64 static void egg_find_bar_hide          (GtkWidget *widget);
65 static void egg_find_bar_grab_focus    (GtkWidget *widget);
66 
67 G_DEFINE_TYPE (EggFindBar, egg_find_bar, GTK_TYPE_TOOLBAR);
68 
69 enum
70   {
71     NEXT,
72     PREVIOUS,
73     CLOSE,
74     SCROLL,
75     LAST_SIGNAL
76   };
77 
78 static guint find_bar_signals[LAST_SIGNAL] = { 0 };
79 
80 static void
egg_find_bar_class_init(EggFindBarClass * klass)81 egg_find_bar_class_init (EggFindBarClass *klass)
82 {
83   GObjectClass *object_class;
84   GtkWidgetClass *widget_class;
85   GtkBindingSet *binding_set;
86 
87   egg_find_bar_parent_class = g_type_class_peek_parent (klass);
88 
89   object_class = (GObjectClass *)klass;
90   widget_class = (GtkWidgetClass *)klass;
91 
92   object_class->set_property = egg_find_bar_set_property;
93   object_class->get_property = egg_find_bar_get_property;
94 
95   object_class->finalize = egg_find_bar_finalize;
96 
97   widget_class->show = egg_find_bar_show;
98   widget_class->hide = egg_find_bar_hide;
99 
100   widget_class->grab_focus = egg_find_bar_grab_focus;
101 
102   find_bar_signals[NEXT] =
103     g_signal_new ("next",
104 		  G_OBJECT_CLASS_TYPE (object_class),
105 		  G_SIGNAL_RUN_FIRST,
106                   G_STRUCT_OFFSET (EggFindBarClass, next),
107 		  NULL, NULL,
108 		  g_cclosure_marshal_VOID__VOID,
109 		  G_TYPE_NONE, 0);
110   find_bar_signals[PREVIOUS] =
111     g_signal_new ("previous",
112 		  G_OBJECT_CLASS_TYPE (object_class),
113 		  G_SIGNAL_RUN_FIRST,
114                   G_STRUCT_OFFSET (EggFindBarClass, previous),
115 		  NULL, NULL,
116 		  g_cclosure_marshal_VOID__VOID,
117 		  G_TYPE_NONE, 0);
118   find_bar_signals[CLOSE] =
119     g_signal_new ("close",
120 		  G_OBJECT_CLASS_TYPE (object_class),
121 		  G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
122                   G_STRUCT_OFFSET (EggFindBarClass, close),
123 		  NULL, NULL,
124 		  g_cclosure_marshal_VOID__VOID,
125 		  G_TYPE_NONE, 0);
126   find_bar_signals[SCROLL] =
127     g_signal_new ("scroll",
128 		  G_OBJECT_CLASS_TYPE (object_class),
129 		  G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
130                   G_STRUCT_OFFSET (EggFindBarClass, scroll),
131 		  NULL, NULL,
132 		  g_cclosure_marshal_VOID__ENUM,
133 		  G_TYPE_NONE, 1,
134 		  GTK_TYPE_SCROLL_TYPE);
135 
136   /**
137    * EggFindBar:search_string:
138    *
139    * The current string to search for. NULL or empty string
140    * both mean no current string.
141    *
142    */
143   g_object_class_install_property (object_class,
144 				   PROP_SEARCH_STRING,
145 				   g_param_spec_string ("search_string",
146 							("Search string"),
147 							("The name of the string to be found"),
148 							NULL,
149 							G_PARAM_READWRITE));
150 
151   /**
152    * EggFindBar:case_sensitive:
153    *
154    * TRUE for a case sensitive search.
155    *
156    */
157   g_object_class_install_property (object_class,
158 				   PROP_CASE_SENSITIVE,
159 				   g_param_spec_boolean ("case_sensitive",
160                                                          ("Case sensitive"),
161                                                          ("TRUE for a case sensitive search"),
162                                                          FALSE,
163                                                          G_PARAM_READWRITE));
164 
165   /* Style properties */
166   gtk_widget_class_install_style_property (widget_class,
167                                            g_param_spec_boxed ("all_matches_color",
168                                                                ("Highlight color"),
169                                                                ("Color of highlight for all matches"),
170                                                                GDK_TYPE_COLOR,
171                                                                G_PARAM_READABLE));
172 
173   gtk_widget_class_install_style_property (widget_class,
174                                            g_param_spec_boxed ("current_match_color",
175                                                                ("Current color"),
176                                                                ("Color of highlight for the current match"),
177                                                                GDK_TYPE_COLOR,
178                                                                G_PARAM_READABLE));
179 
180   g_type_class_add_private (object_class, sizeof (EggFindBarPrivate));
181 
182   binding_set = gtk_binding_set_by_class (klass);
183 
184   gtk_binding_entry_add_signal (binding_set, GDK_Escape, 0,
185 				"close", 0);
186 
187   gtk_binding_entry_add_signal (binding_set, GDK_Up, 0,
188                                 "scroll", 1,
189                                 GTK_TYPE_SCROLL_TYPE, GTK_SCROLL_STEP_BACKWARD);
190   gtk_binding_entry_add_signal (binding_set, GDK_Down, 0,
191                                 "scroll", 1,
192                                 GTK_TYPE_SCROLL_TYPE, GTK_SCROLL_STEP_FORWARD);
193   gtk_binding_entry_add_signal (binding_set, GDK_Page_Up, 0,
194 				"scroll", 1,
195 				GTK_TYPE_SCROLL_TYPE, GTK_SCROLL_PAGE_BACKWARD);
196   gtk_binding_entry_add_signal (binding_set, GDK_KP_Page_Up, 0,
197 				"scroll", 1,
198 				GTK_TYPE_SCROLL_TYPE, GTK_SCROLL_PAGE_BACKWARD);
199   gtk_binding_entry_add_signal (binding_set, GDK_Page_Down, 0,
200 				"scroll", 1,
201 				GTK_TYPE_SCROLL_TYPE, GTK_SCROLL_PAGE_FORWARD);
202   gtk_binding_entry_add_signal (binding_set, GDK_KP_Page_Down, 0,
203 				"scroll", 1,
204 				GTK_TYPE_SCROLL_TYPE, GTK_SCROLL_PAGE_FORWARD);
205 }
206 
207 static void
egg_find_bar_emit_next(EggFindBar * find_bar)208 egg_find_bar_emit_next (EggFindBar *find_bar)
209 {
210   g_signal_emit (find_bar, find_bar_signals[NEXT], 0);
211 }
212 
213 static void
egg_find_bar_emit_previous(EggFindBar * find_bar)214 egg_find_bar_emit_previous (EggFindBar *find_bar)
215 {
216   g_signal_emit (find_bar, find_bar_signals[PREVIOUS], 0);
217 }
218 
219 static void
next_clicked_callback(GtkButton * button,void * data)220 next_clicked_callback (GtkButton *button,
221                        void      *data)
222 {
223   EggFindBar *find_bar = EGG_FIND_BAR (data);
224 
225   egg_find_bar_emit_next (find_bar);
226 }
227 
228 static void
previous_clicked_callback(GtkButton * button,void * data)229 previous_clicked_callback (GtkButton *button,
230                            void      *data)
231 {
232   EggFindBar *find_bar = EGG_FIND_BAR (data);
233 
234   egg_find_bar_emit_previous (find_bar);
235 }
236 
237 static void
case_sensitive_toggled_callback(GtkCheckButton * button,void * data)238 case_sensitive_toggled_callback (GtkCheckButton *button,
239                                  void           *data)
240 {
241   EggFindBar *find_bar = EGG_FIND_BAR (data);
242 
243   egg_find_bar_set_case_sensitive (find_bar,
244                                    gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)));
245 }
246 
247 static void
entry_activate_callback(GtkEntry * entry,void * data)248 entry_activate_callback (GtkEntry *entry,
249                           void     *data)
250 {
251   EggFindBar *find_bar = EGG_FIND_BAR (data);
252 
253   if (find_bar->priv->search_string != NULL)
254     egg_find_bar_emit_next (find_bar);
255 }
256 
257 static void
entry_changed_callback(GtkEntry * entry,void * data)258 entry_changed_callback (GtkEntry *entry,
259                         void     *data)
260 {
261   EggFindBar *find_bar = EGG_FIND_BAR (data);
262   char *text;
263 
264   /* paranoid strdup because set_search_string() sets
265    * the entry text
266    */
267   text = g_strdup (gtk_entry_get_text (entry));
268 
269   egg_find_bar_set_search_string (find_bar, text);
270 
271   g_free (text);
272 }
273 
274 static void
set_focus_cb(GtkWidget * window,GtkWidget * widget,EggFindBar * bar)275 set_focus_cb (GtkWidget *window,
276 	      GtkWidget *widget,
277 	      EggFindBar *bar)
278 {
279   GtkWidget *wbar = GTK_WIDGET (bar);
280 
281   while (widget != NULL && widget != wbar)
282     {
283       widget = gtk_widget_get_parent (widget);
284     }
285 
286   /* if widget == bar, the new focus widget is in the bar, so we
287    * don't deactivate.
288    */
289   if (widget != wbar)
290     {
291       g_signal_emit (bar, find_bar_signals[CLOSE], 0);
292     }
293 }
294 
295 static void
egg_find_bar_init(EggFindBar * find_bar)296 egg_find_bar_init (EggFindBar *find_bar)
297 {
298   EggFindBarPrivate *priv;
299   GtkWidget *label;
300   GtkWidget *alignment;
301   GtkWidget *box;
302   GtkToolItem *item;
303   GtkWidget *arrow;
304 
305   /* Data */
306   priv = EGG_FIND_BAR_GET_PRIVATE (find_bar);
307 
308   find_bar->priv = priv;
309   priv->search_string = NULL;
310 
311   gtk_toolbar_set_style (GTK_TOOLBAR (find_bar), GTK_TOOLBAR_BOTH_HORIZ);
312 
313   /* Find: |_____| */
314   item = gtk_tool_item_new ();
315   box = gtk_hbox_new (FALSE, 12);
316 
317   alignment = gtk_alignment_new (0.0, 0.5, 1.0, 0.0);
318   gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 0, 0, 2, 2);
319 
320   label = gtk_label_new_with_mnemonic (_("Find:"));
321 
322   priv->find_entry = gtk_entry_new ();
323   gtk_entry_set_width_chars (GTK_ENTRY (priv->find_entry), 32);
324   gtk_entry_set_max_length (GTK_ENTRY (priv->find_entry), 512);
325   gtk_label_set_mnemonic_widget (GTK_LABEL (label), priv->find_entry);
326 
327   /* Prev */
328   arrow = gtk_arrow_new (GTK_ARROW_LEFT, GTK_SHADOW_NONE);
329   priv->previous_button = gtk_tool_button_new (arrow, Q_("Find Previous"));
330   gtk_tool_item_set_is_important (priv->previous_button, TRUE);
331 #if GTK_CHECK_VERSION (2, 11, 5)
332   gtk_widget_set_tooltip_text (GTK_WIDGET (priv->previous_button),
333 			       _("Find previous occurrence of the search string"));
334 #else
335   gtk_tool_item_set_tooltip (priv->previous_button, GTK_TOOLBAR (find_bar)->tooltips,
336 		             _("Find previous occurrence of the search string"),
337 		             NULL);
338 #endif
339 
340   /* Next */
341   arrow = gtk_arrow_new (GTK_ARROW_RIGHT, GTK_SHADOW_NONE);
342   priv->next_button = gtk_tool_button_new (arrow, Q_("Find Next"));
343   gtk_tool_item_set_is_important (priv->next_button, TRUE);
344 #if GTK_CHECK_VERSION (2, 11, 5)
345   gtk_widget_set_tooltip_text (GTK_WIDGET (priv->next_button),
346 			       _("Find next occurrence of the search string"));
347 #else
348   gtk_tool_item_set_tooltip (priv->next_button, GTK_TOOLBAR (find_bar)->tooltips,
349 		             _("Find next occurrence of the search string"),
350 		             NULL);
351 #endif
352 
353   /* Separator*/
354   priv->status_separator = gtk_separator_tool_item_new();
355 
356   /* Case button */
357   priv->case_button = gtk_toggle_tool_button_new ();
358   g_object_set (G_OBJECT (priv->case_button), "label", _("C_ase Sensitive"), NULL);
359   gtk_tool_item_set_is_important (priv->case_button, TRUE);
360 #if GTK_CHECK_VERSION (2, 11, 5)
361   gtk_widget_set_tooltip_text (GTK_WIDGET (priv->case_button),
362 			       _("Toggle case sensitive search"));
363 #else
364   gtk_tool_item_set_tooltip (priv->case_button, GTK_TOOLBAR (find_bar)->tooltips,
365 		             _("Toggle case sensitive search"),
366 		             NULL);
367 #endif
368   /* Status */
369   priv->status_item = gtk_tool_item_new();
370   gtk_tool_item_set_expand (priv->status_item, TRUE);
371   priv->status_label = gtk_label_new (NULL);
372   gtk_label_set_ellipsize (GTK_LABEL (priv->status_label),
373                            PANGO_ELLIPSIZE_END);
374   gtk_misc_set_alignment (GTK_MISC (priv->status_label), 0.0, 0.5);
375 
376 
377   g_signal_connect (priv->find_entry, "changed",
378                     G_CALLBACK (entry_changed_callback),
379                     find_bar);
380   g_signal_connect (priv->find_entry, "activate",
381                     G_CALLBACK (entry_activate_callback),
382                     find_bar);
383   g_signal_connect (priv->next_button, "clicked",
384                     G_CALLBACK (next_clicked_callback),
385                     find_bar);
386   g_signal_connect (priv->previous_button, "clicked",
387                     G_CALLBACK (previous_clicked_callback),
388                     find_bar);
389   g_signal_connect (priv->case_button, "toggled",
390                     G_CALLBACK (case_sensitive_toggled_callback),
391                     find_bar);
392 
393   gtk_box_pack_start (GTK_BOX (box), label, FALSE, FALSE, 0);
394   gtk_box_pack_start (GTK_BOX (box), priv->find_entry, TRUE, TRUE, 0);
395   gtk_container_add (GTK_CONTAINER (alignment), box);
396   gtk_container_add (GTK_CONTAINER (item), alignment);
397   gtk_toolbar_insert (GTK_TOOLBAR (find_bar), item, -1);
398   gtk_toolbar_insert (GTK_TOOLBAR (find_bar), priv->previous_button, -1);
399   gtk_toolbar_insert (GTK_TOOLBAR (find_bar), priv->next_button, -1);
400   gtk_toolbar_insert (GTK_TOOLBAR (find_bar), priv->case_button, -1);
401   gtk_toolbar_insert (GTK_TOOLBAR (find_bar), priv->status_separator, -1);
402   gtk_container_add  (GTK_CONTAINER (priv->status_item), priv->status_label);
403   gtk_toolbar_insert (GTK_TOOLBAR (find_bar), priv->status_item, -1);
404 
405   /* don't show status separator/label until they are set */
406 
407   gtk_widget_show_all (GTK_WIDGET (item));
408   gtk_widget_show_all (GTK_WIDGET (priv->next_button));
409   gtk_widget_show_all (GTK_WIDGET (priv->previous_button));
410   gtk_widget_show (priv->status_label);
411 }
412 
413 static void
egg_find_bar_finalize(GObject * object)414 egg_find_bar_finalize (GObject *object)
415 {
416   EggFindBar *find_bar = EGG_FIND_BAR (object);
417   EggFindBarPrivate *priv = (EggFindBarPrivate *)find_bar->priv;
418 
419   g_free (priv->search_string);
420 
421   G_OBJECT_CLASS (egg_find_bar_parent_class)->finalize (object);
422 }
423 
424 static void
egg_find_bar_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)425 egg_find_bar_set_property (GObject      *object,
426                            guint         prop_id,
427                            const GValue *value,
428                            GParamSpec   *pspec)
429 {
430   EggFindBar *find_bar = EGG_FIND_BAR (object);
431 
432   switch (prop_id)
433     {
434     case PROP_SEARCH_STRING:
435       egg_find_bar_set_search_string (find_bar, g_value_get_string (value));
436       break;
437     case PROP_CASE_SENSITIVE:
438       egg_find_bar_set_case_sensitive (find_bar, g_value_get_boolean (value));
439       break;
440     default:
441       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
442       break;
443     }
444 }
445 
446 static void
egg_find_bar_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)447 egg_find_bar_get_property (GObject    *object,
448                            guint       prop_id,
449                            GValue     *value,
450                            GParamSpec *pspec)
451 {
452   EggFindBar *find_bar = EGG_FIND_BAR (object);
453   EggFindBarPrivate *priv = (EggFindBarPrivate *)find_bar->priv;
454 
455   switch (prop_id)
456     {
457     case PROP_SEARCH_STRING:
458       g_value_set_string (value, priv->search_string);
459       break;
460     case PROP_CASE_SENSITIVE:
461       g_value_set_boolean (value, priv->case_sensitive);
462       break;
463     default:
464       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
465       break;
466     }
467 }
468 
469 static void
egg_find_bar_show(GtkWidget * widget)470 egg_find_bar_show (GtkWidget *widget)
471 {
472   EggFindBar *bar = EGG_FIND_BAR (widget);
473   EggFindBarPrivate *priv = bar->priv;
474 
475   GTK_WIDGET_CLASS (egg_find_bar_parent_class)->show (widget);
476 
477   if (priv->set_focus_handler == 0)
478     {
479       GtkWidget *toplevel;
480 
481       toplevel = gtk_widget_get_toplevel (widget);
482 
483       priv->set_focus_handler =
484 	g_signal_connect (toplevel, "set-focus",
485 			  G_CALLBACK (set_focus_cb), bar);
486     }
487 }
488 
489 static void
egg_find_bar_hide(GtkWidget * widget)490 egg_find_bar_hide (GtkWidget *widget)
491 {
492   EggFindBar *bar = EGG_FIND_BAR (widget);
493   EggFindBarPrivate *priv = bar->priv;
494 
495   if (priv->set_focus_handler != 0)
496     {
497       GtkWidget *toplevel;
498 
499       toplevel = gtk_widget_get_toplevel (widget);
500 
501       g_signal_handlers_disconnect_by_func
502 	(toplevel, (void (*)) G_CALLBACK (set_focus_cb), bar);
503       priv->set_focus_handler = 0;
504     }
505 
506   GTK_WIDGET_CLASS (egg_find_bar_parent_class)->hide (widget);
507 }
508 
509 static void
egg_find_bar_grab_focus(GtkWidget * widget)510 egg_find_bar_grab_focus (GtkWidget *widget)
511 {
512   EggFindBar *find_bar = EGG_FIND_BAR (widget);
513   EggFindBarPrivate *priv = find_bar->priv;
514 
515   gtk_widget_grab_focus (priv->find_entry);
516 }
517 
518 /**
519  * egg_find_bar_new:
520  *
521  * Creates a new #EggFindBar.
522  *
523  * Returns: a newly created #EggFindBar
524  *
525  * Since: 2.6
526  */
527 GtkWidget *
egg_find_bar_new(void)528 egg_find_bar_new (void)
529 {
530   EggFindBar *find_bar;
531 
532   find_bar = g_object_new (EGG_TYPE_FIND_BAR, NULL);
533 
534   return GTK_WIDGET (find_bar);
535 }
536 
537 /**
538  * egg_find_bar_set_search_string:
539  *
540  * Sets the string that should be found/highlighted in the document.
541  * Empty string is converted to NULL.
542  *
543  * Since: 2.6
544  */
545 void
egg_find_bar_set_search_string(EggFindBar * find_bar,const char * search_string)546 egg_find_bar_set_search_string  (EggFindBar *find_bar,
547                                  const char *search_string)
548 {
549   EggFindBarPrivate *priv;
550 
551   g_return_if_fail (EGG_IS_FIND_BAR (find_bar));
552 
553   priv = (EggFindBarPrivate *)find_bar->priv;
554 
555   g_object_freeze_notify (G_OBJECT (find_bar));
556 
557   if (priv->search_string != search_string)
558     {
559       char *old;
560 
561       old = priv->search_string;
562 
563       if (search_string && *search_string == '\0')
564         search_string = NULL;
565 
566       /* Only update if the string has changed; setting the entry
567        * will emit changed on the entry which will re-enter
568        * this function, but we'll handle that fine with this
569        * short-circuit.
570        */
571       if ((old && search_string == NULL) ||
572           (old == NULL && search_string) ||
573           (old && search_string &&
574            strcmp (old, search_string) != 0))
575         {
576 	  gboolean not_empty;
577 
578           priv->search_string = g_strdup (search_string);
579           g_free (old);
580 
581           gtk_entry_set_text (GTK_ENTRY (priv->find_entry),
582                               priv->search_string ?
583                               priv->search_string :
584                               "");
585 
586           not_empty = (search_string == NULL) ? FALSE : TRUE;
587 
588           gtk_widget_set_sensitive (GTK_WIDGET (find_bar->priv->next_button), not_empty);
589           gtk_widget_set_sensitive (GTK_WIDGET (find_bar->priv->previous_button), not_empty);
590 
591           g_object_notify (G_OBJECT (find_bar),
592                            "search_string");
593         }
594     }
595 
596   g_object_thaw_notify (G_OBJECT (find_bar));
597 }
598 
599 
600 /**
601  * egg_find_bar_get_search_string:
602  *
603  * Gets the string that should be found/highlighted in the document.
604  *
605  * Returns: the string
606  *
607  * Since: 2.6
608  */
609 const char*
egg_find_bar_get_search_string(EggFindBar * find_bar)610 egg_find_bar_get_search_string  (EggFindBar *find_bar)
611 {
612   EggFindBarPrivate *priv;
613 
614   g_return_val_if_fail (EGG_IS_FIND_BAR (find_bar), NULL);
615 
616   priv = find_bar->priv;
617 
618   return priv->search_string ? priv->search_string : "";
619 }
620 
621 /**
622  * egg_find_bar_set_case_sensitive:
623  *
624  * Sets whether the search is case sensitive
625  *
626  * Since: 2.6
627  */
628 void
egg_find_bar_set_case_sensitive(EggFindBar * find_bar,gboolean case_sensitive)629 egg_find_bar_set_case_sensitive (EggFindBar *find_bar,
630                                  gboolean    case_sensitive)
631 {
632   EggFindBarPrivate *priv;
633 
634   g_return_if_fail (EGG_IS_FIND_BAR (find_bar));
635 
636   priv = (EggFindBarPrivate *)find_bar->priv;
637 
638   g_object_freeze_notify (G_OBJECT (find_bar));
639 
640   case_sensitive = case_sensitive != FALSE;
641 
642   if (priv->case_sensitive != case_sensitive)
643     {
644       priv->case_sensitive = case_sensitive;
645 
646       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->case_button),
647                                     priv->case_sensitive);
648 
649       g_object_notify (G_OBJECT (find_bar),
650                        "case_sensitive");
651     }
652 
653   g_object_thaw_notify (G_OBJECT (find_bar));
654 }
655 
656 /**
657  * egg_find_bar_get_case_sensitive:
658  *
659  * Gets whether the search is case sensitive
660  *
661  * Returns: TRUE if it's case sensitive
662  *
663  * Since: 2.6
664  */
665 gboolean
egg_find_bar_get_case_sensitive(EggFindBar * find_bar)666 egg_find_bar_get_case_sensitive (EggFindBar *find_bar)
667 {
668   EggFindBarPrivate *priv;
669 
670   g_return_val_if_fail (EGG_IS_FIND_BAR (find_bar), FALSE);
671 
672   priv = (EggFindBarPrivate *)find_bar->priv;
673 
674   return priv->case_sensitive;
675 }
676 
677 static void
get_style_color(EggFindBar * find_bar,const char * style_prop_name,GdkColor * color)678 get_style_color (EggFindBar *find_bar,
679                  const char *style_prop_name,
680                  GdkColor   *color)
681 {
682   GdkColor *style_color;
683 
684   gtk_widget_ensure_style (GTK_WIDGET (find_bar));
685   gtk_widget_style_get (GTK_WIDGET (find_bar),
686                         "color", &style_color, NULL);
687   if (style_color)
688     {
689       *color = *style_color;
690       gdk_color_free (style_color);
691     }
692 }
693 
694 /**
695  * egg_find_bar_get_all_matches_color:
696  *
697  * Gets the color to use to highlight all the
698  * known matches.
699  *
700  * Since: 2.6
701  */
702 void
egg_find_bar_get_all_matches_color(EggFindBar * find_bar,GdkColor * color)703 egg_find_bar_get_all_matches_color (EggFindBar *find_bar,
704                                     GdkColor   *color)
705 {
706   GdkColor found_color = { 0, 0, 0, 0x0f0f };
707 
708   get_style_color (find_bar, "all_matches_color", &found_color);
709 
710   *color = found_color;
711 }
712 
713 /**
714  * egg_find_bar_get_current_match_color:
715  *
716  * Gets the color to use to highlight the match
717  * we're currently on.
718  *
719  * Since: 2.6
720  */
721 void
egg_find_bar_get_current_match_color(EggFindBar * find_bar,GdkColor * color)722 egg_find_bar_get_current_match_color (EggFindBar *find_bar,
723                                       GdkColor   *color)
724 {
725   GdkColor found_color = { 0, 0, 0, 0xffff };
726 
727   get_style_color (find_bar, "current_match_color", &found_color);
728 
729   *color = found_color;
730 }
731 
732 /**
733  * egg_find_bar_set_status_text:
734  *
735  * Sets some text to display if there's space; typical text would
736  * be something like "5 results on this page" or "No results"
737  *
738  * @text: the text to display
739  *
740  * Since: 2.6
741  */
742 void
egg_find_bar_set_status_text(EggFindBar * find_bar,const char * text)743 egg_find_bar_set_status_text (EggFindBar *find_bar,
744                               const char *text)
745 {
746   EggFindBarPrivate *priv;
747 
748   g_return_if_fail (EGG_IS_FIND_BAR (find_bar));
749 
750   priv = (EggFindBarPrivate *)find_bar->priv;
751 
752   gtk_label_set_text (GTK_LABEL (priv->status_label), text);
753   g_object_set (priv->status_separator, "visible", text != NULL && *text != '\0', NULL);
754   g_object_set (priv->status_item, "visible", text != NULL && *text !='\0', NULL);
755 }
756