PageRenderTime 328ms CodeModel.GetById 130ms app.highlight 89ms RepoModel.GetById 105ms app.codeStats 0ms

/src/ftk_menu_panel.c

http://ftk.googlecode.com/
C | 336 lines | 253 code | 50 blank | 33 comment | 56 complexity | 3c62955929ddea652e502410815e21b6 MD5 | raw file
  1/*
  2 * File: ftk_menu_panel.c
  3 * Author: Li XianJing <xianjimli@hotmail.com>
  4 * Brief:  ftk menu panel
  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-10-30 Li XianJing <xianjimli@hotmail.com> created
 29 *
 30 */
 31
 32#include "ftk_window.h"
 33#include "ftk_globals.h"
 34#include "ftk_menu_item.h"
 35
 36typedef struct _MenuPanelPrivInfo
 37{
 38	int changed;
 39	int items_nr;
 40	FtkWidget* items[FTK_MENU_MAX_ITEM];	
 41	FtkWidgetOnEvent parent_on_event;
 42	FtkWidgetOnPaint parent_on_paint;
 43	FtkWidgetDestroy parent_destroy;
 44}PrivInfo;
 45
 46static int ftk_menu_panel_count_visible_items(FtkWidget* thiz)
 47{
 48	int i = 0;
 49	int n = 0;
 50	DECL_PRIV1(thiz, priv);
 51	for(i = 0; i < priv->items_nr; i++)
 52	{
 53		if(ftk_widget_is_visible(priv->items[i]))
 54		{
 55			n++;
 56		}
 57	}
 58
 59	return n;
 60}
 61
 62static FtkRect* ftk_menu_panel_calc_rects(FtkWidget* thiz, int* nr)
 63{
 64	int i = 0;
 65	int n = 0;
 66	int w = 0;
 67	FtkRect* rect = NULL;
 68	DECL_PRIV1(thiz, priv);
 69	int screen_width = ftk_display_width(ftk_default_display());
 70	int max_items_per_row = screen_width/FTK_MENU_ITEM_WIDTH;
 71	return_val_if_fail(priv->items_nr > 0, NULL);
 72	n = ftk_menu_panel_count_visible_items(thiz);
 73	return_val_if_fail(n > 0, NULL);
 74
 75	n = n <= max_items_per_row * 2 ? n : max_items_per_row * 2;
 76	rect = (FtkRect*)FTK_ALLOC(sizeof(FtkRect) * n);
 77	return_val_if_fail(rect != NULL, NULL);
 78
 79	*nr = n;
 80	if(n <= max_items_per_row)
 81	{
 82		w = screen_width/n;
 83		for(i = 0; i < n; i++)
 84		{
 85			rect[i].x = w * i;
 86			rect[i].y = 0;
 87			rect[i].width = w;
 88			rect[i].height = FTK_MENU_ITEM_HEIGHT;
 89		}
 90	}
 91	else
 92	{
 93		int first_row_nr = n/2;
 94		int second_row_nr = (n+1)/2;
 95		
 96		w = screen_width/first_row_nr;
 97		for(i = 0; i < first_row_nr; i++)
 98		{
 99			rect[i].x = w * i;
100			rect[i].y = 0;
101			rect[i].width = w;
102			rect[i].height = FTK_MENU_ITEM_HEIGHT;
103		}
104		
105		w = screen_width/second_row_nr;
106		for(i = 0; i < second_row_nr; i++)
107		{
108			rect[first_row_nr + i].x = w * i;
109			rect[first_row_nr + i].y = FTK_MENU_ITEM_HEIGHT;
110			rect[first_row_nr + i].width = w;
111			rect[first_row_nr + i].height = FTK_MENU_ITEM_HEIGHT;
112		}
113	}
114
115	return rect;
116}
117
118Ret ftk_menu_panel_relayout(FtkWidget* thiz)
119{
120	int i = 0;
121	int j = 0;
122	int nr = 0;
123	int h  = 0;
124	DECL_PRIV1(thiz, priv);
125	FtkRect* rects = ftk_menu_panel_calc_rects(thiz, &nr);
126	int screen_height = ftk_display_height(ftk_default_display());
127	int screen_width = ftk_display_width(ftk_default_display());
128	int max_items_per_row = screen_width/FTK_MENU_ITEM_WIDTH;	
129	return_val_if_fail(priv->items_nr > 0 && rects != NULL && nr > 0, RET_FAIL);
130
131	h = nr > max_items_per_row ? FTK_MENU_ITEM_HEIGHT * 2 : FTK_MENU_ITEM_HEIGHT;
132	ftk_widget_move_resize(thiz, 0, screen_height - h, screen_width, h);
133
134	/*relayout the items*/
135	for(i = 0, j = 0; i < nr; j++)
136	{
137		if(ftk_widget_is_visible(priv->items[j]))
138		{
139			ftk_widget_move_resize(priv->items[j], rects[i].x, rects[i].y, rects[i].width, rects[i].height);
140			i++;
141		}
142	}
143
144	/*hide items that there is no space for them*/
145	for(; j < priv->items_nr; j++)
146	{
147		ftk_widget_move_resize(priv->items[j], 0, 0, 0, 0);
148	}
149
150	FTK_FREE(rects);
151
152	return RET_OK;
153}
154
155static Ret  ftk_menu_panel_on_event(FtkWidget* thiz, FtkEvent* event)
156{
157	Ret ret = RET_OK;
158	DECL_PRIV1(thiz, priv);
159
160	if(event->type == FTK_EVT_KEY_UP && event->u.key.code == FTK_KEY_MENU)
161	{
162		ftk_widget_unref(thiz);
163
164		return ret;
165	}
166
167	if(event->type == FTK_EVT_SHOW)
168	{
169		ftk_wnd_manager_grab(ftk_default_wnd_manager(), thiz);
170	}
171	
172	if(event->type == FTK_EVT_HIDE)
173	{
174		ftk_wnd_manager_ungrab(ftk_default_wnd_manager(), thiz);
175	}
176	
177	if((event->type == FTK_EVT_MOUSE_UP && ret != RET_IGNORED)
178		|| (event->type == FTK_EVT_KEY_UP && FTK_IS_ACTIVE_KEY(event->u.key.code)))
179	{
180		ftk_widget_show(thiz, 0);
181	}
182
183	ret = priv->parent_on_event(thiz, event);
184
185	if((event->type == FTK_EVT_MOUSE_UP && ret != RET_IGNORED)
186		|| (event->type == FTK_EVT_KEY_UP && FTK_IS_ACTIVE_KEY(event->u.key.code)))
187	{
188		ftk_widget_unref(thiz);
189	}
190
191	return ret;
192}
193
194static Ret  ftk_menu_panel_on_paint(FtkWidget* thiz)
195{
196	int i = 0;
197	int w = 0;
198	int nr = 0;
199	int first_row_nr = 0;
200	int second_row_nr = 0;
201	FtkGc gc = {0};
202	DECL_PRIV1(thiz, priv);
203	int screen_width = ftk_display_width(ftk_default_display());
204	int max_items_per_row = screen_width/FTK_MENU_ITEM_WIDTH;	
205	FTK_BEGIN_PAINT(x, y, width, height, canvas);
206	return_val_if_fail(priv != NULL, RET_FAIL);
207	return_val_if_fail(ftk_widget_is_visible(thiz), RET_FAIL);
208
209	/*draw border*/
210	gc.mask = FTK_GC_FG;
211	gc.fg = ftk_theme_get_border_color(ftk_default_theme(), FTK_MENU_PANEL, ftk_widget_state(thiz));
212	ftk_canvas_set_gc(canvas, &gc);
213	ftk_canvas_draw_rect(canvas, x, y, width, height, 0, 0);
214	ftk_canvas_draw_rect(canvas, x+1, y+1, width-2, height-2, 0, 0);
215
216	/*draw grid*/
217	gc.fg = ftk_widget_get_gc(thiz)->fg;
218	ftk_canvas_set_gc(canvas, &gc);
219	nr = ftk_menu_panel_count_visible_items(thiz);
220	nr = nr <= max_items_per_row * 2 ? nr : max_items_per_row * 2;
221
222	if(nr > max_items_per_row)
223	{
224		first_row_nr = nr/2;
225		second_row_nr = (nr+1)/2;
226		ftk_canvas_draw_hline(canvas, x, y+FTK_MENU_ITEM_HEIGHT, screen_width);
227	}
228	else
229	{
230		first_row_nr = nr;
231	}
232
233	if(first_row_nr > 0)
234	{
235		w = screen_width/first_row_nr;
236		for(i = 1; i < first_row_nr; i++)
237		{
238			ftk_canvas_draw_vline(canvas, x+i*w, y, FTK_MENU_ITEM_HEIGHT);
239		}
240	}
241
242	if(second_row_nr > 0)
243	{
244		w = screen_width/second_row_nr;
245		for(i = 1; i < second_row_nr; i++)
246		{
247			ftk_canvas_draw_vline(canvas, x+i*w, y+FTK_MENU_ITEM_HEIGHT, FTK_MENU_ITEM_HEIGHT);
248		}
249	}
250
251	priv->parent_on_paint(thiz);
252
253	return RET_OK;
254}
255
256static void ftk_menu_panel_destroy(FtkWidget* thiz)
257{
258	DECL_PRIV1(thiz, priv);
259	FtkWidgetDestroy parent_destroy = priv->parent_destroy;
260	parent_destroy(thiz);
261	FTK_ZFREE(thiz->priv_subclass[1], sizeof(PrivInfo));
262
263	return;
264}
265
266FtkWidget* ftk_menu_panel_create(void)
267{
268	FtkWidget* thiz = ftk_window_create(FTK_MENU_PANEL, 0, 0, 0, 0, 0);
269	return_val_if_fail(thiz != NULL, NULL);
270
271	thiz->priv_subclass[1] = (PrivInfo*)FTK_ZALLOC(sizeof(PrivInfo));
272	if(thiz->priv_subclass[1] != NULL)
273	{
274		DECL_PRIV1(thiz, priv);
275		priv->parent_on_event = thiz->on_event;
276		priv->parent_on_paint = thiz->on_paint;
277		priv->parent_destroy  = thiz->destroy;
278		thiz->on_event = ftk_menu_panel_on_event;
279		thiz->on_paint = ftk_menu_panel_on_paint;
280		thiz->destroy  = ftk_menu_panel_destroy;
281	}
282	else
283	{
284		ftk_widget_destroy(thiz);
285		thiz = NULL;
286	}
287
288	return thiz;
289}
290
291
292Ret ftk_menu_panel_add(FtkWidget* thiz, FtkWidget* item)
293{
294	DECL_PRIV1(thiz, priv);
295	return_val_if_fail(thiz != NULL && item != NULL, RET_FAIL);
296	return_val_if_fail(priv->items_nr < FTK_MENU_MAX_ITEM, RET_FAIL);
297
298	priv->items[priv->items_nr++] = item;
299	priv->changed = 1;
300	ftk_widget_append_child(thiz, item);
301
302	return RET_OK;
303}
304
305Ret        ftk_menu_panel_remove(FtkWidget* thiz, FtkWidget* item)
306{
307	int i = 0;
308	Ret ret = RET_FAIL;
309	DECL_PRIV1(thiz, priv);
310	return_val_if_fail(thiz != NULL && item != NULL, RET_FAIL);
311
312	for(i = 0; i < priv->items_nr; i++)
313	{
314		if(priv->items[i] == item)
315		{
316			for(; i < priv->items_nr; i++)
317			{
318				priv->items[i] = priv->items[i+1];
319			}
320			priv->items_nr--;
321
322			ret = RET_OK;
323			break;
324		}
325	}
326
327	if(ret == RET_OK)
328	{
329		priv->changed = 1;
330		ftk_widget_remove_child(thiz, item);
331	}
332
333	return RET_OK;
334}
335
336