PageRenderTime 1131ms CodeModel.GetById 776ms app.highlight 143ms RepoModel.GetById 208ms app.codeStats 0ms

/src/ftk_progress_bar.c

http://ftk.googlecode.com/
C | 305 lines | 232 code | 43 blank | 30 comment | 41 complexity | 5214b02a4f6c8e648e8af01834873cff MD5 | raw file
  1/*
  2 * File: ftk_progress_bar.c
  3 * Author:  Li XianJing <xianjimli@hotmail.com>
  4 * Brief:   progress bar
  5 *
  6 * Copyright (c) 2009 - 2010  Li XianJing <xianjimli@hotmail.com>
  7 *
  8 * Licensed under the Academic Free License version 2.1
  9 *
 10 * This program is free software; you can redistribute it and/or modify
 11 * it under the terms of the GNU General Public License as published by
 12 * the Free Software Foundation; either version 2 of the License, or
 13 * (at your option) any later version.
 14 *
 15 * This program is distributed in the hope that it will be useful,
 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 18 * GNU General Public License for more details.
 19 *
 20 * You should have received a copy of the GNU General Public License
 21 * along with this program; if not, write to the Free Software
 22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 23 */
 24
 25/*
 26 * History:
 27 * ================================================================
 28 * 2009-11-15 Li XianJing <xianjimli@hotmail.com> created
 29 * 2010-09-22 Li XianJing <xianjimli@hotmail.com> add interactive feature.
 30 *
 31 */
 32
 33#include "ftk_window.h"
 34#include "ftk_globals.h"
 35#include "ftk_text_layout.h"
 36#include "ftk_progress_bar.h"
 37
 38typedef struct _ProgressBarPrivInfo
 39{
 40	int percent;
 41	int interactive; 
 42	int mouse_pressed;
 43	FtkBitmap* bg;
 44	FtkBitmap* cursor;
 45}PrivInfo;
 46
 47static Ret ftk_progress_bar_on_event(FtkWidget* thiz, FtkEvent* event)
 48{
 49	return RET_OK;
 50}
 51
 52static Ret ftk_progress_bar_on_paint(FtkWidget* thiz)
 53{
 54	int fg_width = 0;
 55	DECL_PRIV0(thiz, priv);
 56	FtkGc gc = {0};
 57	FTK_BEGIN_PAINT(x, y, width, height, canvas);
 58	return_val_if_fail(width > 4 && height > 4, RET_FAIL);
 59
 60	gc.mask = FTK_GC_FG;
 61	gc.fg = ftk_widget_get_gc(thiz)->bg;
 62	ftk_canvas_set_gc(canvas, &gc);
 63	ftk_canvas_draw_rect(canvas, x, y, width, height, 1, 1);
 64	
 65	gc.fg = ftk_widget_get_gc(thiz)->fg;
 66	ftk_canvas_set_gc(canvas, &gc);
 67	fg_width = width * priv->percent/100;
 68
 69	if(fg_width >= 10)
 70	{
 71		ftk_canvas_draw_rect(canvas, x+1, y+1, fg_width-2, height-2, 1, 1);
 72		if(fg_width < width && fg_width > 2)
 73		{
 74			ftk_canvas_clear_rect(canvas, x + fg_width - 3, y+1, 3, height-2);
 75		}
 76	}
 77	
 78	ftk_canvas_reset_gc(canvas, ftk_widget_get_gc(thiz)); 
 79	if(ftk_widget_get_text(thiz) != NULL)
 80	{
 81		int xoffset = 0;
 82		int yoffset = FTK_HALF(height);
 83		FtkTextLine line = {0};
 84		const char* text = ftk_widget_get_text(thiz);
 85		FtkTextLayout* text_layout = ftk_default_text_layout();
 86
 87		gc.fg.a = 0xff;
 88		gc.fg.r = 0x00;
 89		gc.fg.g = 0x00;
 90		gc.fg.b = 0x00;
 91		ftk_canvas_set_gc(canvas, &gc);
 92		ftk_text_layout_init(text_layout, text, -1, canvas, width); 
 93		if(ftk_text_layout_get_visual_line(text_layout, &line) == RET_OK)
 94		{
 95			xoffset = FTK_HALF(width - line.extent); 
 96			ftk_canvas_draw_string(canvas, x + xoffset, y + yoffset, text, -1, 1);
 97		}
 98	}
 99
100	FTK_END_PAINT();
101}
102
103static Ret ftk_progress_bar_on_event_interactive(FtkWidget* thiz, FtkEvent* event)
104{
105	DECL_PRIV0(thiz, priv);
106	int percent = priv->percent;
107	return_val_if_fail(thiz != NULL && event != NULL, RET_FAIL);
108	
109	if(event->type == FTK_EVT_KEY_UP)
110	{
111		switch(event->u.key.code)
112		{
113			case FTK_KEY_HOME:
114			{
115				percent  = 0;
116				break;
117			}
118			case FTK_KEY_END:
119			{
120				percent  = 100;
121				break;
122			}
123			case FTK_KEY_PAGEUP:
124			{
125				percent += 10;
126				break;
127			}
128			case FTK_KEY_PAGEDOWN:
129			{
130				percent -= 10;
131				break;
132			}
133			case FTK_KEY_LEFT:
134			case FTK_KEY_DOWN:
135			{
136				percent--;
137				break;
138			}
139			case FTK_KEY_UP:
140			case FTK_KEY_RIGHT:
141			{
142				percent++;
143				break;
144			}
145			default:break;
146		}
147	}
148	else if(event->type == FTK_EVT_MOUSE_DOWN)
149	{
150		priv->mouse_pressed = 1;
151		ftk_window_grab(ftk_widget_toplevel(thiz), thiz);
152	}
153	else if(event->type == FTK_EVT_MOUSE_MOVE && priv->mouse_pressed)
154	{
155		int width = ftk_widget_width(thiz);
156		int offset = event->u.mouse.x - ftk_widget_left_abs(thiz);
157		
158		percent = 100 * offset / width;
159	}
160	else if(event->type == FTK_EVT_MOUSE_UP)
161	{
162		int width = ftk_widget_width(thiz);
163		int offset = event->u.mouse.x - ftk_widget_left_abs(thiz);
164		
165		priv->mouse_pressed = 0;
166		percent = 100 * offset / width;
167		ftk_window_ungrab(ftk_widget_toplevel(thiz), thiz);
168	}
169	else
170	{
171		return RET_OK;
172	}
173
174	ftk_progress_bar_set_percent(thiz, percent);
175
176	return RET_OK;
177}
178
179static Ret ftk_progress_bar_on_paint_interactive(FtkWidget* thiz)
180{
181	int ox = 0;
182	int oy = 0;
183	DECL_PRIV0(thiz, priv);
184	FTK_BEGIN_PAINT(x, y, width, height, canvas);
185	return_val_if_fail(thiz != NULL, RET_FAIL);
186
187	oy = y + FTK_HALF(height - ftk_bitmap_height(priv->bg));
188	ftk_canvas_draw_bg_image(canvas, priv->bg, FTK_BG_FOUR_CORNER, x, oy, width,
189		ftk_bitmap_height(priv->bg));
190
191	ox = x + width * priv->percent / 100 - FTK_HALF(ftk_bitmap_width(priv->cursor));
192	oy = y + FTK_HALF(height) - FTK_HALF(ftk_bitmap_height(priv->cursor));
193
194	if(ox < x)
195	{
196		ox = x;
197	}
198
199	if(ox > (x + width - ftk_bitmap_width(priv->cursor)))
200	{
201		ox = x + width - ftk_bitmap_width(priv->cursor);
202	}
203
204	ftk_canvas_draw_bitmap_simple(canvas, priv->cursor, 0, 0, ftk_bitmap_width(priv->cursor), 
205		ftk_bitmap_height(priv->cursor), ox, oy);
206	
207	FTK_END_PAINT();
208}
209
210static void ftk_progress_bar_destroy(FtkWidget* thiz)
211{
212	if(thiz != NULL)
213	{
214		DECL_PRIV0(thiz, priv);
215
216		FTK_BITMAP_UNREF(priv->bg);
217		FTK_BITMAP_UNREF(priv->cursor);
218
219		FTK_ZFREE(priv, sizeof(PrivInfo));
220	}
221
222	return;
223}
224
225FtkWidget* ftk_progress_bar_create(FtkWidget* parent, int x, int y, int width, int height)
226{
227	FtkWidget* thiz = (FtkWidget*)FTK_ZALLOC(sizeof(FtkWidget));
228	return_val_if_fail(thiz != NULL, NULL);
229
230	thiz->priv_subclass[0] = (PrivInfo*)FTK_ZALLOC(sizeof(PrivInfo));
231	if(thiz->priv_subclass[0] != NULL)
232	{
233		thiz->on_event = ftk_progress_bar_on_event;
234		thiz->on_paint = ftk_progress_bar_on_paint;
235		thiz->destroy  = ftk_progress_bar_destroy;
236
237		ftk_widget_init(thiz, FTK_PROGRESS_BAR, 0, x, y, width, height, 
238			FTK_ATTR_TRANSPARENT|FTK_ATTR_INSENSITIVE);
239		ftk_widget_append_child(parent, thiz);
240	}
241	else
242	{
243		FTK_FREE(thiz);
244	}
245
246	return thiz;
247}
248
249Ret ftk_progress_bar_set_percent(FtkWidget* thiz, int percent)
250{
251	DECL_PRIV0(thiz, priv);
252	return_val_if_fail(thiz != NULL, RET_FAIL);
253
254	percent = percent < 0 ? 0 : percent;
255	percent = percent > 100 ? 100 : percent;
256	if(percent != priv->percent)
257	{
258		priv->percent = percent;
259		ftk_widget_invalidate(thiz);
260	}
261
262	return RET_OK;
263}
264
265int ftk_progress_bar_get_percent(FtkWidget* thiz)
266{
267	DECL_PRIV0(thiz, priv);
268	return_val_if_fail(thiz != NULL, 0);
269
270	return priv->percent;
271}
272
273Ret ftk_progress_bar_set_interactive(FtkWidget* thiz, int interactive)
274{
275	DECL_PRIV0(thiz, priv);
276	return_val_if_fail(thiz != NULL, RET_FAIL);
277
278	priv->interactive = interactive;
279	if(interactive)
280	{
281		if(priv->bg == NULL)
282		{
283			priv->bg = ftk_theme_load_image(ftk_default_theme(), 
284				"progressbar_i_bg"FTK_STOCK_IMG_SUFFIX); 
285		}
286
287		if(priv->cursor == NULL)
288		{
289			priv->cursor = ftk_theme_load_image(ftk_default_theme(), 
290				"progressbar_i_cursor"FTK_STOCK_IMG_SUFFIX); 
291		}
292
293		thiz->on_event = ftk_progress_bar_on_event_interactive;
294		thiz->on_paint = ftk_progress_bar_on_paint_interactive;
295	}
296	else
297	{
298		thiz->on_event = ftk_progress_bar_on_event;
299		thiz->on_paint = ftk_progress_bar_on_paint;
300	}
301	ftk_widget_set_insensitive(thiz, !interactive);
302
303	return RET_OK;
304}
305