274fa794a536155f8c6072e927a6f93b697092ec
[platform/framework/native/uifw.git] / src / ui / controls / FUiCtrl_PopupImpl.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 /**
19  * @file                FUiCtrl_PopupImpl.cpp
20  * @brief       This is the implementation file for the _PopupImpl class.
21  */
22
23
24 #include <FUiLayout.h>
25 #include <FBaseSysLog.h>
26 #include <FUiAccessibilityContainer.h>
27 #include <FUiAccessibilityElement.h>
28 #include "FUi_CoordinateSystemUtils.h"
29 #include "FUi_UiBuilder.h"
30 #include "FUi_DataBindingContextImpl.h"
31 #include "FUi_ResourceSizeInfo.h"
32 #include "FUi_ResourceManager.h"
33 #include "FUi_ControlImplManager.h"
34 #include "FUi_LayoutImpl.h"
35 #include "FUi_Math.h"
36 #include "FUiCtrl_FrameImpl.h"
37 #include "FUiCtrl_PopupImpl.h"
38 #include "FUiCtrl_Popup.h"
39 #include "FUiCtrl_Form.h"
40 #include "FUiCtrl_Indicator.h"
41
42
43 using namespace Tizen::Ui::Animations;
44 using namespace Tizen::Graphics;
45 using namespace Tizen::Ui;
46
47
48 namespace Tizen { namespace Ui { namespace Controls
49 {
50
51
52 FloatDimension
53 _PopupImpl::PopupSizeInfo::GetDefaultMinimumSizeF(_ControlOrientation orientation) const
54 {
55         result r = E_SUCCESS;
56         FloatDimension dimension(0, 0);
57
58         r = GET_DIMENSION_CONFIG(POPUP::MIN_SIZE, orientation, dimension);
59         SysTryReturn(NID_UI_CTRL, r == E_SUCCESS, dimension, r, "[%s] A system error occurred.", GetErrorMessage(r));
60         SetLastResult(r);
61
62         return dimension;
63 }
64
65 _PopupImpl*
66 _PopupImpl::GetInstance(Popup& pPopup)
67 {
68         return static_cast <_PopupImpl*>(pPopup._pControlImpl);
69 }
70
71 const _PopupImpl*
72 _PopupImpl::GetInstance(const Popup& pPopup)
73 {
74         return static_cast <const _PopupImpl*>(pPopup._pControlImpl);
75 }
76
77 _PopupImpl::_PopupImpl(Popup* pPublic, _Popup* pCore, Layout* pPublicPortraitLayout, Layout* pPublicLandscapeLayout)
78         : _WindowImpl(pPublic, pCore, pPublicPortraitLayout, pPublicLandscapeLayout)
79         , _isModal(false)
80         , _centerAlign(false)
81         , __init(false)
82         , __callBoundsChange(false)
83         , __prevPos(0.0f, 0.0f)
84         , __boundsChangedInternally(false)
85         , __boundsChangedExternally(false)
86 {
87         //empty statement
88 }
89
90 _PopupImpl::~_PopupImpl(void)
91 {
92         //empty statement
93 }
94
95 _PopupImpl*
96 _PopupImpl::CreatePopupImplN(Popup* pControl, const Tizen::Graphics::FloatDimension& dim, Layout* pPublicPortraitLayout, Layout* pPublicLandscapeLayout)
97 {
98         result r = E_SUCCESS;
99
100         r = GET_SIZE_INFO(Popup).CheckInitialSizeValidF(dim, _CONTROL_ORIENTATION_PORTRAIT);
101         SysTryReturn(NID_UI_CTRL, r == E_SUCCESS, null, E_INVALID_ARG, "[E_INVALID_ARG] The given size is not valid.");
102
103         _PopupImpl* pImpl = null;
104         _Popup* pCore = null;
105
106         pCore = _Popup::CreatePopupN();
107         SysTryReturn(NID_UI_CTRL, pCore, null, E_SYSTEM, "[%s] Propagating.", GetErrorMessage(GetLastResult()));
108
109         pImpl = new (std::nothrow) _PopupImpl(pControl, pCore, pPublicPortraitLayout, pPublicLandscapeLayout);
110         r = CheckConstruction(pCore, pImpl);
111         SysTryReturn(NID_UI_CTRL, r == E_SUCCESS, null, r, "[%s] Propagating.", GetErrorMessage(r));
112
113         r = pImpl->InitializeBoundsPropertiesF(GET_SIZE_INFO(Popup), dim, pCore->GetOrientation());
114         SysTryCatch(NID_UI_CTRL, r == E_SUCCESS, , r, "[%s] Propagating.", GetErrorMessage(r));
115
116         ClearLastResult();
117
118         return pImpl;
119
120 CATCH:
121         delete pImpl;   //This deletes pCore as well
122
123         return null;
124 }
125
126 result
127 _PopupImpl::Initialize(bool hasTitle, const Tizen::Graphics::FloatDimension& dim)
128 {
129         result r = E_SUCCESS;
130
131         FloatRectangle bounds = GetCenterAlignedRect(dim.width, dim.height);
132         __init = true;
133         _centerAlign = true;
134         __boundsChangedInternally = true;
135         r = SetBounds(bounds);
136         __boundsChangedInternally = false;
137         SysTryReturn(NID_UI_CTRL, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
138         return GetCore().Initialize(hasTitle, bounds);
139 }
140
141 const char*
142 _PopupImpl::GetPublicClassName(void) const
143 {
144         return "Tizen::Ui::Controls::Popup";
145 }
146
147 const Popup&
148 _PopupImpl::GetPublic(void) const
149 {
150         return static_cast <const Popup&>(_ControlImpl::GetPublic());
151 }
152
153 Popup&
154 _PopupImpl::GetPublic(void)
155 {
156         return static_cast <Popup&>(_ControlImpl::GetPublic());
157 }
158
159 const _Popup&
160 _PopupImpl::GetCore(void) const
161 {
162         return static_cast <const _Popup&>(_ControlImpl::GetCore());
163 }
164
165 _Popup&
166 _PopupImpl::GetCore(void)
167 {
168         return static_cast <_Popup&>(_ControlImpl::GetCore());
169 }
170
171 FloatRectangle
172 _PopupImpl::GetCenterAlignedRect(float width, float height) const
173 {
174         float x = 0.0f;
175         float y = 0.0f;
176
177         _ControlManager* pControlManager = _ControlManager::GetInstance();
178
179         FloatDimension screenRect = pControlManager->GetScreenSizeF();
180
181         if (GetCore().GetOrientation() == _CONTROL_ORIENTATION_LANDSCAPE)
182         {
183                 float temp = screenRect.width;
184                 screenRect.width = screenRect.height;
185                 screenRect.height = temp;
186         }
187
188         x = (screenRect.width - width) / 2.0f;
189         y = (screenRect.height - height) / 2.0f;
190
191         return FloatRectangle(x, y, width, height);
192 }
193
194 FloatRectangle
195 _PopupImpl::GetClientAreaBounds(void) const
196 {
197         return CoordinateSystem::AlignToDevice(_ControlImpl::GetClientBoundsF());
198 }
199
200 Canvas*
201 _PopupImpl::GetClientAreaCanvasN(void) const
202 {
203         return GetCore().GetClientAreaCanvasN();
204 }
205
206 FloatPoint
207 _PopupImpl::TranslateFromClientAreaPosition(const FloatPoint& clientPosition) const
208 {
209         return GetCore().TranslateFromClientAreaPosition(clientPosition);
210 }
211
212 FloatPoint
213 _PopupImpl::TranslateToClientAreaPosition(const FloatPoint& position) const
214 {
215         return GetCore().TranslateToClientAreaPosition(position);
216 }
217
218 result
219 _PopupImpl::DoModal(int& modalResult)
220 {
221         SysTryReturn(NID_UI_CTRL, GetVisibleState() != false, E_INVALID_STATE,
222                                         E_INVALID_STATE, "[E_INVALID_STATE] The Popup is not visible");
223
224         _isModal = true;
225
226         return GetCore().DoModal(modalResult);
227 }
228
229 result
230 _PopupImpl::EndModal(int modalResult)
231 {
232         SysTryReturn(NID_UI_CTRL, _isModal == true, E_INVALID_STATE, E_INVALID_STATE,
233                                 "[E_INVALID_STATE] The method is not supported because this popup isn't running as a modal window.");
234
235         return GetCore().EndModal(modalResult);
236 }
237
238 result
239 _PopupImpl::SetColor(const Color& color)
240 {
241         GetCore().SetColor(color);
242
243         return E_SUCCESS;
244 }
245
246 Color
247 _PopupImpl::GetColor(void) const
248 {
249         return GetCore().GetColor();
250 }
251
252 result
253 _PopupImpl::SetTitleText(const Tizen::Base::String& title)
254 {
255         result r = GetCore().SetTitleText(title);
256         SysTryReturn(NID_UI_CTRL, r == E_SUCCESS, E_SYSTEM, r, "[%s] Propagating.", GetErrorMessage(r));
257
258         return r;
259 }
260
261 Tizen::Base::String
262 _PopupImpl::GetTitleText(void) const
263 {
264         return GetCore().GetTitleText();
265 }
266
267 result
268 _PopupImpl::SetTitleTextColor(const Color& color)
269 {
270         GetCore().SetTitleTextColor(color);
271
272         return E_SUCCESS;
273 }
274
275 Color
276 _PopupImpl::GetTitleTextColor() const
277 {
278         return GetCore().GetTitleTextColor();
279 }
280
281 DataBindingContext*
282 _PopupImpl::GetDataBindingContextN(void) const
283 {
284         return Tizen::Ui::_DataBindingContextImpl::GetDataBindingContextN(*this);
285 }
286
287 bool
288 _PopupImpl::GetXmlBounds(Tizen::Graphics::FloatRectangle& rect)
289 {
290         Rectangle builderBounds;
291         _ControlOrientation controlOrientation = _CONTROL_ORIENTATION_PORTRAIT;
292         bool exist = GetBuilderBounds(controlOrientation, builderBounds);
293         if(!exist)
294         {
295                 return false;
296         }
297
298         controlOrientation = GetCore().GetOrientation();
299
300         if (controlOrientation == _CONTROL_ORIENTATION_LANDSCAPE)
301         {
302                 exist = GetBuilderBounds(controlOrientation, builderBounds);
303         }
304         rect = _CoordinateSystemUtils::ConvertToFloat(builderBounds);
305
306         return true;
307 }
308 void
309 _PopupImpl::OnChangeLayout(_ControlOrientation orientation)
310 {
311         result r = E_SUCCESS;
312         FloatRectangle bounds;
313         if (!__callBoundsChange)
314         {
315                 _centerAlign = true;
316
317                 if (__boundsChangedExternally)
318                 {
319                         bounds = GetCenterAlignedRect(GetBounds().width, GetBounds().height);
320                         __boundsChangedInternally = true;
321                         r = SetBounds(bounds);
322                         __boundsChangedInternally = false;
323                 }
324                 else
325                 {
326
327                         if(GetXmlBounds(bounds))
328                         {
329                                 bounds = GetCenterAlignedRect(bounds.width, bounds.height);
330                         }
331                         else
332                         {
333                                 bounds = GetCenterAlignedRect(GetBounds().width, GetBounds().height);
334                         }
335                         __boundsChangedInternally = true;
336                         r = SetBounds(bounds);
337                         __boundsChangedInternally =  false;
338                 }
339
340                 SysTryReturnVoidResult(NID_UI_CTRL, r == E_SUCCESS, r, "[%s] Propagating.", GetErrorMessage(r));
341         }
342         else
343         {
344                 if (!__boundsChangedExternally)
345                 {
346                         if(GetXmlBounds(bounds))
347                         {
348                                 __boundsChangedInternally = true;
349                                 r = SetBounds(bounds);
350                                 __boundsChangedInternally = false;
351                         }
352                 }
353
354                 SysTryReturnVoidResult(NID_UI_CTRL, r == E_SUCCESS, r, "[%s] Propagating.", GetErrorMessage(r));
355
356         }
357
358         Layout* pLayout;
359
360         pLayout = GetPublicLayoutN();
361
362         if (pLayout != null)
363         {
364                 Tizen::Ui::_SharedPtr<Tizen::Ui::_LayoutImpl> pLayoutImpl = _LayoutImpl::GetLayoutImpl(pLayout);
365
366                 if (!pLayoutImpl.IsNull())
367                 {
368                         r = GetCore().SetCurrentLayout(pLayoutImpl->GetCore());
369                         SysTryReturnVoidResult(NID_UI_CTRL, r == E_SUCCESS, E_SYSTEM, "[E_SYSTEM] Failed to set up the current layout");
370                 }
371         }
372
373         return GetCore().OnChangeLayout(orientation);
374 }
375
376 result
377 _PopupImpl::OnBoundsChanging(const FloatRectangle& bounds)
378 {
379         __prevPos = GetBoundsF().GetTopLeft();
380
381         return _ControlImpl::OnBoundsChanging(bounds);
382 }
383
384 void
385 _PopupImpl::OnBoundsChanged(void)
386 {
387         if (!__boundsChangedInternally && __init)
388         {
389                 __boundsChangedExternally = true;
390         }
391
392         FloatRectangle rect = GetBoundsF();
393         if (__init)
394         {
395                 if ((_centerAlign || (_FloatCompare(__prevPos.x, rect.x) && _FloatCompare(__prevPos.y, rect.y))) && __callBoundsChange == false)
396                 {
397                         rect = GetCenterAlignedRect(GetSizeF().width, GetSizeF().height);
398                 }
399                 else
400                 {
401                         __callBoundsChange = true;
402                 }
403         }
404
405         _centerAlign = true;
406         __boundsChangedInternally = true;
407         result r = SetBounds(rect, true);
408         __boundsChangedInternally = false;
409         if (IsFailed(r))
410         {
411                 // Error propagation fall through
412                 ClearLastResult();
413         }
414
415         _ControlImpl::OnBoundsChanged();
416
417         _centerAlign = false;
418 }
419
420
421 class _PopupMaker
422         : public _UiBuilderControlMaker
423 {
424 public:
425         _PopupMaker(_UiBuilder* uibuilder)
426                 : _UiBuilderControlMaker(uibuilder){};
427         virtual ~_PopupMaker(){};
428
429         static _UiBuilderControlMaker* GetInstance(_UiBuilder* uibuilder)
430         {
431                 _PopupMaker* pPopupMaker = new (std::nothrow) _PopupMaker(uibuilder);
432
433                 return static_cast<_UiBuilderControlMaker*>(pPopupMaker);
434         };
435
436 protected:
437         virtual Tizen::Ui::Control* Make(_UiBuilderControl* pControl)
438         {
439                 bool hasTitle = false;
440                 result r = E_SYSTEM;
441                 _UiBuilderControlLayout* pControlProperty = null;
442                 Tizen::Base::String elementString;
443                 Color color;
444                 Tizen::Graphics::FloatDimension dim;
445                 Tizen::Graphics::FloatRectangle rect;
446
447                 Popup* pPopup = dynamic_cast <Popup*>(GetContainer());
448                 SysTryReturn(NID_UI_CTRL, pPopup != null, null, E_SYSTEM, "[E_SYSTEM] This instance is not constructed.");
449
450                 SetUiBuilderRotateState(UIBUIDER_SCREEN_VERTICAL);
451                 GetProperty(pControl, &pControlProperty);
452
453                 if (pControlProperty == null)
454                 {
455                         return null;
456                 }
457
458                 if (pControl->GetElement("titleText", elementString))
459                 {
460                         hasTitle = true;
461                 }
462                 else
463                 {
464                         hasTitle = false;
465                 }
466
467                 //pPopup = new (std::nothrow) Popup();
468                 rect = pControlProperty->GetRectF();
469
470                 dim.width = rect.width;
471                 dim.height = rect.height;
472
473                 _UiBuilderLayoutType layoutType = UIBUILDER_LAYOUT_NONE;
474                 __pLayoutMaker->GetLayoutType(pControlProperty, layoutType);
475
476                 if (layoutType == UIBUILDER_LAYOUT_NONE)
477                 {
478                         r = pPopup->Construct(hasTitle, dim);
479                 }
480                 else
481                 {
482                         Layout* pPortraitLayout = null;
483                         Layout* pLandscapeLayout = null;
484                         result tempResult = E_SUCCESS;
485
486                         tempResult = __pLayoutMaker->GetLayoutN(pControl, pPortraitLayout, pLandscapeLayout);
487
488                         if (E_SUCCESS == tempResult)
489                         {
490                                 r = pPopup->Construct(*pPortraitLayout, *pLandscapeLayout, hasTitle, dim);
491                         }
492                         else
493                         {
494                                 r = tempResult;
495                         }
496
497                         _UiBuilderLayoutType layoutType = UIBUILDER_LAYOUT_NONE;
498
499                         if (__pLayoutMaker->GetLayoutType(pControlProperty, layoutType) == false)
500                         {
501                                 return null;
502                         }
503
504                         if ( layoutType == UIBUILDER_LAYOUT_GRID)
505                         {
506                                 for (int i = 0; i < UIBUILDER_ATTRIBUTE_NUM; i++)
507                                 {
508                                         GridLayout* pGridLayout = null;
509                                         pControlProperty = pControl->GetAttribute(i);
510
511                                         if ( i == UIBUILDER_ATTRIBUTE_PORTRAIT)
512                                         {
513                                                 pGridLayout = dynamic_cast<GridLayout*>(pPortraitLayout);
514                                         }
515                                         else
516                                         {
517                                                 pGridLayout = dynamic_cast<GridLayout*>(pLandscapeLayout);
518                                         }
519                                         __pLayoutMaker->SetGridLayoutContainerProperty(pGridLayout, pControlProperty);
520                                 }
521                         }
522
523                         delete pPortraitLayout;
524
525                         if (pPortraitLayout != pLandscapeLayout)
526                         {
527                                 delete pLandscapeLayout;
528                         }
529                 //      CONSTRUCT_WITH_LAYOUT_ARG2(pPopup, hasTitle, dim);
530                 }
531
532                 if (r != E_SUCCESS)
533                 {
534                         SysLog(NID_UI_CTRL, "Failed to create Popup.");
535                         return null;
536                 }
537
538                 if (hasTitle == true)
539                 {
540                         pPopup->SetTitleText(elementString);
541                 }
542
543                 //set property
544                 if (pControl->GetElement("color", elementString))
545                 {
546                         ConvertStringToColor(elementString, color);
547                         pPopup->SetColor(color);
548                 }
549
550                 if (pControl->GetElement("titleTextColor", elementString))
551                 {
552                         ConvertStringToColor(elementString, color);
553                         pPopup->SetTitleTextColor(color);
554                 }
555
556                 if (pControl->GetElement(L"accessibilityHint", elementString))
557                 {
558                         AccessibilityContainer* pContainer = pPopup->GetAccessibilityContainer();
559                         if (pContainer)
560                         {
561                                 AccessibilityElement* pElement = pContainer->GetElement(L"PopupTitleText");
562                                 if (pElement)
563                                 {
564                                         pElement->SetHint(elementString);
565                                 }
566                         }
567                 }
568
569                 return pPopup;
570         }
571
572 private:
573
574 };      // _PopupMaker
575
576 _PopupRegister::_PopupRegister()
577 {
578         _UiBuilderControlTableManager* pUiBuilderControlTableManager = _UiBuilderControlTableManager::GetInstance();
579         pUiBuilderControlTableManager->RegisterControl(L"Popup", _PopupMaker::GetInstance);
580 }
581
582 _PopupRegister::~_PopupRegister()
583 {
584         _UiBuilderControlTableManager* pUiBuilderControlTableManager = _UiBuilderControlTableManager::GetInstance();
585         pUiBuilderControlTableManager->UnregisterControl(L"Popup");
586 }
587 static _PopupRegister PopupRegisterToUiBuilder;
588
589 }}} // Tizen::Ui::Controls