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_progress progress
;
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;
144 if (self
->end
== self
->start
)
147 nticks
= (self
->num_ticks
148 * (self
->value
- self
->start
)
149 / (self
->end
- self
->start
));
150 /* Do ticks appear or disappear as the value approached the end? */
151 if (self
->ticks_disappear
)
154 tick_end
= self
->num_ticks
- 1;
159 tick_end
= nticks
- 1;
163 for (i
= tick_begin
; i
< tick_end
; i
++)
169 /* Calculate the location of the tick. */
170 angle
= self
->start_angle
+ i
* GRUB_TRIG_ANGLE_MAX
/ self
->num_ticks
;
171 x
= width
/ 2 + (grub_cos (angle
) * radius
/ GRUB_TRIG_FRACTION_SCALE
);
172 y
= height
/ 2 + (grub_sin (angle
) * radius
/ GRUB_TRIG_FRACTION_SCALE
);
174 /* Adjust (x,y) so the tick is centered. */
176 y
-= tick_height
/ 2;
179 grub_video_blit_bitmap (self
->tick_bitmap
, GRUB_VIDEO_BLIT_BLEND
,
180 x
, y
, 0, 0, tick_width
, tick_height
);
183 grub_gui_restore_viewport (&vpsave
);
187 circprog_set_parent (void *vself
, grub_gui_container_t parent
)
189 circular_progress_t self
= vself
;
190 self
->parent
= parent
;
193 static grub_gui_container_t
194 circprog_get_parent (void *vself
)
196 circular_progress_t self
= vself
;
201 circprog_set_bounds (void *vself
, const grub_video_rect_t
*bounds
)
203 circular_progress_t self
= vself
;
204 self
->bounds
= *bounds
;
208 circprog_get_bounds (void *vself
, grub_video_rect_t
*bounds
)
210 circular_progress_t self
= vself
;
211 *bounds
= self
->bounds
;
215 circprog_set_property (void *vself
, const char *name
, const char *value
)
217 circular_progress_t self
= vself
;
218 if (grub_strcmp (name
, "num_ticks") == 0)
220 self
->num_ticks
= grub_strtol (value
, 0, 10);
222 else if (grub_strcmp (name
, "start_angle") == 0)
224 self
->start_angle
= grub_strtol (value
, 0, 10);
226 else if (grub_strcmp (name
, "ticks_disappear") == 0)
228 self
->ticks_disappear
= grub_strcmp (value
, "false") != 0;
230 else if (grub_strcmp (name
, "center_bitmap") == 0)
232 self
->need_to_load_pixmaps
= 1;
233 grub_free (self
->center_file
);
234 self
->center_file
= value
? grub_strdup (value
) : 0;
236 else if (grub_strcmp (name
, "tick_bitmap") == 0)
238 self
->need_to_load_pixmaps
= 1;
239 grub_free (self
->tick_file
);
240 self
->tick_file
= value
? grub_strdup (value
) : 0;
242 else if (grub_strcmp (name
, "theme_dir") == 0)
244 self
->need_to_load_pixmaps
= 1;
245 grub_free (self
->theme_dir
);
246 self
->theme_dir
= value
? grub_strdup (value
) : 0;
248 else if (grub_strcmp (name
, "id") == 0)
250 grub_free (self
->id
);
252 self
->id
= grub_strdup (value
);
260 circprog_set_state (void *vself
, int visible
, int start
,
261 int current
, int end
)
263 circular_progress_t self
= vself
;
264 self
->visible
= visible
;
266 self
->value
= current
;
270 static struct grub_gui_component_ops circprog_ops
=
272 .destroy
= circprog_destroy
,
273 .get_id
= circprog_get_id
,
274 .is_instance
= circprog_is_instance
,
275 .paint
= circprog_paint
,
276 .set_parent
= circprog_set_parent
,
277 .get_parent
= circprog_get_parent
,
278 .set_bounds
= circprog_set_bounds
,
279 .get_bounds
= circprog_get_bounds
,
280 .set_property
= circprog_set_property
283 static struct grub_gui_progress_ops circprog_prog_ops
=
285 .set_state
= circprog_set_state
289 grub_gui_circular_progress_new (void)
291 circular_progress_t self
;
292 self
= grub_zalloc (sizeof (*self
));
295 self
->progress
.ops
= &circprog_prog_ops
;
296 self
->progress
.component
.ops
= &circprog_ops
;
298 self
->num_ticks
= 64;
299 self
->start_angle
= -64;
301 return (grub_gui_component_t
) self
;