1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
2  *
3  * Copyright (C) 2012 Richard Hughes <richard@hughsie.com>
4  *
5  * Licensed under the GNU Lesser General Public License Version 2.1
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library 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 GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
20  */
21 
22 #include "config.h"
23 
24 #include <gtk/gtk.h>
25 #include <colord.h>
26 
27 #include "cd-sample-widget.h"
28 
29 G_DEFINE_TYPE (CdSampleWidget, cd_sample_widget, GTK_TYPE_DRAWING_AREA);
30 #define CD_SAMPLE_WIDGET_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), CD_TYPE_SAMPLE_WIDGET, CdSampleWidgetPrivate))
31 
32 struct CdSampleWidgetPrivate
33 {
34 	cairo_t			*cr;
35 	CdColorRGB		 color;
36 };
37 
38 enum
39 {
40 	PROP_0,
41 	PROP_COLOR,
42 };
43 
44 /**
45  * up_sample_get_property:
46  **/
47 static void
up_sample_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)48 up_sample_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
49 {
50 	CdSampleWidget *sample = CD_SAMPLE_WIDGET (object);
51 	switch (prop_id) {
52 	case PROP_COLOR:
53 		g_value_set_boxed (value, &sample->priv->color);
54 		break;
55 	default:
56 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
57 		break;
58 	}
59 }
60 
61 /**
62  * up_sample_set_property:
63  **/
64 static void
up_sample_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)65 up_sample_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
66 {
67 	CdColorRGB *tmp;
68 	CdSampleWidget *sample = CD_SAMPLE_WIDGET (object);
69 
70 	switch (prop_id) {
71 	case PROP_COLOR:
72 		tmp = g_value_get_boxed (value);
73 		cd_color_rgb_copy (tmp, &sample->priv->color);
74 		break;
75 	default:
76 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
77 		break;
78 	}
79 
80 	/* refresh widget */
81 	gtk_widget_hide (GTK_WIDGET (sample));
82 	gtk_widget_show (GTK_WIDGET (sample));
83 }
84 
85 /**
86  * cd_sample_widget_draw_rounded_rectangle:
87  **/
88 static void
cd_sample_widget_draw_rounded_rectangle(cairo_t * cr,gdouble x,gdouble y,gdouble width,gdouble height,gdouble corner_radius)89 cd_sample_widget_draw_rounded_rectangle (cairo_t *cr,
90 					 gdouble x,
91 					 gdouble y,
92 					 gdouble width,
93 					 gdouble height,
94 					 gdouble corner_radius)
95 {
96 	gdouble aspect = width / height;
97 	gdouble radius = corner_radius / aspect;
98 	gdouble degrees = G_PI / 180.0;
99 
100 	cairo_new_sub_path (cr);
101 	cairo_arc (cr, x + width - radius, y + radius,
102 		   radius, -90 * degrees, 0 * degrees);
103 	cairo_arc (cr, x + width - radius, y + height - radius,
104 		   radius, 0 * degrees, 90 * degrees);
105 	cairo_arc (cr, x + radius, y + height - radius,
106 		   radius, 90 * degrees, 180 * degrees);
107 	cairo_arc (cr, x + radius, y + radius,
108 		   radius, 180 * degrees, 270 * degrees);
109 	cairo_close_path (cr);
110 }
111 
112 /**
113  * cd_sample_widget_draw:
114  **/
115 static gboolean
cd_sample_widget_draw(GtkWidget * widget,cairo_t * cr)116 cd_sample_widget_draw (GtkWidget *widget, cairo_t *cr)
117 {
118 	CdColorRGB *color;
119 	CdSampleWidget *sample = CD_SAMPLE_WIDGET (widget);
120 	GtkAllocation allocation;
121 
122 	g_return_val_if_fail (CD_IS_SAMPLE_WIDGET (sample), FALSE);
123 
124 	color = &sample->priv->color;
125 	gtk_widget_get_allocation (widget, &allocation);
126 	cairo_save (cr);
127 	cairo_set_source_rgb (cr, color->R, color->G, color->B);
128 	cd_sample_widget_draw_rounded_rectangle (cr, 0, 0,
129 						 allocation.width,
130 						 allocation.height,
131 						 10.5);
132 	cairo_fill_preserve (cr);
133 	cairo_set_source_rgba (cr, 0.5, 0.5, 0.5, 1.0);
134 	cairo_set_line_width (cr, 1.0);
135 	cairo_stroke (cr);
136 	cairo_restore (cr);
137 	return FALSE;
138 }
139 
140 /**
141  * cd_sample_window_enter_notify_event_cb:
142  **/
143 static gboolean
cd_sample_window_enter_notify_event_cb(GtkWidget * widget,GdkEvent * event,gpointer user_data)144 cd_sample_window_enter_notify_event_cb (GtkWidget *widget,
145 					GdkEvent *event,
146 					gpointer user_data)
147 {
148 	GdkCursor *cursor;
149 	GdkWindow *window;
150 
151 	cursor = gdk_cursor_new (GDK_BLANK_CURSOR);
152 	window = gtk_widget_get_window (widget);
153 	gdk_window_set_cursor (window, cursor);
154 	g_object_unref (cursor);
155 	return TRUE;
156 }
157 
158 /**
159  * cd_sample_window_leave_notify_event_cb:
160  **/
161 static gboolean
cd_sample_window_leave_notify_event_cb(GtkWidget * widget,GdkEvent * event,gpointer user_data)162 cd_sample_window_leave_notify_event_cb (GtkWidget *widget,
163 					GdkEvent *event,
164 					gpointer user_data)
165 {
166 	GdkCursor *cursor;
167 	GdkWindow *window;
168 
169 	cursor = gdk_cursor_new (GDK_ARROW);
170 	window = gtk_widget_get_window (widget);
171 	gdk_window_set_cursor (window, cursor);
172 	g_object_unref (cursor);
173 	return TRUE;
174 }
175 
176 /**
177  * cd_sample_widget_class_init:
178  **/
179 static void
cd_sample_widget_class_init(CdSampleWidgetClass * class)180 cd_sample_widget_class_init (CdSampleWidgetClass *class)
181 {
182 	GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
183 	GObjectClass *object_class = G_OBJECT_CLASS (class);
184 
185 	widget_class->draw = cd_sample_widget_draw;
186 	object_class->get_property = up_sample_get_property;
187 	object_class->set_property = up_sample_set_property;
188 
189 	g_type_class_add_private (class, sizeof (CdSampleWidgetPrivate));
190 
191 	/* properties */
192 	g_object_class_install_property (object_class,
193 					 PROP_COLOR,
194 					 g_param_spec_boxed ("color", NULL, NULL,
195 							     CD_TYPE_COLOR_RGB,
196 							     G_PARAM_READWRITE));
197 }
198 
199 /**
200  * cd_example_window_realize_cb:
201  **/
202 static void
cd_example_window_realize_cb(GtkWidget * widget,gpointer user_data)203 cd_example_window_realize_cb (GtkWidget *widget, gpointer user_data)
204 {
205 	GdkWindow *window;
206 
207 	/* hide the mouse pointer when over the calibration widget */
208 	window = gtk_widget_get_window (widget);
209 	g_assert (window != NULL);
210 	gdk_window_set_events (window, GDK_EXPOSURE_MASK |
211 				       GDK_ENTER_NOTIFY_MASK |
212 				       GDK_LEAVE_NOTIFY_MASK);
213 }
214 
215 /**
216  * cd_sample_widget_init:
217  **/
218 static void
cd_sample_widget_init(CdSampleWidget * sample)219 cd_sample_widget_init (CdSampleWidget *sample)
220 {
221 	sample->priv = CD_SAMPLE_WIDGET_GET_PRIVATE (sample);
222 	cd_color_rgb_set (&sample->priv->color, 1.0, 1.0, 1.0);
223 
224 	g_signal_connect (sample, "realize",
225 			  G_CALLBACK (cd_example_window_realize_cb), NULL);
226 	g_signal_connect (sample, "enter-notify-event",
227 			  G_CALLBACK (cd_sample_window_enter_notify_event_cb), NULL);
228 	g_signal_connect (sample, "leave-notify-event",
229 			  G_CALLBACK (cd_sample_window_leave_notify_event_cb), NULL);
230 }
231 
232 /**
233  * cd_sample_widget_set_color:
234  * @sample: This class instance
235  * @color: A color
236  *
237  * Sets the color for the sample widget
238  *
239  * Since: 0.1.24
240  **/
241 void
cd_sample_widget_set_color(CdSampleWidget * sample,const CdColorRGB * color)242 cd_sample_widget_set_color (CdSampleWidget *sample, const CdColorRGB *color)
243 {
244 	g_return_if_fail (color != NULL);
245 	g_return_if_fail (CD_IS_SAMPLE_WIDGET (sample));
246 
247 	/* set new color and refresh */
248 	cd_color_rgb_copy (color, &sample->priv->color);
249 	gtk_widget_queue_draw (GTK_WIDGET (sample));
250 }
251 
252 /**
253  * cd_sample_widget_new:
254  *
255  * Return value: A new #CdSampleWidget object.
256  *
257  * Since: 0.1.24
258  **/
259 GtkWidget *
cd_sample_widget_new(void)260 cd_sample_widget_new (void)
261 {
262 	return g_object_new (CD_TYPE_SAMPLE_WIDGET, NULL);
263 }
264