12 #include <yui/Libyui_config.h> 13 #include "ygtksteps.h" 18 #define CURRENT_MARK_ANIMATION_TIME 250 19 #define CURRENT_MARK_ANIMATION_OFFSET 3 20 #define CURRENT_MARK_FRAMES_NB (CURRENT_MARK_ANIMATION_OFFSET*2) 22 G_DEFINE_TYPE (
YGtkSteps, ygtk_steps, GTK_TYPE_BOX)
24 static
void ygtk_steps_init (
YGtkSteps *steps)
26 gtk_box_set_spacing (GTK_BOX (steps), 8);
27 gtk_orientable_set_orientation (GTK_ORIENTABLE (steps), GTK_ORIENTATION_VERTICAL);
28 gtk_container_set_border_width (GTK_CONTAINER (steps), 4);
30 const gchar *check =
"\u2714", *current =
"\u25b6", *todo =
"\u26ab";
31 if (gtk_widget_get_default_direction() == GTK_TEXT_DIR_RTL)
33 PangoContext *context = gtk_widget_get_pango_context (GTK_WIDGET (steps));
34 steps->check_mark_layout = pango_layout_new (context);
35 steps->current_mark_layout = pango_layout_new (context);
36 steps->todo_mark_layout = pango_layout_new (context);
37 pango_layout_set_text (steps->check_mark_layout, check, -1);
38 pango_layout_set_text (steps->current_mark_layout, current, -1);
39 pango_layout_set_text (steps->todo_mark_layout, todo, -1);
40 steps->current_mark_timeout_id = steps->current_mark_frame = 0;
43 static void ygtk_steps_destroy (GtkWidget *widget)
46 if (steps->current_mark_timeout_id) {
47 g_source_remove (steps->current_mark_timeout_id);
48 steps->current_mark_timeout_id = 0;
50 if (steps->check_mark_layout)
51 g_object_unref (steps->check_mark_layout);
52 steps->check_mark_layout = NULL;
53 if (steps->current_mark_layout)
54 g_object_unref (steps->current_mark_layout);
55 if (steps->todo_mark_layout)
56 g_object_unref (steps->todo_mark_layout);
57 steps->todo_mark_layout = NULL;
59 GTK_WIDGET_CLASS (ygtk_steps_parent_class)->destroy(widget);
62 static void ygtk_step_update_layout (
YGtkSteps *steps, gint step)
65 gboolean bold = steps->current_step == step;
66 GList *children = gtk_container_get_children (GTK_CONTAINER (steps));
67 GtkWidget *label = (GtkWidget *) g_list_nth_data (children, step);
68 if (g_object_get_data (G_OBJECT (label),
"is-header"))
71 PangoAttrList *attrbs = pango_attr_list_new();
72 pango_attr_list_insert (attrbs, pango_attr_weight_new (PANGO_WEIGHT_BOLD));
73 gtk_label_set_attributes (GTK_LABEL (label), attrbs);
74 pango_attr_list_unref (attrbs);
75 atk_object_set_description (gtk_widget_get_accessible (label), _(
"Current step"));
78 gtk_label_set_attributes (GTK_LABEL (label), NULL);
79 atk_object_set_description (gtk_widget_get_accessible (label),
"");
81 g_list_free (children);
84 static gboolean ygtk_steps_draw (GtkWidget *widget, cairo_t *cr)
86 GTK_WIDGET_CLASS (ygtk_steps_parent_class)->draw(widget, cr);
89 gboolean reverse = gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL;
90 GList *children = gtk_container_get_children (GTK_CONTAINER (widget)), *i;
92 cairo_set_source_rgb (cr, 0, 0, 0);
94 for (i = children; i; i = i->next, n++) {
95 GtkWidget *label = i->data;
97 gtk_widget_get_allocation(label, &alloc);
99 if (g_object_get_data (G_OBJECT (label),
"is-header"))
102 if (n < steps->current_step)
103 layout = steps->check_mark_layout;
104 else if (n == steps->current_step)
105 layout = steps->current_mark_layout;
107 layout = steps->todo_mark_layout;
108 int x = alloc.x, y = alloc.y;
111 pango_layout_get_pixel_extents (layout, NULL, &rect);
112 x += alloc.width - rect.width - 4;
116 if (n == steps->current_step) {
118 if (steps->current_mark_frame < CURRENT_MARK_FRAMES_NB/2)
119 offset = steps->current_mark_frame * CURRENT_MARK_ANIMATION_OFFSET;
121 offset = (CURRENT_MARK_FRAMES_NB - steps->current_mark_frame) *
122 CURRENT_MARK_ANIMATION_OFFSET;
123 x += offset * (reverse ? 1 : -1);
126 cairo_move_to (cr, x, y);
127 pango_cairo_show_layout (cr, layout);
129 g_list_free (children);
133 GtkWidget* ygtk_steps_new (
void)
135 return g_object_new (YGTK_TYPE_STEPS, NULL);
138 gint ygtk_steps_append (
YGtkSteps *steps,
const gchar *text)
140 GtkWidget *label = gtk_label_new (text);
141 GdkRGBA black = { 0.0, 0.0, 0.0, 1.0 };
142 gtk_widget_override_color (label, GTK_STATE_NORMAL, &black);
143 gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
145 pango_layout_get_pixel_size (steps->check_mark_layout, &mark_width, NULL);
146 gtk_misc_set_padding (GTK_MISC (label), mark_width+12, 0);
147 gtk_widget_show (label);
148 gtk_box_pack_start (GTK_BOX (steps), label, FALSE, TRUE, 0);
149 return ygtk_steps_total (steps)-1;
152 void ygtk_steps_append_heading (
YGtkSteps *steps,
const gchar *heading)
154 GtkWidget *label = gtk_label_new (heading);
155 GdkRGBA black = { 0.0, 0.0, 0.0, 1.0 };
156 gtk_widget_override_color (label, GTK_STATE_NORMAL, &black);
157 g_object_set_data (G_OBJECT (label),
"is-header", GINT_TO_POINTER (1));
158 gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
160 PangoAttrList *attrbs = pango_attr_list_new();
161 pango_attr_list_insert (attrbs, pango_attr_weight_new (PANGO_WEIGHT_BOLD));
162 pango_attr_list_insert (attrbs, pango_attr_scale_new (PANGO_SCALE_LARGE));
163 gtk_label_set_attributes (GTK_LABEL (label), attrbs);
164 pango_attr_list_unref (attrbs);
166 gtk_widget_show (label);
167 gtk_box_pack_start (GTK_BOX (steps), label, FALSE, TRUE, 6);
170 static gboolean current_mark_animation_cb (
void *steps_ptr)
175 gtk_widget_queue_draw (GTK_WIDGET (steps));
177 if (++steps->current_mark_frame == CURRENT_MARK_FRAMES_NB) {
178 steps->current_mark_frame = 0;
184 void ygtk_steps_set_current (
YGtkSteps *steps, gint step)
186 gint old_step = steps->current_step;
187 steps->current_step = step;
190 if (old_step != step) {
191 ygtk_step_update_layout (steps, old_step);
192 ygtk_step_update_layout (steps, step);
195 if (step != -1 && step != old_step) {
196 steps->current_mark_frame = 0;
197 steps->current_mark_timeout_id = g_timeout_add
198 (CURRENT_MARK_ANIMATION_TIME / CURRENT_MARK_FRAMES_NB,
199 current_mark_animation_cb, steps);
205 GList *children = gtk_container_get_children (GTK_CONTAINER (steps));
206 int steps_nb = g_list_length (children);
207 g_list_free (children);
211 const gchar *ygtk_steps_get_nth_label (
YGtkSteps *steps, gint n)
213 if (n < 0)
return NULL;
215 GList *children = gtk_container_get_children (GTK_CONTAINER (steps));
216 step = g_list_nth_data (children, n);
217 g_list_free (children);
219 return gtk_label_get_text (GTK_LABEL (step));
225 GList *children = gtk_container_get_children (GTK_CONTAINER (steps)), *i;
226 for (i = children; i; i = i->next)
227 gtk_container_remove (GTK_CONTAINER (steps), (GtkWidget *) i->data);
228 g_list_free (children);
233 ygtk_steps_parent_class = g_type_class_peek_parent (klass);
235 GtkWidgetClass* widget_class = GTK_WIDGET_CLASS (klass);
236 widget_class->draw = ygtk_steps_draw;
237 widget_class->destroy = ygtk_steps_destroy;