2 * Light emitting diode-like control.
4 * Copyright (C) 2008 Krzysztof Foltman
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General
17 * Public License along with this program; if not, write to the
18 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301 USA
21 #include <calf/ctl_led.h>
29 GtkWidget
*widget
= GTK_WIDGET( g_object_new (CALF_TYPE_LED
, NULL
));
34 calf_led_expose (GtkWidget
*widget
, GdkEventExpose
*event
)
36 g_assert(CALF_IS_LED(widget
));
38 CalfLed
*self
= CALF_LED(widget
);
39 GdkWindow
*window
= widget
->window
;
40 cairo_t
*c
= gdk_cairo_create(GDK_DRAWABLE(window
));
41 GtkStyle
*style
= gtk_widget_get_style(widget
);
45 int sx
= widget
->allocation
.width
- ox
* 2;
46 int sy
= widget
->allocation
.height
- oy
* 2;
47 int xc
= widget
->allocation
.width
/ 2;
48 int yc
= widget
->allocation
.height
/ 2;
51 if( self
->cache_surface
== NULL
) {
52 // looks like its either first call or the widget has been resized.
53 // create the cache_surface.
54 cairo_surface_t
*window_surface
= cairo_get_target( c
);
55 self
->cache_surface
= cairo_surface_create_similar( window_surface
,
57 widget
->allocation
.width
,
58 widget
->allocation
.height
);
59 cairo_t
*cache_cr
= cairo_create( self
->cache_surface
);
61 // if(widget->style->bg_pixmap[0] == NULL) {
62 gdk_cairo_set_source_color(cache_cr
,&style
->bg
[GTK_STATE_NORMAL
]);
64 // gdk_cairo_set_source_pixbuf(cache_cr, GDK_PIXBUF(&style->bg_pixmap[0]), widget->allocation.x, widget->allocation.y + 20);
66 cairo_paint(cache_cr
);
71 cairo_arc(cache_cr
, rad
+ pad
, rad
+ pad
, rad
, 0, 2 * M_PI
);
72 cairo_arc(cache_cr
, ox
* 2 + sx
- rad
- pad
, rad
+ pad
, rad
, 0, 2 * M_PI
);
73 cairo_arc(cache_cr
, rad
+ pad
, oy
* 2 + sy
- rad
- pad
, rad
, 0, 2 * M_PI
);
74 cairo_arc(cache_cr
, ox
* 2 + sx
- rad
- pad
, oy
* 2 + sy
- rad
- pad
, rad
, 0, 2 * M_PI
);
75 cairo_rectangle(cache_cr
, pad
, rad
+ pad
, sx
+ ox
* 2 - pad
* 2, sy
+ oy
* 2 - rad
* 2 - pad
* 2);
76 cairo_rectangle(cache_cr
, rad
+ pad
, pad
, sx
+ ox
* 2 - rad
* 2 - pad
* 2, sy
+ oy
* 2 - pad
* 2);
77 cairo_pattern_t
*pat2
= cairo_pattern_create_linear (0, 0, 0, sy
+ oy
* 2 - pad
* 2);
78 cairo_pattern_add_color_stop_rgba (pat2
, 0, 0, 0, 0, 0.3);
79 cairo_pattern_add_color_stop_rgba (pat2
, 1, 1, 1, 1, 0.6);
80 cairo_set_source (cache_cr
, pat2
);
86 cairo_arc(cache_cr
, rad
+ pad
, rad
+ pad
, rad
, 0, 2 * M_PI
);
87 cairo_arc(cache_cr
, ox
* 2 + sx
- rad
- pad
, rad
+ pad
, rad
, 0, 2 * M_PI
);
88 cairo_arc(cache_cr
, rad
+ pad
, oy
* 2 + sy
- rad
- pad
, rad
, 0, 2 * M_PI
);
89 cairo_arc(cache_cr
, ox
* 2 + sx
- rad
- pad
, oy
* 2 + sy
- rad
- pad
, rad
, 0, 2 * M_PI
);
90 cairo_rectangle(cache_cr
, pad
, rad
+ pad
, sx
+ ox
* 2 - pad
* 2, sy
+ oy
* 2 - rad
* 2 - pad
* 2);
91 cairo_rectangle(cache_cr
, rad
+ pad
, pad
, sx
+ ox
* 2 - rad
* 2 - pad
* 2, sy
+ oy
* 2 - pad
* 2);
92 pat2
= cairo_pattern_create_linear (0, 0, 0, sy
+ oy
* 2 - pad
* 2);
93 cairo_pattern_add_color_stop_rgba (pat2
, 0, 0.23, 0.23, 0.23, 1);
94 cairo_pattern_add_color_stop_rgba (pat2
, 0.5, 0, 0, 0, 1);
95 cairo_set_source (cache_cr
, pat2
);
96 //cairo_set_source_rgb(cache_cr, 0, 0, 0);
99 cairo_rectangle(cache_cr
, ox
, oy
, sx
, sy
);
100 cairo_set_source_rgb (cache_cr
, 0, 0, 0);
101 cairo_fill(cache_cr
);
103 cairo_destroy( cache_cr
);
106 cairo_set_source_surface( c
, self
->cache_surface
, 0,0 );
110 cairo_pattern_t
*pt
= cairo_pattern_create_radial(xc
, yc
, 0, xc
, yc
, xc
> yc
? xc
: yc
);
112 float value
= self
->led_value
;
114 if(self
->led_mode
>= 4 && self
->led_mode
<= 5 && value
> 1.f
) {
117 switch (self
->led_mode
) {
121 cairo_pattern_add_color_stop_rgb(pt
, 0.0, value
> 0.f
? 0.2 : 0.0, value
> 0.f
? 1.0 : 0.25, value
> 0.f
? 1.0 : 0.5);
122 cairo_pattern_add_color_stop_rgb(pt
, 0.5, value
> 0.f
? 0.1 : 0.0, value
> 0.f
? 0.6 : 0.15, value
> 0.f
? 0.75 : 0.3);
123 cairo_pattern_add_color_stop_rgb(pt
, 1.0, 0.0, value
> 0.f
? 0.3 : 0.1, value
> 0.f
? 0.5 : 0.2);
127 cairo_pattern_add_color_stop_rgb(pt
, 0.0, value
> 0.f
? 1.0 : 0.5, value
> 0.f
? 0.5 : 0.0, value
> 0.f
? 0.2 : 0.0);
128 cairo_pattern_add_color_stop_rgb(pt
, 0.5, value
> 0.f
? 0.75 : 0.3, value
> 0.f
? 0.2 : 0.0, value
> 0.f
? 0.1 : 0.0);
129 cairo_pattern_add_color_stop_rgb(pt
, 1.0, value
> 0.f
? 0.5 : 0.2, value
> 0.f
? 0.1 : 0.0, 0.0);
133 // blue-dynamic (limited)
134 cairo_pattern_add_color_stop_rgb(pt
, 0.0, value
* 0.2, value
* 0.75 + 0.25, value
* 0.5 + 0.5);
135 cairo_pattern_add_color_stop_rgb(pt
, 0.5, value
* 0.1, value
* 0.45 + 0.15, value
* 0.45 + 0.3);
136 cairo_pattern_add_color_stop_rgb(pt
, 1.0, 0.0, value
* 0.2 + 0.1, value
* 0.3 + 0.2);
140 // red-dynamic (limited)
141 cairo_pattern_add_color_stop_rgb(pt
, 0.0, value
* 0.5 + 0.5, value
* 0.5, value
* 0.2);
142 cairo_pattern_add_color_stop_rgb(pt
, 0.5, value
* 0.45 + 0.3, value
* 0.2, value
* 0.1);
143 cairo_pattern_add_color_stop_rgb(pt
, 1.0, value
* 0.3 + 0.2, value
* 0.1, 0.0);
146 // blue-dynamic with red peak at >= 1.f
148 cairo_pattern_add_color_stop_rgb(pt
, 0.0, value
* 0.2, value
* 0.75 + 0.25, value
* 0.5 + 0.5);
149 cairo_pattern_add_color_stop_rgb(pt
, 0.5, value
* 0.1, value
* 0.45 + 0.15, value
* 0.45 + 0.3);
150 cairo_pattern_add_color_stop_rgb(pt
, 1.0, 0.0, value
* 0.2 + 0.1, value
* 0.3 + 0.2);
152 cairo_pattern_add_color_stop_rgb(pt
, 0.0, 1.0, 0.5, 0.2);
153 cairo_pattern_add_color_stop_rgb(pt
, 0.5, 0.75, 0.2, 0.1);
154 cairo_pattern_add_color_stop_rgb(pt
, 1.0, 0.5, 0.1, 0.0);
158 // off @ 0.0, blue < 1.0, red @ 1.0
159 if(value
< 1.f
and value
> 0.f
) {
161 cairo_pattern_add_color_stop_rgb(pt
, 0.0, 0.2, 1.0, 1.0);
162 cairo_pattern_add_color_stop_rgb(pt
, 0.5, 0.1, 0.6, 0.75);
163 cairo_pattern_add_color_stop_rgb(pt
, 1.0, 0.0, 0.3, 0.5);
164 } else if(value
== 0.f
) {
166 cairo_pattern_add_color_stop_rgb(pt
, 0.0, 0.0, 0.25, 0.5);
167 cairo_pattern_add_color_stop_rgb(pt
, 0.5, 0.0, 0.15, 0.3);
168 cairo_pattern_add_color_stop_rgb(pt
, 1.0, 0.0, 0.1, 0.2);
171 cairo_pattern_add_color_stop_rgb(pt
, 0.0, 1.0, 0.5, 0.2);
172 cairo_pattern_add_color_stop_rgb(pt
, 0.5, 0.75, 0.2, 0.1);
173 cairo_pattern_add_color_stop_rgb(pt
, 1.0, 0.5, 0.1, 0.0);
178 cairo_rectangle(c
, ox
+ 1, oy
+ 1, sx
- 2, sy
- 2);
179 cairo_set_source (c
, pt
);
180 cairo_fill_preserve(c
);
181 pt
= cairo_pattern_create_linear (ox
, oy
, ox
, ox
+ sy
);
182 cairo_pattern_add_color_stop_rgba (pt
, 0, 1, 1, 1, 0.4);
183 cairo_pattern_add_color_stop_rgba (pt
, 0.4, 1, 1, 1, 0.1);
184 cairo_pattern_add_color_stop_rgba (pt
, 0.401, 0, 0, 0, 0.0);
185 cairo_pattern_add_color_stop_rgba (pt
, 1, 0, 0, 0, 0.2);
186 cairo_set_source (c
, pt
);
188 cairo_pattern_destroy(pt
);
196 calf_led_realize(GtkWidget
*widget
)
198 GTK_WIDGET_SET_FLAGS(widget
, GTK_REALIZED
);
200 GdkWindowAttr attributes
;
201 attributes
.event_mask
= GDK_EXPOSURE_MASK
| GDK_BUTTON_PRESS_MASK
;
202 attributes
.x
= widget
->allocation
.x
;
203 attributes
.y
= widget
->allocation
.y
;
204 attributes
.width
= widget
->allocation
.width
;
205 attributes
.height
= widget
->allocation
.height
;
206 attributes
.wclass
= GDK_INPUT_OUTPUT
;
207 attributes
.window_type
= GDK_WINDOW_CHILD
;
209 widget
->window
= gdk_window_new(gtk_widget_get_parent_window (widget
), &attributes
, GDK_WA_X
| GDK_WA_Y
);
211 gdk_window_set_user_data(widget
->window
, widget
);
212 widget
->style
= gtk_style_attach(widget
->style
, widget
->window
);
216 calf_led_size_request (GtkWidget
*widget
,
217 GtkRequisition
*requisition
)
219 g_assert(CALF_IS_LED(widget
));
221 requisition
->width
= 24;
222 requisition
->height
= 18;
226 calf_led_size_allocate (GtkWidget
*widget
,
227 GtkAllocation
*allocation
)
229 g_assert(CALF_IS_LED(widget
));
230 CalfLed
*led
= CALF_LED(widget
);
232 widget
->allocation
= *allocation
;
234 if( led
->cache_surface
)
235 cairo_surface_destroy( led
->cache_surface
);
236 led
->cache_surface
= NULL
;
238 if (GTK_WIDGET_REALIZED(widget
))
239 gdk_window_move_resize(widget
->window
, allocation
->x
, allocation
->y
, allocation
->width
, allocation
->height
);
243 calf_led_button_press (GtkWidget
*widget
, GdkEventButton
*event
)
249 calf_led_class_init (CalfLedClass
*klass
)
251 GtkWidgetClass
*widget_class
= GTK_WIDGET_CLASS(klass
);
252 widget_class
->realize
= calf_led_realize
;
253 widget_class
->expose_event
= calf_led_expose
;
254 widget_class
->size_request
= calf_led_size_request
;
255 widget_class
->size_allocate
= calf_led_size_allocate
;
256 widget_class
->button_press_event
= calf_led_button_press
;
260 calf_led_init (CalfLed
*self
)
262 GtkWidget
*widget
= GTK_WIDGET(self
);
263 // GtkWidget *widget = GTK_WIDGET(self);
264 // GTK_WIDGET_SET_FLAGS (widget, GTK_CAN_FOCUS);
265 self
->led_value
= 0.f
;
266 widget
->requisition
.width
= 24;
267 widget
->requisition
.height
= 18;
270 void calf_led_set_value(CalfLed
*led
, float value
)
272 if (value
!= led
->led_value
)
274 led
->led_value
= value
;
275 GtkWidget
*widget
= GTK_WIDGET (led
);
276 if (GTK_WIDGET_REALIZED(widget
))
277 gtk_widget_queue_draw (widget
);
281 gboolean
calf_led_get_value(CalfLed
*led
)
283 return led
->led_value
;
287 calf_led_get_type (void)
289 static GType type
= 0;
291 static const GTypeInfo type_info
= {
292 sizeof(CalfLedClass
),
293 NULL
, /* base_init */
294 NULL
, /* base_finalize */
295 (GClassInitFunc
)calf_led_class_init
,
296 NULL
, /* class_finalize */
297 NULL
, /* class_data */
300 (GInstanceInitFunc
)calf_led_init
303 for (int i
= 0; ; i
++) {
304 char *name
= g_strdup_printf("CalfLed%u%d",
305 ((unsigned int)(intptr_t)calf_led_class_init
) >> 16, i
);
306 if (g_type_from_name(name
)) {
310 type
= g_type_register_static(GTK_TYPE_WIDGET
,