PageRenderTime 83ms CodeModel.GetById 32ms app.highlight 45ms RepoModel.GetById 2ms app.codeStats 0ms

/src/ftk_dialog.c

http://ftk.googlecode.com/
C | 393 lines | 286 code | 78 blank | 29 comment | 55 complexity | 1ce621ec12f6d9913c4d4aca0a2a7f97 MD5 | raw file
  1/*
  2 * File: ftk_dialog.c
  3 * Author: Li XianJing <xianjimli@hotmail.com>
  4 * Brief:  dialog
  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-15 Li XianJing <xianjimli@hotmail.com> created
 29 * 2012-5-3  woodysu@gmail.com modified
 30 */
 31
 32#include "ftk_dialog.h"
 33#include "ftk_globals.h"
 34#include "ftk_main_loop.h"
 35#include "ftk_source_timer.h"
 36
 37typedef struct _DialogPrivInfo
 38{
 39	int no_title;
 40	int title_height;
 41	FtkBitmap* icon;
 42	FtkBitmap* bg;
 43	FtkBitmap* title_bg;
 44	FtkSource* timer;
 45	FtkMainLoop* main_loop;
 46	FtkWidgetOnEvent parent_on_event;
 47	FtkWidgetOnPaint parent_on_paint;
 48	FtkWidgetDestroy parent_destroy;
 49}PrivInfo;
 50
 51static int ftk_dialog_is_modal(FtkWidget* thiz)
 52{
 53	DECL_PRIV1(thiz, priv);
 54
 55	return priv != NULL && priv->main_loop != NULL;
 56}
 57
 58Ret ftk_dialog_set_icon(FtkWidget* thiz, FtkBitmap* icon)
 59{
 60	DECL_PRIV1(thiz, priv);
 61	return_val_if_fail(thiz != NULL, RET_FAIL);
 62
 63	if(priv->icon != NULL)
 64	{
 65		ftk_bitmap_unref(priv->icon);
 66	}
 67	priv->icon = icon;
 68	if(priv->icon != NULL)
 69	{
 70		ftk_bitmap_ref(priv->icon);
 71	}
 72
 73	return RET_OK;	
 74}
 75
 76Ret ftk_dialog_hide_title(FtkWidget* thiz)
 77{
 78	DECL_PRIV1(thiz, priv);
 79	return_val_if_fail(thiz != NULL, RET_FAIL);
 80
 81	priv->no_title = 1;
 82
 83	return RET_OK;
 84}
 85
 86static Ret  ftk_dialog_on_event(FtkWidget* thiz, FtkEvent* event)
 87{
 88	DECL_PRIV1(thiz, priv);
 89	Ret ret = priv->parent_on_event(thiz, event);
 90
 91	if(ret == RET_QUIT && ftk_dialog_is_modal(thiz))
 92	{
 93		ftk_main_loop_quit(priv->main_loop);
 94	}
 95
 96	switch(event->type)
 97	{
 98		case FTK_EVT_ADD_CHILD:
 99		{
100			int x = 0;
101			int y = 0;
102			FtkWidget* child = (FtkWidget*)event->u.extra;
103			x = ftk_widget_left(child) + FTK_DIALOG_BORDER;
104			y = ftk_widget_top(child) + (priv->no_title ? FTK_DIALOG_BORDER : priv->title_height);
105
106			ftk_widget_move(child, x, y);
107
108			break;
109		}
110		case FTK_EVT_MOUSE_UP:
111		{
112			int p_x = event->u.mouse.x;
113			int p_y = event->u.mouse.y;
114
115			int x = ftk_widget_left_abs(thiz);
116			int y = ftk_widget_top_abs(thiz);
117			int w = ftk_widget_width(thiz);
118			int h = ftk_widget_height(thiz);
119
120			if(p_x < x || p_y < y || (p_x > (x + w)) || (p_y > (y + h)))
121			{
122				if(thiz->ref > 1 && ftk_widget_has_attr(thiz, FTK_ATTR_POPUP))
123				{
124					if(ftk_dialog_is_modal(thiz))
125					{
126						ftk_dialog_quit(thiz);
127					}
128					else
129					{
130						ftk_widget_unref(thiz);
131					}
132				}
133			}
134			break;
135		}
136		default:break;
137	}
138
139	return RET_OK;
140}
141
142static Ret  ftk_dialog_clear_alpha(FtkCanvas* canvas, int x, int y)
143{
144	return RET_OK;
145}
146
147static Ret  ftk_dialog_change_alpha(FtkWidget* thiz, FtkCanvas* canvas, int x, int y, int width, int height)
148{
149	ftk_dialog_clear_alpha(canvas, x, y);
150	ftk_dialog_clear_alpha(canvas, x+1, y);
151	ftk_dialog_clear_alpha(canvas, x, y+1);
152	
153	ftk_dialog_clear_alpha(canvas, x+width-1, y)  ;
154	ftk_dialog_clear_alpha(canvas, x+width-2, y)  ;
155	ftk_dialog_clear_alpha(canvas, x+width-1, y+1);
156	
157	ftk_dialog_clear_alpha(canvas, x, y+height-1)  ;
158	ftk_dialog_clear_alpha(canvas, x+1, y+height-1);
159	ftk_dialog_clear_alpha(canvas, x, y+height-2)  ;
160	
161	ftk_dialog_clear_alpha(canvas, x+width-1, y+height-1);
162	ftk_dialog_clear_alpha(canvas, x+width-2, y+height-1);
163	ftk_dialog_clear_alpha(canvas, x+width-1, y+height-2);
164
165	return RET_OK;
166}
167
168static Ret  ftk_dialog_paint_border(FtkWidget* thiz, FtkCanvas* canvas, int x, int y, int width, int height)
169{
170	DECL_PRIV1(thiz, priv);
171	return_val_if_fail(priv->bg != NULL && priv->title_bg != NULL, RET_FAIL);
172
173	if(!ftk_window_is_opaque(thiz))
174	{
175		return RET_OK;
176	}
177	
178	if(priv->no_title)
179	{
180		ftk_canvas_draw_bg_image(canvas, priv->bg, FTK_BG_FOUR_CORNER, x, y, width, height);	
181	}
182	else
183	{
184		int title_height = ftk_bitmap_height(priv->title_bg);
185		
186		return_val_if_fail(title_height < height, RET_FAIL);
187		ftk_canvas_draw_bg_image(canvas, priv->title_bg, FTK_BG_TILE, x, y, width, title_height);
188		ftk_canvas_draw_bg_image(canvas, priv->bg, FTK_BG_FOUR_CORNER, x, y+title_height, width, height-title_height);	
189	}
190
191	return RET_OK;
192}
193
194static Ret  ftk_dialog_paint_title(FtkWidget* thiz, FtkCanvas* canvas, int x, int y, int width, int height)
195{
196	DECL_PRIV1(thiz, priv);
197
198	if(priv->no_title) return RET_OK;
199
200	if(priv->icon != NULL)
201	{
202		ftk_canvas_draw_bg_image(canvas, priv->icon, FTK_BG_CENTER, x + FTK_DIALOG_BORDER, y, 
203			priv->title_height, priv->title_height);
204	}
205
206	ftk_canvas_set_gc(canvas, ftk_widget_get_gc(thiz));
207	if(ftk_widget_get_text(thiz) != NULL)
208	{
209		int xoffset = FTK_DIALOG_BORDER + (priv->icon != NULL ? priv->title_height : FTK_DIALOG_BORDER);
210		int yoffset = priv->title_height >> 1;
211		const char* text = ftk_widget_get_text(thiz);
212		const char*	end = ftk_canvas_calc_str_visible_range(canvas, text, 0, -1, 
213			width - xoffset - FTK_DIALOG_BORDER, NULL);
214
215		ftk_canvas_draw_string(canvas, x + xoffset, y + yoffset, text, end - text, 1);
216	}
217
218	return RET_OK;
219}
220
221static Ret  ftk_dialog_on_paint(FtkWidget* thiz)
222{
223	DECL_PRIV1(thiz, priv);
224	FTK_BEGIN_PAINT(x, y, width, height, canvas);
225	
226	return_val_if_fail(ftk_widget_is_visible(thiz), RET_FAIL);
227	
228	ftk_dialog_paint_border(thiz, canvas, x, y, width, height);
229
230	ftk_dialog_paint_title(thiz, canvas, x, y, width, height);
231
232	ftk_dialog_change_alpha(thiz, canvas, x, y, width, height);
233	
234	priv->parent_on_paint(thiz);
235
236	return RET_OK;
237}
238
239static void ftk_dialog_destroy(FtkWidget* thiz)
240{
241	DECL_PRIV1(thiz, priv);
242
243	if(priv->parent_destroy != NULL)
244	{
245		priv->parent_destroy(thiz);
246	}
247
248	if(priv->icon != NULL)
249	{
250		ftk_bitmap_unref(priv->icon);
251	}
252
253	if(priv->bg != NULL)
254	{
255		ftk_bitmap_unref(priv->bg);
256	}
257	
258	if(priv->title_bg != NULL)
259	{
260		ftk_bitmap_unref(priv->title_bg);
261	}
262
263	if(priv->timer != NULL)
264	{
265		ftk_main_loop_remove_source(ftk_default_main_loop(), priv->timer);
266	}
267
268	FTK_ZFREE(thiz->priv_subclass[1], sizeof(PrivInfo));
269
270	return;
271}
272
273FtkWidget* ftk_dialog_create_ex(int attr, int x, int y, int width, int height)
274{
275	FtkWidget* thiz = ftk_window_create(FTK_DIALOG, attr, x, y, width, height);
276	return_val_if_fail(thiz != NULL, NULL);
277
278	thiz->priv_subclass[1] = (PrivInfo*)FTK_ZALLOC(sizeof(PrivInfo));
279	if(thiz->priv_subclass[1] != NULL)
280	{
281		DECL_PRIV1(thiz, priv);
282		priv->parent_on_event = thiz->on_event;
283		priv->parent_on_paint = thiz->on_paint;
284		priv->parent_destroy  = thiz->destroy;
285		thiz->on_event = ftk_dialog_on_event;
286		thiz->on_paint = ftk_dialog_on_paint;
287		thiz->destroy  = ftk_dialog_destroy;
288
289		priv->bg = ftk_theme_load_image(ftk_default_theme(), "dialog_bg"FTK_STOCK_IMG_SUFFIX);
290		priv->title_bg = ftk_theme_load_image(ftk_default_theme(), "dialog_title_bg"FTK_STOCK_IMG_SUFFIX);
291		priv->title_height = ftk_bitmap_height(priv->title_bg);
292	}
293	else
294	{
295		ftk_widget_destroy(thiz);
296		thiz = NULL;
297	}
298
299	return thiz;
300}
301
302Ret ftk_dialog_set_bg(FtkWidget* thiz, FtkBitmap* bitmap)
303{
304    DECL_PRIV1(thiz, priv);
305    return_val_if_fail(priv != NULL, RET_FAIL);
306
307    ftk_bitmap_unref(priv->bg);
308    priv->bg = bitmap;
309    ftk_bitmap_ref(priv->bg);
310    return RET_OK;
311}
312
313FtkWidget* ftk_dialog_create(int x, int y, int width, int height)
314{
315	return ftk_dialog_create_ex(FTK_ATTR_AUTO_LAYOUT, x, y, width, height);
316}
317
318Ret ftk_dialog_quit(FtkWidget* thiz)
319{
320	DECL_PRIV1(thiz, priv);
321	return_val_if_fail(ftk_dialog_is_modal(thiz), RET_FAIL);
322
323	ftk_main_loop_quit(priv->main_loop);
324
325	return RET_OK;
326}
327
328static Ret ftk_dialog_timeout_quit(void* ctx)
329{
330	FtkWidget* thiz = (FtkWidget*)ctx;
331	DECL_PRIV1(thiz, priv);
332	return_val_if_fail(priv != NULL && priv->timer != NULL, RET_REMOVE);
333
334	priv->timer = NULL;
335	if(ftk_dialog_is_modal(thiz))
336	{
337		ftk_dialog_quit(thiz);
338	}
339	else
340	{
341		ftk_widget_unref(thiz);
342	}
343
344	return RET_REMOVE;
345}
346
347Ret ftk_dialog_quit_after(FtkWidget* thiz, int ms)
348{
349	DECL_PRIV1(thiz, priv);
350	return_val_if_fail(priv != NULL && priv->timer == NULL, RET_FAIL);
351	
352	priv->timer = ftk_source_timer_create(ms, ftk_dialog_timeout_quit, thiz);
353	ftk_main_loop_add_source(ftk_default_main_loop(), priv->timer);
354
355	return RET_OK;
356}
357
358int ftk_dialog_run(FtkWidget* thiz)
359{
360    FtkMainLoop* prev_main_loop = ftk_default_main_loop();
361	DECL_PRIV1(thiz, priv);
362	return_val_if_fail(thiz != NULL, RET_FAIL);
363	return_val_if_fail(ftk_widget_type(thiz) == FTK_DIALOG, RET_FAIL);
364
365    priv->main_loop = ftk_main_loop_create(ftk_default_sources_manager());
366
367    ftk_set_main_loop(priv->main_loop);
368
369    ftk_widget_show_all(thiz, 1);
370
371	ftk_main_loop_run(priv->main_loop);
372
373    ftk_set_main_loop(prev_main_loop);
374
375	ftk_main_loop_destroy(priv->main_loop);
376	priv->main_loop = NULL;
377
378	return ftk_widget_id(ftk_window_get_focus(thiz));
379}
380
381int ftk_dialog_get_title_height(void)
382{
383	static int title_height = 0;
384	if(title_height == 0)
385	{
386		FtkBitmap* title_bg = ftk_theme_load_image(ftk_default_theme(), "dialog_title_bg"FTK_STOCK_IMG_SUFFIX);
387		title_height =  ftk_bitmap_height(title_bg);
388		ftk_bitmap_unref(title_bg);
389	}
390
391	return title_height;
392}
393