/src/ftk_input_method_preeditor_default.c

http://ftk.googlecode.com/ · C · 296 lines · 211 code · 56 blank · 29 comment · 19 complexity · c2a7df526f2583e5deff34818411bcac MD5 · raw file

  1. /*
  2. * File: ftk_input_method_preeditor.h
  3. * Author: Li XianJing <xianjimli@hotmail.com>
  4. * Brief: default implementation of input candidate selector.
  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. * History:
  26. * ================================================================
  27. * 2010-02-11 Li XianJing <xianjimli@hotmail.com> created
  28. *
  29. */
  30. #include "ftk_button.h"
  31. #include "ftk_window.h"
  32. #include "ftk_globals.h"
  33. #include "ftk_list_view.h"
  34. #include "ftk_text_buffer.h"
  35. #include "ftk_list_model_default.h"
  36. #include "ftk_list_render_default.h"
  37. #include "ftk_input_method_preeditor.h"
  38. typedef struct _InputMethodPreeditorPrivInfo
  39. {
  40. FtkWidget* widget;
  41. FtkWidget* editor;
  42. FtkListModel* model;
  43. FtkWidget* raw_text_button;
  44. FtkTextBuffer* text_buffer;
  45. }PrivInfo;
  46. #define IDC_RAW_TEXT 1000
  47. #define IDC_CANDIDATES 1001
  48. #define FTK_IM_PREEDITOR_WIDTH 120
  49. #define FTK_IM_PREEDITOR_ITEM_HEIGHT 20
  50. #define FTK_ROW_HEIGHT (FTK_FONT_SIZE + 2 * FTK_V_MARGIN)
  51. static Ret ftk_popup_on_raw_text_clicked(void* ctx, void* button)
  52. {
  53. PrivInfo* priv = (PrivInfo*)ctx;
  54. FtkEvent event;
  55. ftk_event_init(&event, FTK_EVT_IM_COMMIT);
  56. event.widget = priv->editor;
  57. event.u.extra = (char*)ftk_widget_get_text((FtkWidget*)button);
  58. ftk_widget_event(priv->editor, &event);
  59. ftk_widget_show_all(ftk_widget_toplevel((FtkWidget*)button), 0);
  60. ftk_widget_set_text((FtkWidget*)button, "");
  61. return RET_OK;
  62. }
  63. static Ret ftk_popup_on_item_clicked(void* ctx, void* list)
  64. {
  65. PrivInfo* priv = (PrivInfo*)ctx;
  66. FtkListItemInfo* info = NULL;
  67. FtkListModel* model = priv->model;
  68. int i = ftk_list_view_get_selected((FtkWidget*)list);
  69. ftk_list_model_get_data(model, i, (void**)&info);
  70. if(info != NULL)
  71. {
  72. FtkEvent event;
  73. ftk_event_init(&event, FTK_EVT_IM_COMMIT);
  74. event.widget = priv->editor;
  75. event.u.extra = (void*)info->text;
  76. ftk_widget_event(priv->editor, &event);
  77. }
  78. ftk_widget_show_all(ftk_widget_toplevel((FtkWidget*)list), 0);
  79. return RET_OK;
  80. }
  81. static Ret ftk_input_method_preeditor_default_resize(FtkImPreeditor* thiz, int candidate_nr, FtkPoint* caret)
  82. {
  83. int x = 0;
  84. int y = 0;
  85. int w = 0;
  86. int h = 0;
  87. DECL_PRIV(thiz, priv);
  88. FtkRect work_rect = {0};
  89. FtkWidget* widget = priv->widget;
  90. w = FTK_IM_PREEDITOR_WIDTH;
  91. h = (candidate_nr + 1) * FTK_IM_PREEDITOR_ITEM_HEIGHT + 2 * FTK_V_MARGIN;
  92. ftk_wnd_manager_get_work_area(ftk_default_wnd_manager(), &work_rect);
  93. if((caret->y + h + FTK_ROW_HEIGHT) <= (work_rect.y + work_rect.height))
  94. {
  95. y = caret->y + FTK_ROW_HEIGHT;
  96. }
  97. else
  98. {
  99. y = caret->y - h;
  100. }
  101. if((caret->x + w) <= (work_rect.x + work_rect.width))
  102. {
  103. x = caret->x;
  104. }
  105. else
  106. {
  107. x = work_rect.x + work_rect.width - w;
  108. }
  109. ftk_widget_move_resize(widget, x, y, w, h);
  110. ftk_widget_move_resize(ftk_widget_lookup(widget, IDC_RAW_TEXT), 0,
  111. 0, w, FTK_IM_PREEDITOR_ITEM_HEIGHT);
  112. ftk_widget_move_resize(ftk_widget_lookup(widget, IDC_CANDIDATES), 0,
  113. FTK_IM_PREEDITOR_ITEM_HEIGHT, w, h - FTK_IM_PREEDITOR_ITEM_HEIGHT);
  114. return RET_OK;
  115. }
  116. static Ret ftk_input_method_preeditor_default_reset(FtkImPreeditor* thiz)
  117. {
  118. DECL_PRIV(thiz, priv);
  119. return_val_if_fail(thiz != NULL, RET_FAIL);
  120. ftk_list_model_reset(priv->model);
  121. ftk_text_buffer_reset(priv->text_buffer);
  122. ftk_widget_set_text(priv->raw_text_button, " ");
  123. return RET_OK;
  124. }
  125. static Ret ftk_input_method_preeditor_default_set_editor(FtkImPreeditor* thiz, FtkWidget* editor)
  126. {
  127. DECL_PRIV(thiz, priv);
  128. return_val_if_fail(thiz != NULL && editor != NULL, RET_FAIL);
  129. priv->editor = editor;
  130. return RET_OK;
  131. }
  132. static Ret ftk_input_method_preeditor_default_set_raw_text(FtkImPreeditor* thiz, const char* text)
  133. {
  134. DECL_PRIV(thiz, priv);
  135. return_val_if_fail(priv != NULL, RET_FAIL);
  136. ftk_widget_set_text(priv->raw_text_button, text);
  137. return RET_OK;
  138. }
  139. static Ret ftk_input_method_preeditor_default_add_candidate(FtkImPreeditor* thiz, const char* text)
  140. {
  141. FtkListItemInfo info = {0};
  142. DECL_PRIV(thiz, priv);
  143. return_val_if_fail(priv != NULL && text != NULL, RET_FAIL);
  144. info.user_data = thiz;
  145. info.type = FTK_LIST_ITEM_NORMAL;
  146. info.text = ftk_text_buffer_append_string(priv->text_buffer, text);
  147. return ftk_list_model_add(priv->model, &info);
  148. }
  149. static void ftk_input_method_preeditor_default_destroy(FtkImPreeditor* thiz)
  150. {
  151. DECL_PRIV(thiz, priv);
  152. if(thiz != NULL)
  153. {
  154. ftk_list_model_unref(priv->model);
  155. ftk_text_buffer_destroy(priv->text_buffer);
  156. FTK_FREE(thiz);
  157. }
  158. return;
  159. }
  160. static Ret ftk_input_method_preeditor_default_hide(FtkImPreeditor* thiz)
  161. {
  162. DECL_PRIV(thiz, priv);
  163. return_val_if_fail(thiz != NULL, RET_FAIL);
  164. ftk_widget_show_all(priv->widget, 0);
  165. return RET_OK;
  166. }
  167. static Ret ftk_input_method_preeditor_default_show(FtkImPreeditor* thiz, FtkPoint* caret)
  168. {
  169. DECL_PRIV(thiz, priv);
  170. int candidate_nr = 0;
  171. return_val_if_fail(thiz != NULL, RET_FAIL);
  172. ftk_wnd_manager_restack(ftk_default_wnd_manager(), priv->widget, FTK_MAX_WINDOWS);
  173. candidate_nr = ftk_list_model_get_total(priv->model);
  174. candidate_nr = FTK_MIN(candidate_nr, FTK_IM_PREEDITOR_MAX_ROW);
  175. ftk_input_method_preeditor_default_resize(thiz, candidate_nr, caret);
  176. ftk_widget_show_all(priv->widget, 1);
  177. return RET_OK;
  178. }
  179. FtkImPreeditor* ftk_input_method_preeditor_default_create(void)
  180. {
  181. int x = 0;
  182. int y = 0;
  183. FtkGc gc = {0};
  184. FtkWidget* list = NULL;
  185. FtkWidget* button = NULL;
  186. FtkWidget* popup = NULL;
  187. FtkListModel* model = NULL;
  188. FtkListRender* render = NULL;
  189. FtkImPreeditor* thiz = NULL;
  190. int w = FTK_IM_PREEDITOR_WIDTH;
  191. int h = FTK_IM_PREEDITOR_ITEM_HEIGHT * FTK_IM_PREEDITOR_MAX_ROW;
  192. model = ftk_list_model_default_create(10);
  193. return_val_if_fail(model != NULL, NULL);
  194. popup = ftk_window_create(FTK_WINDOW_MISC, 0, x, y, w, h);
  195. ftk_window_set_animation_hint(popup, "im_preeditor");
  196. ftk_widget_set_text(popup, "im preeditor");
  197. render = ftk_list_render_default_create();
  198. button = ftk_button_create(popup, 0, 0, w, FTK_IM_PREEDITOR_ITEM_HEIGHT);
  199. ftk_widget_set_id(button, IDC_RAW_TEXT);
  200. ftk_widget_unset_attr(button, FTK_ATTR_TRANSPARENT);
  201. gc.mask = FTK_GC_BG | FTK_GC_FG | FTK_GC_FONT;
  202. gc.font = ftk_default_font();
  203. gc.bg = ftk_theme_get_bg_color(ftk_default_theme(), FTK_BUTTON, FTK_WIDGET_NORMAL);
  204. gc.fg = ftk_theme_get_fg_color(ftk_default_theme(), FTK_BUTTON, FTK_WIDGET_NORMAL);
  205. ftk_widget_reset_gc(button, FTK_WIDGET_NORMAL, &gc);
  206. gc.bg = ftk_theme_get_bg_color(ftk_default_theme(), FTK_BUTTON, FTK_WIDGET_FOCUSED);
  207. gc.fg = ftk_theme_get_fg_color(ftk_default_theme(), FTK_BUTTON, FTK_WIDGET_FOCUSED);
  208. ftk_widget_reset_gc(button, FTK_WIDGET_FOCUSED, &gc);
  209. gc.bg = ftk_theme_get_bg_color(ftk_default_theme(), FTK_BUTTON, FTK_WIDGET_ACTIVE);
  210. gc.fg = ftk_theme_get_fg_color(ftk_default_theme(), FTK_BUTTON, FTK_WIDGET_ACTIVE);
  211. ftk_widget_reset_gc(button, FTK_WIDGET_ACTIVE, &gc);
  212. list = ftk_list_view_create(popup, 0, FTK_IM_PREEDITOR_ITEM_HEIGHT,
  213. w, h - FTK_IM_PREEDITOR_ITEM_HEIGHT);
  214. ftk_widget_set_id(list, IDC_CANDIDATES);
  215. ftk_window_set_focus(popup, list);
  216. ftk_list_view_init(list, model, render, FTK_IM_PREEDITOR_ITEM_HEIGHT);
  217. thiz = FTK_NEW_PRIV(FtkImPreeditor);
  218. if(thiz != NULL)
  219. {
  220. DECL_PRIV(thiz, priv);
  221. thiz->hide = ftk_input_method_preeditor_default_hide;
  222. thiz->show = ftk_input_method_preeditor_default_show;
  223. thiz->reset = ftk_input_method_preeditor_default_reset;
  224. thiz->set_editor = ftk_input_method_preeditor_default_set_editor;
  225. thiz->set_raw_text = ftk_input_method_preeditor_default_set_raw_text;
  226. thiz->add_candidate = ftk_input_method_preeditor_default_add_candidate;
  227. thiz->destroy = ftk_input_method_preeditor_default_destroy;
  228. priv->model = model;
  229. priv->widget = popup;
  230. priv->raw_text_button = button;
  231. priv->text_buffer = ftk_text_buffer_create(1024);
  232. ftk_button_set_clicked_listener(button, ftk_popup_on_raw_text_clicked, priv);
  233. ftk_list_view_set_clicked_listener(list, ftk_popup_on_item_clicked, priv);
  234. }
  235. else
  236. {
  237. ftk_widget_unref(popup);
  238. }
  239. return thiz;
  240. }