1 /* gui_circular_process.c - GUI circular progress indicator component. */
3 * GRUB -- GRand Unified Bootloader
4 * Copyright (C) 2008,2009 Free Software Foundation, Inc.
6 * GRUB is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * GRUB 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
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
21 #include <grub/misc.h>
23 #include <grub/font.h>
24 #include <grub/gui_string_util.h>
25 #include <grub/gfxmenu_view.h>
26 #include <grub/gfxwidgets.h>
27 #include <grub/trig.h>
29 struct grub_gui_circular_progress
31 struct grub_gui_component comp
;
33 grub_gui_container_t parent
;
34 grub_video_rect_t bounds
;
44 int need_to_load_pixmaps
;
47 struct grub_video_bitmap
*center_bitmap
;
48 struct grub_video_bitmap
*tick_bitmap
;
51 typedef struct grub_gui_circular_progress
*circular_progress_t
;
54 circprog_destroy (void *vself
)
56 circular_progress_t self
= vself
;
61 circprog_get_id (void *vself
)
63 circular_progress_t self
= vself
;
68 circprog_is_instance (void *vself
__attribute__((unused
)), const char *type
)
70 return grub_strcmp (type
, "component") == 0;
73 static struct grub_video_bitmap
*
74 load_bitmap (const char *dir
, const char *file
)
76 struct grub_video_bitmap
*bitmap
;
79 /* Check arguments. */
83 /* Resolve to an absolute path. */
84 abspath
= grub_resolve_relative_path (dir
, file
);
89 grub_errno
= GRUB_ERR_NONE
;
90 grub_video_bitmap_load (&bitmap
, abspath
);
91 grub_errno
= GRUB_ERR_NONE
;
98 check_pixmaps (circular_progress_t self
)
100 if (self
->need_to_load_pixmaps
)
102 if (self
->center_bitmap
)
103 grub_video_bitmap_destroy (self
->center_bitmap
);
104 self
->center_bitmap
= load_bitmap (self
->theme_dir
, self
->center_file
);
105 self
->tick_bitmap
= load_bitmap (self
->theme_dir
, self
->tick_file
);
106 self
->need_to_load_pixmaps
= 0;
109 return (self
->center_bitmap
!= 0 && self
->tick_bitmap
!= 0);
113 circprog_paint (void *vself
, const grub_video_rect_t
*region
)
115 circular_progress_t self
= vself
;
120 if (!grub_video_have_common_points (region
, &self
->bounds
))
123 if (! check_pixmaps (self
))
126 grub_video_rect_t vpsave
;
127 grub_gui_set_viewport (&self
->bounds
, &vpsave
);
129 int width
= self
->bounds
.width
;
130 int height
= self
->bounds
.height
;
131 int center_width
= grub_video_bitmap_get_width (self
->center_bitmap
);
132 int center_height
= grub_video_bitmap_get_height (self
->center_bitmap
);
133 int tick_width
= grub_video_bitmap_get_width (self
->tick_bitmap
);
134 int tick_height
= grub_video_bitmap_get_height (self
->tick_bitmap
);
135 grub_video_blit_bitmap (self
->center_bitmap
, GRUB_VIDEO_BLIT_BLEND
,
136 (width
- center_width
) / 2,
137 (height
- center_height
) / 2, 0, 0,
138 center_width
, center_height
);
140 int radius
= width
/ 2 - tick_width
/ 2 - 1;
141 int nticks
= (self
->num_ticks
142 * (self
->value
- self
->start
)
143 / (self
->end
- self
->start
));
146 /* Do ticks appear or disappear as the value approached the end? */
147 if (self
->ticks_disappear
)
150 tick_end
= self
->num_ticks
- 1;
155 tick_end
= nticks
- 1;
159 for (i
= tick_begin
; i
< tick_end
; i
++)
165 /* Calculate the location of the tick. */
166 angle
= self
->start_angle
+ i
* GRUB_TRIG_ANGLE_MAX
/ self
->num_ticks
;
167 x
= width
/ 2 + (grub_cos (angle
) * radius
/ GRUB_TRIG_FRACTION_SCALE
);
168 y
= height
/ 2 + (grub_sin (angle
) * radius
/ GRUB_TRIG_FRACTION_SCALE
);
170 /* Adjust (x,y) so the tick is centered. */
172 y
-= tick_height
/ 2;
175 grub_video_blit_bitmap (self
->tick_bitmap
, GRUB_VIDEO_BLIT_BLEND
,
176 x
, y
, 0, 0, tick_width
, tick_height
);
179 grub_gui_restore_viewport (&vpsave
);
183 circprog_set_parent (void *vself
, grub_gui_container_t parent
)
185 circular_progress_t self
= vself
;
186 self
->parent
= parent
;
189 static grub_gui_container_t
190 circprog_get_parent (void *vself
)
192 circular_progress_t self
= vself
;
197 circprog_set_bounds (void *vself
, const grub_video_rect_t
*bounds
)
199 circular_progress_t self
= vself
;
200 self
->bounds
= *bounds
;
204 circprog_get_bounds (void *vself
, grub_video_rect_t
*bounds
)
206 circular_progress_t self
= vself
;
207 *bounds
= self
->bounds
;
211 circprog_set_property (void *vself
, const char *name
, const char *value
)
213 circular_progress_t self
= vself
;
214 if (grub_strcmp (name
, "value") == 0)
216 self
->value
= grub_strtol (value
, 0, 10);
218 else if (grub_strcmp (name
, "start") == 0)
220 self
->start
= grub_strtol (value
, 0, 10);
222 else if (grub_strcmp (name
, "end") == 0)
224 self
->end
= grub_strtol (value
, 0, 10);
226 else if (grub_strcmp (name
, "num_ticks") == 0)
228 self
->num_ticks
= grub_strtol (value
, 0, 10);
230 else if (grub_strcmp (name
, "start_angle") == 0)
232 self
->start_angle
= grub_strtol (value
, 0, 10);
234 else if (grub_strcmp (name
, "ticks_disappear") == 0)
236 self
->ticks_disappear
= grub_strcmp (value
, "false") != 0;
238 else if (grub_strcmp (name
, "center_bitmap") == 0)
240 self
->need_to_load_pixmaps
= 1;
241 grub_free (self
->center_file
);
242 self
->center_file
= value
? grub_strdup (value
) : 0;
244 else if (grub_strcmp (name
, "tick_bitmap") == 0)
246 self
->need_to_load_pixmaps
= 1;
247 grub_free (self
->tick_file
);
248 self
->tick_file
= value
? grub_strdup (value
) : 0;
250 else if (grub_strcmp (name
, "theme_dir") == 0)
252 self
->need_to_load_pixmaps
= 1;
253 grub_free (self
->theme_dir
);
254 self
->theme_dir
= value
? grub_strdup (value
) : 0;
256 else if (grub_strcmp (name
, "visible") == 0)
258 self
->visible
= grub_strcmp (value
, "false") != 0;
260 else if (grub_strcmp (name
, "id") == 0)
262 grub_free (self
->id
);
264 self
->id
= grub_strdup (value
);
271 static struct grub_gui_component_ops circprog_ops
=
273 .destroy
= circprog_destroy
,
274 .get_id
= circprog_get_id
,
275 .is_instance
= circprog_is_instance
,
276 .paint
= circprog_paint
,
277 .set_parent
= circprog_set_parent
,
278 .get_parent
= circprog_get_parent
,
279 .set_bounds
= circprog_set_bounds
,
280 .get_bounds
= circprog_get_bounds
,
281 .set_property
= circprog_set_property
285 grub_gui_circular_progress_new (void)
287 circular_progress_t self
;
288 self
= grub_zalloc (sizeof (*self
));
291 self
->comp
.ops
= &circprog_ops
;
293 self
->num_ticks
= 64;
294 self
->start_angle
= -64;
296 return (grub_gui_component_t
) self
;