Changed indicator bg color.
[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         if (__pTextLabel != null)
128         {
129                 DetachChild(*__pTextLabel);
130                 delete __pTextLabel;
131                 __pTextLabel = null;
132         }
133
134         if (__pBitmapLabel != null)
135         {
136                 DetachChild(*__pBitmapLabel);
137                 delete __pBitmapLabel;
138                 __pBitmapLabel = null;
139         }
140
141         _AccessibilityContainer* pContainer = GetAccessibilityContainer();
142         if (pContainer)
143         {
144                 pContainer->RemoveAllElement();
145         }
146 }
147
148 _ContextMenuItem*
149 _ContextMenuItem::CreateContextMenuItemN(void)
150 {
151         ClearLastResult();
152
153         _ContextMenuItem* pItem = null;
154
155         pItem = new (std::nothrow) _ContextMenuItem();
156         if (pItem == null)
157         {
158                 SetLastResult(E_OUT_OF_MEMORY);
159                 return null;
160         }
161
162         pItem->AcquireHandle();
163
164         SetLastResult(E_SUCCESS);
165         return pItem;
166 }
167
168 void
169 _ContextMenuItem::InitializeAccessibilityElement(void)
170 {
171         _AccessibilityContainer* pContainer = GetAccessibilityContainer();
172         if (pContainer)
173         {
174                 pContainer->Activate(true);
175                 _AccessibilityElement* pElement = new (std::nothrow) _AccessibilityElement(true);
176                 SysTryReturnVoidResult(NID_UI_CTRL, pElement, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Memory shortage.");
177
178                 pElement->SetTraitWithStringId("IDS_TPLATFORM_BODY_CONTEXTUAL_POP_UP_T_TTS");
179                 pElement->SetBounds(FloatRectangle(0.0f, 0.0f, GetBoundsF().width, GetBoundsF().height));
180                 pContainer->AddElement(*pElement);
181         }
182
183         return;
184 }
185
186 void
187 _ContextMenuItem::SetBitmapLabel(_Label* pLabel)
188 {
189         __pBitmapLabel = pLabel;
190 }
191
192 void
193 _ContextMenuItem::SetTextLabel(_Label* pLabel)
194 {
195         __pTextLabel = pLabel;
196 }
197
198
199 void
200 _ContextMenuItem::SetType(ContextMenuItemDrawingType type)
201 {
202         __type = type;
203 }
204
205 ContextMenuItemDrawingType
206 _ContextMenuItem::GetType(void) const
207 {
208         return __type;
209 }
210
211 void
212 _ContextMenuItem::SetActionId(int actionId)
213 {
214         __actionId = actionId;
215 }
216
217 int
218 _ContextMenuItem::GetActionId(void) const
219 {
220         return __actionId;
221 }
222
223 void
224 _ContextMenuItem::SetUpperDivider(bool drawDivider)
225 {
226         __upperDividerLine = drawDivider;
227 }
228
229 void
230 _ContextMenuItem::SetLowerDivider(bool drawDivider)
231 {
232         __lowerDividerLine = drawDivider;
233 }
234
235 bool
236 _ContextMenuItem::HasUpperDivider(void) const
237 {
238         return __upperDividerLine;
239 }
240
241 bool
242 _ContextMenuItem::HasLowerDivider(void) const
243 {
244         return __lowerDividerLine;
245 }
246
247 void
248 _ContextMenuItem::SetTextSize(float size)
249 {
250         __textSize = size;
251 }
252
253 result
254 _ContextMenuItem::SetText(const Tizen::Base::String& text)
255 {
256         if (text.GetLength() <= 0)
257         {
258                 return E_INVALID_ARG;
259         }
260
261         __text = text;
262
263         return E_SUCCESS;
264 }
265
266 const Tizen::Base::String&
267 _ContextMenuItem::GetText(void) const
268 {
269         return __text;
270 }
271
272 result
273 _ContextMenuItem::SetBitmap(ContextMenuItemDrawingStatus status, const Tizen::Graphics::Bitmap* pBitmap)
274 {
275         if (status < CONTEXT_MENU_ITEM_DRAWING_STATUS_NORMAL || status > CONTEXT_MENU_ITEM_DRAWING_STATUS_HIGHLIGHTED)
276         {
277                 return E_INVALID_ARG;
278         }
279
280         SysTryReturn(NID_UI_CTRL, (status != CONTEXT_MENU_ITEM_DRAWING_STATUS_NORMAL || pBitmap != null), E_INVALID_ARG,
281                                 E_INVALID_ARG,
282                                 "[E_INVALID_ARG] The normal bitmap must not be null.");
283
284         Bitmap* pClonedBitmap = _BitmapImpl::CloneN(*pBitmap);
285
286         // If bitmap is in _ContextMenuItem, delete old one.
287         if (__pBitmap[status] != null)
288         {
289                 delete __pBitmap[status];
290                 __pBitmap[status] = null;
291         }
292
293         __pBitmap[status] = pClonedBitmap;
294
295         return E_SUCCESS;
296 }
297
298 const Tizen::Graphics::Bitmap*
299 _ContextMenuItem::GetBitmap(ContextMenuItemDrawingStatus status) const
300 {
301         if (status < CONTEXT_MENU_ITEM_DRAWING_STATUS_NORMAL || status > CONTEXT_MENU_ITEM_DRAWING_STATUS_HIGHLIGHTED)
302         {
303                 return null;
304         }
305
306         return __pBitmap[status];
307 }
308
309 void
310 _ContextMenuItem::SetSize(Tizen::Graphics::FloatDimension size)
311 {
312         __size = size;
313 }
314
315 Tizen::Graphics::FloatDimension
316 _ContextMenuItem::GetSize(void) const
317 {
318         return __size;
319 }
320
321 void
322 _ContextMenuItem::SetDrawRect(Tizen::Graphics::FloatRectangle rect)
323 {
324         __drawRect = rect;
325
326 }
327
328 Tizen::Graphics::FloatRectangle
329 _ContextMenuItem::GetDrawRect(void) const
330 {
331         return __drawRect;
332 }
333
334 void
335 _ContextMenuItem::SetPressedDrawRect(Tizen::Graphics::FloatRectangle rect)
336 {
337         __pressedDrawRect = rect;
338
339 }
340
341 Tizen::Graphics::FloatRectangle
342 _ContextMenuItem::GetPressedDrawRect(void) const
343 {
344         return __pressedDrawRect;
345 }
346
347 int
348 _ContextMenuItem::Release(void)
349 {
350         delete this;
351
352         return 0;
353 }
354
355 void
356 _ContextMenuItem::OnBoundsChanged(void)
357 {
358         _AccessibilityContainer* pContainer = GetAccessibilityContainer();
359         if (pContainer)
360         {
361                 _AccessibilityElement* pElement = pContainer->GetChildElement(0);
362                 if (pElement)
363                 {
364                         pElement->SetBounds(FloatRectangle(0.0f, 0.0f, GetBoundsF().width, GetBoundsF().height));
365                 }
366         }
367 }
368
369 void
370 _ContextMenuItem::OnDraw(void)
371 {
372         DrawItem();
373 }
374
375 void
376 _ContextMenuItem::DrawItem(void)
377 {
378         if (__upperDividerLine)
379         {
380                 DrawItemUpperDivider();
381         }
382
383         if (__lowerDividerLine)
384         {
385                 DrawItemLowerDivider();
386         }
387
388         DrawItemBackground();
389 }
390
391 void
392 _ContextMenuItem::DrawItemUpperDivider(void)
393 {
394         FloatRectangle bounds(0.0f, 0.0f, 0.0f, 0.0f);
395         Color dividerLineColor = Color(0, 0, 0, 0);
396
397         if (__pUpperDividerLineLabel == null)
398         {
399                 __pUpperDividerLineLabel = _Label::CreateLabelN();
400                 SysTryReturnVoidResult(NID_UI_CTRL, __pUpperDividerLineLabel, E_OUT_OF_MEMORY, "[%s] Propagating.", GetErrorMessage(GetLastResult()));
401
402                 AttachChild(*__pUpperDividerLineLabel);
403
404                 _AccessibilityContainer* pContainer = __pUpperDividerLineLabel->GetAccessibilityContainer();
405                 if (pContainer)
406                 {
407                         pContainer->Activate(false);
408                 }
409         }
410
411         bounds = GetBoundsF();
412         if (__selected == false)
413         {
414                 dividerLineColor = __upperDividerLineColor;
415         }
416
417         __pUpperDividerLineLabel->SetBounds(FloatRectangle(__leftMargin, 0.0f, bounds.width - __leftMargin - __rightMargin, __dividerHeight));
418         __pUpperDividerLineLabel->SetBackgroundColor(dividerLineColor);
419         __pUpperDividerLineLabel->Invalidate();
420 }
421
422 void
423 _ContextMenuItem::DrawItemBackground(void)
424 {
425         float topMargin = 0.0f, bottomMargin = 0.0f;
426
427         SetBackgroundColor(Color(0, 0, 0, 0));
428
429         if (__pBackgroundLabel == null)
430         {
431                 __pBackgroundLabel = _Label::CreateLabelN();
432                 SysTryReturnVoidResult(NID_UI_CTRL, __pBackgroundLabel, E_OUT_OF_MEMORY, "[%s] Propagating.", GetErrorMessage(GetLastResult()));
433
434                 __pBackgroundLabel->SetTouchPressThreshold(TOUCH_PRESS_THRESHOLD_INSENSITIVE);
435                 AttachChild(*__pBackgroundLabel);
436                 MoveChildToBottom(*__pBackgroundLabel);
437
438                 _AccessibilityContainer* pContainer = __pBackgroundLabel->GetAccessibilityContainer();
439                 if (pContainer)
440                 {
441                         pContainer->Activate(false);
442                 }
443         }
444
445         Color color= Color(0, 0, 0, 0);
446         if (__selected == true)
447         {
448                 color = __selectedBgColor;
449         }
450
451         FloatRectangle bounds = GetBoundsF();
452         _ScrollPanel* pScrollPanel = static_cast<_ScrollPanel*>(GetParent());
453         FloatRectangle boundsScrollPanel = pScrollPanel->GetBoundsF();
454
455         float topOverlap = pScrollPanel->GetScrollPosition() - bounds.y;
456         if (topOverlap > 0.0f)
457         {
458                 topMargin = topOverlap + __bgPressedMargin;
459         }
460         else if (!__upperDividerLine)
461         {
462                 topMargin = __bgPressedMargin;
463         }
464
465         float bottomOverlap = bounds.y + bounds.height - (pScrollPanel->GetScrollPosition() + boundsScrollPanel.height);
466         if (bottomOverlap > 0.0f)
467         {
468                 bottomMargin = bottomOverlap + __bgPressedMargin;
469         }
470         else if (!__lowerDividerLine)
471         {
472                 bottomMargin = __bgPressedMargin;
473         }
474
475         __pBackgroundLabel->SetBounds(FloatRectangle(__bgPressedMargin, topMargin, bounds.width - __bgPressedMargin * 2.0f, bounds.height - topMargin - bottomMargin));
476
477         Bitmap* BgBitmap = _BitmapImpl::GetColorReplacedBitmapN(*__pMagentaBgBitmap, Color::GetColor(COLOR_ID_MAGENTA), color);
478         SysTryReturnVoidResult(NID_UI_CTRL, BgBitmap, E_OUT_OF_MEMORY, "[%s] Propagating.", GetErrorMessage(GetLastResult()));
479
480         __pBackgroundLabel->SetBackgroundBitmap(*BgBitmap);
481         delete BgBitmap;
482         BgBitmap = null;
483
484         __pBackgroundLabel->Invalidate();
485 }
486
487 void
488 _ContextMenuItem::DrawItemLowerDivider(void)
489 {
490         FloatRectangle bounds(0.0f, 0.0f, 0.0f, 0.0f);
491         Color dividerLineColor(0, 0, 0, 0);
492
493         if (__pLowerDividerLineLabel == null)
494         {
495                 __pLowerDividerLineLabel = _Label::CreateLabelN();
496                 SysTryReturnVoidResult(NID_UI_CTRL, __pLowerDividerLineLabel, E_OUT_OF_MEMORY, "[%s] Propagating.", GetErrorMessage(GetLastResult()));
497
498                 AttachChild(*__pLowerDividerLineLabel);
499
500                 _AccessibilityContainer* pContainer = __pLowerDividerLineLabel->GetAccessibilityContainer();
501                 if (pContainer)
502                 {
503                         pContainer->Activate(false);
504                 }
505         }
506
507         bounds = GetBoundsF();
508         if (__selected == false)
509         {
510                 dividerLineColor = __lowerDividerLineColor;
511         }
512
513         __pLowerDividerLineLabel->SetBounds(FloatRectangle(__leftMargin, bounds.height - __dividerHeight, bounds.width - __leftMargin - __rightMargin, __dividerHeight));
514         __pLowerDividerLineLabel->SetBackgroundColor(dividerLineColor);
515         __pLowerDividerLineLabel->Invalidate();
516 }
517
518 _UiTouchEventDelivery
519 _ContextMenuItem::OnPreviewTouchPressed(const _Control& source, const _TouchInfo& touchinfo)
520 {
521         SetAndInvalidate(true);
522
523         return _UI_TOUCH_EVENT_DELIVERY_FORCED_YES;
524 }
525
526 bool
527 _ContextMenuItem::OnTouchPressed(const _Control& source, const _TouchInfo& touchinfo)
528 {
529         SetAndInvalidate(true);
530
531         return false;
532 }
533
534 _UiTouchEventDelivery
535 _ContextMenuItem::OnPreviewTouchMoved(const _Control& source, const _TouchInfo& touchinfo)
536 {
537         TouchMoved(source, touchinfo);
538
539         return _UI_TOUCH_EVENT_DELIVERY_FORCED_YES;
540 }
541
542 bool
543 _ContextMenuItem::OnTouchMoved(const _Control& source, const _TouchInfo& touchinfo)
544 {
545         TouchMoved(source, touchinfo);
546
547         return false;
548 }
549
550 _UiTouchEventDelivery
551 _ContextMenuItem::OnPreviewTouchReleased(const _Control& source, const _TouchInfo& touchinfo)
552 {
553         SetAndInvalidate(false);
554
555         return _UI_TOUCH_EVENT_DELIVERY_FORCED_YES;
556 }
557
558 bool
559 _ContextMenuItem::OnTouchReleased(const _Control& source, const _TouchInfo& touchinfo)
560 {
561         SetAndInvalidate(false);
562
563         return false;
564 }
565
566 _UiTouchEventDelivery
567 _ContextMenuItem::OnPreviewTouchCanceled(const _Control& source, const _TouchInfo& touchinfo)
568 {
569         return _UI_TOUCH_EVENT_DELIVERY_FORCED_YES;
570 }
571
572 bool
573 _ContextMenuItem::OnTouchCanceled(const _Control& source, const _TouchInfo& touchinfo)
574 {
575         SetAndInvalidate(false);
576
577         return false;
578 }
579
580 void
581 _ContextMenuItem::TouchMoved(const _Control& source, const _TouchInfo& touchinfo)
582 {
583         FloatPoint touchPosition = touchinfo.GetCurrentPosition();
584
585         if (__pressed)
586         {
587                 if (__parentScrollEnable)
588                 {
589                         if (__selected)
590                         {
591                                 __selected = false;
592                                 Invalidate();
593                         }
594                 }
595                 else
596                 {
597                         int oldSelected = __selected;
598
599                         FloatRectangle bounds(0.0f, 0.0f, __size.width, __size.height);
600                         if (bounds.Contains(touchPosition))
601                         {
602                                 __selected = true;
603                         }
604                         else
605                         {
606                                 __selected = false;
607                         }
608
609                         if (oldSelected != __selected)
610                         {
611                                 Invalidate();
612                         }
613                 }
614         }
615 }
616
617 void
618 _ContextMenuItem::OnFontChanged(Tizen::Graphics::Font* pFont)
619 {
620         String fontName = _Control::GetFont();
621
622         if (__pTextLabel != null)
623         {
624                 __pTextLabel->SetFont(fontName);
625         }
626 }
627
628 void
629 _ContextMenuItem::OnFontInfoRequested(unsigned long& style, float& size)
630 {
631         style = FONT_STYLE_PLAIN;
632         size = __textSize;
633 }
634
635 void
636 _ContextMenuItem::SetParentScrollEnable(bool enable)
637 {
638         __parentScrollEnable = enable;
639 }
640
641 bool
642 _ContextMenuItem::GetParentScrollEnable() const
643 {
644         return __parentScrollEnable;
645 }
646
647 bool
648 _ContextMenuItem::IsSelected() const
649 {
650         return __selected;
651 }
652
653 void
654 _ContextMenuItem::SetAndInvalidate(bool flag)
655 {
656         __selected = flag;
657         __pressed = flag;
658         Invalidate();
659 }
660
661 const Tizen::Graphics::Bitmap*
662 _ContextMenuItem::GetMagentaBgBitmap() const
663 {
664         return __pMagentaBgBitmap;
665 }
666
667 }}} // Tizen::Ui::Controls