d8a18a48af4f4b8a9136331dc96b2c993c5d6cb7
[platform/framework/native/uifw.git] / src / ui / controls / FUiCtrl_ContextMenuItem.cpp
1 //
2 // Open Service Platform
3 // Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
4 //
5 // Licensed under the Apache License, Version 2.0 (the License);
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 //     http://www.apache.org/licenses/LICENSE-2.0/
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17 /**
18  * @file                FUiCtrl_ContextMenuItem.cpp
19  * @brief               This is the implementation file for the _ContextMenuItem class.
20  */
21
22 #include <FBaseSysLog.h>
23 #include <FGrp_BitmapImpl.h>
24 #include "FUi_AccessibilityContainer.h"
25 #include "FUi_AccessibilityElement.h"
26 #include "FUi_CoordinateSystemUtils.h"
27 #include "FUi_Math.h"
28 #include "FUi_ResourceManager.h"
29
30 #include "FUiCtrl_ScrollPanel.h"
31 #include "FUiCtrl_ContextMenuItem.h"
32
33 using namespace Tizen::Base;
34 using namespace Tizen::Graphics;
35 using namespace Tizen::Ui;
36
37 namespace {
38 static const float TOUCH_PRESS_THRESHOLD_INSENSITIVE = 0.16f;
39 }
40
41 namespace Tizen { namespace Ui { namespace Controls
42 {
43
44 _ContextMenuItem::_ContextMenuItem(void)
45         : __type(CONTEXT_MENU_ITEM_DRAWING_TYPE_NONE)
46         , __actionId(-1)
47         , __upperDividerLine(false)
48         , __lowerDividerLine(false)
49         , __selected(false)
50         , __parentScrollEnable(false)
51         , __leftMargin(0.0f)
52         , __rightMargin(0.0f)
53         , __dividerHeight(0.0f)
54         , __bgPressedMargin(0.0f)
55         , __textSize(0.0f)
56         , __text(L"")
57         , __pMagentaBgBitmap(null)
58         , __size(FloatDimension(0.0f, 0.0f))
59         , __drawRect(FloatRectangle(0.0f, 0.0f, 0.0f, 0.0f))
60         , __pBitmapLabel(null)
61         , __pTextLabel(null)
62         , __pUpperDividerLineLabel(null)
63         , __pBackgroundLabel(null)
64         , __pLowerDividerLineLabel(null)
65 {
66         __pBitmap[CONTEXT_MENU_ITEM_DRAWING_STATUS_NORMAL] = null;
67         __pBitmap[CONTEXT_MENU_ITEM_DRAWING_STATUS_PRESSED] = null;
68         __pBitmap[CONTEXT_MENU_ITEM_DRAWING_STATUS_HIGHLIGHTED] = null;
69
70         GET_SHAPE_CONFIG(CONTEXTMENU::LIST_LEFT_MARGIN,  _CONTROL_ORIENTATION_PORTRAIT, __leftMargin);
71         GET_SHAPE_CONFIG(CONTEXTMENU::LIST_RIGHT_MARGIN, _CONTROL_ORIENTATION_PORTRAIT, __rightMargin);
72         GET_SHAPE_CONFIG(CONTEXTMENU::LIST_DIVIDER_HEIGHT, _CONTROL_ORIENTATION_PORTRAIT, __dividerHeight);
73         GET_SHAPE_CONFIG(CONTEXTMENU::ITEM_BG_PRESSED_MARGIN, _CONTROL_ORIENTATION_PORTRAIT, __bgPressedMargin);
74
75         GET_COLOR_CONFIG(CONTEXTMENU::ITEM_BG_PRESSED, __selectedBgColor);
76         GET_COLOR_CONFIG(CONTEXTMENU::LIST_ITEM_DIVIDER_01_NORMAL, __lowerDividerLineColor);    // lower divider of item n and
77         GET_COLOR_CONFIG(CONTEXTMENU::LIST_ITEM_DIVIDER_02_NORMAL, __upperDividerLineColor);    // upper divider of item n+1 are bonded together.
78         GET_BITMAP_CONFIG_N(CONTEXTMENU::ITEM_BG_PRESSED, BITMAP_PIXEL_FORMAT_ARGB8888, __pMagentaBgBitmap);
79
80         InitializeAccessibilityElement();
81 }
82
83 _ContextMenuItem::~_ContextMenuItem(void)
84 {
85         if (__pBitmap[CONTEXT_MENU_ITEM_DRAWING_STATUS_NORMAL] != null)
86         {
87                 delete __pBitmap[CONTEXT_MENU_ITEM_DRAWING_STATUS_NORMAL];
88                 __pBitmap[CONTEXT_MENU_ITEM_DRAWING_STATUS_NORMAL] = null;
89         }
90
91         if (__pBitmap[CONTEXT_MENU_ITEM_DRAWING_STATUS_PRESSED] != null)
92         {
93                 delete __pBitmap[CONTEXT_MENU_ITEM_DRAWING_STATUS_PRESSED];
94                 __pBitmap[CONTEXT_MENU_ITEM_DRAWING_STATUS_PRESSED] = null;
95         }
96
97         if (__pBitmap[CONTEXT_MENU_ITEM_DRAWING_STATUS_HIGHLIGHTED] != null)
98         {
99                 delete __pBitmap[CONTEXT_MENU_ITEM_DRAWING_STATUS_HIGHLIGHTED];
100                 __pBitmap[CONTEXT_MENU_ITEM_DRAWING_STATUS_HIGHLIGHTED] = null;
101         }
102
103         if (__pUpperDividerLineLabel != null)
104         {
105                 DetachChild(*__pUpperDividerLineLabel);
106                 delete __pUpperDividerLineLabel;
107                 __pUpperDividerLineLabel = null;
108         }
109
110         if (__pBackgroundLabel != null)
111         {
112                 DetachChild(*__pBackgroundLabel);
113                 delete __pBackgroundLabel;
114                 __pBackgroundLabel = null;
115         }
116
117         delete __pMagentaBgBitmap;
118         __pMagentaBgBitmap = null;
119
120         if (__pLowerDividerLineLabel != null)
121         {
122                 DetachChild(*__pLowerDividerLineLabel);
123                 delete __pLowerDividerLineLabel;
124                 __pLowerDividerLineLabel = null;
125         }
126
127         _AccessibilityContainer* pContainer = GetAccessibilityContainer();
128         if (pContainer)
129         {
130                 pContainer->RemoveAllElement();
131         }
132 }
133
134 _ContextMenuItem*
135 _ContextMenuItem::CreateContextMenuItemN(void)
136 {
137         ClearLastResult();
138
139         _ContextMenuItem* pItem = null;
140
141         pItem = new (std::nothrow) _ContextMenuItem();
142         if (pItem == null)
143         {
144                 SetLastResult(E_OUT_OF_MEMORY);
145                 return null;
146         }
147
148         pItem->AcquireHandle();
149
150         SetLastResult(E_SUCCESS);
151         return pItem;
152 }
153
154 void
155 _ContextMenuItem::InitializeAccessibilityElement(void)
156 {
157         _AccessibilityContainer* pContainer = GetAccessibilityContainer();
158         if (pContainer)
159         {
160                 pContainer->Activate(true);
161                 _AccessibilityElement* pElement = new (std::nothrow) _AccessibilityElement(true);
162                 SysTryReturnVoidResult(NID_UI_CTRL, pElement, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Memory shortage.");
163
164                 pElement->SetTraitWithStringId("IDS_TPLATFORM_BODY_CONTEXTUAL_POP_UP_T_TTS");
165                 pElement->SetBounds(FloatRectangle(0.0f, 0.0f, GetBoundsF().width, GetBoundsF().height));
166                 pContainer->AddElement(*pElement);
167         }
168
169         return;
170 }
171
172 void
173 _ContextMenuItem::SetBitmapLabel(_Label* pLabel)
174 {
175         __pBitmapLabel = pLabel;
176 }
177
178 void
179 _ContextMenuItem::SetTextLabel(_Label* pLabel)
180 {
181         __pTextLabel = pLabel;
182 }
183
184
185 void
186 _ContextMenuItem::SetType(ContextMenuItemDrawingType type)
187 {
188         __type = type;
189 }
190
191 ContextMenuItemDrawingType
192 _ContextMenuItem::GetType(void) const
193 {
194         return __type;
195 }
196
197 void
198 _ContextMenuItem::SetActionId(int actionId)
199 {
200         __actionId = actionId;
201 }
202
203 int
204 _ContextMenuItem::GetActionId(void) const
205 {
206         return __actionId;
207 }
208
209 void
210 _ContextMenuItem::SetUpperDivider(bool drawDivider)
211 {
212         __upperDividerLine = drawDivider;
213 }
214
215 void
216 _ContextMenuItem::SetLowerDivider(bool drawDivider)
217 {
218         __lowerDividerLine = drawDivider;
219 }
220
221 bool
222 _ContextMenuItem::HasUpperDivider(void) const
223 {
224         return __upperDividerLine;
225 }
226
227 bool
228 _ContextMenuItem::HasLowerDivider(void) const
229 {
230         return __lowerDividerLine;
231 }
232
233 void
234 _ContextMenuItem::SetTextSize(float size)
235 {
236         __textSize = size;
237 }
238
239 result
240 _ContextMenuItem::SetText(const Tizen::Base::String& text)
241 {
242         if (text.GetLength() <= 0)
243         {
244                 return E_INVALID_ARG;
245         }
246
247         __text = text;
248
249         return E_SUCCESS;
250 }
251
252 const Tizen::Base::String&
253 _ContextMenuItem::GetText(void) const
254 {
255         return __text;
256 }
257
258 result
259 _ContextMenuItem::SetBitmap(ContextMenuItemDrawingStatus status, const Tizen::Graphics::Bitmap* pBitmap)
260 {
261         if (status < CONTEXT_MENU_ITEM_DRAWING_STATUS_NORMAL || status > CONTEXT_MENU_ITEM_DRAWING_STATUS_HIGHLIGHTED)
262         {
263                 return E_INVALID_ARG;
264         }
265
266         SysTryReturn(NID_UI_CTRL, (status != CONTEXT_MENU_ITEM_DRAWING_STATUS_NORMAL || pBitmap != null), E_INVALID_ARG,
267                                 E_INVALID_ARG,
268                                 "[E_INVALID_ARG] The normal bitmap must not be null.");
269
270         Bitmap* pClonedBitmap = _BitmapImpl::CloneN(*pBitmap);
271
272         // If bitmap is in _ContextMenuItem, delete old one.
273         if (__pBitmap[status] != null)
274         {
275                 delete __pBitmap[status];
276                 __pBitmap[status] = null;
277         }
278
279         __pBitmap[status] = pClonedBitmap;
280
281         return E_SUCCESS;
282 }
283
284 const Tizen::Graphics::Bitmap*
285 _ContextMenuItem::GetBitmap(ContextMenuItemDrawingStatus status) const
286 {
287         if (status < CONTEXT_MENU_ITEM_DRAWING_STATUS_NORMAL || status > CONTEXT_MENU_ITEM_DRAWING_STATUS_HIGHLIGHTED)
288         {
289                 return null;
290         }
291
292         return __pBitmap[status];
293 }
294
295 void
296 _ContextMenuItem::SetSize(Tizen::Graphics::FloatDimension size)
297 {
298         __size = size;
299 }
300
301 Tizen::Graphics::FloatDimension
302 _ContextMenuItem::GetSize(void) const
303 {
304         return __size;
305 }
306
307 void
308 _ContextMenuItem::SetDrawRect(Tizen::Graphics::FloatRectangle rect)
309 {
310         __drawRect = rect;
311
312 }
313
314 Tizen::Graphics::FloatRectangle
315 _ContextMenuItem::GetDrawRect(void) const
316 {
317         return __drawRect;
318 }
319
320 void
321 _ContextMenuItem::SetPressedDrawRect(Tizen::Graphics::FloatRectangle rect)
322 {
323         __pressedDrawRect = rect;
324
325 }
326
327 Tizen::Graphics::FloatRectangle
328 _ContextMenuItem::GetPressedDrawRect(void) const
329 {
330         return __pressedDrawRect;
331 }
332
333 int
334 _ContextMenuItem::Release(void)
335 {
336         delete this;
337
338         return 0;
339 }
340
341 void
342 _ContextMenuItem::OnBoundsChanged(void)
343 {
344         _AccessibilityContainer* pContainer = GetAccessibilityContainer();
345         if (pContainer)
346         {
347                 _AccessibilityElement* pElement = pContainer->GetChildElement(0);
348                 if (pElement)
349                 {
350                         pElement->SetBounds(FloatRectangle(0.0f, 0.0f, GetBoundsF().width, GetBoundsF().height));
351                 }
352         }
353 }
354
355 void
356 _ContextMenuItem::OnDraw(void)
357 {
358         DrawItem();
359 }
360
361 void
362 _ContextMenuItem::DrawItem(void)
363 {
364         if (__upperDividerLine)
365         {
366                 DrawItemUpperDivider();
367         }
368
369         if (__lowerDividerLine)
370         {
371                 DrawItemLowerDivider();
372         }
373
374         DrawItemBackground();
375 }
376
377 void
378 _ContextMenuItem::DrawItemUpperDivider(void)
379 {
380         if (__pUpperDividerLineLabel == null)
381         {
382                 __pUpperDividerLineLabel = _Label::CreateLabelN();
383                 SysTryReturnVoidResult(NID_UI_CTRL, __pUpperDividerLineLabel, E_OUT_OF_MEMORY, "[%s] Propagating.", GetErrorMessage(GetLastResult()));
384
385                 FloatRectangle bounds = GetBoundsF();
386                 __pUpperDividerLineLabel->SetBounds(FloatRectangle(__leftMargin, 0.0f, bounds.width - __leftMargin - __rightMargin, __dividerHeight));
387
388                 AttachChild(*__pUpperDividerLineLabel);
389
390                 _AccessibilityContainer* pContainer = __pUpperDividerLineLabel->GetAccessibilityContainer();
391                 if (pContainer)
392                 {
393                         pContainer->Activate(false);
394                 }
395         }
396
397         Color dividerLineColor = Color(0, 0, 0, 0);
398         if (__selected == false)
399         {
400                 dividerLineColor = __upperDividerLineColor;
401         }
402
403         __pUpperDividerLineLabel->SetBackgroundColor(dividerLineColor);
404         __pUpperDividerLineLabel->Invalidate();
405 }
406
407 void
408 _ContextMenuItem::DrawItemBackground(void)
409 {
410         float topMargin = 0.0f, bottomMargin = 0.0f;
411
412         SetBackgroundColor(Color(0, 0, 0, 0));
413
414         if (__pBackgroundLabel == null)
415         {
416                 __pBackgroundLabel = _Label::CreateLabelN();
417                 SysTryReturnVoidResult(NID_UI_CTRL, __pBackgroundLabel, E_OUT_OF_MEMORY, "[%s] Propagating.", GetErrorMessage(GetLastResult()));
418
419                 __pBackgroundLabel->SetTouchPressThreshold(TOUCH_PRESS_THRESHOLD_INSENSITIVE);
420                 AttachChild(*__pBackgroundLabel);
421                 MoveChildToBottom(*__pBackgroundLabel);
422
423                 _AccessibilityContainer* pContainer = __pBackgroundLabel->GetAccessibilityContainer();
424                 if (pContainer)
425                 {
426                         pContainer->Activate(false);
427                 }
428         }
429
430         Color color= Color(0, 0, 0, 0);
431         if (__selected == true)
432         {
433                 color = __selectedBgColor;
434         }
435
436         FloatRectangle bounds = GetBoundsF();
437         _ScrollPanel* pScrollPanel = static_cast<_ScrollPanel*>(GetParent());
438         FloatRectangle boundsScrollPanel = pScrollPanel->GetBoundsF();
439
440         float topOverlap = pScrollPanel->GetScrollPosition() - bounds.y;
441         if (topOverlap > 0.0f)
442         {
443                 topMargin = topOverlap + __bgPressedMargin;
444         }
445         else if (!__upperDividerLine)
446         {
447                 topMargin = __bgPressedMargin;
448         }
449
450         float bottomOverlap = bounds.y + bounds.height - (pScrollPanel->GetScrollPosition() + boundsScrollPanel.height);
451         if (bottomOverlap > 0.0f)
452         {
453                 bottomMargin = bottomOverlap + __bgPressedMargin;
454         }
455         else if (!__lowerDividerLine)
456         {
457                 bottomMargin = __bgPressedMargin;
458         }
459
460         __pBackgroundLabel->SetBounds(FloatRectangle(__bgPressedMargin, topMargin, bounds.width - __bgPressedMargin * 2.0f, bounds.height - topMargin - bottomMargin));
461
462         Bitmap* BgBitmap = _BitmapImpl::GetColorReplacedBitmapN(*__pMagentaBgBitmap, Color::GetColor(COLOR_ID_MAGENTA), color);
463         SysTryReturnVoidResult(NID_UI_CTRL, BgBitmap, E_OUT_OF_MEMORY, "[%s] Propagating.", GetErrorMessage(GetLastResult()));
464
465         __pBackgroundLabel->SetBackgroundBitmap(*BgBitmap);
466         delete BgBitmap;
467         BgBitmap = null;
468
469         __pBackgroundLabel->Invalidate();
470 }
471
472 void
473 _ContextMenuItem::DrawItemLowerDivider(void)
474 {
475         if (__pLowerDividerLineLabel == null)
476         {
477                 __pLowerDividerLineLabel = _Label::CreateLabelN();
478                 SysTryReturnVoidResult(NID_UI_CTRL, __pLowerDividerLineLabel, E_OUT_OF_MEMORY, "[%s] Propagating.", GetErrorMessage(GetLastResult()));
479
480                 FloatRectangle bounds = GetBoundsF();
481                 __pLowerDividerLineLabel->SetBounds(FloatRectangle(__leftMargin, bounds.height - __dividerHeight, bounds.width - __leftMargin - __rightMargin, __dividerHeight));
482
483                 AttachChild(*__pLowerDividerLineLabel);
484
485                 _AccessibilityContainer* pContainer = __pLowerDividerLineLabel->GetAccessibilityContainer();
486                 if (pContainer)
487                 {
488                         pContainer->Activate(false);
489                 }
490         }
491
492         Color dividerLineColor = Color(0, 0, 0, 0);
493         if (__selected == false)
494         {
495                 dividerLineColor = __lowerDividerLineColor;
496         }
497
498         __pLowerDividerLineLabel->SetBackgroundColor(dividerLineColor);
499         __pLowerDividerLineLabel->Invalidate();
500 }
501
502 _UiTouchEventDelivery
503 _ContextMenuItem::OnPreviewTouchPressed(const _Control& source, const _TouchInfo& touchinfo)
504 {
505         SetAndInvalidate(true);
506
507         return _UI_TOUCH_EVENT_DELIVERY_FORCED_YES;
508 }
509
510 bool
511 _ContextMenuItem::OnTouchPressed(const _Control& source, const _TouchInfo& touchinfo)
512 {
513         SetAndInvalidate(true);
514
515         return false;
516 }
517
518 _UiTouchEventDelivery
519 _ContextMenuItem::OnPreviewTouchMoved(const _Control& source, const _TouchInfo& touchinfo)
520 {
521         TouchMoved(source, touchinfo);
522
523         return _UI_TOUCH_EVENT_DELIVERY_FORCED_YES;
524 }
525
526 bool
527 _ContextMenuItem::OnTouchMoved(const _Control& source, const _TouchInfo& touchinfo)
528 {
529         TouchMoved(source, touchinfo);
530
531         return false;
532 }
533
534 _UiTouchEventDelivery
535 _ContextMenuItem::OnPreviewTouchReleased(const _Control& source, const _TouchInfo& touchinfo)
536 {
537         SetAndInvalidate(false);
538
539         return _UI_TOUCH_EVENT_DELIVERY_FORCED_YES;
540 }
541
542 bool
543 _ContextMenuItem::OnTouchReleased(const _Control& source, const _TouchInfo& touchinfo)
544 {
545         SetAndInvalidate(false);
546
547         return false;
548 }
549
550 _UiTouchEventDelivery
551 _ContextMenuItem::OnPreviewTouchCanceled(const _Control& source, const _TouchInfo& touchinfo)
552 {
553         return _UI_TOUCH_EVENT_DELIVERY_FORCED_YES;
554 }
555
556 bool
557 _ContextMenuItem::OnTouchCanceled(const _Control& source, const _TouchInfo& touchinfo)
558 {
559         SetAndInvalidate(false);
560
561         return false;
562 }
563
564 void
565 _ContextMenuItem::TouchMoved(const _Control& source, const _TouchInfo& touchinfo)
566 {
567         FloatPoint touchPosition = touchinfo.GetCurrentPosition();
568
569         if (__pressed)
570         {
571                 if (__parentScrollEnable)
572                 {
573                         if (__selected)
574                         {
575                                 __selected = false;
576                                 Invalidate();
577                         }
578                 }
579                 else
580                 {
581                         int oldSelected = __selected;
582
583                         FloatRectangle bounds(0.0f, 0.0f, __size.width, __size.height);
584                         if (bounds.Contains(touchPosition))
585                         {
586                                 __selected = true;
587                         }
588                         else
589                         {
590                                 __selected = false;
591                         }
592
593                         if (oldSelected != __selected)
594                         {
595                                 Invalidate();
596                         }
597                 }
598         }
599 }
600
601 void
602 _ContextMenuItem::OnFontChanged(Tizen::Graphics::Font* pFont)
603 {
604         String fontName = _Control::GetFont();
605
606         if (__pTextLabel != null)
607         {
608                 __pTextLabel->SetFont(fontName);
609         }
610 }
611
612 void
613 _ContextMenuItem::OnFontInfoRequested(unsigned long& style, float& size)
614 {
615         style = FONT_STYLE_PLAIN;
616         size = __textSize;
617 }
618
619 void
620 _ContextMenuItem::SetParentScrollEnable(bool enable)
621 {
622         __parentScrollEnable = enable;
623 }
624
625 bool
626 _ContextMenuItem::GetParentScrollEnable() const
627 {
628         return __parentScrollEnable;
629 }
630
631 bool
632 _ContextMenuItem::IsSelected() const
633 {
634         return __selected;
635 }
636
637 void
638 _ContextMenuItem::SetAndInvalidate(bool flag)
639 {
640         __selected = flag;
641         __pressed = flag;
642         Invalidate();
643 }
644
645 const Tizen::Graphics::Bitmap*
646 _ContextMenuItem::GetMagentaBgBitmap() const
647 {
648         return __pMagentaBgBitmap;
649 }
650
651 }}} // Tizen::Ui::Controls