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>
25 #include <calf/drawingutils.h>
30 GtkWidget
*widget
= GTK_WIDGET( g_object_new (CALF_TYPE_LED
, NULL
));
35 calf_led_expose (GtkWidget
*widget
, GdkEventExpose
*event
)
37 g_assert(CALF_IS_LED(widget
));
39 CalfLed
*self
= CALF_LED(widget
);
40 GdkWindow
*window
= widget
->window
;
41 cairo_t
*c
= gdk_cairo_create(GDK_DRAWABLE(window
));
42 GtkStyle
*style
= gtk_widget_get_style(widget
);
44 int width
= widget
->allocation
.width
;
45 int height
= widget
->allocation
.height
;
46 int x
= widget
->allocation
.x
;
47 int y
= widget
->allocation
.y
;
48 int ox
= widget
->style
->xthickness
;
49 int oy
= widget
->style
->ythickness
;
50 int sx
= width
- ox
* 2;
51 int sy
= height
- oy
* 2;
52 int xc
= x
+ width
/ 2;
53 int yc
= y
+ height
/ 2;
57 if( self
->cache_surface
== NULL
) {
58 // looks like its either first call or the widget has been resized.
59 // create the cache_surface.
60 self
->cache_surface
= cairo_image_surface_create( CAIRO_FORMAT_ARGB32
, width
, height
);
61 cairo_t
*cache_cr
= cairo_create( self
->cache_surface
);
64 get_bg_color(widget
, NULL
, &r
, &g
, &b
);
65 gtk_widget_style_get(widget
, "border-radius", &radius
, "bevel", &bevel
, NULL
);
66 create_rectangle(cache_cr
, 0, 0, width
, height
, radius
);
67 cairo_set_source_rgb(cache_cr
, r
, g
, b
);
69 draw_bevel(cache_cr
, 0, 0, width
, height
, radius
, bevel
);
70 cairo_rectangle(cache_cr
, ox
, oy
, sx
, sy
);
71 cairo_set_source_rgb (cache_cr
, 0, 0, 0);
74 cairo_destroy( cache_cr
);
77 cairo_set_source_surface( c
, self
->cache_surface
, x
, y
);
83 cairo_pattern_t
*pt
= cairo_pattern_create_radial(xc
, yc
, 0, xc
, yc
, sx
> sy
? sx
/2 : sy
/2);
85 float value
= self
->led_value
;
87 if(self
->led_mode
>= 4 && self
->led_mode
<= 5 && value
> 1.f
) {
90 switch (self
->led_mode
) {
94 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.35);
95 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.2);
96 cairo_pattern_add_color_stop_rgb(pt
, 1.0, 0.0, value
> 0.f
? 0.3 : 0.1, value
> 0.f
? 0.5 : 0.1);
100 cairo_pattern_add_color_stop_rgb(pt
, 0.0, value
> 0.f
? 1.0 : 0.35, value
> 0.f
? 0.5 : 0.0, value
> 0.f
? 0.2 : 0.0);
101 cairo_pattern_add_color_stop_rgb(pt
, 0.5, value
> 0.f
? 0.80 : 0.2, value
> 0.f
? 0.2 : 0.0, value
> 0.f
? 0.1 : 0.0);
102 cairo_pattern_add_color_stop_rgb(pt
, 1.0, value
> 0.f
? 0.65 : 0.1, value
> 0.f
? 0.1 : 0.0, 0.0);
106 // blue-dynamic (limited)
107 cairo_pattern_add_color_stop_rgb(pt
, 0.0, value
* 0.2, value
* 0.75 + 0.25, value
* 0.65 + 0.35);
108 cairo_pattern_add_color_stop_rgb(pt
, 0.5, value
* 0.1, value
* 0.45 + 0.15, value
* 0.55 + 0.2);
109 cairo_pattern_add_color_stop_rgb(pt
, 1.0, 0.0, value
* 0.2 + 0.1, value
* 0.4 + 0.1);
113 // red-dynamic (limited)
114 cairo_pattern_add_color_stop_rgb(pt
, 0.0, value
* 0.65 + 0.35, value
* 0.5, value
* 0.2);
115 cairo_pattern_add_color_stop_rgb(pt
, 0.5, value
* 0.6 + 0.2, value
* 0.2, value
* 0.1);
116 cairo_pattern_add_color_stop_rgb(pt
, 1.0, value
* 0.66 + 0.1, value
* 0.1, 0.0);
119 // blue-dynamic with red peak at >= 1.f
121 cairo_pattern_add_color_stop_rgb(pt
, 0.0, value
* 0.2, value
* 0.75 + 0.25, value
* 0.65 + 0.35);
122 cairo_pattern_add_color_stop_rgb(pt
, 0.5, value
* 0.1, value
* 0.45 + 0.15, value
* 0.55 + 0.2);
123 cairo_pattern_add_color_stop_rgb(pt
, 1.0, 0.0, value
* 0.2 + 0.1, value
* 0.4 + 0.1);
125 cairo_pattern_add_color_stop_rgb(pt
, 0.0, 1.0, 0.5, 0.2);
126 cairo_pattern_add_color_stop_rgb(pt
, 0.5, 0.80, 0.2, 0.1);
127 cairo_pattern_add_color_stop_rgb(pt
, 1.0, 0.66, 0.1, 0.0);
131 // off @ 0.0, blue < 1.0, red @ 1.0
132 if(value
< 1.f
and value
> 0.f
) {
134 cairo_pattern_add_color_stop_rgb(pt
, 0.0, 0.2, 1.0, 1.0);
135 cairo_pattern_add_color_stop_rgb(pt
, 0.5, 0.1, 0.6, 0.75);
136 cairo_pattern_add_color_stop_rgb(pt
, 1.0, 0.0, 0.3, 0.5);
137 } else if(value
== 0.f
) {
139 cairo_pattern_add_color_stop_rgb(pt
, 0.0, 0.0, 0.25, 0.35);
140 cairo_pattern_add_color_stop_rgb(pt
, 0.5, 0.0, 0.15, 0.2);
141 cairo_pattern_add_color_stop_rgb(pt
, 1.0, 0.0, 0.1, 0.1);
144 cairo_pattern_add_color_stop_rgb(pt
, 0.0, 1.0, 0.5, 0.2);
145 cairo_pattern_add_color_stop_rgb(pt
, 0.5, 0.80, 0.2, 0.1);
146 cairo_pattern_add_color_stop_rgb(pt
, 1.0, 0.66, 0.1, 0.0);
151 cairo_rectangle(c
, ox
+ 1, oy
+ 1, sx
- 2, sy
- 2);
152 cairo_set_source (c
, pt
);
153 cairo_fill_preserve(c
);
155 pt
= cairo_pattern_create_linear (ox
, oy
, ox
, oy
+ sy
);
156 cairo_pattern_add_color_stop_rgba (pt
, 0, 1, 1, 1, 0.4);
157 cairo_pattern_add_color_stop_rgba (pt
, 0.4, 1, 1, 1, 0.1);
158 cairo_pattern_add_color_stop_rgba (pt
, 0.401, 0, 0, 0, 0.0);
159 cairo_pattern_add_color_stop_rgba (pt
, 1, 0, 0, 0, 0.2);
160 cairo_set_source (c
, pt
);
162 cairo_pattern_destroy(pt
);
170 calf_led_size_request (GtkWidget
*widget
,
171 GtkRequisition
*requisition
)
173 g_assert(CALF_IS_LED(widget
));
174 CalfLed
*self
= CALF_LED(widget
);
175 requisition
->width
= self
->size
? 24 : 19;
176 requisition
->height
= self
->size
? 18 : 14;
180 calf_led_size_allocate (GtkWidget
*widget
,
181 GtkAllocation
*allocation
)
183 g_assert(CALF_IS_LED(widget
));
184 CalfLed
*led
= CALF_LED(widget
);
186 widget
->allocation
= *allocation
;
188 if( led
->cache_surface
)
189 cairo_surface_destroy( led
->cache_surface
);
190 led
->cache_surface
= NULL
;
192 if (GTK_WIDGET_REALIZED(widget
))
193 gdk_window_move_resize(widget
->window
, allocation
->x
, allocation
->y
, allocation
->width
, allocation
->height
);
197 calf_led_button_press (GtkWidget
*widget
, GdkEventButton
*event
)
203 calf_led_class_init (CalfLedClass
*klass
)
205 GtkWidgetClass
*widget_class
= GTK_WIDGET_CLASS(klass
);
206 widget_class
->expose_event
= calf_led_expose
;
207 widget_class
->size_request
= calf_led_size_request
;
208 widget_class
->size_allocate
= calf_led_size_allocate
;
209 widget_class
->button_press_event
= calf_led_button_press
;
210 gtk_widget_class_install_style_property(
211 widget_class
, g_param_spec_float("border-radius", "Border Radius", "Generate round edges",
212 0, 24, 4, GParamFlags(G_PARAM_READWRITE
)));
213 gtk_widget_class_install_style_property(
214 widget_class
, g_param_spec_float("bevel", "Bevel", "Bevel the object",
215 -2, 2, 0.2, GParamFlags(G_PARAM_READWRITE
)));
219 calf_led_init (CalfLed
*self
)
221 GtkWidget
*widget
= GTK_WIDGET(self
);
222 // GtkWidget *widget = GTK_WIDGET(self);
223 // GTK_WIDGET_SET_FLAGS (widget, GTK_CAN_FOCUS);
224 self
->led_value
= 0.f
;
225 self
->cache_surface
= NULL
;
226 widget
->requisition
.width
= self
->size
? 24 : 19;
227 widget
->requisition
.height
= self
->size
? 18 : 14;
228 gtk_widget_set_has_window(widget
, FALSE
);
231 void calf_led_set_value(CalfLed
*led
, float value
)
233 if (value
!= led
->led_value
)
235 float old_value
= led
->led_value
;
236 led
->led_value
= value
;
237 if (led
->led_mode
>= 2 || (old_value
> 0) != (value
> 0))
239 GtkWidget
*widget
= GTK_WIDGET (led
);
240 if (GTK_WIDGET_REALIZED(widget
))
241 gtk_widget_queue_draw (widget
);
246 gboolean
calf_led_get_value(CalfLed
*led
)
248 return led
->led_value
;
252 calf_led_get_type (void)
254 static GType type
= 0;
256 static const GTypeInfo type_info
= {
257 sizeof(CalfLedClass
),
258 NULL
, /* base_init */
259 NULL
, /* base_finalize */
260 (GClassInitFunc
)calf_led_class_init
,
261 NULL
, /* class_finalize */
262 NULL
, /* class_data */
265 (GInstanceInitFunc
)calf_led_init
268 for (int i
= 0; ; i
++) {
269 const char *name
= "CalfLed";
270 //char *name = g_strdup_printf("CalfLed%u%d",
271 //((unsigned int)(intptr_t)calf_led_class_init) >> 16, i);
272 if (g_type_from_name(name
)) {
276 type
= g_type_register_static(GTK_TYPE_DRAWING_AREA
,