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