Tizen 2.1 base
[framework/osp/uifw.git] / src / ui / controls / FUiCtrl_ListViewItem.cpp
1 //
2 // Open Service Platform
3 // Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
4 //
5 // Licensed under the Flora License, Version 1.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://floralicense.org/license/
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 /**
19  * @file        FUiCtrl_ListViewItem.cpp
20  * @brief   This is the implementation file for _ListViewItem class.
21  *
22  * This file contains the implementation of _ListViewItem class.
23  */
24
25 #include <FBaseSysLog.h>
26 #include <FGrp_BitmapImpl.h>
27 #include <FGrp_EnrichedTextImpl.h>
28 #include <FGrp_TextElementImpl.h>
29 #include <FGrp_TextTextCutLink.h>
30 #include <FGrp_TextTextCutLinkParser.h>
31 #include <FGrp_TextTextSimple.h>
32 #include "FUi_AccessibilityContainer.h"
33 #include "FUi_AccessibilityElement.h"
34 #include "FUi_AccessibilityManager.h"
35 #include "FUi_ITouchLongPressGestureEventListener.h"
36 #include "FUi_ResourceManager.h"
37 #include "FUi_TouchLongPressGestureDetector.h"
38 #include "FUiAnim_VisualElement.h"
39 #include "FUiCtrl_Label.h"
40 #include "FUiCtrl_ListViewContextItem.h"
41 #include "FUiCtrl_ListViewItem.h"
42 #include "FUiCtrl_Progress.h"
43 #include "FUiCtrl_UiListViewItemEvent.h"
44 #include "FUiCtrl_UiListViewItemEventArg.h"
45
46 #ifdef MEMORY_LEAK_CHECK
47 #include "mem_leak_check.h"
48 #endif
49
50 using namespace Tizen::Base;
51 using namespace Tizen::Base::Runtime;
52 using namespace Tizen::Base::Utility;
53 using namespace Tizen::Graphics;
54 using namespace Tizen::Graphics::_Text;
55 using namespace Tizen::Ui;
56 using namespace Tizen::Ui::Animations;
57
58 namespace Tizen { namespace Ui { namespace Controls
59 {
60
61 _ListViewItem::_ListViewItem(int itemHeight)
62         : _TableViewItem(itemHeight)
63         , __touchPressed(false)
64         , __selectedElementId(-1)
65         , __progressLeftMargin(0)
66         , __progressRightMargin(0)
67         , __pProgress(null)
68         , __descriptionTextShowState(false)
69         , __pDescriptionText(null)
70         , __pDivider(null)
71         , __selectionEabled(false)
72         , __fontStyle(0)
73         , __fontSize(0)
74         , __fontName(L"")
75         , __prevTouchPos(-1, -1)
76         , __pTextSlideTimer(null)
77         , __pLongPressedGesture(null)
78 {
79         GET_COLOR_CONFIG(LISTVIEW::ITEM_DESCRIPTION_TEXT_NORMAL, __descriptionTextColor);
80
81         ___stateChangedInfo.selectionType = LISTVIEW_ITEM_SELECTED;
82         ___stateChangedInfo.elementId = -1;
83         ___stateChangedInfo.pUiLinkInfo = null;
84 }
85
86 _ListViewItem::~_ListViewItem(void)
87 {
88         DeleteAllElement();
89
90         delete ___stateChangedInfo.pUiLinkInfo;
91         ___stateChangedInfo.pUiLinkInfo = null;
92
93         delete __pTextSlideTimer;
94         __pTextSlideTimer = null;
95
96         if (__pLongPressedGesture != null)
97         {
98                 RemoveGestureDetector(*__pLongPressedGesture);
99
100                 delete __pLongPressedGesture;
101                 __pLongPressedGesture = null;
102         }
103
104         if (__pProgress != null)
105         {
106                 DetachChild(*__pProgress);
107
108                 delete __pProgress;
109                 __pProgress = null;
110         }
111
112         if (__pDescriptionText != null)
113         {
114                 DetachChild(*__pDescriptionText);
115
116                 delete __pDescriptionText;
117                 __pDescriptionText = null;
118         }
119
120         if (__pDivider != null)
121         {
122                 DetachChild(*__pDivider);
123
124                 delete __pDivider;
125                 __pDivider = null;
126         }
127 }
128
129 _ListViewItem*
130 _ListViewItem::CreateListViewItemN(int itemHeight)
131 {
132         _ListViewItem* pItem = new (std::nothrow) _ListViewItem(itemHeight);
133         SysTryReturn(NID_UI_CTRL, (pItem != null), null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
134
135         pItem->AcquireHandle();
136
137         result r = pItem->Initialize();
138         SysTryCatch(NID_UI_CTRL, r == E_SUCCESS, , r = E_SYSTEM, "[E_SYSTEM] Unable to create _ListViewItem");
139
140         return pItem;
141
142 CATCH:
143         delete pItem;
144
145         return null;
146 }
147
148 void
149 _ListViewItem::SetListViewItemType(ListViewItemType type)
150 {
151         __itemType = type;
152 }
153
154 void
155 _ListViewItem::AddTouchLongPressGestureEventListener(_ITouchLongPressGestureEventListener& listener)
156 {
157         if (__pLongPressedGesture == null)
158         {
159                 __pLongPressedGesture = new (std::nothrow) _TouchLongPressGestureDetector();
160                 SysTryReturnVoidResult(NID_UI_CTRL, (__pLongPressedGesture != null), E_OUT_OF_MEMORY,
161                                 "[E_OUT_OF_MEMORY] The memory is insufficient.");
162
163                 __pLongPressedGesture->SetDuration(TOUCH_LONGPRESSED_EVENT_DURATION);
164                 AddGestureDetector(*__pLongPressedGesture);
165         }
166
167         result r = __pLongPressedGesture->AddGestureListener(listener);
168         SysTryReturnVoidResult(NID_UI_CTRL, r == E_SUCCESS, r, "[%s] Failed to add gesture listener.", GetErrorMessage(r));
169 }
170
171 void
172 _ListViewItem::RemoveTouchLongPressGestureEventListener(_ITouchLongPressGestureEventListener& listener)
173 {
174         if (__pLongPressedGesture != null)
175         {
176                 __pLongPressedGesture->RemoveGestureListener(listener);
177         }
178 }
179
180 result
181 _ListViewItem::AddElement(Rectangle& rect, int elementId, const String& text, bool textSliding)
182 {
183         result r = E_SUCCESS;
184
185         SysTryReturn(NID_UI_CTRL, (HasElement(elementId) == false), E_INVALID_ARG, E_INVALID_ARG,
186                         ("[E_INVALID_ARG] This elementId already exists."));
187
188         // Convert String to TextObject
189         TextObject* pText = new (std::nothrow) TextObject();
190         pText->Construct();
191
192         if (text.IsEmpty() == false)
193         {
194                 TextSimple* pSimpleText = new (std::nothrow) TextSimple(const_cast <wchar_t*>(text.GetPointer()), text.GetLength());
195                 pText->AppendElement(*pSimpleText);
196
197                 pText->SetAlignment(TEXT_OBJECT_ALIGNMENT_LEFT | TEXT_OBJECT_ALIGNMENT_MIDDLE);
198                 pText->SetWrap(TEXT_OBJECT_WRAP_TYPE_NONE);
199         }
200
201         // Make element object
202         _ListViewItemElement element;
203         memset(&element, 0, sizeof(_ListViewItemElement));
204
205         element.elementId = elementId;
206         element.elementType = LISTVIEW_ITEM_ELEMENT_TEXT;
207         element.bounds = rect;
208
209         element.pTextElement = new (std::nothrow) _ListViewItemElementText();
210         SysTryReturn(NID_UI_CTRL, (element.pTextElement != null), (r = GetLastResult()), r, "[%s] Propagating.", GetErrorMessage(r));
211
212         element.pTextElement->pTextObject = pText;
213         element.pTextElement->textSlidingEnabled = textSliding;
214
215         GET_SHAPE_CONFIG(LISTVIEW::ITEM_DEFAULT_FONT_SIZE, _CONTROL_ORIENTATION_PORTRAIT, element.pTextElement->textSize);
216         GET_COLOR_CONFIG(LISTVIEW::ITEM_TEXT_NORMAL, element.pTextElement->textColor[LISTVIEW_ITEM_STATUS_NORMAL]);
217         GET_COLOR_CONFIG(LISTVIEW::ITEM_TEXT_PRESSED, element.pTextElement->textColor[LISTVIEW_ITEM_STATUS_PRESSED]);
218         GET_COLOR_CONFIG(LISTVIEW::ITEM_TEXT_HIGHLIGHTED, element.pTextElement->textColor[LISTVIEW_ITEM_STATUS_HIGHLIGHTED]);
219
220         // Set Visual element for this element
221         _VisualElement* pVE = new (std::nothrow) _VisualElement();
222         pVE->Construct();
223         pVE->SetImplicitAnimationEnabled(false);
224         pVE->SetContentProvider(&__hitTestVEDelegator);
225         element.pTextElement->pVE = pVE;
226
227         __elements.push_back(element);
228
229         return r;
230 }
231
232 result
233 _ListViewItem::AddElement(Rectangle& rect, int elementId, const EnrichedText* pEnrichedText, bool textSliding)
234 {
235         SysTryReturn(NID_UI_CTRL, (HasElement(elementId) == false), E_INVALID_ARG, E_INVALID_ARG,
236                         ("[E_INVALID_ARG] This elementId already exists."));
237
238         SysTryReturn(NID_GRP, (pEnrichedText != null) && (_EnrichedTextImpl::GetInstance(*pEnrichedText) != null),
239                         E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] This _EnrichedText element is null.");
240
241         // Set Text element
242         _EnrichedTextImpl* pCloneText = _EnrichedTextImpl::GetInstance(*pEnrichedText)->GetCloneN();
243         SysTryReturn(NID_GRP, (pCloneText != null), E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] This _EnrichedText element can not clone.");
244
245         TextObject* pText = pCloneText->GetTextObject();
246
247         // Make element object
248         _ListViewItemElement element;
249         memset(&element, 0, sizeof(_ListViewItemElement));
250
251         element.elementId = elementId;
252         element.elementType = LISTVIEW_ITEM_ELEMENT_TEXT;
253         element.bounds = rect;
254
255         element.pTextElement = new (std::nothrow) _ListViewItemElementText();
256         SysTryReturn(NID_UI_CTRL, (element.pTextElement != null), GetLastResult(), GetLastResult(), "[%s] Propagating.",
257                         GetErrorMessage(GetLastResult()));
258
259         element.pTextElement->pTextObject = pText;
260         element.pTextElement->pEnrichedText = pCloneText;
261         element.pTextElement->textSlidingEnabled = textSliding;
262
263         GET_COLOR_CONFIG(LISTVIEW::ITEM_TEXT_NORMAL, element.pTextElement->textColor[LISTVIEW_ITEM_STATUS_NORMAL]);
264         GET_COLOR_CONFIG(LISTVIEW::ITEM_TEXT_PRESSED, element.pTextElement->textColor[LISTVIEW_ITEM_STATUS_PRESSED]);
265         GET_COLOR_CONFIG(LISTVIEW::ITEM_TEXT_HIGHLIGHTED, element.pTextElement->textColor[LISTVIEW_ITEM_STATUS_HIGHLIGHTED]);
266
267         // Set Visual element for this element
268         _VisualElement* pVE = new (std::nothrow) _VisualElement();
269         pVE->Construct();
270         pVE->SetImplicitAnimationEnabled(false);
271         pVE->SetContentProvider(&__hitTestVEDelegator);
272         element.pTextElement->pVE = pVE;
273
274         __elements.push_back(element);
275
276         return E_SUCCESS;
277 }
278
279 result
280 _ListViewItem::AddElement(Rectangle& rect, int elementId, const Bitmap* pNormalBitmap, const Bitmap* pPressedBitmap, const Bitmap* pHighlightedBitmap)
281 {
282         SysTryReturn(NID_UI_CTRL, (HasElement(elementId) == false), E_INVALID_ARG, E_INVALID_ARG,
283                         ("[E_INVALID_ARG] This elementId already exists."));
284
285         SysTryReturn(NID_GRP, (pNormalBitmap != null), E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] This Bitmap element is null.");
286
287         _ListViewItemElement element;
288         _VisualElement* pVE = null;
289         Bitmap* pClonePressedBitmap = null;
290         Bitmap* pCloneHighlightedBitmap = null;
291         result r = E_SUCCESS;
292
293         Bitmap* pCloneNormalBitmap = _BitmapImpl::CloneN(*pNormalBitmap);
294         SysTryReturn(NID_UI_CTRL, (pCloneNormalBitmap != null), (r = GetLastResult()), r, "[%s] Propagating.", GetErrorMessage(GetLastResult()));
295
296         if (pPressedBitmap != null)
297         {
298                 pClonePressedBitmap = _BitmapImpl::CloneN(*pPressedBitmap);
299                 SysTryCatch(NID_UI_CTRL, (pClonePressedBitmap != null), (r = GetLastResult()), r, "[%s] Propagating.", GetErrorMessage(GetLastResult()));
300         }
301
302         if (pHighlightedBitmap != null)
303         {
304                 pCloneHighlightedBitmap = _BitmapImpl::CloneN(*pHighlightedBitmap);
305                 SysTryCatch(NID_UI_CTRL, (pCloneHighlightedBitmap != null), (r = GetLastResult()), r, "[%s] Propagating.", GetErrorMessage(GetLastResult()));
306         }
307
308         // Make element object
309         memset(&element, 0, sizeof(_ListViewItemElement));
310
311         element.elementId = elementId;
312         element.elementType = LISTVIEW_ITEM_ELEMENT_BITMAP;
313         element.bounds = rect;
314
315         element.pBitmapElement = new (std::nothrow) _ListViewItemElementBitmap();
316         SysTryCatch(NID_UI_CTRL, (element.pBitmapElement != null), (r = GetLastResult()), r, "[%s] Propagating.", GetErrorMessage(GetLastResult()));
317
318         element.pBitmapElement->pBitmap[LISTVIEW_ITEM_STATUS_NORMAL] = pCloneNormalBitmap;
319         element.pBitmapElement->pBitmap[LISTVIEW_ITEM_STATUS_PRESSED] = pClonePressedBitmap;
320         element.pBitmapElement->pBitmap[LISTVIEW_ITEM_STATUS_HIGHLIGHTED] = pCloneHighlightedBitmap;
321
322         pVE = new (std::nothrow) _VisualElement();
323         pVE->Construct();
324         pVE->SetImplicitAnimationEnabled(false);
325         pVE->SetContentProvider(&__hitTestVEDelegator);
326         element.pBitmapElement->pVE = pVE;
327
328         __elements.push_back(element);
329
330         return E_SUCCESS;
331
332 CATCH:
333         delete pCloneNormalBitmap;
334         delete pClonePressedBitmap;
335         delete pCloneHighlightedBitmap;
336
337         return r;
338 }
339
340 result
341 _ListViewItem::AddElement(Rectangle& rect, int elementId, const _ICustomElement* pCustom)
342 {
343         SysTryReturn(NID_UI_CTRL, (HasElement(elementId) == false), E_INVALID_ARG, E_INVALID_ARG,
344                         ("[E_INVALID_ARG] This elementId already exists."));
345
346         SysTryReturn(NID_GRP, (pCustom != null), E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] This Custom element is null.");
347
348         // Make element object
349         _ListViewItemElement element;
350         memset(&element, 0, sizeof(_ListViewItemElement));
351
352         element.elementId = elementId;
353         element.elementType = LISTVIEW_ITEM_ELEMENT_OBJ;
354         element.bounds = rect;
355
356         element.pCustomElement = new (std::nothrow) _ListViewItemElementCustom();
357         SysTryReturn(NID_UI_CTRL, (element.pCustomElement != null), GetLastResult(), GetLastResult(), "[%s] Propagating.", GetErrorMessage(GetLastResult()));
358
359         element.pCustomElement->pCustom = const_cast<_ICustomElement*>(pCustom);
360
361         _VisualElement* pVE = new (std::nothrow) _VisualElement();
362         pVE->Construct();
363         pVE->SetImplicitAnimationEnabled(false);
364         pVE->SetContentProvider(&__hitTestVEDelegator);
365         element.pCustomElement->pVE = pVE;
366
367         if (pVE->GetParent() == null)
368         {
369                 GetVisualElement()->AttachChild(*(pVE));
370                 pVE->SetShowState(true);
371                 pVE->SetBounds(FloatRectangle(rect.x, rect.y, rect.width, rect.height));
372         }
373
374         __elements.push_back(element);
375
376         return E_SUCCESS;
377 }
378
379 bool
380 _ListViewItem::DeleteElement(int elementId)
381 {
382         _LinkedList <_ListViewItemElement>::_Iterator iter;
383
384         for (iter = __elements.begin(); iter != __elements.end(); iter++)
385         {
386                 if (iter->elementId == elementId)
387                 {
388                         DeleteElement(&(*iter));
389                         __elements.erase(iter);
390
391                         return true;
392                 }
393         }
394
395         return false;
396 }
397
398 void
399 _ListViewItem::DeleteAllElement(void)
400 {
401         _LinkedList <_ListViewItemElement>::_Iterator iter;
402
403         for (iter = __elements.begin(); iter != __elements.end(); iter++)
404         {
405                 DeleteElement(&(*iter));
406         }
407
408         __elements.clear();
409 }
410
411 void
412 _ListViewItem::DeleteElement(_ListViewItemElement* pElement)
413 {
414         if (pElement->pTextElement != null)
415         {
416                 if (pElement->pTextElement->pEnrichedText != null)
417                 {
418                         (pElement->pTextElement->pEnrichedText)->RemoveAllTextElements(true);
419
420                         delete pElement->pTextElement->pEnrichedText;
421                         pElement->pTextElement->pEnrichedText = null;
422
423                         pElement->pTextElement->pTextObject = null;
424                 }
425                 else
426                 {
427                         delete pElement->pTextElement->pTextObject;
428                         pElement->pTextElement->pTextObject = null;
429                 }
430
431                 if (pElement->pTextElement->pVE != null)
432                 {
433                         pElement->pTextElement->pVE->Destroy();
434                         pElement->pTextElement->pVE = null;
435                 }
436
437                 if (pElement->pTextElement->pAccessibilityElement)
438                 {
439                         pElement->pTextElement->pAccessibilityElement->Activate(false);
440                         pElement->pTextElement->pAccessibilityElement = null;
441                 }
442
443                 delete pElement->pTextElement;
444                 pElement->pTextElement = null;
445         }
446
447         if (pElement->pBitmapElement != null)
448         {
449                 for (int i = 0; i < LISTVIEW_ITEM_STATUS_MAX; i++)
450                 {
451                         delete pElement->pBitmapElement->pBitmap[i];
452                         pElement->pBitmapElement->pBitmap[i] = null;
453                 }
454
455                 if (pElement->pBitmapElement->pVE != null)
456                 {
457                         pElement->pBitmapElement->pVE->Destroy();
458                         pElement->pBitmapElement->pVE = null;
459                 }
460
461                 delete pElement->pBitmapElement;
462                 pElement->pBitmapElement = null;
463         }
464
465         if (pElement->pCustomElement)
466         {
467                 delete pElement->pCustomElement->pCustom;
468                 pElement->pCustomElement->pCustom = null;
469
470                 if (pElement->pCustomElement->pVE != null)
471                 {
472                         pElement->pCustomElement->pVE->Destroy();
473                         pElement->pCustomElement->pVE = null;
474                 }
475
476                 delete pElement->pCustomElement;
477                 pElement->pCustomElement = null;
478         }
479 }
480
481 bool
482 _ListViewItem::HasElement(int elementId)
483 {
484         _ListViewItemElement* pElement = GetElement(elementId);
485
486         return (pElement != null);
487 }
488
489 bool
490 _ListViewItem::RefreshElement(int elementId)
491 {
492         _ListViewItemElement* pElement = GetElement(elementId);
493
494         if (pElement != null)
495         {
496                 DrawElement(pElement);
497         }
498
499         return (pElement != null);
500 }
501
502 void
503 _ListViewItem::SetLastStateChangedInfo(void)
504 {
505         ClearLastStateChangedInfo();
506
507         int elementId = GetElementIdFromCurrentTouchPosition();
508         _ListViewItemElement* pElement = GetElement(elementId);
509
510         if ((pElement != null) && (__itemType == LISTVIEW_ITEM_TYPE_CUSTOM))
511         {
512                 _ListViewItemUiLinkInfo* pInfo = null;
513                 int cutlinkTextTouchedIndex = -1;
514
515                 if (IsCutlinkTextSelected(__prevTouchPos, &cutlinkTextTouchedIndex, &pInfo))
516                 {
517                         if ((GetItemStyle() == TABLE_VIEW_ANNEX_STYLE_DETAILED)
518                                         && (pElement->actionElement == true) && (pElement->selectionEnabled == false))
519                         {
520                                 elementId = -1;
521                         }
522
523                         if (cutlinkTextTouchedIndex >= 0)
524                         {
525                                 ___stateChangedInfo.selectionType = LISTVIEW_ITEM_UILINK_SELECTED;
526                                 ___stateChangedInfo.elementId = elementId;
527                                 ___stateChangedInfo.pUiLinkInfo = pInfo;
528                         }
529                         else
530                         {
531                                 ___stateChangedInfo.selectionType = LISTVIEW_ITEM_ELEMENT_SELECTED;
532                                 ___stateChangedInfo.elementId = elementId;
533                         }
534                 }
535                 else
536                 {
537                         if ((GetItemStyle() == TABLE_VIEW_ANNEX_STYLE_DETAILED)
538                                         && (pElement->actionElement == true) && (pElement->selectionEnabled == false))
539                         {
540                                 elementId = -1;
541                         }
542
543                         ___stateChangedInfo.selectionType = LISTVIEW_ITEM_ELEMENT_SELECTED;
544                         ___stateChangedInfo.elementId = elementId;
545                 }
546         }
547         else
548         {
549                 ___stateChangedInfo.selectionType = LISTVIEW_ITEM_ELEMENT_SELECTED;
550                 ___stateChangedInfo.elementId = -1;
551         }
552 }
553
554 bool
555 _ListViewItem::GetLastStateChangedInfo(_ListViewItemStateChangedInfo& changedInfo) const
556 {
557         changedInfo = ___stateChangedInfo;
558
559         return (___stateChangedInfo.selectionType != LISTVIEW_ITEM_SELECTED);
560 }
561
562 void
563 _ListViewItem::ClearLastStateChangedInfo(void)
564 {
565         delete ___stateChangedInfo.pUiLinkInfo;
566
567         ___stateChangedInfo.selectionType = LISTVIEW_ITEM_SELECTED;
568         ___stateChangedInfo.elementId = -1;
569         ___stateChangedInfo.pUiLinkInfo = null;
570 }
571
572 int
573 _ListViewItem::GetElementIdFromPosition(const Point& position) const
574 {
575         _LinkedList <_ListViewItemElement>::_ReverseIterator reverseIter;
576
577         for (reverseIter = __elements.rbegin(); reverseIter != __elements.rend(); reverseIter++)
578         {
579                 if ((*reverseIter).bounds.Contains(position))
580                 {
581                         return (*reverseIter).elementId;
582                 }
583         }
584
585         return -1;
586 }
587
588 int
589 _ListViewItem::GetElementIdFromCurrentTouchPosition(void) const
590 {
591         return GetElementIdFromPosition(__prevTouchPos);
592 }
593
594 _ListViewItemElement*
595 _ListViewItem::GetElement(int elementId) const
596 {
597         _LinkedList <_ListViewItemElement>::_Iterator iter;
598
599         for (iter = __elements.begin(); iter != __elements.end(); iter++)
600         {
601                 if (iter->elementId == elementId)
602                 {
603                         return &(*iter);
604                 }
605         }
606
607         return null;
608 }
609
610 ListViewItemElementType
611 _ListViewItem::GetElementType(int elementId) const
612 {
613         _ListViewItemElement* pElement = GetElement(elementId);
614
615         return ((pElement != null) ? pElement->elementType : LISTVIEW_ITEM_ELEMENT_INVALID);
616 }
617
618 TextObject*
619 _ListViewItem::GetTextObjectInElement(int elementId) const
620 {
621         _ListViewItemElementText* pElement = GetElementText(elementId);
622
623         return ((pElement != null) ? pElement->pTextObject : null);
624 }
625
626 _ListViewItemElementText*
627 _ListViewItem::GetElementText(int elementId) const
628 {
629         _ListViewItemElement* pElement = GetElement(elementId);
630
631         if ((pElement != null) && (pElement->elementType == LISTVIEW_ITEM_ELEMENT_TEXT)
632                         &&  (pElement->pTextElement->pTextObject != null))
633         {
634                 return pElement->pTextElement;
635         }
636
637         return null;
638 }
639
640 _ListViewItemElementBitmap*
641 _ListViewItem::GetElementBitmap(int elementId) const
642 {
643         _ListViewItemElement* pElement = GetElement(elementId);
644
645         if ((pElement != null) && (pElement->elementType == LISTVIEW_ITEM_ELEMENT_BITMAP))
646         {
647                 return pElement->pBitmapElement;
648         }
649
650         return null;
651 }
652
653 bool
654 _ListViewItem::SetElementSelectionEnabled(int elementId, bool enable)
655 {
656         _ListViewItemElement* pElement = GetElement(elementId);
657
658         if (pElement == null)
659         {
660                 return false;
661         }
662
663         pElement->actionElement = true;
664         pElement->selectionEnabled = enable;
665
666         return true;
667 }
668
669 bool
670 _ListViewItem::GetElementSelectionEnabled(int elementId, bool& enable)
671 {
672         _ListViewItemElement* pElement = GetElement(elementId);
673
674         if ((pElement == null) || (pElement->actionElement == false))
675         {
676                 return false;
677         }
678
679         enable = pElement->selectionEnabled;
680
681         return true;
682 }
683
684 bool
685 _ListViewItem::SetTextCutlinkMask(int elementId, unsigned long mask)
686 {
687         _ListViewItemElementText* pElement = GetElementText(elementId);
688
689         if (pElement == null)
690         {
691                 return false;
692         }
693
694         pElement->cutlinkMaskType = mask;
695
696         return true;
697 }
698
699 bool
700 _ListViewItem::SetTextCutlinkViewMode(int elementId, bool cutlinkViewMode, bool cutlinkParseEnable)
701 {
702         _ListViewItemElementText* pElement = GetElementText(elementId);
703
704         if (pElement == null)
705         {
706                 return false;
707         }
708
709         pElement->cutlinkViewModeEnabled = cutlinkViewMode;
710         pElement->cutlinkParseEnabled = cutlinkParseEnable;
711         pElement->cutlinkMaskType = LINK_TYPE_MAX;
712
713         return true;
714 }
715
716 bool
717 _ListViewItem::SetTextAlignment(int elementId, TextObjectAlignment textAlignment)
718 {
719         TextObject* pTextObject = GetTextObjectInElement(elementId);
720
721         if (pTextObject == null)
722         {
723                 return false;
724         }
725
726         TextObjectAlignment originAlign = pTextObject->GetAlignment();
727
728         // reset original alignment
729         if ((0x0007 & textAlignment) != 0x0000)                 // TextHorizontalAlignment
730         {
731                 originAlign &= 0x0700;
732         }
733         else if ((0x0700 & textAlignment) != 0x0000)    // TextVerticalAlignment
734         {
735                 originAlign &= 0x0007;
736         }
737
738         pTextObject->SetAlignment(originAlign | textAlignment);
739
740         return true;
741 }
742
743 bool
744 _ListViewItem::GetTextAlignment(int elementId, TextObjectAlignment& textAlignment) const
745 {
746         TextObject* pTextObject = GetTextObjectInElement(elementId);
747
748         if (pTextObject == null)
749         {
750                 return false;
751         }
752
753         textAlignment = pTextObject->GetAlignment();
754
755         return true;
756 }
757
758 bool
759 _ListViewItem::SetTextWrapType(int elementId, TextObjectWrapType wrapType)
760 {
761         TextObject* pTextObject = GetTextObjectInElement(elementId);
762
763         if (pTextObject == null)
764         {
765                 return false;
766         }
767
768         pTextObject->SetWrap(wrapType);
769
770         return true;
771 }
772
773 bool
774 _ListViewItem::SetTextSize(int elementId, int textSize)
775 {
776         _ListViewItemElementText* pElement = GetElementText(elementId);
777
778         if ((pElement != null) && (textSize > 0))
779         {
780                 pElement->textSize = textSize;
781
782                 return true;
783         }
784
785         return false;
786 }
787
788 bool
789 _ListViewItem::SetTextColor(int elementId, Color textColor, ListViewItemDrawingStatus status)
790 {
791         _ListViewItemElementText* pElement = GetElementText(elementId);
792
793         if (pElement == null)
794         {
795                 return false;
796         }
797
798         pElement->textColor[status] = textColor;
799
800         return true;
801 }
802
803 bool
804 _ListViewItem::GetTextColor(int elementId, Color& textColor, ListViewItemDrawingStatus status) const
805 {
806         _ListViewItemElementText* pElement = GetElementText(elementId);
807
808         if (pElement == null)
809         {
810                 return false;
811         }
812
813         textColor = pElement->textColor[status];
814
815         return true;
816 }
817
818 bool
819 _ListViewItem::SetProgressValue(int value)
820 {
821         if ((value < 0) || (value > 100))
822         {
823                 if (__pProgress != null)
824                 {
825                         __pProgress->SetVisibleState(false);
826                 }
827
828                 return false;
829         }
830
831         if (__pProgress == null)
832         {
833                 __pProgress = _Progress::CreateProgressN();
834                 SysTryReturn(NID_UI_CTRL, (__pProgress != null), false, E_SYSTEM, "[%s] Propagating.", GetErrorMessage(GetLastResult()));
835
836                 __pProgress->SetRange(0, 100);
837                 AttachChild(*__pProgress);
838
839                 AdjustProgressBounds();
840         }
841
842         __pProgress->SetValue(value);
843         __pProgress->SetVisibleState(true);
844
845         return true;
846 }
847
848 bool
849 _ListViewItem::SetProgressMargins(int leftMargin, int rightMargin)
850 {
851         if ((leftMargin < 0) || (rightMargin < 0) || (GetBounds().width - leftMargin - rightMargin <= 0))
852         {
853                 return false;
854         }
855
856         __progressLeftMargin = leftMargin;
857         __progressRightMargin = rightMargin;
858
859         AdjustProgressBounds();
860
861         return true;
862 }
863
864 void
865 _ListViewItem::AdjustProgressBounds(void)
866 {
867         if (__pProgress != null)
868         {
869                 Rectangle progressRect = GetBounds();
870                 int progressHeight = 0;
871                 int bottomMargin = 0;
872
873                 // Calculate progress position
874                 GET_SHAPE_CONFIG(SLIDER::BAR_HEIGHT, _CONTROL_ORIENTATION_PORTRAIT, progressHeight);
875                 GET_SHAPE_CONFIG(LISTVIEW::ITEM_PROGRESS_BOTTOM_MARGIN, _CONTROL_ORIENTATION_PORTRAIT, bottomMargin);
876
877                 progressRect.x = __progressLeftMargin;
878                 progressRect.y = progressRect.height - progressHeight - bottomMargin;
879                 progressRect.width = progressRect.width -  __progressLeftMargin - __progressRightMargin;
880                 progressRect.height = progressHeight;
881
882                 progressRect.y -= ((__descriptionTextShowState) ? GetDescriptionTextHeight() : 0);
883
884                 __pProgress->SetBounds(progressRect);
885         }
886 }
887
888 bool
889 _ListViewItem::SetDescriptionText(const String& text)
890 {
891         if (text.IsEmpty())
892         {
893                 if (__pDescriptionText != null)
894                 {
895                         DetachChild(*__pDescriptionText);
896
897                         delete __pDescriptionText;
898                         __pDescriptionText = null;
899                 }
900
901                 return true;
902         }
903         else
904         {
905                 if (__pDescriptionText == null)
906                 {
907                         __pDescriptionText = _Label::CreateLabelN();
908                         result r = GetLastResult();
909                         SysTryReturn(NID_UI_CTRL, (__pDescriptionText != null), r, r, "[%s] Propagating.", GetErrorMessage(r));
910
911                         __pDescriptionText->SetVisibleState(false);
912                         __pDescriptionText->SetMargin(0, 0);
913                         __pDescriptionText->SetTextHorizontalAlignment(ALIGNMENT_LEFT);
914
915                         SetAccessibilityElement();
916
917                         AttachChild(*__pDescriptionText);
918                 }
919
920                 Rectangle bounds = GetBounds();
921                 Rectangle textBounds;
922                 int textSize = 0;
923                 bool ret = true;
924
925                 GET_SHAPE_CONFIG(LISTVIEW::ITEM_DESCRIPTION_TEXT_LEFT_MARGIN, _CONTROL_ORIENTATION_PORTRAIT, textBounds.x);
926                 GET_SHAPE_CONFIG(LISTVIEW::ITEM_DESCRIPTION_TEXT_TOP_MARGIN, _CONTROL_ORIENTATION_PORTRAIT, textBounds.y);
927                 GET_SHAPE_CONFIG(LISTVIEW::ITEM_DESCRIPTION_TEXT_FONT_SIZE, _CONTROL_ORIENTATION_PORTRAIT, textSize);
928
929                 textBounds.width = bounds.width - (textBounds.x * 2);
930
931                 TextObject* pText = new (std::nothrow) TextObject();
932                 SysTryReturn(NID_UI_CTRL, (pText != null), false, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
933
934                 pText->Construct();
935
936                 TextSimple* pSimpleText = new (std::nothrow) TextSimple((const_cast<wchar_t*>(text.GetPointer())), text.GetLength());
937                 SysTryCatch(NID_UI_CTRL, (pSimpleText != null), (ret = false), E_OUT_OF_MEMORY, "[%s] Propagating.", GetErrorMessage(GetLastResult()));
938
939                 pText->AppendElement(*pSimpleText);
940                 pText->SetAlignment(TEXT_OBJECT_ALIGNMENT_LEFT | TEXT_OBJECT_ALIGNMENT_TOP);
941                 pText->SetWrap(TEXT_OBJECT_WRAP_TYPE_WORD);
942                 pText->SetFont(GetFont(FONT_STYLE_PLAIN, textSize), 0, pText->GetTextLength());
943                 pText->SetBounds(Rectangle(0, 0, textBounds.width, 1));
944                 pText->Compose();
945
946                 textBounds.height = pText->GetTotalHeight();
947
948                 __pDescriptionText->SetBounds(Rectangle(textBounds.x, bounds.height + textBounds.y, textBounds.width, textBounds.height));
949                 __pDescriptionText->SetBackgroundColor(Color(0, 0, 0, 0));
950                 __pDescriptionText->SetTextColor(__descriptionTextColor);
951                 __pDescriptionText->SetTextConfig(textSize, LABEL_TEXT_STYLE_NORMAL);
952                 __pDescriptionText->SetText(text);
953
954 CATCH:
955                 delete pText;
956
957                 return ret;
958         }
959 }
960
961 void
962 _ListViewItem::SetDescriptionTextColor(const Color& color)
963 {
964         __descriptionTextColor = color;
965 }
966
967 int
968 _ListViewItem::GetDescriptionTextHeight(void)
969 {
970         if (__pDescriptionText != null)
971         {
972                 int margin = 0;
973                 GET_SHAPE_CONFIG(LISTVIEW::ITEM_DESCRIPTION_TEXT_TOP_MARGIN, _CONTROL_ORIENTATION_PORTRAIT, margin);
974
975                 return ((margin * 2) + __pDescriptionText->GetBounds().height);
976         }
977
978         return 0;
979 }
980
981 void
982 _ListViewItem::SetDescriptionTextShowState(bool show)
983 {
984         if (__descriptionTextShowState != show)
985         {
986                 __descriptionTextShowState = show;
987
988                 if (__pDescriptionText != null)
989                 {
990                         __pDescriptionText->SetVisibleState(__descriptionTextShowState);
991
992                         Dimension itemDimension = GetSize();
993                         int descriptionTextHeight = GetDescriptionTextHeight();
994
995                         itemDimension.height += ((__descriptionTextShowState) ? (descriptionTextHeight) : (-descriptionTextHeight));
996
997                         // Set position & item height
998                         SetItemCustomHeight((__descriptionTextShowState ? (itemDimension.height - descriptionTextHeight) : 0));
999                         SetItemHeight(itemDimension.height);
1000
1001                         SetSize(itemDimension);
1002                 }
1003         }
1004 }
1005
1006 void
1007 _ListViewItem::SetContextItemEventListener(_IActionEventListener& listener)
1008 {
1009         __pContextItemEventListener = &listener;
1010 }
1011
1012 void
1013 _ListViewItem::SetContextItemActivationState(bool activate)
1014 {
1015         _ListViewContextItem* pContextItem = static_cast<_ListViewContextItem*>(GetContextItem());
1016
1017         if ((pContextItem != null) && (__pContextItemEventListener != null))
1018         {
1019                 if (activate)
1020                 {
1021                         pContextItem->AddContextItemEventListener(*__pContextItemEventListener);
1022                 }
1023                 else
1024                 {
1025                         pContextItem->RemoveContextItemEventListener(*__pContextItemEventListener);
1026                 }
1027         }
1028 }
1029
1030 bool
1031 _ListViewItem::OnTouchPressed(const _Control& source, const _TouchInfo& touchinfo)
1032 {
1033         _TableViewItem::OnTouchPressed(source, touchinfo);
1034
1035         if ((&source != this) && (source.GetParent() != this))
1036         {
1037                 return false;
1038         }
1039
1040         ClearLastStateChangedInfo();
1041         StopTextSlideTimer();
1042
1043         Point pos = touchinfo.GetCurrentPosition();
1044         __prevTouchPos.SetPosition(pos.x, pos.y);
1045
1046         __selectedElementId = GetElementIdFromPosition(pos);
1047
1048         _ListViewItemElement* pElement = GetElement(__selectedElementId);
1049
1050         if (pElement != null)
1051         {
1052                 if ((pElement->actionElement) && (pElement->selectionEnabled))
1053                 {
1054                         __selectionEabledBgColor = GetItemBackgroundColor(LIST_ITEM_STATE_PRESSED);
1055                         SetItemBackgroundColor(LIST_ITEM_STATE_PRESSED, GetItemBackgroundColor(LIST_ITEM_STATE_NORMAL));
1056
1057                         __selectionEabled = true;
1058                 }
1059
1060                 if (pElement->elementType == LISTVIEW_ITEM_ELEMENT_TEXT)
1061                 {
1062                         SetCutlinkTextFocus(pos);
1063
1064                         if (pElement->pTextElement->textSlidingEnabled)
1065                         {
1066                                 pElement->pTextElement->pTextObject->SetAction(TEXT_OBJECT_ACTION_TYPE_SLIDE_LEFT);
1067                                 pElement->pTextElement->pTextObject->Compose();
1068
1069                                 if (pElement->pTextElement->pTextObject->IsActionOn())
1070                                 {
1071                                         StartTextSlideTimer();
1072                                 }
1073                         }
1074                 }
1075         }
1076
1077         __touchPressed = true;
1078
1079         SetLastStateChangedInfo();
1080         Invalidate();
1081
1082         return false;
1083 }
1084
1085 bool
1086 _ListViewItem::OnTouchReleased(const _Control& source, const _TouchInfo& touchinfo)
1087 {
1088         _TableViewItem::OnTouchReleased(source, touchinfo);
1089
1090         if ((&source != this) && (source.GetParent() != this))
1091         {
1092                 return false;
1093         }
1094
1095         ResetTextSlide();
1096         ResetCutlinkFocus();
1097
1098         if (__selectionEabled)
1099         {
1100                 SetItemBackgroundColor(LIST_ITEM_STATE_PRESSED, __selectionEabledBgColor);
1101                 __selectionEabled = false;
1102         }
1103
1104         __selectedElementId = -1;
1105         __touchPressed = false;
1106
1107         Invalidate();
1108
1109         return false;
1110 }
1111
1112 bool
1113 _ListViewItem::OnTouchMoved(const _Control& source, const _TouchInfo& touchinfo)
1114 {
1115         _TableViewItem::OnTouchMoved(source, touchinfo);
1116
1117         if (__touchPressed)
1118         {
1119                 ClearLastStateChangedInfo();
1120         }
1121
1122         ResetTextSlide();
1123
1124         __selectedElementId = -1;
1125         __touchPressed = false;
1126
1127         Invalidate();
1128
1129         return false;
1130 }
1131
1132 bool
1133 _ListViewItem::OnTouchCanceled(const _Control& source, const _TouchInfo& touchinfo)
1134 {
1135         _TableViewItem::OnTouchCanceled(source, touchinfo);
1136
1137         ResetTextSlide();
1138
1139         if (__selectionEabled)
1140         {
1141                 SetItemBackgroundColor(LIST_ITEM_STATE_PRESSED, __selectionEabledBgColor);
1142                 __selectionEabled = false;
1143         }
1144
1145         Invalidate();
1146
1147         return false;
1148 }
1149
1150 void
1151 _ListViewItem::OnDraw(void)
1152 {
1153         _TableViewItem::OnDraw();
1154
1155         DrawElements();
1156         DrawDivider();
1157 }
1158
1159 void
1160 _ListViewItem::OnBoundsChanged(void)
1161 {
1162         _TableViewItem::OnBoundsChanged();
1163
1164         _ListViewContextItem* pContextItem = static_cast<_ListViewContextItem*>(GetContextItem());
1165
1166         if (pContextItem != null)
1167         {
1168                 Rectangle bounds = GetBounds();
1169                 pContextItem->AdjustItemBounds(bounds);
1170         }
1171 }
1172
1173 ListViewItemDrawingStatus
1174 _ListViewItem::GetItemDrawingStatus(void)
1175 {
1176         TableViewItemDrawingStatus parentStatus = GetDrawingStatus();
1177         ListViewItemDrawingStatus status;
1178
1179         switch (parentStatus)
1180         {
1181         case TABLE_VIEW_ITEM_DRAWING_STATUS_PRESSED:
1182                 status = LISTVIEW_ITEM_STATUS_PRESSED;
1183                 break;
1184
1185         case TABLE_VIEW_ITEM_DRAWING_STATUS_HIGHLIGHTED:
1186                 status = LISTVIEW_ITEM_STATUS_HIGHLIGHTED;
1187                 break;
1188
1189         default:
1190                 status = LISTVIEW_ITEM_STATUS_NORMAL;
1191                 break;
1192         }
1193
1194         return status;
1195 }
1196
1197 void
1198 _ListViewItem::DrawElement(_ListViewItemElement* pElement)
1199 {
1200         // Get Current TableViewItem drawing status
1201         ListViewItemDrawingStatus status = GetItemDrawingStatus();
1202         Rectangle elementRect;
1203
1204         // Check element selection enabled
1205         if (status != LISTVIEW_ITEM_STATUS_NORMAL)
1206         {
1207                 if (__selectedElementId == -1)
1208                 {
1209                         if ((pElement->actionElement) && (pElement->selectionEnabled))
1210                         {
1211                                 status = LISTVIEW_ITEM_STATUS_NORMAL;
1212                         }
1213                 }
1214                 else if (__selectedElementId == pElement->elementId)
1215                 {
1216                         if ((pElement->actionElement) && (pElement->selectionEnabled))
1217                         {
1218                                 status = LISTVIEW_ITEM_STATUS_NORMAL;
1219                         }
1220                 }
1221                 else
1222                 {
1223                         bool enabled = false;
1224
1225                         if (GetElementSelectionEnabled(__selectedElementId, enabled) && enabled)
1226                         {
1227                                 status = LISTVIEW_ITEM_STATUS_NORMAL;
1228                         }
1229                 }
1230         }
1231
1232         Canvas* pCanvas = null;
1233
1234         switch (pElement->elementType)
1235         {
1236         case LISTVIEW_ITEM_ELEMENT_TEXT:
1237                 DrawText(pElement->bounds, status, pElement->pTextElement);
1238                 break;
1239
1240         case LISTVIEW_ITEM_ELEMENT_BITMAP:
1241                 DrawBitmap(pElement->bounds, status, pElement->pBitmapElement);
1242                 break;
1243
1244         case LISTVIEW_ITEM_ELEMENT_OBJ:
1245                 pCanvas = pElement->pCustomElement->pVE->GetCanvasN();
1246
1247                 if (pCanvas != null)
1248                 {
1249                         pCanvas->SetBackgroundColor(Color(0, 0, 0, 0));
1250                         pCanvas->Clear();
1251                         elementRect.SetBounds(0, 0, pElement->bounds.width, pElement->bounds.height);
1252
1253                         pElement->pCustomElement->pCustom->DrawElement(pCanvas, elementRect, status);
1254                 }
1255                 break;
1256
1257         default:
1258                 break;
1259         }
1260
1261         delete pCanvas;
1262 }
1263
1264 void
1265 _ListViewItem::DrawElements(void)
1266 {
1267         _LinkedList <_ListViewItemElement>::_Iterator iter;
1268
1269         for (iter = __elements.begin(); iter != __elements.end(); iter++)
1270         {
1271                 DrawElement(&(*iter));
1272         }
1273 }
1274
1275 bool
1276 _ListViewItem::DrawText(Rectangle& rect, ListViewItemDrawingStatus status, _ListViewItemElementText* pText)
1277 {
1278         SysTryReturn(NID_UI_CTRL, (pText != null), false, E_INVALID_ARG, "[E_INVALID_ARG] This Text element is null.");
1279
1280         Rectangle bounds(rect.x, rect.y, rect.width, rect.height);
1281
1282         if (pText->pVE->GetParent() == null)
1283         {
1284                 GetVisualElement()->AttachChild(*(pText->pVE));
1285                 pText->pVE->SetShowState(true);
1286         }
1287
1288         if (pText->textSize > 0)
1289         {
1290                 pText->pTextObject->SetFont(GetFont(FONT_STYLE_PLAIN, pText->textSize), 0, pText->pTextObject->GetTextLength());
1291         }
1292
1293         // Calculate Text element bounds
1294         if (pText->pEnrichedText == null)
1295         {
1296                 Dimension textDimension = pText->pTextObject->GetTextExtent(0, pText->pTextObject->GetTextLength());
1297                 TextObjectAlignment textAlign = pText->pTextObject->GetAlignment();
1298
1299                 if (__itemType == LISTVIEW_ITEM_TYPE_CUSTOM)
1300                 {
1301                         if (textDimension.width < bounds.width)
1302                         {
1303                                 bounds.width = textDimension.width;
1304
1305                                 if ((0x0007 & textAlign) == TEXT_OBJECT_ALIGNMENT_CENTER)
1306                                 {
1307                                         bounds.x = rect.x + ((rect.width - bounds.width) / 2);
1308                                 }
1309                                 else if ((0x0007 & textAlign) == TEXT_OBJECT_ALIGNMENT_RIGHT)
1310                                 {
1311                                         bounds.x = rect.x + (rect.width - bounds.width);
1312                                 }
1313                         }
1314                         if (textDimension.height < bounds.height)
1315                         {
1316                                 bounds.height = textDimension.height;
1317
1318                                 if ((0x0700 & textAlign) == TEXT_OBJECT_ALIGNMENT_MIDDLE)
1319                                 {
1320                                         bounds.y = rect.y + ((rect.height - bounds.height) / 2);
1321                                 }
1322                                 else if ((0x0700 & textAlign) == TEXT_OBJECT_ALIGNMENT_BOTTOM)
1323                                 {
1324                                         bounds.y = rect.y + (rect.height - bounds.height);
1325                                 }
1326                         }
1327                 }
1328                 else
1329                 {
1330                         if ((bounds.width != textDimension.width) || (bounds.height != textDimension.height))
1331                         {
1332                                 int itemWidth = GetBounds().width;
1333
1334                                 bounds.x = rect.x;
1335                                 bounds.y = rect.y + ((rect.height - textDimension.height) / 2);
1336                                 bounds.width = ((itemWidth > bounds.x + textDimension.width) ? textDimension.width : (itemWidth - bounds.x));
1337                                 bounds.height = textDimension.height;
1338
1339                                 rect = bounds;
1340                         }
1341                 }
1342         }
1343
1344         pText->pVE->SetBounds(FloatRectangle(bounds.x, bounds.y, bounds.width, bounds.height));
1345
1346         // Check to EnrichedText contains Cutlink
1347         if ((pText->cutlinkViewModeEnabled == true) && (pText->cutlinkParseEnabled == true)
1348                         && (pText->pTextObject->GetTotalCutLinkElementCount() <= 0))
1349         {
1350                 if (ParseCutlinkText(pText) == true)
1351                 {
1352                         pText->pTextObject->SetCutLinkViewMode(true);
1353                 }
1354         }
1355         else if (pText->pEnrichedText == null)
1356         {
1357                 if (IsItemEnabled() == true)
1358                 {
1359                         pText->pTextObject->SetForegroundColor(pText->textColor[status], 0, pText->pTextObject->GetTextLength());
1360                 }
1361                 else
1362                 {
1363                         Color disableTextColor;
1364                         GET_COLOR_CONFIG(LISTVIEW::ITEM_TEXT_DISABLED, disableTextColor);
1365
1366                         pText->pTextObject->SetForegroundColor(disableTextColor, 0, pText->pTextObject->GetTextLength());
1367                 }
1368         }
1369
1370         pText->pTextObject->SetAction(TEXT_OBJECT_ACTION_TYPE_ABBREV);
1371         pText->pTextObject->SetBounds(Rectangle(0, 0, bounds.width, bounds.height));
1372
1373         Canvas* pCanvas = pText->pVE->GetCanvasN();
1374         SysTryReturn(NID_UI_CTRL, (pCanvas != null), false, GetLastResult(), "[%s] Propagating.", GetErrorMessage(GetLastResult()));
1375
1376         pCanvas->SetBackgroundColor(Color(0, 0, 0, 0));
1377         pCanvas->Clear();
1378
1379         pText->pTextObject->Draw(*_CanvasImpl::GetInstance(*pCanvas));
1380
1381         delete pCanvas;
1382
1383         return true;
1384 }
1385
1386 bool
1387 _ListViewItem::DrawBitmap(Rectangle& rect, ListViewItemDrawingStatus status, _ListViewItemElementBitmap* pBitmap)
1388 {
1389         SysTryReturn(NID_UI_CTRL, (pBitmap != null), false, E_INVALID_ARG, "[E_INVALID_ARG] This Bitmap element is null.");
1390
1391         Bitmap* pDrawBitmap = pBitmap->pBitmap[status];
1392         if ((pDrawBitmap == null) && (status != LISTVIEW_ITEM_STATUS_NORMAL))
1393         {
1394                 pDrawBitmap = pBitmap->pBitmap[LISTVIEW_ITEM_STATUS_NORMAL];
1395         }
1396
1397         SysTryReturn(NID_UI_CTRL, (pDrawBitmap != null), false, E_INVALID_ARG, "[E_INVALID_ARG] This Bitmap element is null.");
1398
1399         if (pBitmap->pVE->GetParent() == null)
1400         {
1401                 GetVisualElement()->AttachChild(*(pBitmap->pVE));
1402                 pBitmap->pVE->SetShowState(true);
1403         }
1404
1405         pBitmap->pVE->SetBounds(FloatRectangle(rect.x, rect.y, rect.width, rect.height));
1406
1407         Canvas* pCanvas = pBitmap->pVE->GetCanvasN();
1408         SysTryReturn(NID_UI_CTRL, (pCanvas != null), false, GetLastResult(), "[%s] Propagating.", GetErrorMessage(GetLastResult()));
1409
1410         pCanvas->SetBackgroundColor(Color(0, 0, 0, 0));
1411         pCanvas->Clear();
1412
1413         if (pDrawBitmap->IsNinePatchedBitmap())
1414         {
1415                 pCanvas->DrawNinePatchedBitmap(Rectangle(0, 0, rect.width, rect.height), *pDrawBitmap);
1416         }
1417         else
1418         {
1419                 pCanvas->DrawBitmap(Rectangle(0, 0, rect.width, rect.height), *pDrawBitmap);
1420         }
1421
1422         delete pCanvas;
1423
1424         return true;
1425 }
1426
1427 void
1428 _ListViewItem::DrawDivider(void)
1429 {
1430         if ((__itemType == LISTVIEW_ITEM_TYPE_GROUP) && (GetItemBackgroundBitmap(LIST_ITEM_STATE_NORMAL) == null))
1431         {
1432                 int lineHeight = 0;
1433                 int lineLeftMargin = 0;
1434                 int lineBottomMargin = 0;
1435                 int lineTopMargin = 0;
1436                 GET_SHAPE_CONFIG(LISTVIEW::GROUPITEM_DIVIDER_HEIGHT, _CONTROL_ORIENTATION_PORTRAIT, lineHeight);
1437                 GET_SHAPE_CONFIG(LISTVIEW::GROUPITEM_DIVIDER_LEFT_MARGIN, _CONTROL_ORIENTATION_PORTRAIT, lineLeftMargin);
1438                 GET_SHAPE_CONFIG(LISTVIEW::GROUPITEM_DIVIDER_BOTTOM_MARGIN, _CONTROL_ORIENTATION_PORTRAIT, lineBottomMargin);
1439
1440                 Rectangle bounds = GetBounds();
1441                 _ListViewItemElementText* pElementText = GetElementText(LIST_ITEM_RESERVED_ID_3);
1442                 if ((pElementText != null) && (pElementText->pVE != null))
1443                 {
1444                         FloatRectangle textBounds = pElementText->pVE->GetBounds();
1445                         lineTopMargin = (int)(textBounds.y + textBounds.height);
1446                 }
1447                 else
1448                 {
1449                         lineTopMargin = bounds.height - lineBottomMargin;
1450                 }
1451
1452                 if (bounds.height <= lineTopMargin)
1453                 {
1454                         return;
1455                 }
1456
1457                 if (__pDivider == null)
1458                 {
1459                         __pDivider = _Label::CreateLabelN();
1460                         SysTryReturnVoidResult(NID_UI_CTRL, __pDivider != null, E_OUT_OF_MEMORY, "[%s] Propagating.", GetErrorMessage(GetLastResult()));
1461
1462                         AttachSystemChild(*__pDivider);
1463                 }
1464
1465                 Color underLineColor;
1466                 GET_COLOR_CONFIG(LISTVIEW::GROUPITEM_DIVIDER_NORMAL, underLineColor);
1467
1468                 __pDivider->SetBounds(Rectangle(lineLeftMargin, lineTopMargin, bounds.width - lineLeftMargin * 2, lineHeight));
1469                 __pDivider->SetBackgroundColor(underLineColor);
1470                 __pDivider->Invalidate();
1471         }
1472 }
1473
1474 void
1475 _ListViewItem::StartTextSlideTimer(void)
1476 {
1477         result r = E_SUCCESS;
1478
1479         if (__pTextSlideTimer == null)
1480         {
1481                 __pTextSlideTimer = new (std::nothrow) Timer();
1482
1483                 r = __pTextSlideTimer->Construct(*this);
1484                 SysTryCatch(NID_UI, (r == E_SUCCESS), ,E_SYSTEM, ("[E_SYSTEM] Timer cannot construct."));
1485         }
1486         else
1487         {
1488                 __pTextSlideTimer->Cancel();
1489         }
1490
1491         r = __pTextSlideTimer->Start(TEXT_SLIDING_TIMER_DURATION);
1492         SysTryCatch(NID_UI, (r == E_SUCCESS), , E_SYSTEM, ("[E_SYSTEM] Timer Start failed."));
1493
1494         return;
1495
1496 CATCH:
1497         StopTextSlideTimer();
1498 }
1499
1500 void
1501 _ListViewItem::StopTextSlideTimer(void)
1502 {
1503         delete __pTextSlideTimer;
1504         __pTextSlideTimer = null;
1505 }
1506
1507 bool
1508 _ListViewItem::IsTextSlideTimerRunning(void)
1509 {
1510         return (__pTextSlideTimer != null);
1511 }
1512
1513 void
1514 _ListViewItem::OnTextSlideTimerExpired(void)
1515 {
1516         if (__selectedElementId != -1)
1517         {
1518                 _ListViewItemElement* pElement = GetElement(__selectedElementId);
1519
1520                 if ((pElement != null) && (pElement->pTextElement->pTextObject != null))
1521                 {
1522                         TextObject* pTextObject = pElement->pTextElement->pTextObject;
1523
1524                         Canvas* pCanvas = (pElement->pTextElement->pVE)->GetCanvasN();
1525                         SysTryReturnVoidResult(NID_UI_CTRL, (pCanvas != null), GetLastResult(), "[%s] Propagating.", GetErrorMessage(GetLastResult()));
1526
1527                         pCanvas->SetBackgroundColor(Color(0, 0, 0, 0));
1528                         pCanvas->Clear();
1529
1530                         pTextObject->SetForegroundColor(pElement->pTextElement->textColor[LISTVIEW_ITEM_STATUS_PRESSED], 0, pTextObject->GetTextLength());
1531                         pTextObject->SetAction(TEXT_OBJECT_ACTION_TYPE_SLIDE_LEFT);
1532                         pTextObject->Compose();
1533                         pTextObject->DrawWithOffset(*_CanvasImpl::GetInstance(*pCanvas));
1534
1535                         pCanvas->Show(pElement->bounds);
1536                         StartTextSlideTimer();
1537
1538                         delete pCanvas;
1539                         pCanvas = null;
1540                 }
1541         }
1542 }
1543
1544 void
1545 _ListViewItem::ResetTextSlide(void)
1546 {
1547         if (IsTextSlideTimerRunning())
1548         {
1549                 StopTextSlideTimer();
1550
1551                 _ListViewItemElement* pElement = GetElement(__selectedElementId);
1552
1553                 if ((pElement != null) && (pElement->pTextElement->pTextObject != null))
1554                 {
1555                         pElement->pTextElement->pTextObject->SetAction(TEXT_OBJECT_ACTION_TYPE_ABBREV);
1556                         pElement->pTextElement->pTextObject->SetForegroundColor(pElement->pTextElement->textColor[LISTVIEW_ITEM_STATUS_NORMAL],
1557                                         0, pElement->pTextElement->pTextObject->GetTextLength());
1558                 }
1559         }
1560 }
1561
1562 void
1563 _ListViewItem::OnTimerExpired(Timer& timer)
1564 {
1565         _TableViewItem::OnTimerExpired(timer);
1566
1567         if (&timer == __pTextSlideTimer)
1568         {
1569                 OnTextSlideTimerExpired();
1570         }
1571 }
1572
1573 bool
1574 _ListViewItem::ParseCutlinkText(_ListViewItemElementText* pElementText)
1575 {
1576         if ((pElementText == null) || (pElementText->pEnrichedText == null))
1577         {
1578                 return false;
1579         }
1580
1581         TextObject* pTextObject = pElementText->pTextObject;
1582         unsigned long cutlinkMaskType = pElementText->cutlinkMaskType;
1583         TextLinkInfo* pTextLinkInfo = null;
1584         TextLinkInfo* pNextLinkInfo = null;
1585         int currentOffset = 0;
1586         bool isChangingCutlink = false;
1587         wchar_t* pCutlinkString = null;
1588         bool ret = true;
1589
1590         int strLength = pTextObject->GetTextLength();
1591         wchar_t* pStr = new (std::nothrow) wchar_t[strLength + 1];
1592         SysTryReturn(NID_UI, (pStr != null), false, E_OUT_OF_MEMORY, ("[E_OUT_OF_MEMORY] The memory is insufficient."));
1593
1594         pTextObject->GetText(pStr, strLength);
1595
1596         TextCutLinkParser* pParser = new (std::nothrow) TextCutLinkParser();
1597         SysTryCatch(NID_UI, (pParser != null), (ret = false), E_OUT_OF_MEMORY, ("[E_OUT_OF_MEMORY] The memory is insufficient."));
1598
1599         pParser->SetCutLinkMask(cutlinkMaskType);
1600
1601         pTextLinkInfo = pParser->Parse(pStr, strLength, 0);
1602         SysTryCatch(NID_UI, (pTextLinkInfo != null), (ret = false), E_SYSTEM, ("[E_SYSTEM] TextLinkInfo is not valid."));
1603
1604         // remove all text element in _EnrichedTextImpl
1605         pElementText->pEnrichedText->RemoveAllTextElements(true);
1606
1607         while (pTextLinkInfo != null)
1608         {
1609                 isChangingCutlink = false;
1610
1611                 switch (pTextLinkInfo->linkType)
1612                 {
1613                 case LINK_TYPE_URL:
1614                         if (cutlinkMaskType & LINK_TYPE_URL)
1615                         {
1616                                 isChangingCutlink = true;
1617                         }
1618                         break;
1619
1620                 case LINK_TYPE_EMAIL:
1621                         if (cutlinkMaskType & LINK_TYPE_EMAIL)
1622                         {
1623                                 isChangingCutlink = true;
1624                         }
1625                         break;
1626
1627                 case LINK_TYPE_TEL_NUM:
1628                         if (cutlinkMaskType & LINK_TYPE_TEL_NUM)
1629                         {
1630                                 isChangingCutlink = true;
1631                         }
1632                         break;
1633
1634                 case LINK_TYPE_APPCONTROL:
1635                         if (cutlinkMaskType & LINK_TYPE_APPCONTROL)
1636                         {
1637                                 isChangingCutlink = true;
1638                         }
1639                         break;
1640
1641                 case LINK_TYPE_MIME:
1642                         if (cutlinkMaskType & LINK_TYPE_MIME)
1643                         {
1644                                 isChangingCutlink = true;
1645                         }
1646                         break;
1647
1648                 default:
1649                         break;
1650                 }
1651
1652                 pCutlinkString = new (std::nothrow) wchar_t[pTextLinkInfo->length + 1];
1653
1654                 if (pCutlinkString == null)
1655                 {
1656                         while (pTextLinkInfo != null)
1657                         {
1658                                 pNextLinkInfo = pTextLinkInfo->pNextLinkInfo;
1659                                 delete pTextLinkInfo;
1660                                 pTextLinkInfo = pNextLinkInfo;
1661                         }
1662                         SysTryCatch(NID_UI, (pTextLinkInfo != null), (ret = false), E_SYSTEM, ("[E_SYSTEM] TextLinkInfo is not valid."));
1663                 }
1664
1665                 for (int i = 0; i < pTextLinkInfo->length; i++)
1666                 {
1667                         pCutlinkString[i] = pStr[pTextLinkInfo->srcOffset + i];
1668                 }
1669
1670                 pCutlinkString[pTextLinkInfo->length] = null;
1671
1672                 if (currentOffset < pTextLinkInfo->srcOffset)
1673                 {
1674                         TextSimple* pSimpleText = new (std::nothrow) TextSimple(pStr + currentOffset, pTextLinkInfo->srcOffset - currentOffset);
1675                         pTextObject->AppendElement(*pSimpleText);
1676                 }
1677
1678                 if (isChangingCutlink == true)
1679                 {
1680                         TextCutLink* pTextElement = new (std::nothrow) TextCutLink(false, pTextLinkInfo->linkType, pStr + pTextLinkInfo->srcOffset,
1681                                                                                                                                            pTextLinkInfo->length);
1682                         pTextElement->SetEditModeEnable(true);
1683                         pTextObject->AppendElement(*pTextElement);
1684                 }
1685                 else
1686                 {
1687                         TextSimple* pSimpleText = new (std::nothrow) TextSimple(pCutlinkString, pTextLinkInfo->length);
1688                         pTextObject->AppendElement(*pSimpleText);
1689                 }
1690
1691                 currentOffset = pTextLinkInfo->srcOffset + pTextLinkInfo->length;
1692
1693                 pNextLinkInfo = pTextLinkInfo->pNextLinkInfo;
1694                 delete pTextLinkInfo;
1695                 pTextLinkInfo = pNextLinkInfo;
1696
1697                 delete[] pCutlinkString;
1698                 pCutlinkString = null;
1699         }
1700
1701         if (strLength != currentOffset)
1702         {
1703                 TextSimple* pSimpleText = new (std::nothrow) TextSimple(pStr + currentOffset, strLength - currentOffset);
1704                 pTextObject->AppendElement(*pSimpleText);
1705         }
1706
1707         //pTextObject->SetRange(0, pTextObject->GetLength());
1708         //pTextObject->NotifyTextChanged(0, pTextObject->GetLength());
1709         pTextObject->Compose();
1710
1711 CATCH:
1712         delete pParser;
1713         pParser = null;
1714
1715         if (pStr != null)
1716         {
1717                 delete[] pStr;
1718                 pStr = null;
1719         }
1720
1721         return ret;
1722 }
1723
1724 bool
1725 _ListViewItem::IsCutlinkTextSelected(const Point& position, int* index, _ListViewItemUiLinkInfo** ppInfo) const
1726 {
1727         int elementId = GetElementIdFromPosition(position);
1728         _ListViewItemElementText* pElement = GetElementText(elementId);
1729
1730         if ((pElement != null) && (pElement->pTextObject) && (pElement->cutlinkViewModeEnabled))
1731         {
1732                 TextObject* pTextObject = pElement->pTextObject;
1733                 Rectangle displayRect = pTextObject->GetBounds();
1734                 int selectedIndex = pTextObject->GetCutLinkIndexFromPositionData(position.x - displayRect.x, position.y - displayRect.y);
1735
1736                 if (selectedIndex >= 0)
1737                 {
1738                         *index = selectedIndex;
1739                         TextCutLink* pCutLinkObject = dynamic_cast<TextCutLink*>(pTextObject->GetCutLinkElementAtCutLinkElementIndex(selectedIndex));
1740                         if (pCutLinkObject == null)
1741                         {
1742                                 return false;
1743                         }
1744
1745                         String cutLinkString(pCutLinkObject->GetText());
1746                         LinkType baseLinkType = pCutLinkObject->GetCutLinkType();
1747
1748                         if (baseLinkType & pElement->cutlinkMaskType)
1749                         {
1750                                 _ListViewItemUiLinkInfo* pUiLinkInfo = new (std::nothrow) _ListViewItemUiLinkInfo();
1751
1752                                 pUiLinkInfo->textInfo = cutLinkString;
1753                                 pUiLinkInfo->linkType = baseLinkType;
1754                                 pUiLinkInfo->linkInfo = cutLinkString;
1755
1756                                 *ppInfo = pUiLinkInfo;
1757                         }
1758                 }
1759
1760                 return true;
1761         }
1762
1763         return false;
1764 }
1765
1766 bool
1767 _ListViewItem::SetCutlinkTextFocus(const Point& position)
1768 {
1769         int elementId = GetElementIdFromPosition(position);
1770         _ListViewItemElementText* pElement = GetElementText(elementId);
1771
1772         if ((pElement != null) && (pElement->pTextObject != null) && (pElement->cutlinkViewModeEnabled))
1773         {
1774                 TextObject* pTextObject = pElement->pTextObject;
1775                 Rectangle displayRect = pTextObject->GetBounds();
1776
1777                 int index = pTextObject->GetCutLinkIndexFromPositionData(position.x - displayRect.x, position.y - displayRect.y);
1778
1779                 if (index >= 0)
1780                 {
1781                         pTextObject->ChangeCutLinkState(index, true);
1782                         return true;
1783                 }
1784         }
1785
1786         return false;
1787 }
1788
1789 bool
1790 _ListViewItem::ResetCutlinkFocus(void)
1791 {
1792         _LinkedList <_ListViewItemElement>::_Iterator iter;
1793
1794         for (iter = __elements.begin(); iter != __elements.end(); iter++)
1795         {
1796                 if ((iter->elementType == LISTVIEW_ITEM_ELEMENT_TEXT) && (iter->pTextElement->pTextObject))
1797                 {
1798                         iter->pTextElement->pTextObject->ResetAllCutLinkElementsState();
1799                 }
1800         }
1801
1802         return true;
1803 }
1804
1805 Font*
1806 _ListViewItem::GetFont(unsigned long fontStyle, int fontSize)
1807 {
1808         __fontStyle = fontStyle;
1809         __fontSize = fontSize;
1810
1811         return GetFallbackFont();
1812 }
1813
1814 void
1815 _ListViewItem::OnFontChanged(Font* pFont)
1816 {
1817         __fontName = _Control::GetFont();
1818
1819         if (__pDescriptionText != null)
1820         {
1821                 __pDescriptionText->SetFont(__fontName);
1822         }
1823
1824         if (GetContextItem() != null)
1825         {
1826                 GetContextItem()->SetFont(__fontName);
1827         }
1828 }
1829
1830 void
1831 _ListViewItem::OnFontInfoRequested(unsigned long& style, int& size)
1832 {
1833         style = __fontStyle;
1834         size =  __fontSize;
1835 }
1836
1837 void
1838 _ListViewItem::OnAncestorEnableStateChanged(const _Control& control)
1839 {
1840         _LinkedList <_ListViewItemElement>::_Iterator iter;
1841
1842         for (iter = __elements.begin(); iter != __elements.end(); iter++)
1843         {
1844                 if (iter->elementType == LISTVIEW_ITEM_ELEMENT_TEXT)
1845                 {
1846                         DrawText(iter->bounds, GetItemDrawingStatus(), iter->pTextElement);
1847                 }
1848         }
1849 }
1850
1851 bool
1852 CompareAccessibilityElement(_ListViewItemElement* a, _ListViewItemElement* b)
1853 {
1854         if (a->bounds.y == b->bounds.y)
1855         {
1856                 return (a->bounds.x < b->bounds.x);
1857         }
1858
1859         return (a->bounds.y < b->bounds.y);
1860 }
1861
1862 void
1863 _ListViewItem::SetAccessibilityElement(void)
1864 {
1865         _AccessibilityContainer* pContainer = GetAccessibilityContainer();
1866
1867         if (pContainer)
1868         {
1869                 pContainer->RemoveAllElement();
1870
1871                 _LinkedList <_ListViewItemElement*> accessibilityElementList;
1872
1873                 _LinkedList <_ListViewItemElement>::_Iterator iter;
1874
1875                 for (iter = __elements.begin(); iter != __elements.end(); iter++)
1876                 {
1877                         if (iter->elementType == LISTVIEW_ITEM_ELEMENT_TEXT)
1878                         {
1879                                 accessibilityElementList.push_back(&(*iter));
1880                         }
1881                 }
1882
1883                 accessibilityElementList.sort(CompareAccessibilityElement);
1884
1885                 _LinkedList <_ListViewItemElement*>::_Iterator accessibilityIter;
1886                 _ListViewItemElement* pElement = null;
1887
1888                 for (accessibilityIter = accessibilityElementList.begin(); accessibilityIter != accessibilityElementList.end(); accessibilityIter++)
1889                 {
1890                         pElement = *accessibilityIter;
1891
1892                         int textLength = pElement->pTextElement->pTextObject->GetTextLength();
1893
1894                         wchar_t* pAccessibilityText = new (std::nothrow) wchar_t[textLength + 1];
1895                         SysTryReturnVoidResult(NID_UI_CTRL, (pAccessibilityText != null), E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
1896
1897                         pElement->pTextElement->pTextObject->GetText(pAccessibilityText, textLength);
1898
1899                         pElement->pTextElement->pAccessibilityElement = new (std::nothrow) _AccessibilityElement(true);
1900                         SysTryReturnVoidResult(NID_UI_CTRL, (pElement->pTextElement->pAccessibilityElement != null), E_OUT_OF_MEMORY,
1901                                         "[E_OUT_OF_MEMORY] The memory is insufficient.");
1902
1903                         pElement->pTextElement->pAccessibilityElement->SetBounds(pElement->bounds);
1904                         pElement->pTextElement->pAccessibilityElement->SetLabel(String(pAccessibilityText));
1905                         pElement->pTextElement->pAccessibilityElement->SetTrait(ACCESSIBILITY_TRAITS_LIST);
1906                         pElement->pTextElement->pAccessibilityElement->SetName(L"ListViewItemText");
1907
1908                         pContainer->AddElement(*(pElement->pTextElement->pAccessibilityElement));
1909
1910                         delete[] pAccessibilityText;
1911                 }
1912
1913                 accessibilityElementList.clear();
1914
1915                 if (__pDivider != null)
1916                 {
1917                         _AccessibilityContainer* pDividerContainer = __pDivider->GetAccessibilityContainer();
1918                         if (pDividerContainer != null)
1919                         {
1920                                 pDividerContainer->Activate(false);
1921                         }
1922                 }
1923         }
1924 }
1925
1926 _ListViewItemHitTestVEDelegator::_ListViewItemHitTestVEDelegator(void)
1927 {
1928 }
1929
1930 _ListViewItemHitTestVEDelegator::~_ListViewItemHitTestVEDelegator(void)
1931 {
1932 }
1933
1934 HitTestResult
1935 _ListViewItemHitTestVEDelegator::HitTest(VisualElement& target, const FloatPoint& point)
1936 {
1937         return HIT_TEST_NOWHERE;
1938 }
1939
1940 }}} // Tizen::Ui::Controls