]> git.sur5r.net Git - glabels/blob - src/font-combo.c
Imported Upstream version 3.2.0
[glabels] / 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 <glib/gi18n.h>
26 #include <gtk/gtk.h>
27
28 #include "font-combo-menu.h"
29 #include "font-util.h"
30 #include "marshal.h"
31
32
33
34 /*========================================================*/
35 /* Private types.                                         */
36 /*========================================================*/
37
38 /** GL_FONT_COMBO Private fields */
39 struct _glFontComboPrivate {
40
41         gchar      *font_family;
42
43         GtkWidget  *label;
44
45         GtkWidget  *menu;
46 };
47
48 enum {
49         CHANGED,
50         LAST_SIGNAL
51 };
52
53
54 /*========================================================*/
55 /* Private globals.                                       */
56 /*========================================================*/
57
58 static guint signals[LAST_SIGNAL] = {0};
59
60
61 /*========================================================*/
62 /* Private function prototypes.                           */
63 /*========================================================*/
64
65 static void gl_font_combo_finalize      (GObject             *object);
66
67 static gboolean
68 button_press_event_cb (GtkWidget      *widget,
69                        GdkEventButton *event,
70                        glFontCombo    *this);
71
72 static void
73 menu_font_changed_cb   (glFontComboMenu  *menu,
74                         glFontCombo      *this);
75
76 static void
77 menu_selection_done_cb (GtkMenuShell     *object,
78                         glFontCombo      *this);
79
80
81 /*****************************************************************************/
82 /* Object infrastructure.                                                    */
83 /*****************************************************************************/
84 G_DEFINE_TYPE (glFontCombo, gl_font_combo, GTK_TYPE_TOGGLE_BUTTON)
85
86
87 /*****************************************************************************/
88 /* Class Init Function.                                                      */
89 /*****************************************************************************/
90 static void
91 gl_font_combo_class_init (glFontComboClass *class)
92 {
93         GObjectClass      *gobject_class = (GObjectClass *) class;
94
95         gl_font_combo_parent_class = g_type_class_peek_parent (class);
96
97         gobject_class->finalize = gl_font_combo_finalize;
98
99         signals[CHANGED] =
100                 g_signal_new ("changed",
101                               G_OBJECT_CLASS_TYPE (gobject_class),
102                               G_SIGNAL_RUN_LAST,
103                               G_STRUCT_OFFSET (glFontComboClass, changed),
104                               NULL, NULL,
105                               gl_marshal_VOID__VOID,
106                               G_TYPE_NONE, 0);
107 }
108
109
110 /*****************************************************************************/
111 /* Object Instance Init Function.                                            */
112 /*****************************************************************************/
113 static void
114 gl_font_combo_init (glFontCombo *this)
115 {
116         GtkWidget *hbox;
117         GtkWidget *arrow;
118
119         this->priv = g_new0 (glFontComboPrivate, 1);
120
121         hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 3);
122         gtk_container_add (GTK_CONTAINER (this), hbox);
123         
124         this->priv->label = gtk_label_new ("");
125         gtk_misc_set_alignment (GTK_MISC (this->priv->label), 0.0, 0.5);
126         gtk_widget_set_size_request (this->priv->label, 180, -1);
127         gtk_box_pack_start (GTK_BOX (hbox), this->priv->label, TRUE, TRUE, 0);
128
129         arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_IN);
130         gtk_box_pack_end (GTK_BOX (hbox), arrow, FALSE, FALSE, 0);
131
132         g_signal_connect (this, "button_press_event",
133                           G_CALLBACK(button_press_event_cb), this);
134 }
135
136
137 /*****************************************************************************/
138 /* Finalize Method.                                                          */
139 /*****************************************************************************/
140 static void
141 gl_font_combo_finalize (GObject *object)
142 {
143         glFontCombo    *this;
144
145         g_return_if_fail (object && IS_GL_FONT_COMBO (object));
146         this = GL_FONT_COMBO (object);
147
148         g_free (this->priv->font_family);
149         g_object_ref_sink (this->priv->menu);
150         g_free (this->priv);
151
152         G_OBJECT_CLASS (gl_font_combo_parent_class)->finalize (object);
153 }
154
155
156 /*****************************************************************************/
157 /** New Object Generator.                                                    */
158 /*****************************************************************************/
159 GtkWidget *
160 gl_font_combo_new (const gchar  *font_family)
161 {
162         glFontCombo  *this;
163
164         this = g_object_new (TYPE_GL_FONT_COMBO, NULL);
165
166         this->priv->font_family = gl_font_util_validate_family (font_family);
167
168         gtk_label_set_text (GTK_LABEL (this->priv->label), this->priv->font_family);
169
170         this->priv->menu = gl_font_combo_menu_new ();
171
172         gtk_widget_show_all (this->priv->menu);
173
174         g_signal_connect (this->priv->menu, "font_changed",
175                           G_CALLBACK (menu_font_changed_cb), this);
176         g_signal_connect (this->priv->menu, "selection_done",
177                           G_CALLBACK (menu_selection_done_cb), this);
178
179         return GTK_WIDGET (this);
180 }
181
182
183 /*****************************************************************************/
184 /** Set relief style.                                                        */
185 /*****************************************************************************/
186 void
187 gl_font_combo_set_relief( glFontCombo    *this,
188                           GtkReliefStyle  relief )
189 {
190         gtk_button_set_relief (GTK_BUTTON (this), relief);
191 }
192
193
194 /*****************************************************************************/
195 /* Set font family.                                                          */
196 /*****************************************************************************/
197 void
198 gl_font_combo_set_family (glFontCombo  *this,
199                           const gchar  *font_family)
200 {
201
202         this->priv->font_family = gl_font_util_validate_family (font_family);
203
204         gtk_label_set_text (GTK_LABEL (this->priv->label), this->priv->font_family);
205 }
206
207
208 /*****************************************************************************/
209 /* Get font family.                                                          */
210 /*****************************************************************************/
211 gchar *
212 gl_font_combo_get_family (glFontCombo  *this)
213 {
214         return g_strdup (this->priv->font_family);
215 }
216
217
218 /*****************************************************************************/
219 /* Menu positioning function.                                                */
220 /*****************************************************************************/
221 static void
222 menu_position_function (GtkMenu      *menu,
223                         gint         *x,
224                         gint         *y,
225                         gboolean     *push_in,
226                         glFontCombo  *this)
227 {
228         GdkScreen          *screen;
229         gint                w_screen, h_screen;
230         GdkWindow          *window;
231         gint                x_window, y_window;
232         GtkAllocation       allocation;
233         gint                x_this, y_this, h_this;
234         GtkRequisition      menu_requisition;
235         gint                h_menu, w_menu;
236
237         /*
238          * Screen size
239          */
240         screen = gtk_widget_get_screen (GTK_WIDGET (this));
241         w_screen = gdk_screen_get_width (screen);
242         h_screen = gdk_screen_get_height (screen);
243
244         /*
245          * Absolute position of "this" window on screen.
246          */
247         window = gtk_widget_get_window (GTK_WIDGET (this));
248         gdk_window_get_origin (window, &x_window, &y_window);
249
250         /*
251          *  Position and size of "this" inside window
252          */
253         gtk_widget_get_allocation (GTK_WIDGET (this), &allocation);
254         x_this = allocation.x;
255         y_this = allocation.y;
256         h_this = allocation.height;
257
258         /*
259          * Size of menu.
260          */
261         gtk_widget_get_preferred_size (this->priv->menu, NULL, &menu_requisition);
262         h_menu = menu_requisition.height;
263         w_menu = menu_requisition.width;
264
265         /*
266          * Default position anchored to lower left corner of "this".
267          */
268         *x = x_window + x_this;
269         *y = y_window + y_this + h_this;
270                 
271         /*
272          * Adjust vertical position if menu if extends past bottom of screen.
273          */
274         if ( (*y + h_menu) > h_screen )
275         {
276                 *y = y_window + y_this - h_menu;
277
278                 if ( *y < 0 )
279                 {
280                         *y = h_screen - h_menu;
281                 }
282         }
283
284         /*
285          * Adjust horizontal position if menu if extends past edge of screen.
286          */
287         if ( (*x + w_menu) > w_screen )
288         {
289                 *x = w_screen - w_menu;
290         }
291
292
293         *push_in = TRUE;
294 }
295
296
297 /*****************************************************************************/
298 /* Button "button_press_event" callback.                                     */
299 /*****************************************************************************/
300 static gboolean
301 button_press_event_cb (GtkWidget      *widget,
302                        GdkEventButton *event,
303                        glFontCombo   *this)
304 {
305         switch (event->button)
306         {
307
308         case 1:
309                 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (this), TRUE);
310
311                 gtk_menu_popup (GTK_MENU (this->priv->menu),
312                                 NULL, NULL,
313                                 (GtkMenuPositionFunc)menu_position_function, this,
314                                 event->button, event->time);
315                 break;
316
317         default:
318                 break;
319
320         }
321
322         return FALSE;
323 }
324
325
326 /*****************************************************************************/
327 /* Menu "font changed" callback.                                             */
328 /*****************************************************************************/
329 static void
330 menu_font_changed_cb (glFontComboMenu     *menu,
331                       glFontCombo         *this)
332 {
333         this->priv->font_family = gl_font_combo_menu_get_family (menu);
334
335         gtk_label_set_text (GTK_LABEL (this->priv->label), this->priv->font_family);
336
337         g_signal_emit (this, signals[CHANGED], 0);
338 }
339
340
341 /*****************************************************************************/
342 /* Menu "selection done" callback.                                           */
343 /*****************************************************************************/
344 static void
345 menu_selection_done_cb (GtkMenuShell         *object,
346                         glFontCombo         *this)
347 {
348         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (this), FALSE);
349 }
350
351
352
353 /*
354  * Local Variables:       -- emacs
355  * mode: C                -- emacs
356  * c-basic-offset: 8      -- emacs
357  * tab-width: 8           -- emacs
358  * indent-tabs-mode: nil  -- emacs
359  * End:                   -- emacs
360  */