8494f450f307164fc4b216a498b277048b7e4e55
[framework/uifw/ise-default.git] / mcf / mcfutils.cpp
1 /*
2  * Copyright 2012  Samsung Electronics Co., Ltd
3  *
4  * Licensed under the Flora License, Version 1.0 (the License);
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.tizenopensource.org/license
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an AS IS BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17
18
19 #include <sys/time.h>
20 #include <sys/types.h>
21 #include <unistd.h>
22 #include <math.h>
23
24 #include "mcfutils.h"
25 #include "mcfconfig.h"
26 #include "mcfdebug.h"
27 #include "mcfcontext.h"
28 #include "mcfresource.h"
29 #include "mcfresourcecache.h"
30
31 using namespace mcf;
32
33 CMCFUtils* CMCFUtils::sInstance; /* For singleton */
34 #define MCF_MAX_UNIQUE_ID 1000
35
36 CMCFUtils::CMCFUtils()
37 {
38     MCF_DEBUG();
39     mXScnRate = 1.0;
40     mYScnRate = 1.0;
41     mScnResolutionX = 0;
42     mScnResolutionY = 0;
43     init();
44 }
45
46 CMCFUtils::~CMCFUtils()
47 {
48     MCF_DEBUG();
49 }
50
51 CMCFUtils* CMCFUtils::get_instance()
52 {
53     if (!sInstance) {
54         sInstance = new CMCFUtils();
55     }
56     return (CMCFUtils*)sInstance;
57 }
58
59 void
60 CMCFUtils::init()
61 {
62     MCF_DEBUG();
63     GetCMCFUtilsImpl()->get_screen_resolution(&mScnResolutionX, &mScnResolutionY);
64     mXScnRate = mScnResolutionX / (float)MCF_BASE_SCREEN_WIDTH;
65     mYScnRate = mScnResolutionY / (float)MCF_BASE_SCREEN_HEIGHT;
66     if(MCF_AUTO_DETECT_PORTRAIT_LANDSCAPE) {
67         /* If the width of screen is bigger than the height, switch portrait mode and landscape mode */
68         if(mScnResolutionX > mScnResolutionY) {
69             mXScnRate = mScnResolutionX / (float)MCF_BASE_SCREEN_HEIGHT;
70             mYScnRate = mScnResolutionY / (float)MCF_BASE_SCREEN_WIDTH;
71         }
72     }
73
74     mNinePatchInfoMap.clear();
75 }
76
77 /**
78  * Returns a scale rate (see default screen resolution in mcfconfig.h file)
79  */
80 mcffloat
81 CMCFUtils::get_smallest_scale_rate()
82 {
83     /* Try to return smaller scale rate, to avoid UI crash */
84     return (mXScnRate < mYScnRate) ? mXScnRate : mYScnRate;
85 }
86
87 /**
88 * Returns a scale rate X (see default screen resolution in mcfconfig.h file)
89 */
90 mcffloat
91 CMCFUtils::get_scale_rate_x()
92 {
93     /* Try to return smaller scale rate, to avoid UI crash */
94     return mXScnRate;
95 }
96
97 /**
98 * Returns a scale rate Y (see default screen resolution in mcfconfig.h file)
99 */
100 mcffloat
101 CMCFUtils::get_scale_rate_y()
102 {
103     /* Try to return smaller scale rate, to avoid UI crash */
104     return mYScnRate;
105 }
106
107 /**
108  * Recalculates x value according to the current screen resolution
109  */
110 void
111 CMCFUtils::scale_x(mcf16 *x)
112 {
113     if (x) {
114         ((*x)*=mXScnRate);
115     }
116 }
117
118 /**
119 * Recalculates y value according to the current screen resolution
120  */
121 void
122 CMCFUtils::scale_y(mcf16 *y)
123 {
124     if (y) {
125         ((*y)*=mYScnRate);
126     }
127 }
128
129 /**
130  * Returns a calculated x value according to the current screen resolution
131  */
132 mcf16
133 CMCFUtils::get_scale_x(mcf16 x)
134 {
135     return static_cast<mcf16>(x*mXScnRate);
136 }
137
138 /**
139  * Returns a calculated y value according to the current screen resolution
140  */
141 mcf16
142 CMCFUtils::get_scale_y(mcf16 y)
143 {
144     return static_cast<mcf16>(y*mYScnRate);
145 }
146
147 /**
148  * portable sleep function
149  */
150 mcfboolean
151 CMCFUtils::sleep(mcfulong msc)
152 {
153     MCF_DEBUG();
154     fd_set dummy;
155     struct timeval toWait;
156     FD_ZERO(&dummy);
157     toWait.tv_sec = msc / 1000;
158     toWait.tv_usec = (msc % 1000) * 1000;
159     select(0, &dummy, NULL, NULL, &toWait);
160     return TRUE;
161 }
162
163 /**
164  * returns the composed path
165  */
166 mcfchar*
167 CMCFUtils::get_composed_path(mcfchar* buf, int bufLength, const mcfchar* path)
168 {
169     MCF_DEBUG();
170
171     if(buf && path) {
172         if(mScnResolutionX == 0 || mScnResolutionY == 0) {
173             CMCFUtilsImpl *impl = GetCMCFUtilsImpl();
174             if(impl) {
175                 impl->get_screen_resolution(&mScnResolutionX, &mScnResolutionY);
176             }
177         }
178
179         const mcfchar *themename = NULL;
180         CMCFResourceCache *cache = CMCFResourceCache::get_instance();
181         if(cache) {
182             themename = cache->get_cur_themename();
183             if (themename == NULL) {
184                 themename = DEFAULT_THEME;
185             } else if (strlen(themename) == 0) {
186                 themename = DEFAULT_THEME;
187             }
188         }
189
190         mcfboolean file_exists = FALSE;
191         snprintf(buf, bufLength, "%s/%dx%d/%s/%s", IMG_PATH_PREFIX, mScnResolutionX, mScnResolutionY, themename, path);
192         if(access(buf, R_OK) == 0) {
193             file_exists = TRUE;
194         }
195
196         /* Check if the file exists in the current theme directory */
197         if (!file_exists && themename != DEFAULT_THEME) {
198             /* Use default theme name if not found */
199             snprintf(buf, bufLength, "%s/%dx%d/%s/%s", IMG_PATH_PREFIX, mScnResolutionX, mScnResolutionY, DEFAULT_THEME, path);
200             if(access(buf, R_OK) == 0) {
201                 file_exists = TRUE;
202             }
203         }
204
205         /* FIXME : Should look for what other resolutions are available */
206         /* If the file still doesn't exist, look for the file in different resolution */
207         if (!file_exists) {
208             /* Use default theme name if not found */
209             snprintf(buf, bufLength, "%s/%dx%d/%s/%s", IMG_PATH_PREFIX, MCF_BASE_SCREEN_WIDTH,
210                          MCF_BASE_SCREEN_HEIGHT, DEFAULT_THEME, path);
211             if(access(buf, R_OK) == 0) {
212                 file_exists = TRUE;
213             }
214         }
215
216         /* Or maybe the path points the absolute path */
217         if (!file_exists) {
218             snprintf(buf, bufLength, "%s", path);
219         }
220     }
221
222   return buf;
223 }
224
225 mcfboolean
226 CMCFUtils::get_autopopup_window_variables(mcfchar * const autopopupKeys[MAX_SIZE_OF_AUTOPOPUP_STRING], mcfbyte *numKeys,
227                                                   mcfbyte *numColumns, mcfbyte *numRows, mcfint *width, mcfint *height)
228 {
229     MCF_DEBUG();
230     mcf_assert_return_false(autopopupKeys);
231     mcf_assert_return_false(numKeys && numColumns && numRows && width && height);
232
233     int loop;
234     mcfboolean ret = FALSE;
235     mcfint scrx, scry;
236
237     if (autopopupKeys && numKeys && numColumns && numRows && width && height) {
238         *numKeys = 0;
239         for (loop = 0;loop < MAX_SIZE_OF_AUTOPOPUP_STRING;loop++) {
240             if (autopopupKeys[loop]) {
241                 if (strlen(autopopupKeys[loop]) > 0) {
242                     (*numKeys)++;
243                 }
244             }
245         }
246         if(*numKeys > 0) {
247             ret = TRUE;
248         }
249
250         this->get_screen_resolution(&scrx, &scry);
251
252         CMCFContext *context = CMCFContext::get_instance();
253
254         *numColumns = (scrx - (2 * mcf_autopopup_configure.bgPadding)) /
255                       (mcf_autopopup_configure.btnWidth + mcf_autopopup_configure.btnSpacing);
256         if (*numColumns > mcf_autopopup_configure.maxColumn && mcf_autopopup_configure.maxColumn > 0)
257             *numColumns = mcf_autopopup_configure.maxColumn;
258         *numRows = ((*numKeys - 1) / *numColumns) + 1;
259         if (*numColumns > *numKeys) *numColumns = *numKeys;
260
261         /* Try to spread evenly on each lines */
262         *numColumns = (*numKeys) / (*numRows);
263         if ((*numKeys) % *numRows != 0) (*numColumns)++;
264
265         *width =
266             (*numColumns * mcf_autopopup_configure.btnWidth) +
267             (2 * mcf_autopopup_configure.bgPadding) +
268             ((*numColumns - 1) * mcf_autopopup_configure.btnSpacing);
269         *height =
270             (*numRows * mcf_autopopup_configure.btnHeight) +
271             (2 * mcf_autopopup_configure.bgPadding) +
272             ((*numRows - 1) * mcf_autopopup_configure.btnSpacing);
273
274         *width += (2 * mcf_autopopup_configure.wndDecoSize);
275         *height += (2 * mcf_autopopup_configure.wndDecoSize);
276     }
277
278     return ret;
279 }
280
281 /**
282  * Returns a duplicated string pointer by given str
283  */
284 mcfchar*
285 CMCFUtils::get_str_dup(const mcfchar* str)
286 {
287     MCF_DEBUG();
288     mcfchar *new_str;
289     mcfint length;
290
291     if (str) {
292         length = strlen(str) + 1;
293         new_str = (mcfchar*)malloc(length);
294         memcpy(new_str, str, length);
295         new_str[length - 1] = '\0';
296     } else {
297         new_str = NULL;
298     }
299
300     return new_str;
301 }
302
303 /**
304  * Returns an unique ID
305  */
306 mcf16
307 CMCFUtils::get_unique_id()
308 {
309     MCF_DEBUG();
310     static mcf16 uniId;
311     if (uniId < MCF_MAX_UNIQUE_ID) {
312         uniId++;
313     } else {
314         uniId = 0;
315     }
316     return uniId;
317 }
318
319 mcfboolean
320 CMCFUtils::is_rect_overlap(McfRectangle rect1, McfRectangle rect2)
321 {
322     if (rect1.x < rect2.x + rect2.width && rect1.x + rect1.width > rect2.x &&
323             rect1.y < rect2.y + rect2.height && rect1.y + rect1.height > rect2.y) {
324         return true;
325     }
326     return false;
327 }
328
329 mcffloat
330 CMCFUtils::get_distance( mcfint x1, mcfint y1, mcfint x2, mcfint y2 )
331 {
332     mcfint dx = x1 - x2;
333     mcfint dy = y1 - y2;
334     return sqrt((dx * dx) + (dy * dy));
335 }
336
337 mcffloat
338 CMCFUtils::get_distance( McfPoint pt1, McfPoint pt2 )
339 {
340     return get_distance(pt1.x, pt1.y, pt2.x, pt2.y);
341 }
342
343 mcffloat
344 CMCFUtils::get_approximate_distance( mcfint x1, mcfint y1, mcfint x2, mcfint y2 )
345 {
346     mcfint dx = abs(x1 - x2);
347     mcfint dy = abs(y1 - y2);
348     return dx + dy;
349 }
350
351 mcffloat
352 CMCFUtils::get_approximate_distance( McfPoint pt1, McfPoint pt2 )
353 {
354     return get_approximate_distance(pt1.x, pt1.y, pt2.x, pt2.y);
355 }
356
357 const McfNinePatchInfo*
358 CMCFUtils::get_nine_patch_info(const mcfchar *imgPath)
359 {
360     MCF_DEBUG();
361
362     if(!imgPath) return NULL;
363
364     /* FIXME : This is implemented in very inefficient way. Should optimize later. */
365     for (int loop = 0;loop < (sizeof(mcf_nine_patch_info) / sizeof(McfNinePatchInfo));loop++) {
366         mcfchar buf[_POSIX_PATH_MAX];
367         get_composed_path(buf, sizeof(buf), mcf_nine_patch_info[loop].imgPath);
368         if (strcmp(buf, imgPath) == 0) {
369             return &mcf_nine_patch_info[loop];
370         }
371     }
372
373     return NULL;
374 }
375
376 mcfint CMCFUtils::log(const mcfchar *fmt, ...)
377 {
378     MCF_DEBUG();
379     va_list argptr;
380     mcfint ret = 0;
381
382     va_start(argptr, fmt);
383     CMCFUtilsImpl *impl = GetCMCFUtilsImpl();
384     if(impl) {
385         ret = impl->log(fmt, argptr);
386     }
387     va_end(argptr);
388
389     return ret;
390 }