GnuCash  4.11-11-ge9df8d41d2+
gnc-gtk-utils.c
1 /********************************************************************\
2  * gnc-gtk-utils.c -- utility functions based on glib functions *
3  * Copyright (C) 2006 David Hampton <hampton@employees.org> *
4  * *
5  * This program is free software; you can redistribute it and/or *
6  * modify it under the terms of the GNU General Public License as *
7  * published by the Free Software Foundation; either version 2 of *
8  * the License, or (at your option) any later version. *
9  * *
10  * This program is distributed in the hope that it will be useful, *
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13  * GNU General Public License for more details. *
14  * *
15  * You should have received a copy of the GNU General Public License*
16  * along with this program; if not, contact: *
17  * *
18  * Free Software Foundation Voice: +1-617-542-5942 *
19  * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
20  * Boston, MA 02110-1301, USA gnu@gnu.org *
21  * *
22 \********************************************************************/
23 
24 #include <config.h>
25 
26 #include "gnc-gtk-utils.h"
27 
28 #define LAST_INDEX "last_index"
29 #define CHANGED_ID "changed_id"
30 
31 
40 void
41 gnc_cbwe_set_by_string(GtkComboBox *cbwe,
42  const gchar *text)
43 {
44  GtkTreeModel *model;
45  GtkTreeIter iter;
46  gchar *tree_string;
47  gint column, index, id;
48  gboolean match;
49 
50  model = gtk_combo_box_get_model(GTK_COMBO_BOX(cbwe));
51  if (!gtk_tree_model_get_iter_first(model, &iter))
52  {
53  /* empty tree */
54  gtk_combo_box_set_active(GTK_COMBO_BOX(cbwe), -1);
55  return;
56  }
57 
58  column = gtk_combo_box_get_entry_text_column(cbwe);
59  do
60  {
61  gtk_tree_model_get(model, &iter, column, &tree_string, -1);
62  match = g_utf8_collate(text, tree_string) == 0;
63  g_free(tree_string);
64  if (!match)
65  continue;
66 
67  /* Found a matching string */
68  id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(cbwe), CHANGED_ID));
69  g_signal_handler_block(cbwe, id);
70  gtk_combo_box_set_active_iter(GTK_COMBO_BOX(cbwe), &iter);
71  g_signal_handler_unblock(cbwe, id);
72 
73  index = gtk_combo_box_get_active(GTK_COMBO_BOX(cbwe));
74  g_object_set_data(G_OBJECT(cbwe), LAST_INDEX, GINT_TO_POINTER(index));
75  return;
76  }
77  while (gtk_tree_model_iter_next(model, &iter));
78 }
79 
80 
88 static void
89 gnc_cbwe_changed_cb (GtkComboBox *widget,
90  GtkComboBox *cbwe)
91 {
92  gint index;
93 
94  index = gtk_combo_box_get_active(widget);
95  if (index == -1)
96  return;
97  g_object_set_data(G_OBJECT(cbwe), LAST_INDEX, GINT_TO_POINTER(index));
98 }
99 
100 
117 static gboolean
118 gnc_cbwe_match_selected_cb (GtkEntryCompletion *completion,
119  GtkTreeModel *comp_model,
120  GtkTreeIter *comp_iter,
121  GtkComboBox *cbwe)
122 {
123  gint column;
124  gchar *text;
125 
126  column = gtk_combo_box_get_entry_text_column(cbwe);
127  gtk_tree_model_get(comp_model, comp_iter, column, &text, -1);
128  gnc_cbwe_set_by_string(cbwe, text);
129  g_free(text);
130  return FALSE;
131 }
132 
133 
146 static gboolean
147 gnc_cbwe_focus_out_cb (GtkEntry *entry,
148  GdkEventFocus *event,
149  GtkComboBox *cbwe)
150 {
151  const gchar *text;
152  gint index;
153 
154  /* Make a final attempt to match the current text. */
155  text = gtk_entry_get_text(entry);
156  gnc_cbwe_set_by_string(cbwe, text);
157 
158  /* Get the last known index (which may have just been set). */
159  index = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(cbwe), LAST_INDEX));
160  gtk_combo_box_set_active(GTK_COMBO_BOX(cbwe), index);
161  return FALSE;
162 }
163 
164 void
165 gnc_cbwe_add_completion (GtkComboBox *cbwe)
166 {
167  GtkEntry *entry;
168  GtkEntryCompletion *completion;
169  GtkTreeModel *model;
170 
171  entry = GTK_ENTRY(gtk_bin_get_child(GTK_BIN(cbwe)));
172  completion = gtk_entry_get_completion(entry);
173  if (completion)
174  return;
175 
176  /* No completion yet? Set one up. */
177  completion = gtk_entry_completion_new();
178  model = gtk_combo_box_get_model(GTK_COMBO_BOX(cbwe));
179  gtk_entry_completion_set_model(completion, model);
180  gtk_entry_completion_set_text_column(completion, 0);
181  gtk_entry_set_completion(entry, completion);
182  g_object_unref(completion);
183 }
184 
185 void
186 gnc_cbwe_require_list_item (GtkComboBox *cbwe)
187 {
188  GtkEntry *entry;
189  GtkEntryCompletion *completion;
190  GtkTreeModel *model;
191  GtkTreeIter iter;
192  gint index, id;
193 
194  /* Ensure completion is set up. */
195  gnc_cbwe_add_completion(cbwe);
196 
197  /* If an item in the combo box isn't already selected, then force
198  * select the first item. Take care, the combo box may not have been
199  * filled yet. */
200  entry = GTK_ENTRY(gtk_bin_get_child(GTK_BIN(cbwe)));
201  completion = gtk_entry_get_completion(entry);
202  index = gtk_combo_box_get_active(GTK_COMBO_BOX(cbwe));
203  if (index == -1)
204  {
205  model = gtk_entry_completion_get_model(completion);
206  if (gtk_tree_model_get_iter_first(model, &iter))
207  {
208  gtk_combo_box_set_active(GTK_COMBO_BOX(cbwe), 0);
209  index = 0;
210  }
211  }
212  g_object_set_data(G_OBJECT(cbwe), LAST_INDEX, GINT_TO_POINTER(index));
213 
214  /* Now the signals to make sure the user can't leave the
215  widget without a valid match. */
216  id = g_signal_connect(cbwe, "changed",
217  G_CALLBACK(gnc_cbwe_changed_cb), cbwe);
218  g_signal_connect(completion, "match_selected",
219  G_CALLBACK(gnc_cbwe_match_selected_cb), cbwe);
220  g_signal_connect(entry, "focus-out-event",
221  G_CALLBACK(gnc_cbwe_focus_out_cb), cbwe);
222 
223  g_object_set_data(G_OBJECT(cbwe), CHANGED_ID, GINT_TO_POINTER(id));
224 }
225 
235 gboolean
236 gnc_is_dark_theme (GdkRGBA *fg_color)
237 {
238  gboolean is_dark = FALSE;
239 
240  // Counting the perceptive luminance - human eye favors green color...
241  double lightness = (0.299 * fg_color->red + 0.587 * fg_color->green + 0.114 * fg_color->blue);
242 
243  if (lightness > 0.5)
244  is_dark = TRUE;
245 
246  return is_dark;
247 }
248 
257 void
258 gnc_style_context_get_background_color (GtkStyleContext *context,
259  GtkStateFlags state,
260  GdkRGBA *color)
261 {
262  GdkRGBA *c;
263 
264  g_return_if_fail (color != NULL);
265  g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
266 
267  gtk_style_context_get (context,
268  state,
269  GTK_STYLE_PROPERTY_BACKGROUND_COLOR, &c,
270  NULL);
271  *color = *c;
272  gdk_rgba_free (c);
273 }
274 
283 void
284 gnc_style_context_get_border_color (GtkStyleContext *context,
285  GtkStateFlags state,
286  GdkRGBA *color)
287 {
288  GdkRGBA *c;
289 
290  g_return_if_fail (color != NULL);
291  g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
292 
293  gtk_style_context_get (context,
294  state,
295  GTK_STYLE_PROPERTY_BORDER_COLOR, &c,
296  NULL);
297  *color = *c;
298  gdk_rgba_free (c);
299 }
void gnc_cbwe_set_by_string(GtkComboBox *cbwe, const gchar *text)
Find an entry in the GtkComboBox by its text value, and set the widget to that value.
Definition: gnc-gtk-utils.c:41
gtk helper routines.
gboolean gnc_is_dark_theme(GdkRGBA *fg_color)
Return whether the current gtk theme is a dark one.
void gnc_style_context_get_border_color(GtkStyleContext *context, GtkStateFlags state, GdkRGBA *color)
Wrapper to get the border color of a widget for a given state.
void gnc_style_context_get_background_color(GtkStyleContext *context, GtkStateFlags state, GdkRGBA *color)
Wrapper to get the background color of a widget for a given state.