GnuCash  5.6-150-g038405b370+
gnc-general-select.c
1 /*
2  * gnc-general-select.c -- General Selection Widget
3  *
4  * Copyright (C) 2001 Free Software Foundation
5  * All rights reserved.
6  *
7  * Derek Atkins <warlord@MIT.EDU>
8  *
9  * Gnucash is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Library General Public License
11  * as published by the Free Software Foundation; either version 2 of the
12  * License, or (at your option) any later version.
13  *
14  * Gnucash is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17  * Library General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, contact:
21  *
22  * Free Software Foundation Voice: +1-617-542-5942
23  * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652
24  * Boston, MA 02110-1301, USA gnu@gnu.org
25  *
26  */
27 /*
28  @NOTATION@
29  */
30 
31 #include <config.h>
32 
33 #include <gtk/gtk.h>
34 #include <glib/gi18n.h>
35 #include <string.h>
36 #include <ctype.h>
37 #include <stdio.h>
38 
39 #include "gnc-general-select.h"
40 #include "dialog-utils.h"
41 
42 /* Signal codes */
43 enum
44 {
45  SELECTION_CHANGED,
46  LAST_SIGNAL
47 };
48 
49 
50 static void gnc_general_select_dispose (GObject *object);
51 static void gnc_general_select_finalize (GObject *object);
52 
53 static guint general_select_signals[LAST_SIGNAL];
54 
55 G_DEFINE_TYPE (GNCGeneralSelect, gnc_general_select, GTK_TYPE_BOX)
56 
57 static void
58 gnc_general_select_forall (GtkContainer *container, gboolean include_internals,
59  GtkCallback callback, gpointer callback_data)
60 {
61  g_return_if_fail (container != NULL);
62  g_return_if_fail (GNC_IS_GENERAL_SELECT (container));
63  g_return_if_fail (callback != NULL);
64 
65  /* Let GtkBox handle things only if the internal widgets need
66  * to be poked. */
67  if (!include_internals)
68  return;
69 
70  if (!GTK_CONTAINER_CLASS (gnc_general_select_parent_class)->forall)
71  return;
72 
73  GTK_CONTAINER_CLASS (gnc_general_select_parent_class)->forall (container,
74  include_internals,
75  callback,
76  callback_data);
77 }
78 
79 static void
80 gnc_general_select_class_init (GNCGeneralSelectClass *klass)
81 {
82  GObjectClass *object_class = (GObjectClass *) klass;
83  GtkContainerClass *container_class = (GtkContainerClass *) klass;
84 
85  object_class = (GObjectClass*) klass;
86 
87  general_select_signals[SELECTION_CHANGED] =
88  g_signal_new("changed",
89  G_TYPE_FROM_CLASS(object_class),
90  G_SIGNAL_RUN_FIRST,
91  G_STRUCT_OFFSET(GNCGeneralSelectClass,
92  changed),
93  NULL, NULL,
94  g_cclosure_marshal_VOID__VOID,
95  G_TYPE_NONE, 0);
96 
97  container_class->forall = gnc_general_select_forall;
98 
99  object_class->dispose = gnc_general_select_dispose;
100  object_class->finalize = gnc_general_select_finalize;
101 
102  klass->changed = NULL;
103 }
104 
105 static void
106 gnc_general_select_init (GNCGeneralSelect *gsl)
107 {
108  gtk_orientable_set_orientation (GTK_ORIENTABLE(gsl), GTK_ORIENTATION_HORIZONTAL);
109 
110  // Set the name for this widget so it can be easily manipulated with css
111  gtk_widget_set_name (GTK_WIDGET(gsl), "gnc-id-general-select");
112 
113  gsl->disposed = FALSE;
114  gsl->selected_item = NULL;
115 }
116 
117 static void
118 gnc_general_select_finalize (GObject *object)
119 {
120  g_return_if_fail (object != NULL);
121  g_return_if_fail (GNC_IS_GENERAL_SELECT (object));
122 
123  G_OBJECT_CLASS (gnc_general_select_parent_class)->finalize (object);
124 }
125 
126 static void
127 gnc_general_select_dispose (GObject *object)
128 {
129  GNCGeneralSelect *gsl;
130 
131  g_return_if_fail (object != NULL);
132  g_return_if_fail (GNC_IS_GENERAL_SELECT (object));
133 
134  gsl = GNC_GENERAL_SELECT (object);
135 
136  if (gsl->disposed)
137  return;
138 
139  gsl->disposed = TRUE;
140 
141 
142  gtk_widget_destroy(GTK_WIDGET(gsl->entry));
143  gsl->entry = NULL;
144 
145  gtk_widget_destroy(GTK_WIDGET(gsl->button));
146  gsl->button = NULL;
147 
148  G_OBJECT_CLASS (gnc_general_select_parent_class)->dispose (object);
149 }
150 
151 static void
152 select_cb(GtkButton * button, gpointer user_data)
153 {
154  GNCGeneralSelect *gsl = user_data;
155  gpointer new_selection;
156  GtkWidget *toplevel;
157 
158  toplevel = gtk_widget_get_toplevel (GTK_WIDGET (button));
159 
160  new_selection = (gsl->new_select)(gsl->cb_arg, gsl->selected_item,
161  toplevel);
162 
163  /* NULL return means cancel; no change */
164  if (new_selection == NULL)
165  return;
166 
167  gnc_general_select_set_selected (gsl, new_selection);
168 }
169 
170 static void
171 create_children (GNCGeneralSelect *gsl, GNCGeneralSelectType type)
172 {
173  gsl->entry = gtk_entry_new ();
174  gtk_editable_set_editable (GTK_EDITABLE (gsl->entry), FALSE);
175  gtk_box_pack_start (GTK_BOX (gsl), gsl->entry, TRUE, TRUE, 0);
176  gtk_widget_show (gsl->entry);
177 
178  if (type == GNC_GENERAL_SELECT_TYPE_SELECT)
179  gsl->button = gtk_button_new_with_label (_("Select…"));
180  else if (type == GNC_GENERAL_SELECT_TYPE_EDIT)
181  gsl->button = gtk_button_new_with_label (_("Edit…"));
182  else if (type == GNC_GENERAL_SELECT_TYPE_VIEW)
183  gsl->button = gtk_button_new_with_label (_("View…"));
184 
185  gtk_box_pack_start (GTK_BOX (gsl), gsl->button, FALSE, FALSE, 0);
186  g_signal_connect (G_OBJECT (gsl->button), "clicked",
187  G_CALLBACK (select_cb), gsl);
188  gtk_widget_show (gsl->button);
189 }
190 
199 GtkWidget *
200 gnc_general_select_new (GNCGeneralSelectType type,
201  GNCGeneralSelectGetStringCB get_string,
202  GNCGeneralSelectNewSelectCB new_select,
203  gpointer cb_arg)
204 {
205  GNCGeneralSelect *gsl;
206  g_return_val_if_fail (get_string != NULL, NULL);
207  g_return_val_if_fail (new_select != NULL, NULL);
208 
209  gsl = g_object_new(GNC_TYPE_GENERAL_SELECT, NULL, NULL);
210 
211  create_children (gsl, type);
212  gsl->get_string = get_string;
213  gsl->new_select = new_select;
214  gsl->cb_arg = cb_arg;
215 
216  return GTK_WIDGET (gsl);
217 }
218 
219 /*
220  * gnc_general_select_get_printname:
221  * @gsl: the general selection widget
222  * @selection: the selection to get the printname
223  *
224  * returns the printable name of the selection
225  */
226 const char *
227 gnc_general_select_get_printname (GNCGeneralSelect *gsl, gpointer selection)
228 {
229  g_return_val_if_fail (gsl != NULL, NULL);
230  g_return_val_if_fail (selection != NULL, NULL);
231 
232  return (gsl->get_string)(selection);
233 }
234 
244 void
245 gnc_general_select_set_selected (GNCGeneralSelect *gsl, gpointer selection)
246 {
247  const char *text;
248 
249  g_return_if_fail(gsl != NULL);
250  g_return_if_fail(GNC_IS_GENERAL_SELECT(gsl));
251 
252  gsl->selected_item = selection;
253 
254  if (selection == NULL)
255  text = "";
256  else
257  text = gnc_general_select_get_printname(gsl, selection);
258 
259  gtk_entry_set_text(GTK_ENTRY(gsl->entry), text);
260 
261  g_signal_emit(gsl, general_select_signals[SELECTION_CHANGED], 0);
262 }
263 
270 gpointer
271 gnc_general_select_get_selected (GNCGeneralSelect *gsl)
272 {
273  g_return_val_if_fail(gsl != NULL, NULL);
274  g_return_val_if_fail(GNC_IS_GENERAL_SELECT(gsl), NULL);
275 
276  return gsl->selected_item;
277 }
278 
287 void
288 gnc_general_select_make_mnemonic_target (GNCGeneralSelect *gsl, GtkWidget *label)
289 {
290  g_return_if_fail(gsl);
291  g_return_if_fail(GNC_IS_GENERAL_SELECT(gsl));
292  g_return_if_fail(label);
293 
294  gtk_label_set_mnemonic_widget (GTK_LABEL(label), gsl->entry);
295 }
296