Tizen 2.1 base
[platform/core/uifw/ise-engine-sunpinyin.git] / wrapper / xim / ui.c
1 /*
2  * Copyright (c) 2010 Mike Qin <mikeandmore@gmail.com>
3  *
4  * The contents of this file are subject to the terms of either the GNU Lesser
5  * General Public License Version 2.1 only ("LGPL") or the Common Development and
6  * Distribution License ("CDDL")(collectively, the "License"). You may not use this
7  * file except in compliance with the License. You can obtain a copy of the CDDL at
8  * http://www.opensource.org/licenses/cddl1.php and a copy of the LGPLv2.1 at
9  * http://www.opensource.org/licenses/lgpl-license.php. See the License for the
10  * specific language governing permissions and limitations under the License. When
11  * distributing the software, include this License Header Notice in each file and
12  * include the full text of the License in the License file as well as the
13  * following notice:
14  *
15  * NOTICE PURSUANT TO SECTION 9 OF THE COMMON DEVELOPMENT AND DISTRIBUTION LICENSE
16  * (CDDL)
17  * For Covered Software in this distribution, this License shall be governed by the
18  * laws of the State of California (excluding conflict-of-law provisions).
19  * Any litigation relating to this License shall be subject to the jurisdiction of
20  * the Federal Courts of the Northern District of California and the state courts
21  * of the State of California, with venue lying in Santa Clara County, California.
22  *
23  * Contributor(s):
24  *
25  * If you wish your version of this file to be governed by only the CDDL or only
26  * the LGPL Version 2.1, indicate your decision by adding "[Contributor]" elects to
27  * include this software in this distribution under the [CDDL or LGPL Version 2.1]
28  * license." If you don't indicate a single choice of license, a recipient has the
29  * option to distribute your version of this file under either the CDDL or the LGPL
30  * Version 2.1, or to extend the choice of license to its licensees as provided
31  * above. However, if you add LGPL Version 2.1 code and therefore, elected the LGPL
32  * Version 2 license, then the option applies only if the new code is made subject
33  * to such option by the copyright holder.
34  */
35
36 #include <gtk/gtk.h>
37 #include "ic.h"
38 #include "common.h"
39 #include "ui.h"
40
41 #define ENG_ICON SUNPINYIN_XIM_ICON_DIR"/eng.svg"
42 #define HAN_ICON SUNPINYIN_XIM_ICON_DIR"/han.svg"
43 #define LOGO_FILE_BIG SUNPINYIN_XIM_ICON_DIR"/sunpinyin-logo-big.png"
44
45 #define SYSTEM_SKIN_DIR SUNPINYIN_XIM_SETTING_DIR"/skins"
46 #define USER_SKIN_DIR "%s/.sunpinyin/xim_skins"
47
48
49 static GtkStatusIcon* icbar_tray;
50 static GtkWidget* popup_menu;
51
52 static void
53 show_ui_about(GtkWidget* wid, gpointer user_data)
54 {
55     GError* error = NULL;
56     GdkPixbuf* logo_pixbuf =
57         gdk_pixbuf_new_from_file(LOGO_FILE_BIG, &error);
58
59     gtk_show_about_dialog(NULL,
60                           "program-name", XIM_PROGRAM_NAME,
61                           "logo", logo_pixbuf,
62                           "version", XIM_VERSION,
63                           "website", XIM_WEBSITE,
64                           "comments", XIM_COMMENTS,
65                           NULL);
66 }
67
68 static void
69 launch_preferences(GtkWidget* wid, gpointer user_data)
70 {
71     system("xsunpinyin-preferences&");
72 }
73
74 static void
75 status_icon_popup_menu(GtkStatusIcon *status_icon, guint button,
76                        guint activate_time, gpointer user_data)
77 {
78     gtk_widget_show_all(popup_menu);
79     gtk_menu_popup(GTK_MENU(popup_menu), NULL, NULL,
80                    gtk_status_icon_position_menu, status_icon,
81                    button, activate_time);
82 }
83
84 void
85 ui_tray_init(void)
86 {
87     icbar_tray = gtk_status_icon_new_from_file(ENG_ICON);
88     GtkWidget* setting_menu_item =
89         gtk_image_menu_item_new_from_stock(GTK_STOCK_PREFERENCES, NULL);
90     g_signal_connect(setting_menu_item, "activate",
91                      G_CALLBACK(launch_preferences), NULL);
92
93     GtkWidget* about_menu_item =
94         gtk_image_menu_item_new_from_stock(GTK_STOCK_ABOUT, NULL);
95     g_signal_connect(about_menu_item, "activate",
96                      G_CALLBACK(show_ui_about), NULL);
97
98     /* construct the popup menu */
99     popup_menu = gtk_menu_new();
100     gtk_menu_shell_append(GTK_MENU_SHELL(popup_menu), setting_menu_item);
101     gtk_menu_shell_append(GTK_MENU_SHELL(popup_menu), about_menu_item);
102
103     g_signal_connect(icbar_tray, "popup-menu",
104                      G_CALLBACK(status_icon_popup_menu), NULL);
105 }
106
107 void
108 ui_tray_refresh(void)
109 {
110     IC* ic = icmgr_get_current();
111     const char* filepath = HAN_ICON;
112     if (ic == NULL || !ic->is_enabled || ic->is_english) {
113         filepath = ENG_ICON;
114     }
115     gtk_status_icon_set_from_file(icbar_tray, filepath);
116 }
117
118 GtkWidget*
119 ui_create_window()
120 {
121     GtkWidget* window = gtk_window_new(GTK_WINDOW_POPUP);
122     gtk_window_set_decorated(GTK_WINDOW(window), false);
123     gtk_window_set_deletable(GTK_WINDOW(window), false);
124     gtk_window_set_accept_focus(GTK_WINDOW(window), false);
125     gtk_window_set_focus_on_map(GTK_WINDOW(window), false);
126     gtk_window_set_keep_above(GTK_WINDOW(window), true);
127     gtk_window_set_skip_pager_hint(GTK_WINDOW(window), true);
128     gtk_window_set_skip_taskbar_hint(GTK_WINDOW(window), true);
129     return window;
130 }
131
132 static GdkPixbuf*
133 load_pixbuf(const char* skin_name, const char* filename, gboolean sys_dir)
134 {
135     char filepath[256];
136     if (sys_dir) {
137         snprintf(filepath, 256, SYSTEM_SKIN_DIR"/%s/%s.png", skin_name,
138                  filename);
139     } else {
140         snprintf(filepath, 256, USER_SKIN_DIR"/%s/%s.png", getenv("HOME"),
141                  skin_name, filename);
142     }
143     return gdk_pixbuf_new_from_file(filepath, NULL);
144 }
145
146 #define FILL_PIXBUF(name)                       \
147     info->name = load_pixbuf(skin_name, name, sys_dir)
148
149 static void
150 fill_button_pixbuf(skin_button_info_t* info, const char* skin_name,
151                    gboolean sys_dir, const char* normal1, const char* normal2,
152                    const char* highlight1, const char* highlight2,
153                    const char* pressdown1, const char* pressdown2)
154 {
155     FILL_PIXBUF(normal1);
156     FILL_PIXBUF(normal2);
157     FILL_PIXBUF(highlight1);
158     FILL_PIXBUF(highlight2);
159     FILL_PIXBUF(pressdown1);
160     FILL_PIXBUF(pressdown2);
161 }
162
163 static void
164 fill_label_info(skin_label_info_t* info, FILE* fp)
165 {
166     fscanf(fp, "%d %d\n", &(info->x), &(info->y));
167     fgets(info->font, 256, fp);
168     /* remove the last \n */
169     info->font[strlen(info->font) - 1] = 0;
170
171     fscanf(fp, "%lf %lf %lf %lf\n", &(info->color_r), &(info->color_g),
172            &(info->color_b), &(info->color_a));
173 }
174
175 skin_info_t*
176 ui_skin_new(const char* skin_name)
177 {
178     char filepath[256];
179     gboolean sys_dir = TRUE;
180     snprintf(filepath, 256, SYSTEM_SKIN_DIR"/%s/info", skin_name);
181     FILE* fp = fopen(filepath, "r");
182     if (!fp) {
183         sys_dir = FALSE;
184         snprintf(filepath, 256, USER_SKIN_DIR"/%s/info", getenv("HOME"),
185                  skin_name);
186         fp = fopen(filepath, "r");
187         if (!fp) {
188             fprintf(stderr, "Cannot open skin %s\n", skin_name);
189             return NULL;
190         }
191     }
192     skin_info_t* info = malloc(sizeof(skin_info_t));
193     fscanf(fp, "%d %d %d %d %d %d\n", &(info->eng_btn.x), &(info->eng_btn.y),
194            &(info->full_btn.x), &(info->full_btn.y),
195            &(info->punc_btn.x), &(info->punc_btn.y));
196
197     fill_label_info(&(info->preedit_label), fp);
198     fill_label_info(&(info->candidate_label), fp);
199
200     fscanf(fp, "%d %d\n", &(info->offset_x), &(info->offset_y));
201     fscanf(fp, "%d %d %d %d\n", &(info->top), &(info->left), &(info->bottom),
202            &(info->right));
203
204     fclose(fp);
205
206     fill_button_pixbuf(&(info->eng_btn), skin_name, sys_dir, "eng", "han",
207                        "eng-hover", "han-hover", "eng-press", "han-press");
208     fill_button_pixbuf(&(info->full_btn), skin_name, sys_dir, "full", "half",
209                        "full-hover", "half-hover", "full-press", "half-press");
210     fill_button_pixbuf(&(info->punc_btn), skin_name, sys_dir,
211                        "han-punc", "eng-punc",
212                        "han-punc-hover", "eng-punc-hover",
213                        "han-punc-press", "eng-punc-press");
214     info->icbar_background = load_pixbuf(skin_name, "icbar", sys_dir);
215     info->preedit_background = load_pixbuf(skin_name, "preedit", sys_dir);
216     return info;
217 }
218
219 static void
220 free_button_info(skin_button_info_t* info)
221 {
222     g_object_unref(info->normal1);
223     g_object_unref(info->highlight1);
224     g_object_unref(info->pressdown1);
225     g_object_unref(info->normal2);
226     g_object_unref(info->highlight2);
227     g_object_unref(info->pressdown2);
228 }
229
230 void
231 ui_skin_destroy(skin_info_t* info)
232 {
233     g_object_unref(info->icbar_background);
234     g_object_unref(info->preedit_background);
235
236     free_button_info(&(info->eng_btn));
237     free_button_info(&(info->full_btn));
238     free_button_info(&(info->punc_btn));
239 }