PageRenderTime 369ms CodeModel.GetById 140ms app.highlight 87ms RepoModel.GetById 137ms app.codeStats 1ms

/src/ftk_list_render_default.c

http://ftk.googlecode.com/
C | 356 lines | 278 code | 44 blank | 34 comment | 57 complexity | 3cc8fb4928adecd22fdcc70a0616a8b0 MD5 | raw file
  1/*
  2 * File: ftk_list_render_default.h    
  3 * Author:  Li XianJing <xianjimli@hotmail.com>
  4 * Brief:   default list render
  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-28 Li XianJing <xianjimli@hotmail.com> created
 29 *
 30 */
 31
 32#include "ftk_log.h"
 33#include "ftk_util.h"
 34#include "ftk_globals.h"
 35#include "ftk_icon_cache.h"
 36#include "ftk_source_timer.h"
 37#include "ftk_list_model_default.h"
 38#include "ftk_list_render_default.h"
 39
 40#define MARQUEE_MOVE_INTERVAL 200
 41#define MARQUEE_PAUSE_INTERVAL 2000
 42
 43typedef enum _RenderMarqueeState
 44{
 45	MARQUEE_NONE,
 46	MARQUEE_BEGIN,
 47	MARQUEE_MOVE,
 48	MARQUEE_PAUSE,
 49	MARQUEE_END
 50}RenderMarqueeState;
 51
 52typedef struct _ListRenderDefaultPrivInfo
 53{
 54	FtkBitmap* more;
 55	FtkBitmap* radio_off;
 56	FtkBitmap* radio_on;
 57	FtkBitmap* check_off;
 58	FtkBitmap* check_on;
 59	FtkBitmap* bg_disable;
 60	FtkListModel* model;
 61	FtkWidget* list_view;
 62
 63	int focus_item;
 64	int times_to_move;
 65	int visible_start;
 66	int marquee_width;
 67	int marquee_paint_times;
 68	int marquee_cycle_times;
 69	FtkMarqueeAttr marquee_attr;
 70	FtkSource* marquee_timer;
 71	RenderMarqueeState marquee_state;
 72}PrivInfo;
 73
 74static Ret ftk_list_render_default_init(FtkListRender* thiz, FtkListModel* model, FtkWidget* list_view)
 75{
 76	DECL_PRIV(thiz, priv);
 77	return_val_if_fail(priv != NULL && model != NULL, RET_FAIL);
 78
 79	priv->model = model;
 80	priv->list_view = list_view;
 81
 82	return RET_OK;
 83}
 84
 85static Ret marquee_timer_func(void* ctx)
 86{
 87	FtkListRender* thiz = (FtkListRender*)ctx;
 88	DECL_PRIV(thiz, priv);
 89	FtkWidget* list_view = priv->list_view;
 90
 91	if(priv->marquee_state == MARQUEE_NONE)
 92	{
 93		ftk_source_timer_modify(priv->marquee_timer, MARQUEE_PAUSE_INTERVAL);
 94		return RET_OK;
 95	}
 96
 97	priv->visible_start++;
 98	switch(priv->marquee_state)
 99	{
100		case MARQUEE_BEGIN:
101		{
102			priv->visible_start = 0;
103			priv->marquee_paint_times = 0;
104			priv->marquee_state = MARQUEE_MOVE;
105			ftk_source_timer_modify(priv->marquee_timer, MARQUEE_PAUSE_INTERVAL);
106			break;
107		}
108		case MARQUEE_MOVE:
109		{
110			if(priv->marquee_paint_times == 0)
111			{
112				ftk_source_timer_modify(priv->marquee_timer, MARQUEE_MOVE_INTERVAL);
113			}
114			if(priv->marquee_paint_times < priv->times_to_move)
115			{
116				priv->marquee_paint_times++;
117			}
118			else
119			{
120				priv->marquee_state = MARQUEE_PAUSE;
121				ftk_source_timer_modify(priv->marquee_timer, MARQUEE_PAUSE_INTERVAL);
122			}
123			break;
124		}
125		case MARQUEE_PAUSE:
126		{
127			priv->marquee_paint_times = 0;
128			priv->marquee_state = MARQUEE_MOVE;
129			ftk_source_timer_modify(priv->marquee_timer, MARQUEE_MOVE_INTERVAL);
130			break;
131		}
132		case MARQUEE_END:
133		{
134			priv->visible_start = 0;
135			priv->marquee_cycle_times++;
136			priv->marquee_paint_times = 0;
137			priv->marquee_state = MARQUEE_BEGIN;
138			ftk_source_timer_modify(priv->marquee_timer, MARQUEE_PAUSE_INTERVAL);
139			break;
140		}
141		default:break;
142	}
143
144	//ftk_logd("%s: state=%d paint_times=%d cycle_times=%d vstart=%d\n", __func__, 
145	//	priv->marquee_state, priv->marquee_paint_times, priv->marquee_cycle_times,
146	//	priv->visible_start);
147	ftk_list_view_repaint_focus_item(list_view);
148
149	return RET_OK;
150}
151
152static Ret ftk_list_render_default_focus_check(FtkListRender* thiz)
153{
154	DECL_PRIV(thiz, priv);
155	int focus_item = ftk_list_view_get_selected(priv->list_view);
156	
157	if(focus_item != priv->focus_item && priv->marquee_timer != 0)
158	{
159		priv->visible_start = 0;
160		priv->focus_item = focus_item;
161		priv->marquee_paint_times = 0;
162		priv->marquee_cycle_times = 0;
163		priv->times_to_move = priv->marquee_width/16;
164		priv->marquee_state = MARQUEE_BEGIN;
165		ftk_source_timer_modify(priv->marquee_timer, MARQUEE_PAUSE_INTERVAL);
166	}
167	
168	return RET_OK;
169}
170
171static Ret ftk_list_render_default_paint(FtkListRender* thiz, FtkCanvas* canvas, int pos, int x, int y, int w, int h)
172{
173	int dx = 0;
174	int dy = 0;
175	DECL_PRIV(thiz, priv);
176	FtkBitmap* right_icon = NULL;
177	FtkListItemInfo* info = NULL;
178	return_val_if_fail(thiz != NULL && canvas != NULL && w > 0 && h > 0, RET_FAIL);
179	ftk_list_model_get_data(priv->model, pos, (void**)&info);
180	return_val_if_fail(info != NULL, RET_FAIL);
181
182	if(info->disable)
183	{
184		ftk_canvas_draw_bg_image(canvas, priv->bg_disable, FTK_BG_FOUR_CORNER, x, y, w, h);
185	}
186
187	if(info->left_icon != NULL)
188	{
189		ftk_canvas_draw_bg_image(canvas, info->left_icon, FTK_BG_CENTER, x, y, h, h);
190	}
191	
192	switch(info->type)
193	{
194		case FTK_LIST_ITEM_RADIO:
195		{
196			right_icon = info->state ? priv->radio_on : priv->radio_off;
197			break;
198		}
199		case FTK_LIST_ITEM_CHECK:
200		{
201			right_icon = info->state ? priv->check_on : priv->check_off;
202			break;
203		}
204		case FTK_LIST_ITEM_MORE:
205		{
206			right_icon = priv->more;
207			break;
208		}
209		default:
210		{
211			right_icon = info->right_icon;
212			break;
213		}
214	}
215
216	if(right_icon != NULL)
217	{
218		ftk_canvas_draw_bg_image(canvas, right_icon, FTK_BG_CENTER, x+w-h, y, h, h);
219	}
220
221	if(info->text != NULL)
222	{
223		int text_width = w;
224		int visible_start = 0;
225		FtkTextLine line = {0};
226		const char* text = NULL;
227		FtkTextLayout* text_layout = ftk_default_text_layout();
228		text_width = info->left_icon != NULL  ? text_width - h : text_width;
229		text_width = right_icon != NULL ? text_width - h : text_width;
230		
231		dy = y + FTK_HALF(h);
232		dx = FTK_H_MARGIN + (info->left_icon != NULL  ? x + h : x);
233	
234		priv->marquee_width = text_width;
235		ftk_list_render_default_focus_check(thiz);
236		
237		ftk_text_layout_init(text_layout, info->text, -1, canvas, text_width); 
238		ftk_text_layout_get_visual_line(text_layout, &line);
239
240		do
241		{
242			visible_start = 0;
243			if(priv->marquee_attr == 0 || pos != priv->focus_item)
244			{
245				break;
246			}
247			else if(!(priv->marquee_attr & FTK_MARQUEE_RIGHT2LEFT))
248			{
249				/*NOT support down to up scroll yet.*/
250				break;
251			}
252			else if(!(priv->marquee_attr & FTK_MARQUEE_AUTO))
253			{
254				/*IF text is short dont scroll it.*/
255				break;
256			}
257			else if((priv->marquee_attr & FTK_MARQUEE_ONCE) && (priv->marquee_cycle_times) > 0)
258			{
259				break;
260			}
261			else if((priv->marquee_attr & FTK_MARQUEE_AUTO) && (line.len == strlen(info->text)))
262			{
263				priv->marquee_state = MARQUEE_NONE;
264				break;
265			}
266
267			if(priv->marquee_state == MARQUEE_NONE)
268			{
269				priv->marquee_state = MARQUEE_BEGIN;
270			}
271
272			visible_start = priv->visible_start;
273			ftk_text_layout_init(text_layout, utf8_move_forward(info->text, visible_start), 
274				-1, canvas, text_width); 
275			ftk_text_layout_get_visual_line(text_layout, &line);
276		
277			if((line.extent  + 20) < text_width)
278			{
279				priv->marquee_state = MARQUEE_END;
280				ftk_source_timer_modify(priv->marquee_timer, MARQUEE_PAUSE_INTERVAL);
281			}
282		}while(0);
283
284		text = utf8_move_forward(info->text, visible_start);
285		ftk_text_layout_init(text_layout, text, -1, canvas, text_width); 
286
287		if(ftk_text_layout_get_visual_line(text_layout, &line) == RET_OK)
288		{
289			ftk_canvas_draw_string(canvas, dx + line.xoffset, dy, line.text, line.len, 1);
290		}
291	}
292
293	return RET_OK;
294}
295
296static void ftk_list_render_default_destroy(FtkListRender* thiz)
297{
298	if(thiz != NULL)
299	{
300		DECL_PRIV(thiz, priv);
301		ftk_bitmap_unref(priv->radio_on);
302		ftk_bitmap_unref(priv->radio_off);
303		ftk_bitmap_unref(priv->check_on);
304		ftk_bitmap_unref(priv->check_off);
305		ftk_bitmap_unref(priv->more);
306		ftk_bitmap_unref(priv->bg_disable);
307		if(priv->marquee_timer != NULL)
308		{
309			ftk_source_disable(priv->marquee_timer);
310			ftk_main_loop_remove_source(ftk_default_main_loop(), priv->marquee_timer);
311		}
312		FTK_ZFREE(thiz, sizeof(FtkListRender) + sizeof(PrivInfo));
313	}
314
315	return;
316}
317
318FtkListRender* ftk_list_render_default_create(void)
319{
320	FtkListRender* thiz = FTK_NEW_PRIV(FtkListRender);
321	
322	if(thiz != NULL)
323	{
324		DECL_PRIV(thiz, priv);
325		thiz->init    = ftk_list_render_default_init;
326		thiz->paint   = ftk_list_render_default_paint;
327		thiz->destroy = ftk_list_render_default_destroy;
328
329		priv->focus_item = -1;
330		priv->radio_off = ftk_theme_load_image(ftk_default_theme(), "btn_radio_off"FTK_STOCK_IMG_SUFFIX);
331		priv->radio_on = ftk_theme_load_image(ftk_default_theme(),  "btn_radio_on"FTK_STOCK_IMG_SUFFIX);
332		priv->check_off = ftk_theme_load_image(ftk_default_theme(), "btn_check_off"FTK_STOCK_IMG_SUFFIX);
333		priv->check_on = ftk_theme_load_image(ftk_default_theme(),  "btn_check_on"FTK_STOCK_IMG_SUFFIX);
334		priv->more = ftk_theme_load_image(ftk_default_theme(),      "more"FTK_STOCK_IMG_SUFFIX);
335		priv->bg_disable = ftk_theme_load_image(ftk_default_theme(),  "list_selector_background_disabled"FTK_STOCK_IMG_SUFFIX);
336	}
337
338	return thiz;
339}
340
341Ret ftk_list_render_default_set_marquee_attr(FtkListRender* thiz, FtkMarqueeAttr marquee_attr)
342{
343	DECL_PRIV(thiz, priv);
344	return_val_if_fail(thiz != NULL, RET_FAIL);
345
346	priv->marquee_attr = marquee_attr;
347
348	if(priv->marquee_timer == NULL)
349	{
350		priv->marquee_timer = ftk_source_timer_create(MARQUEE_MOVE_INTERVAL, marquee_timer_func, thiz);
351		ftk_main_loop_add_source(ftk_default_main_loop(), priv->marquee_timer);
352	}
353
354	return RET_OK;
355}
356