]> git.sur5r.net Git - glabels/blob - glabels2/src/font-combo.c
f77d5ad20ec4ed5ee592d8da34a9ec06c7f551ec
[glabels] / glabels2 / src / font-combo.c
1 /*
2  *  font-combo.c
3  *  Copyright (C) 2009  Jim Evins <evins@snaught.com>.
4  *
5  *  This file is part of gLabels.
6  *
7  *  gLabels is free software: you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License as published by
9  *  the Free Software Foundation, either version 3 of the License, or
10  *  (at your option) any later version.
11  *
12  *  gLabels is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *  GNU General Public License for more details.
16  *
17  *  You should have received a copy of the GNU General Public License
18  *  along with gLabels.  If not, see <http://www.gnu.org/licenses/>.
19  */
20
21 #include <config.h>
22
23 #include "font-combo.h"
24
25 #include "font-combo-menu.h"
26 #include "font-util.h"
27 #include <glib/gi18n.h>
28 #include <gtk/gtkhbox.h>
29 #include <gtk/gtklabel.h>
30 #include <gtk/gtkarrow.h>
31 #include "marshal.h"
32
33
34
35 /*========================================================*/
36 /* Private types.                                         */
37 /*========================================================*/
38
39 /** GL_FONT_COMBO Private fields */
40 struct _glFontComboPrivate {
41
42         gchar      *font_family;
43
44         GtkWidget  *label;
45
46         GtkWidget  *menu;
47 };
48
49 enum {
50         CHANGED,
51         LAST_SIGNAL
52 };
53
54
55 /*========================================================*/
56 /* Private globals.                                       */
57 /*========================================================*/
58
59 static guint signals[LAST_SIGNAL] = {0};
60
61
62 /*========================================================*/
63 /* Private function prototypes.                           */
64 /*========================================================*/
65
66 static void gl_font_combo_finalize      (GObject             *object);
67
68 static gboolean
69 button_press_event_cb (GtkWidget      *widget,
70                        GdkEventButton *event,
71                        glFontCombo    *this);
72
73 static void
74 menu_font_changed_cb   (glFontComboMenu  *menu,
75                         glFontCombo      *this);
76
77 static void
78 menu_selection_done_cb (GtkMenuShell     *object,
79                         glFontCombo      *this);
80
81
82 /*****************************************************************************/
83 /* Object infrastructure.                                                    */
84 /*****************************************************************************/
85 G_DEFINE_TYPE (glFontCombo, gl_font_combo, GTK_TYPE_TOGGLE_BUTTON);
86
87
88 /*****************************************************************************/
89 /* Class Init Function.                                                      */
90 /*****************************************************************************/
91 static void
92 gl_font_combo_class_init (glFontComboClass *class)
93 {
94         GObjectClass      *gobject_class = (GObjectClass *) class;
95
96         gl_font_combo_parent_class = g_type_class_peek_parent (class);
97
98         gobject_class->finalize = gl_font_combo_finalize;
99
100         signals[CHANGED] =
101                 g_signal_new ("changed",
102                               G_OBJECT_CLASS_TYPE (gobject_class),
103                               G_SIGNAL_RUN_LAST,
104                               G_STRUCT_OFFSET (glFontComboClass, changed),
105                               NULL, NULL,
106                               gl_marshal_VOID__VOID,
107                               G_TYPE_NONE, 0);
108 }
109
110
111 /*****************************************************************************/
112 /* Object Instance Init Function.                                            */
113 /*****************************************************************************/
114 static void
115 gl_font_combo_init (glFontCombo *this)
116 {
117         GtkWidget *hbox;
118         GtkWidget *arrow;
119
120         this->priv = g_new0 (glFontComboPrivate, 1);
121
122         hbox = gtk_hbox_new (FALSE, 3);
123         gtk_container_add (GTK_CONTAINER (this), hbox);
124         
125         this->priv->label = gtk_label_new ("");
126         gtk_misc_set_alignment (GTK_MISC (this->priv->label), 0.0, 0.5);
127         gtk_widget_set_size_request (this->priv->label, 180, -1);
128         gtk_box_pack_start (GTK_BOX (hbox), this->priv->label, TRUE, TRUE, 0);
129
130         arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_IN);
131         gtk_box_pack_end (GTK_BOX (hbox), arrow, FALSE, FALSE, 0);
132
133         g_signal_connect (this, "button_press_event",
134                           G_CALLBACK(button_press_event_cb), this);
135 }
136
137
138 /*****************************************************************************/
139 /* Finalize Method.                                                          */
140 /*****************************************************************************/
141 static void
142 gl_font_combo_finalize (GObject *object)
143 {
144         glFontCombo    *this;
145
146         g_return_if_fail (object && IS_GL_FONT_COMBO (object));
147         this = GL_FONT_COMBO (object);
148
149         g_free (this->priv->font_family);
150         g_object_ref_sink (this->priv->menu);
151         g_free (this->priv);
152
153         G_OBJECT_CLASS (gl_font_combo_parent_class)->finalize (object);
154 }
155
156
157 /*****************************************************************************/
158 /** New Object Generator.                                                    */
159 /*****************************************************************************/
160 GtkWidget *
161 gl_font_combo_new (const gchar  *font_family)
162 {
163         glFontCombo  *this;
164
165         this = g_object_new (TYPE_GL_FONT_COMBO, NULL);
166
167         this->priv->font_family = gl_font_util_validate_family (font_family);
168
169         gtk_label_set_text (GTK_LABEL (this->priv->label), this->priv->font_family);
170
171         this->priv->menu = gl_font_combo_menu_new ();
172
173         gtk_widget_show_all (this->priv->menu);
174
175         g_signal_connect (this->priv->menu, "font_changed",
176                           G_CALLBACK (menu_font_changed_cb), this);
177         g_signal_connect (this->priv->menu, "selection_done",
178                           G_CALLBACK (menu_selection_done_cb), this);
179
180         return GTK_WIDGET (this);
181 }
182
183
184 /*****************************************************************************/
185 /** Set relief style.                                                        */
186 /*****************************************************************************/
187 void
188 gl_font_combo_set_relief( glFontCombo    *this,
189                           GtkReliefStyle  relief )
190 {
191         gtk_button_set_relief (GTK_BUTTON (this), relief);
192 }
193
194
195 /*****************************************************************************/
196 /* Set font family.                                                          */
197 /*****************************************************************************/
198 void
199 gl_font_combo_set_family (glFontCombo  *this,
200                           const gchar  *font_family)
201 {
202
203         this->priv->font_family = gl_font_util_validate_family (font_family);
204
205         gtk_label_set_text (GTK_LABEL (this->priv->label), this->priv->font_family);
206 }
207
208
209 /*****************************************************************************/
210 /* Get font family.                                                          */
211 /*****************************************************************************/
212 gchar *
213 gl_font_combo_get_family (glFontCombo  *this)
214 {
215         return g_strdup (this->priv->font_family);
216 }
217
218
219 /*****************************************************************************/
220 /* Menu positioning function.                                                */
221 /*****************************************************************************/
222 static void
223 menu_position_function (GtkMenu  *menu,
224                         gint     *x,
225                         gint     *y,
226                         gboolean *push_in,
227                         gpointer  user_data)
228 {
229         glFontCombo *this = GL_FONT_COMBO (user_data);
230         gint          x1, y1;
231         gint          menu_h, menu_w;
232
233         gdk_window_get_origin (GTK_WIDGET (this)->window, &x1, &y1);
234         *x = x1 + GTK_WIDGET (this)->allocation.x;
235         *y = y1 + GTK_WIDGET (this)->allocation.y +
236                 GTK_WIDGET (this)->allocation.height;
237                 
238         menu_h = this->priv->menu->allocation.height;
239         menu_w = this->priv->menu->allocation.width;
240
241         if ((*y + menu_h) > gdk_screen_height ())
242         {
243                 *y = y1 + GTK_WIDGET (this)->allocation.y - menu_h;
244                 if ( *y < 0 )
245                 {
246                         *y = gdk_screen_height () - menu_h;
247                 }
248         }
249
250         if ((*x + menu_w) > gdk_screen_width ())
251         {
252                 *x = gdk_screen_width () - menu_w;
253         }
254
255         *push_in = TRUE;
256 }
257
258
259 /*****************************************************************************/
260 /* Button "button_press_event" callback.                                     */
261 /*****************************************************************************/
262 static gboolean
263 button_press_event_cb (GtkWidget      *widget,
264                        GdkEventButton *event,
265                        glFontCombo   *this)
266 {
267         switch (event->button)
268         {
269
270         case 1:
271                 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (this), TRUE);
272
273                 gtk_menu_popup (GTK_MENU (this->priv->menu),
274                                 NULL, NULL,
275                                 menu_position_function, this,
276                                 event->button, event->time);
277                 break;
278
279         default:
280                 break;
281
282         }
283
284         return FALSE;
285 }
286
287
288 /*****************************************************************************/
289 /* Menu "font changed" callback.                                             */
290 /*****************************************************************************/
291 static void
292 menu_font_changed_cb (glFontComboMenu     *menu,
293                       glFontCombo         *this)
294 {
295         this->priv->font_family = gl_font_combo_menu_get_family (menu);
296
297         gtk_label_set_text (GTK_LABEL (this->priv->label), this->priv->font_family);
298
299         g_signal_emit (this, signals[CHANGED], 0);
300 }
301
302
303 /*****************************************************************************/
304 /* Menu "selection done" callback.                                           */
305 /*****************************************************************************/
306 static void
307 menu_selection_done_cb (GtkMenuShell         *object,
308                         glFontCombo         *this)
309 {
310         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (this), FALSE);
311 }
312
313
314
315 /*
316  * Local Variables:       -- emacs
317  * mode: C                -- emacs
318  * c-basic-offset: 8      -- emacs
319  * tab-width: 8           -- emacs
320  * indent-tabs-mode: nil  -- emacs
321  * End:                   -- emacs
322  */