1 /*
2 * Copyright (C) 2009, 2010 Hermann Meyer, James Warden, Andreas Degert
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 */
18
19 #include "GxSwitch.h"
20 #include "GxToggleImage.h"
21 #include "GxControlParameter.h"
22 #include <gdk/gdkkeysyms.h>
23 #include <unistd.h>
24 #include <string.h>
25
26 #define P_(s) (s) // FIXME -> gettext
27
28 struct _GxSwitchPrivate {
29 gchar *var_id;
30 gchar *base_name;
31 GtkLabel *label;
32 };
33
34 enum {
35 PROP_VAR_ID = 1,
36 PROP_BASE_NAME,
37 PROP_LABEL_REF,
38 };
39
40 static void gx_control_parameter_interface_init (GxControlParameterIface *iface);
41
42 G_DEFINE_TYPE_WITH_CODE(GxSwitch, gx_switch, GTK_TYPE_CHECK_BUTTON,
43 G_ADD_PRIVATE(GxSwitch)
44 G_IMPLEMENT_INTERFACE(GX_TYPE_CONTROL_PARAMETER,
45 gx_control_parameter_interface_init))
46
47 static void gx_switch_destroy(GtkWidget *object);
48 static void gx_switch_set_property(
49 GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
50 static void gx_switch_get_property(
51 GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
52 static gboolean gx_switch_scroll_event(GtkWidget *widget, GdkEventScroll *event);
53 static void gx_switch_style_set(GtkWidget *widget, GtkStyle *previous_style);
54
55 static void
gx_switch_cp_configure(GxControlParameter * self,const gchar * group,const gchar * name,gdouble lower,gdouble upper,gdouble step)56 gx_switch_cp_configure(GxControlParameter *self, const gchar* group, const gchar *name, gdouble lower, gdouble upper, gdouble step)
57 {
58 GxSwitch *swtch = GX_SWITCH(self);
59 if (swtch->priv->label) {
60 gtk_label_set_text(swtch->priv->label, name);
61 }
62 }
63
64 static gdouble
gx_switch_cp_get_value(GxControlParameter * self)65 gx_switch_cp_get_value(GxControlParameter *self)
66 {
67 return gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(self));
68 }
69
70 static void
gx_switch_cp_set_value(GxControlParameter * self,gdouble value)71 gx_switch_cp_set_value(GxControlParameter *self, gdouble value)
72 {
73 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(self), value != 0.0);
74 }
75
76 static void
gx_control_parameter_interface_init(GxControlParameterIface * iface)77 gx_control_parameter_interface_init(GxControlParameterIface *iface)
78 {
79 iface->cp_configure = gx_switch_cp_configure;
80 iface->cp_set_value = gx_switch_cp_set_value;
81 iface->cp_get_value = gx_switch_cp_get_value;
82 }
83
gx_switch_class_init(GxSwitchClass * klass)84 static void gx_switch_class_init(GxSwitchClass *klass)
85 {
86 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
87 GtkWidgetClass *widget_class = (GtkWidgetClass*) klass;
88
89 gobject_class->set_property = gx_switch_set_property;
90 gobject_class->get_property = gx_switch_get_property;
91 widget_class->scroll_event = gx_switch_scroll_event;
92 widget_class->destroy = gx_switch_destroy;
93 widget_class->style_set = gx_switch_style_set;
94
95 g_object_class_install_property (
96 gobject_class, PROP_VAR_ID, g_param_spec_string(
97 "var-id", P_("Variable"),
98 P_("The id of the linked variable"),
99 NULL, GParamFlags(G_PARAM_READWRITE|G_PARAM_STATIC_STRINGS)));
100 g_object_class_install_property (
101 gobject_class, PROP_BASE_NAME,
102 g_param_spec_string("base-name",
103 P_("css class name"),
104 P_("button image should be set in css"),
105 NULL,
106 GParamFlags(G_PARAM_READWRITE|G_PARAM_STATIC_STRINGS)));
107 g_object_class_install_property(
108 gobject_class, PROP_LABEL_REF,
109 g_param_spec_object("label-ref",
110 P_("Label ref"),
111 P_("GtkLabel for caption"),
112 GTK_TYPE_LABEL,
113 GParamFlags(G_PARAM_READWRITE|G_PARAM_STATIC_STRINGS)));
114 }
115
116 /****************************************************************
117 ** init the Switch type/size
118 */
119
gx_switch_init(GxSwitch * swtch)120 static void gx_switch_init(GxSwitch *swtch)
121 {
122 swtch->priv = (GxSwitchPrivate*)gx_switch_get_instance_private(swtch);
123 swtch->priv->var_id = NULL;
124 swtch->priv->base_name = 0;
125 swtch->priv->label = NULL;
126 gx_switch_set_base_name(swtch, "switch");
127 //GTK_BUTTON(swtch)->relief = GTK_RELIEF_NONE;
128 gtk_style_context_add_class(gtk_widget_get_style_context(GTK_WIDGET(swtch)), "gx_switch");
129 gtk_toggle_button_set_mode(GTK_TOGGLE_BUTTON(swtch), TRUE);
130 }
131
132 /****************************************************************
133 */
gx_switch_destroy(GtkWidget * object)134 static void gx_switch_destroy(GtkWidget *object)
135 {
136 GxSwitch *swtch = GX_SWITCH(object);
137 if (swtch->priv->label) {
138 g_clear_object(&swtch->priv->label);
139 }
140 g_free(swtch->priv->base_name);
141 swtch->priv->base_name = 0;
142 g_free(swtch->priv->var_id);
143 swtch->priv->var_id = 0;
144 GTK_WIDGET_CLASS(gx_switch_parent_class)->destroy (object);
145 }
146
147 /****************************************************************
148 */
gx_switch_style_set(GtkWidget * widget,GtkStyle * previous_style)149 static void gx_switch_style_set(GtkWidget *widget, GtkStyle *previous_style) {
150 GTK_WIDGET_CLASS(gx_switch_parent_class)->style_set(widget, previous_style);
151 gtk_widget_queue_resize(widget); // glade-gtk2 bug?
152 }
153
154 /****************************************************************
155 */
gx_switch_scroll_event(GtkWidget * widget,GdkEventScroll * event)156 gboolean gx_switch_scroll_event(GtkWidget *widget, GdkEventScroll *event)
157 {
158 gtk_toggle_button_set_active(
159 GTK_TOGGLE_BUTTON(widget),
160 event->direction == GDK_SCROLL_UP || event->direction == GDK_SCROLL_RIGHT);
161 return TRUE;
162 }
163
164 /****************************************************************
165 ** Properties
166 */
167
gx_switch_set_label_ref(GxSwitch * swtch,GtkLabel * label)168 void gx_switch_set_label_ref(GxSwitch *swtch, GtkLabel *label)
169 {
170 g_return_if_fail(GX_IS_SWITCH(swtch));
171 if (swtch->priv->label) {
172 g_clear_object(&swtch->priv->label);
173 }
174 if (label) {
175 g_return_if_fail(GTK_IS_LABEL(label));
176 swtch->priv->label = label;
177 g_object_ref(label);
178 }
179 g_object_notify(G_OBJECT(swtch), "label-ref");
180 }
181
gx_switch_get_label_ref(GxSwitch * swtch)182 GtkLabel *gx_switch_get_label_ref(GxSwitch *swtch)
183 {
184 g_return_val_if_fail(GX_IS_SWITCH(swtch), 0);
185 return swtch->priv->label;
186 }
187
gx_switch_set_base_name(GxSwitch * swtch,const char * base_name)188 void gx_switch_set_base_name(GxSwitch *swtch, const char *base_name)
189 {
190 g_return_if_fail(GX_IS_SWITCH(swtch));
191 if (!base_name) {
192 base_name = "";
193 }
194 if (swtch->priv->base_name && strcmp(swtch->priv->base_name, base_name) == 0) {
195 return;
196 }
197 char *old = swtch->priv->base_name;
198 GtkStyleContext *context = gtk_widget_get_style_context(GTK_WIDGET(swtch));
199 swtch->priv->base_name = g_strdup(base_name);
200 if (*base_name) {
201 char buffer[100] = "gx_sw_";
202 strncat(buffer, base_name, sizeof buffer - 1);
203 gtk_style_context_add_class(context, buffer);
204 }
205 if (!old) {
206 return;
207 }
208 if (*old) {
209 char buffer[100] = "gx_sw_";
210 strncat(buffer, old, sizeof buffer - 1);
211 gtk_style_context_remove_class(context, buffer);
212 }
213 g_free(old);
214 gtk_widget_queue_resize(GTK_WIDGET(swtch));
215 g_object_notify(G_OBJECT(swtch), "base-name");
216 }
217
gx_switch_get_base_name(GxSwitch * swtch)218 const char *gx_switch_get_base_name(GxSwitch *swtch)
219 {
220 g_return_val_if_fail(GX_IS_SWITCH(swtch), "");
221 return swtch->priv->base_name;
222 }
223
224 static void
gx_switch_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)225 gx_switch_set_property (GObject *object, guint prop_id, const GValue *value,
226 GParamSpec *pspec)
227 {
228 GxSwitch *swtch = GX_SWITCH (object);
229
230 switch(prop_id) {
231 case PROP_VAR_ID: {
232 const char *str = g_value_get_string(value);
233 g_free(swtch->priv->var_id);
234 swtch->priv->var_id = g_strdup(str ? str : "");
235 g_object_notify(object, "var-id");
236 break;
237 }
238 case PROP_BASE_NAME:
239 gx_switch_set_base_name(swtch, g_value_get_string(value));
240 break;
241 case PROP_LABEL_REF:
242 gx_switch_set_label_ref(swtch, GTK_LABEL(g_value_get_object(value)));
243 break;
244 default:
245 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
246 break;
247 }
248 }
249
250 static void
gx_switch_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)251 gx_switch_get_property(GObject *object, guint prop_id, GValue *value,
252 GParamSpec *pspec)
253 {
254 GxSwitch *swtch = GX_SWITCH(object);
255
256 switch(prop_id) {
257 case PROP_VAR_ID:
258 g_value_set_string(value, swtch->priv->var_id);
259 break;
260 case PROP_BASE_NAME:
261 g_value_set_string(value, swtch->priv->base_name);
262 break;
263 case PROP_LABEL_REF:
264 g_value_set_object(value, swtch->priv->label);
265 break;
266 default:
267 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
268 break;
269 }
270 }
271