Modified creation aborted and faulted signal
[platform/core/uifw/widget-viewer-dali.git] / internal / widget_view / widget_view_impl.cpp
1 /*
2  * Samsung API
3  * Copyright (c) 2016 Samsung Electronics Co., Ltd.
4  *
5  * Licensed under the Flora License, Version 1.1 (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 // CLASS HEADER
19 #include <internal/widget_view/widget_view_impl.h>
20
21 // INTERNAL INCLUDES
22
23 // EXTERNAL INCLUDES
24 #include <dali/public-api/common/stage.h>
25 #include <dali/public-api/events/touch-data.h>
26 #include <dali/public-api/events/wheel-event.h>
27 #include <dali/public-api/images/native-image.h>
28 #include <dali/public-api/object/type-registry.h>
29 #include <dali/public-api/object/type-registry-helper.h>
30 #include <dali-toolkit/public-api/visuals/visual-properties.h>
31 #include <dali-toolkit/devel-api/visual-factory/visual-factory.h>
32 #include <dali/integration-api/debug.h>
33 #include <string.h>
34 #include <Ecore_Input.h>
35 #include <widget_service.h>
36 #include <widget_instance.h>
37 #include <tzplatform_config.h>
38 #include <wayland-extension/tizen-extension-client-protocol.h>
39 #include <unistd.h>
40 #include <libintl.h>
41
42 namespace Dali
43 {
44
45 namespace WidgetView
46 {
47
48 namespace Internal
49 {
50
51 namespace
52 {
53
54 const int DEFAULT_FONT_PIXEL_SIZE = 30; // Referred platform widget viewer evas
55
56 #define GET_LOCALE_TEXT(string) dgettext(PKGNAME, string)
57
58 #if defined(DEBUG_ENABLED)
59 Integration::Log::Filter* gWidgetViewLogging  = Integration::Log::Filter::New( Debug::Verbose, false, "LOG_WIDGET_VIEW" );
60 #endif
61
62 BaseHandle Create()
63 {
64   return Dali::BaseHandle();
65 }
66
67 // Setup properties, signals and actions using the type-registry.
68 DALI_TYPE_REGISTRATION_BEGIN( Dali::WidgetView::WidgetView, Toolkit::Control, Create );
69 DALI_PROPERTY_REGISTRATION( Dali::WidgetView, WidgetView, "widgetId", BOOLEAN, WIDGET_ID )
70 DALI_PROPERTY_REGISTRATION( Dali::WidgetView, WidgetView, "instanceId", BOOLEAN, INSTANCE_ID )
71 DALI_PROPERTY_REGISTRATION( Dali::WidgetView, WidgetView, "contentInfo", BOOLEAN, CONTENT_INFO )
72 DALI_PROPERTY_REGISTRATION( Dali::WidgetView, WidgetView, "title", BOOLEAN, TITLE )
73 DALI_PROPERTY_REGISTRATION( Dali::WidgetView, WidgetView, "updatePeriod", BOOLEAN, UPDATE_PERIOD )
74 DALI_PROPERTY_REGISTRATION( Dali::WidgetView, WidgetView, "preview", MAP, PREVIEW )
75 DALI_PROPERTY_REGISTRATION( Dali::WidgetView, WidgetView, "loadingText", MAP, LOADING_TEXT )
76 DALI_PROPERTY_REGISTRATION( Dali::WidgetView, WidgetView, "widgetStateFaulted", BOOLEAN, WIDGET_STATE_FAULTED )
77 DALI_PROPERTY_REGISTRATION( Dali::WidgetView, WidgetView, "permanentDelete", BOOLEAN, PERMANENT_DELETE )
78
79 // Signals
80 DALI_SIGNAL_REGISTRATION( Dali::WidgetView, WidgetView, "widgetAdded", SIGNAL_WIDGET_ADDED )
81 DALI_SIGNAL_REGISTRATION( Dali::WidgetView, WidgetView, "widgetDeleted", SIGNAL_WIDGET_DELETED )
82 DALI_SIGNAL_REGISTRATION( Dali::WidgetView, WidgetView, "widgetCreationAborted", SIGNAL_WIDGET_CREATION_ABORTED )
83 DALI_SIGNAL_REGISTRATION( Dali::WidgetView, WidgetView, "widgetContentUpdated", SIGNAL_WIDGET_CONTENT_UPDATED )
84 DALI_SIGNAL_REGISTRATION( Dali::WidgetView, WidgetView, "widgetUpdatePeriodChanged", SIGNAL_WIDGET_UPDATE_PERIOD_CHANGED )
85 DALI_SIGNAL_REGISTRATION( Dali::WidgetView, WidgetView, "widgetFaulted", SIGNAL_WIDGET_FAULTED )
86 DALI_SIGNAL_REGISTRATION( Dali::WidgetView, WidgetView, "widgetTerminated", SIGNAL_WIDGET_TERMINATED )
87
88 // Actions
89 DALI_ACTION_REGISTRATION( Dali::WidgetView, WidgetView, "pauseWidget", ACTION_WIDGETVIEW_PAUSE_WIDGET );
90 DALI_ACTION_REGISTRATION( Dali::WidgetView, WidgetView, "resumeWidget", ACTION_WIDGETVIEW_RESUME_WIDGET );
91 DALI_ACTION_REGISTRATION( Dali::WidgetView, WidgetView, "cancelTouchEvent", ACTION_WIDGETVIEW_CANCEL_TOUCH_EVENT );
92 DALI_ACTION_REGISTRATION( Dali::WidgetView, WidgetView, "activateFaultedWidget", ACTION_WIDGETVIEW_ACTIVATE_FAULTED_WIDGET );
93
94 DALI_TYPE_REGISTRATION_END()
95
96 struct wl_buffer* preBuffer;
97
98 const char* const FONT_STYLE( "fontStyle" );
99 const char* const TEXT_POINT_SIZE( "textPointSize" );
100 const char* const TEXT_COLOR( "textColor" );
101
102 static void OnBufferUpdated( struct tizen_remote_surface *surface, uint32_t type, struct wl_buffer *buffer,
103                               int32_t img_file_fd, uint32_t img_file_size, uint32_t time, struct wl_array *keys,
104                               const char *appid, const char *instance_id, const int pid, void *data)
105 {
106   Dali::WidgetView::Internal::WidgetView* widgetView = static_cast< Dali::WidgetView::Internal::WidgetView* >( data );
107
108   if( widgetView )
109   {
110     if( !widgetView->IsWidgetImageView() )
111     {
112       tizen_remote_surface_transfer_visibility( surface, TIZEN_REMOTE_SURFACE_VISIBILITY_TYPE_VISIBLE);
113
114       widgetView->CreateWidgetImageView();
115       widgetView->ConnectSignal( surface );
116     }
117
118     //get tbm surface from buffer
119     tbm_surface_h tbmSurface = static_cast< tbm_surface_h >( wl_buffer_get_user_data( buffer ) );
120     widgetView->UpdateImageSource( tbmSurface );
121   }
122
123   if( preBuffer != NULL && tizen_remote_surface_get_version( surface ) >= TIZEN_REMOTE_SURFACE_RELEASE_SINCE_VERSION )
124   {
125     tizen_remote_surface_release( surface, preBuffer );
126   }
127
128   preBuffer = buffer;
129
130   close( img_file_fd );
131 }
132
133 static void OnBufferAdded( const char *appid, const char *instance_id, const int pid, void *data )
134 {
135 }
136
137 static void OnSurfaceRemoved( const char *appid, const char *instance_id, const int pid, void *data )
138 {
139   Dali::WidgetView::Internal::WidgetView* widgetView = static_cast< Dali::WidgetView::Internal::WidgetView* >( data );
140
141   if( widgetView && !widgetView->IsWidgetFaulted() )
142   {
143     widgetView->CloseRemoteSurface();
144     widgetView->RemoveWidgetImage();
145   }
146 }
147
148 } // unnamed namespace
149
150 Dali::WidgetView::WidgetView WidgetView::New( const std::string& widgetId, const std::string& contentInfo, int width, int height, float updatePeriod )
151 {
152   // Create the implementation, temporarily owned on stack
153   IntrusivePtr< WidgetView > internalWidgetView = new WidgetView( widgetId, contentInfo, width, height, updatePeriod );
154
155   // Pass ownership to CustomActor
156   Dali::WidgetView::WidgetView widgetView( *internalWidgetView );
157
158   // Second-phase init of the implementation
159   // This can only be done after the CustomActor connection has been made...
160   internalWidgetView->Initialize();
161
162   return widgetView;
163 }
164
165 WidgetView::WidgetView()
166 : Control( ControlBehaviour( REQUIRES_TOUCH_EVENTS ) ),
167   mWidgetId(),
168   mInstanceId(),
169   mContentInfo(),
170   mTitle(),
171   mWidth( 0 ),
172   mHeight( 0 ),
173   mPid( 0 ),
174   mUpdatePeriod( 0.0 ),
175   mPreviewVisible( true ),
176   mLoadingTextVisible( true ),
177   mRetryTextVisible( true ),
178   mRetryState( false ),
179   mPermanentDelete( false ),
180   mWatcherHandle( NULL ),
181   mRemoteSurface( NULL )
182 {
183 }
184
185 WidgetView::WidgetView( const std::string& widgetId, const std::string& contentInfo, int width, int height, float updatePeriod )
186 : Control( ControlBehaviour( REQUIRES_TOUCH_EVENTS ) ),
187   mWidgetId( widgetId ),
188   mInstanceId(),
189   mContentInfo( contentInfo ),
190   mTitle(),
191   mWidth( width ),
192   mHeight( height ),
193   mPid( 0 ),
194   mUpdatePeriod( updatePeriod ),
195   mPreviewVisible( true ),
196   mLoadingTextVisible( true ),
197   mRetryTextVisible( true ),
198   mRetryState( false ),
199   mPermanentDelete( false ),
200   mWatcherHandle( NULL ),
201   mRemoteSurface( NULL )
202 {
203 }
204
205 WidgetView::~WidgetView()
206 {
207   TerminateWidget();
208 }
209
210 bool WidgetView::PauseWidget()
211 {
212   int ret = widget_instance_pause( mInstanceId.c_str() );
213   if( ret < 0 )
214   {
215     DALI_LOG_INFO( gWidgetViewLogging, Debug::Verbose, "WidgetView::PauseWidget: Fail to pause widget(%s, %s) [%d]\n", mWidgetId.c_str(), mInstanceId.c_str(), ret );
216     return false;
217   }
218
219   DALI_LOG_INFO( gWidgetViewLogging, Debug::Verbose, "WidgetView::PauseWidget: Widget is paused (%s, %s)\n", mWidgetId.c_str(), mInstanceId.c_str() );
220
221   return true;
222 }
223
224 bool WidgetView::ResumeWidget()
225 {
226   int ret = widget_instance_resume( mInstanceId.c_str() );
227   if( ret < 0 )
228   {
229     DALI_LOG_INFO( gWidgetViewLogging, Debug::Verbose, "WidgetView::ResumeWidget: Fail to resume widget(%s, %s) [%d]\n", mWidgetId.c_str(), mInstanceId.c_str(), ret );
230     return false;
231   }
232
233   DALI_LOG_INFO( gWidgetViewLogging, Debug::Verbose, "WidgetView::ResumeWidget: Widget is resumed (%s, %s)\n", mWidgetId.c_str(), mInstanceId.c_str() );
234
235   return true;
236 }
237
238 const std::string& WidgetView::GetWidgetId() const
239 {
240   return mWidgetId;
241 }
242
243 const std::string& WidgetView::GetInstanceId() const
244 {
245   return mInstanceId;
246 }
247
248 const std::string& WidgetView::GetContentInfo()
249 {
250   widget_instance_h instance;
251   char* contentInfo = NULL;
252
253   mContentInfo.clear();
254
255   if( mWidgetId.empty() || mInstanceId.empty() )
256   {
257     DALI_LOG_INFO( gWidgetViewLogging, Debug::Verbose, "WidgetView::GetContentInfo: Widget id (%s) or instance id (%s) is invalid.\n", mWidgetId.c_str(), mInstanceId.c_str() );
258     return mContentInfo;
259   }
260
261   instance = widget_instance_get_instance( mWidgetId.c_str(), mInstanceId.c_str() );
262   if( !instance )
263   {
264     DALI_LOG_INFO( gWidgetViewLogging, Debug::Verbose, "WidgetView::GetContentInfo: widget_instance_get_instance is failed. [%s]\n", mInstanceId.c_str() );
265     return mContentInfo;
266   }
267
268   if( widget_instance_get_content( instance, &contentInfo ) < 0 )
269   {
270     DALI_LOG_INFO( gWidgetViewLogging, Debug::Verbose, "WidgetView::GetContentInfo: Failed to get content of widget. [%s]\n", mInstanceId.c_str() );
271     return mContentInfo;
272   }
273
274   mContentInfo = reinterpret_cast< char* >( contentInfo );
275
276   return mContentInfo;
277 }
278
279 const std::string& WidgetView::GetTitle()
280 {
281   //ToDo: We should add some codes by considering widget_viewer_evas
282   if( mTitle.empty() )
283   {
284     mTitle = widget_service_get_name( mWidgetId.c_str(), NULL );
285   }
286
287   DALI_LOG_INFO( gWidgetViewLogging, Debug::Verbose, "WidgetView::GetTitle: title = %s\n", mTitle.c_str() );
288
289   return mTitle;
290 }
291
292 float WidgetView::GetUpdatePeriod() const
293 {
294   return mUpdatePeriod;
295 }
296
297 bool WidgetView::CancelTouchEvent()
298 {
299   if( mRemoteSurface )
300   {
301     tizen_remote_surface_transfer_touch_cancel( mRemoteSurface );
302     return true;
303   }
304
305   return false;
306 }
307
308 void WidgetView::SetPreviewVisible( bool visible )
309 {
310   if( mPreviewImage && mPreviewVisible != visible )
311   {
312     mPreviewVisible = visible;
313     mPreviewImage.SetVisible( visible );
314   }
315 }
316
317 bool WidgetView::IsPreviewVisible()
318 {
319   return mPreviewVisible;
320 }
321
322 void WidgetView::SetLoadingTextVisible( bool visible )
323 {
324   if( mLoadingText && mLoadingTextVisible != visible )
325   {
326     mLoadingTextVisible = visible;
327
328     if( visible )
329     {
330       mLoadingText.SetProperty( Toolkit::TextLabel::Property::TEXT, GET_LOCALE_TEXT( "IDS_ST_POP_LOADING_ING" ) );
331     }
332     mLoadingText.SetVisible( visible );
333   }
334 }
335
336 bool WidgetView::IsLoadingTextVisible()
337 {
338   return mLoadingTextVisible;
339 }
340
341 void WidgetView::ActivateFaultedWidget()
342 {
343   if( mPid < 0 )
344   {
345     // Enable preview and loading text
346     ShowRetryState( false );
347     ShowLoadingState( true );
348
349     // launch widget again
350     mPid = widget_instance_launch( mInstanceId.c_str(), (char *)mContentInfo.c_str(), mWidth, mHeight );
351     if( mPid < 0)
352     {
353       DALI_LOG_INFO( gWidgetViewLogging, Debug::Verbose, "WidgetView::ActivateFaultedWidget: widget_instance_launch is failed. [%s]\n", mWidgetId.c_str() );
354
355       ShowLoadingState( false );
356       ShowRetryState( true );
357
358       // Emit signal
359       Dali::WidgetView::WidgetView handle( GetOwner() );
360       mWidgetCreationAbortedSignal.Emit( handle );
361
362       return;
363     }
364
365     screen_connector_toolkit_ops ops;
366     ops.updated_cb = OnBufferUpdated;
367     ops.removed_cb = OnSurfaceRemoved;
368     ops.added_cb = OnBufferAdded;
369     mWatcherHandle = screen_connector_toolkit_add(&ops, (char *)mInstanceId.c_str(), SCREEN_CONNECTOR_SCREEEN_TYPE_WIDGET, this);
370
371     DALI_LOG_INFO( gWidgetViewLogging, Debug::Verbose, "WidgetView::ActivateFaultedWidget: widget_instance_launch is called. [%s, mPid = %d]\n", mWidgetId.c_str(), mPid );
372   }
373 }
374
375 bool WidgetView::IsWidgetFaulted()
376 {
377   return mPid < 0 ? true : false;
378 }
379
380 void WidgetView::SetPermanentDelete( bool permanentDelete )
381 {
382   mPermanentDelete = permanentDelete;
383 }
384
385 bool WidgetView::IsPermanentDelete()
386 {
387   return mPermanentDelete;
388 }
389
390 void WidgetView::CreateWidgetImageView()
391 {
392   Any source;
393   mImageSource = Dali::NativeImageSource::New( source );
394   Dali::NativeImage image = Dali::NativeImage::New( *mImageSource );
395
396   mWidgetImageView = Dali::Toolkit::ImageView::New( image );
397
398   mWidgetImageView.SetParentOrigin( ParentOrigin::CENTER );
399   mWidgetImageView.SetAnchorPoint( AnchorPoint::CENTER );
400   mWidgetImageView.SetSize( mWidth, mHeight );
401
402   Self().Add( mWidgetImageView );
403
404   //EFL app should be pre multiplied image.
405   mWidgetImageView.SetProperty( Toolkit::ImageView::Property::PRE_MULTIPLIED_ALPHA, true );
406
407   // Disable preview and text
408   ShowLoadingState( false );
409
410   // Emit signal
411   Dali::WidgetView::WidgetView handle( GetOwner() );
412   mWidgetAddedSignal.Emit( handle );
413
414   DALI_LOG_INFO( gWidgetViewLogging, Debug::Verbose, "WidgetView::CreateWidgetImageView: Widget image is added.\n" );
415 }
416
417 void WidgetView::RemoveWidgetImage()
418 {
419   mWidgetImageView.SetVisible( false );
420   mWidgetImageView.Reset();
421
422   Dali::WidgetView::WidgetView handle( GetOwner() );
423   mWidgetDeletedSignal.Emit( handle );
424
425   DALI_LOG_INFO( gWidgetViewLogging, Debug::Verbose, "WidgetView::RemoveWidgetImage: Widget image is removed.\n" );
426 }
427
428 void WidgetView::TerminateWidget()
429 {
430   if( !mWidgetId.empty() && !mInstanceId.empty() )
431   {
432     widget_instance_terminate( mInstanceId.c_str() );
433
434     if( mPermanentDelete )
435     {
436       widget_instance_destroy( mInstanceId.c_str() );
437     }
438
439     Dali::WidgetView::WidgetView handle( GetOwner() );
440     mWidgetTerminatedSignal.Emit( handle );
441     mWidgetDeletedSignal.Emit( handle );
442
443     mWidgetId.clear();
444     mInstanceId.clear();
445
446     CloseRemoteSurface();
447   }
448
449   DALI_LOG_INFO( gWidgetViewLogging, Debug::Verbose, "WidgetView::TerminateWidget: Widget is terminated/destroyed and deleted signal is emitted.\n" );
450
451 }
452
453 void WidgetView::SendWidgetEvent( int event )
454 {
455   Dali::WidgetView::WidgetView handle( GetOwner() );
456
457   DALI_LOG_INFO( gWidgetViewLogging, Debug::Verbose, "WidgetView::SendWidgetEvent: event = %d widget = %s\n", event,  mWidgetId.c_str() );
458
459   // Emit signal
460   switch( event )
461   {
462     case WIDGET_INSTANCE_EVENT_UPDATE:
463     case WIDGET_INSTANCE_EVENT_EXTRA_UPDATED:
464     {
465       mWidgetContentUpdatedSignal.Emit( handle );
466       break;
467     }
468     case WIDGET_INSTANCE_EVENT_PERIOD_CHANGED:
469     {
470       mWidgetUpdatePeriodChangedSignal.Emit( handle );
471       break;
472     }
473     case WIDGET_INSTANCE_EVENT_FAULT:
474     {
475       mPid = -1;
476       ShowRetryState( true );
477       mWidgetFaultedSignal.Emit( handle );
478       break;
479     }
480     default:
481     {
482       break;
483     }
484   }
485 }
486
487 bool WidgetView::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
488 {
489   Dali::BaseHandle handle( object );
490
491   bool connected( true );
492   Dali::WidgetView::WidgetView widgetView = Dali::WidgetView::WidgetView::DownCast( handle );
493
494   if( strcmp( signalName.c_str(), SIGNAL_WIDGET_ADDED ) == 0 )
495   {
496     widgetView.WidgetAddedSignal().Connect( tracker, functor );
497   }
498   else if( strcmp( signalName.c_str(), SIGNAL_WIDGET_DELETED ) == 0 )
499   {
500     widgetView.WidgetDeletedSignal().Connect( tracker, functor );
501   }
502   else if( strcmp( signalName.c_str(), SIGNAL_WIDGET_CREATION_ABORTED ) == 0 )
503   {
504     widgetView.WidgetCreationAbortedSignal().Connect( tracker, functor );
505   }
506   else if( strcmp( signalName.c_str(), SIGNAL_WIDGET_CONTENT_UPDATED ) == 0 )
507   {
508     widgetView.WidgetContentUpdatedSignal().Connect( tracker, functor );
509   }
510   else if( strcmp( signalName.c_str(), SIGNAL_WIDGET_UPDATE_PERIOD_CHANGED ) == 0 )
511   {
512     widgetView.WidgetUpdatePeriodChangedSignal().Connect( tracker, functor );
513   }
514   else if( strcmp( signalName.c_str(), SIGNAL_WIDGET_FAULTED ) == 0 )
515   {
516     widgetView.WidgetFaultedSignal().Connect( tracker, functor );
517   }
518   else
519   {
520     // signalName does not match any signal
521     connected = false;
522   }
523
524   return connected;
525 }
526
527 bool WidgetView::DoAction( BaseObject* object, const std::string& actionName, const Property::Map& attributes )
528 {
529   bool ret = true;
530
531   Dali::BaseHandle handle( object );
532   Dali::WidgetView::WidgetView widgetView = Dali::WidgetView::WidgetView::DownCast( handle );
533
534   if( !widgetView )
535   {
536     return false;
537   }
538
539   WidgetView& impl = GetImplementation( widgetView );
540
541   if( strcmp( actionName.c_str(), ACTION_WIDGETVIEW_PAUSE_WIDGET ) == 0 )
542   {
543     impl.PauseWidget();
544   }
545   else if( strcmp( actionName.c_str(), ACTION_WIDGETVIEW_RESUME_WIDGET ) == 0 )
546   {
547     impl.ResumeWidget();
548   }
549   else if( strcmp( actionName.c_str(), ACTION_WIDGETVIEW_CANCEL_TOUCH_EVENT ) == 0 )
550   {
551     impl.CancelTouchEvent();
552   }
553   else if( strcmp( actionName.c_str(), ACTION_WIDGETVIEW_ACTIVATE_FAULTED_WIDGET ) == 0 )
554   {
555     impl.ActivateFaultedWidget();
556   }
557   else
558   {
559     ret = false;
560   }
561
562   return ret;
563 }
564
565 void WidgetView::SetProperty( BaseObject* object, Property::Index index, const Property::Value& value )
566 {
567   Dali::WidgetView::WidgetView widgetView = Dali::WidgetView::WidgetView::DownCast( Dali::BaseHandle( object ) );
568
569   if( widgetView )
570   {
571     WidgetView& impl = GetImplementation( widgetView );
572
573     switch( index )
574     {
575       case Dali::WidgetView::WidgetView::Property::PREVIEW:
576       {
577         bool previewEnabled;
578
579         if( value.Get( previewEnabled ) )
580         {
581           impl.SetPreviewVisible( previewEnabled );
582         }
583         break;
584       }
585       case Dali::WidgetView::WidgetView::Property::LOADING_TEXT:
586       {
587         bool textEnabled;
588         Property::Map map;
589
590         if( value.Get( textEnabled ) )
591         {
592           impl.SetLoadingTextVisible( textEnabled );
593         }
594         else if( value.Get( map ) )
595         {
596           impl.SetLoadingTextPropertyMap( map );
597         }
598         break;
599       }
600       case Dali::WidgetView::WidgetView::Property::PERMANENT_DELETE:
601       {
602         bool permanent;
603         if( value.Get( permanent ) )
604         {
605           impl.SetPermanentDelete( permanent );
606         }
607         break;
608       }
609     }
610   }
611 }
612
613 Property::Value WidgetView::GetProperty( BaseObject* object, Property::Index index )
614 {
615   Property::Value value;
616   Dali::WidgetView::WidgetView widgetView = Dali::WidgetView::WidgetView::DownCast( Dali::BaseHandle( object ) );
617
618   if( widgetView )
619   {
620     WidgetView& impl = GetImplementation( widgetView );
621
622     switch( index )
623     {
624       case Dali::WidgetView::WidgetView::Property::WIDGET_ID:
625       {
626         value = impl.GetWidgetId();
627         break;
628       }
629       case Dali::WidgetView::WidgetView::Property::INSTANCE_ID:
630       {
631         value = impl.GetInstanceId();
632         break;
633       }
634       case Dali::WidgetView::WidgetView::Property::CONTENT_INFO:
635       {
636         value = impl.GetContentInfo();
637         break;
638       }
639       case Dali::WidgetView::WidgetView::Property::TITLE:
640       {
641         value = impl.GetTitle();
642         break;
643       }
644       case Dali::WidgetView::WidgetView::Property::UPDATE_PERIOD:
645       {
646         value = impl.GetUpdatePeriod();
647         break;
648       }
649       case Dali::WidgetView::WidgetView::Property::PREVIEW:
650       {
651         value = impl.IsPreviewVisible();
652         break;
653       }
654       case Dali::WidgetView::WidgetView::Property::LOADING_TEXT:
655       {
656         value = impl.IsLoadingTextVisible();
657         break;
658       }
659       case Dali::WidgetView::WidgetView::Property::WIDGET_STATE_FAULTED:
660       {
661         value = impl.IsWidgetFaulted();
662         break;
663       }
664       case Dali::WidgetView::WidgetView::Property::PERMANENT_DELETE:
665       {
666         value = impl.IsPermanentDelete();
667         break;
668       }
669     }
670   }
671
672   return value;
673 }
674
675 Dali::WidgetView::WidgetView::WidgetViewSignalType& WidgetView::WidgetAddedSignal()
676 {
677   return mWidgetAddedSignal;
678 }
679
680 Dali::WidgetView::WidgetView::WidgetViewSignalType& WidgetView::WidgetDeletedSignal()
681 {
682   return mWidgetDeletedSignal;
683 }
684
685 Dali::WidgetView::WidgetView::WidgetViewSignalType& WidgetView::WidgetCreationAbortedSignal()
686 {
687   return mWidgetCreationAbortedSignal;
688 }
689
690 Dali::WidgetView::WidgetView::WidgetViewSignalType& WidgetView::WidgetContentUpdatedSignal()
691 {
692   return mWidgetContentUpdatedSignal;
693 }
694
695 Dali::WidgetView::WidgetView::WidgetViewSignalType& WidgetView::WidgetUpdatePeriodChangedSignal()
696 {
697   return mWidgetUpdatePeriodChangedSignal;
698 }
699
700 Dali::WidgetView::WidgetView::WidgetViewSignalType& WidgetView::WidgetFaultedSignal()
701 {
702   return mWidgetFaultedSignal;
703 }
704
705 Dali::WidgetView::WidgetView::WidgetViewSignalType& WidgetView::WidgetTerminatedSignal()
706 {
707   return mWidgetTerminatedSignal;
708 }
709
710 void WidgetView::OnInitialize()
711 {
712   char* instanceId = NULL;
713   char* previewPath = NULL;
714   std::string previewImage;
715   widget_size_type_e sizeType;
716   screen_connector_toolkit_ops ops;
717
718   int ret = widget_instance_create( mWidgetId.c_str(), &instanceId );
719   if( ret < 0 || !instanceId )
720   {
721     DALI_LOG_INFO( gWidgetViewLogging, Debug::Verbose, "WidgetView::OnInitialize: widget_instance_create is failed [%s].\n", mWidgetId.c_str() );
722     return;
723   }
724
725   DALI_LOG_INFO( gWidgetViewLogging, Debug::Verbose, "WidgetView::OnInitialize: widget_instance_create is called. [widget id = %s, instance id = %s]\n",
726                  mWidgetId.c_str(), instanceId );
727
728   mInstanceId = instanceId;
729
730   // Preview image
731   widget_service_get_size_type( mWidth, mHeight, &sizeType );
732
733   previewPath = widget_service_get_preview_image_path( mWidgetId.c_str(), sizeType );
734   if( previewPath )
735   {
736     previewImage = previewPath;
737     free( previewPath );
738   }
739   else
740   {
741     previewImage = WIDGET_VIEW_RESOURCE_DEFAULT_IMG;
742   }
743
744   DALI_LOG_INFO( gWidgetViewLogging, Debug::Verbose, "WidgetView::OnInitialize: preview image path = %s\n", previewImage.c_str() );
745
746
747   mPreviewActor = Dali::Actor::New();
748   mPreviewActor.SetParentOrigin( ParentOrigin::CENTER );
749   mPreviewActor.SetAnchorPoint( AnchorPoint::CENTER );
750   mPreviewActor.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS );
751
752   mPreviewImage = Toolkit::ImageView::New( previewImage );
753   mPreviewImage.SetParentOrigin( ParentOrigin::CENTER );
754   mPreviewImage.SetAnchorPoint( AnchorPoint::CENTER );
755   mPreviewImage.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS );
756
757   Self().SetResizePolicy( ResizePolicy::FIXED, Dimension::ALL_DIMENSIONS );
758   Self().SetSize( mWidth, mHeight );
759
760   Self().Add( mPreviewActor );
761   mPreviewActor.Add( mPreviewImage );
762
763   mStateTextActor = Dali::Actor::New();
764   mStateTextActor.SetParentOrigin( ParentOrigin::CENTER );
765   mStateTextActor.SetAnchorPoint( AnchorPoint::CENTER );
766   mStateTextActor.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS );
767
768   // Loading text
769   mLoadingText = Toolkit::TextLabel::New( GET_LOCALE_TEXT( "IDS_ST_POP_LOADING_ING" ) );
770   mLoadingText.SetParentOrigin( ParentOrigin::CENTER );
771   mLoadingText.SetAnchorPoint( AnchorPoint::CENTER );
772   mLoadingText.SetProperty( Toolkit::TextLabel::Property::HORIZONTAL_ALIGNMENT, "CENTER" );
773   mLoadingText.SetProperty( Toolkit::TextLabel::Property::VERTICAL_ALIGNMENT, "CENTER" );
774   mLoadingText.SetProperty( Toolkit::TextLabel::Property::TEXT_COLOR, Dali::Color::WHITE );
775   mLoadingText.SetProperty( Toolkit::TextLabel::Property::FONT_STYLE, "Bold" );
776   mLoadingText.SetProperty( Toolkit::TextLabel::Property::POINT_SIZE, TextPixelToPointSize( DEFAULT_FONT_PIXEL_SIZE ) );
777
778   mPreviewActor.Add( mStateTextActor );
779   mStateTextActor.Add( mLoadingText );
780
781   // Retry text
782   mRetryText = Toolkit::TextLabel::New( GET_LOCALE_TEXT( "IDS_HS_BODY_UNABLE_TO_LOAD_DATA_TAP_TO_RETRY" ) );
783   mRetryText.SetParentOrigin( ParentOrigin::CENTER );
784   mRetryText.SetAnchorPoint( AnchorPoint::CENTER );
785   mRetryText.SetProperty( Toolkit::TextLabel::Property::HORIZONTAL_ALIGNMENT, "CENTER" );
786   mRetryText.SetProperty( Toolkit::TextLabel::Property::VERTICAL_ALIGNMENT, "CENTER" );
787   mRetryText.SetProperty( Toolkit::TextLabel::Property::TEXT_COLOR, Dali::Color::WHITE );
788   mRetryText.SetProperty( Toolkit::TextLabel::Property::FONT_STYLE, "Bold" );
789   mRetryText.SetProperty( Toolkit::TextLabel::Property::POINT_SIZE, TextPixelToPointSize( DEFAULT_FONT_PIXEL_SIZE ) );
790
791   mStateTextActor.Add( mRetryText );
792   mRetryText.SetVisible( false );
793
794   // launch widget
795   mPid = widget_instance_launch( instanceId, (char *)mContentInfo.c_str(), mWidth, mHeight );
796   if( mPid < 0)
797   {
798
799     ShowLoadingState( false );
800     ShowRetryState( true );
801
802     DALI_LOG_INFO( gWidgetViewLogging, Debug::Verbose, "WidgetView::OnInitialize: widget_instance_launch is failed. [%s]\n", mWidgetId.c_str() );
803
804     // Emit signal
805     Dali::WidgetView::WidgetView handle( GetOwner() );
806     mWidgetCreationAbortedSignal.Emit( handle );
807
808     return;
809   }
810
811   ops.updated_cb = OnBufferUpdated;
812   ops.removed_cb = OnSurfaceRemoved;
813   ops.added_cb = OnBufferAdded;
814   mWatcherHandle = screen_connector_toolkit_add(&ops, (char *)instanceId, SCREEN_CONNECTOR_SCREEEN_TYPE_WIDGET, this);
815   DALI_LOG_INFO( gWidgetViewLogging, Debug::Verbose, "WidgetView::OnInitialize: widget_instance_launch is called. [%s, mPid = %d]\n", mWidgetId.c_str(), mPid );
816
817 }
818
819 void WidgetView::OnStageConnection( int depth )
820 {
821   Control::OnStageConnection( depth );
822 }
823
824 void WidgetView::OnStageDisconnection()
825 {
826   Control::OnStageDisconnection();
827 }
828
829 void WidgetView::OnSizeSet( const Vector3& targetSize )
830 {
831   if( mWidgetImageView )
832   {
833     mWidgetImageView.SetSize( targetSize );
834   }
835 }
836
837 bool WidgetView::IsWidgetImageView()
838 {
839   return ( mWidgetImageView )? true: false;
840 }
841
842 void WidgetView::UpdateImageSource( tbm_surface_h source )
843 {
844   mImageSource->SetSource( source );
845   Dali::Stage::GetCurrent().KeepRendering( 0.0f );
846 }
847
848 void WidgetView::ConnectSignal( tizen_remote_surface* surface )
849 {
850   if( mWidgetImageView && surface )
851   {
852     mRemoteSurface = surface;
853
854     Self().TouchSignal().Connect( this, &WidgetView::OnTouch );
855     Self().WheelEventSignal().Connect( this, &WidgetView::OnWheelEvent );
856   }
857
858 }
859
860 bool WidgetView::OnTouch( Dali::Actor actor, const Dali::TouchData& event )
861 {
862   tizen_remote_surface_event_type type = TIZEN_REMOTE_SURFACE_EVENT_TYPE_NONE;
863
864   if( event.GetPointCount() == 0 )
865   {
866     return false;
867   }
868
869   switch( event.GetState( 0 ) )
870   {
871     case Dali::PointState::UP:
872     {
873       type = TIZEN_REMOTE_SURFACE_EVENT_TYPE_MOUSE_UP;
874
875       if( mRetryState )
876       {
877         ActivateFaultedWidget();
878         return false;
879       }
880
881       break;
882     }
883     case Dali::PointState::DOWN:
884     {
885       type = TIZEN_REMOTE_SURFACE_EVENT_TYPE_MOUSE_DOWN;
886       break;
887     }
888     case Dali::PointState::MOTION:
889     {
890       type = TIZEN_REMOTE_SURFACE_EVENT_TYPE_MOUSE_MOVE;
891       break;
892     }
893     default:
894     {
895       return false;
896     }
897   }
898
899   if( mRemoteSurface == NULL )
900   {
901     return false;
902   }
903
904   int button = 1;
905
906   if( type == TIZEN_REMOTE_SURFACE_EVENT_TYPE_MOUSE_MOVE )
907   {
908     button = 0 ;
909   }
910
911   Vector2 localPos = event.GetLocalPosition( 0 );
912
913   tizen_remote_surface_transfer_mouse_event( mRemoteSurface,
914                                              type,
915                                              0,
916                                              button,
917                                              (int)localPos.x,
918                                              (int)localPos.y,
919                                              wl_fixed_from_double( event.GetEllipseRadius( 0 ).x ),
920                                              wl_fixed_from_double( event.GetEllipseRadius( 0 ).y ),
921                                              wl_fixed_from_double( event.GetPressure( 0 ) ),
922                                              wl_fixed_from_double( event.GetAngle( 0 ).degree ),
923                                              TIZEN_INPUT_DEVICE_CLAS_TOUCHSCREEN,
924                                              TIZEN_INPUT_DEVICE_SUBCLAS_NONE,
925                                              "",
926                                              event.GetTime()
927                                            );
928   return true;
929 }
930
931 bool WidgetView::OnWheelEvent( Dali::Actor actor, const Dali::WheelEvent& event )
932 {
933   if( mRemoteSurface == NULL )
934   {
935     return false;
936   }
937   //ToDo: We should check TIZEN_INPUT_DEVICE_CLAS_MOUSE
938   tizen_remote_surface_transfer_mouse_wheel( mRemoteSurface,
939                                              event.direction,
940                                              event.z,
941                                              TIZEN_INPUT_DEVICE_CLAS_MOUSE,
942                                              TIZEN_INPUT_DEVICE_SUBCLAS_NONE,
943                                              "",
944                                              event.timeStamp
945                                            );
946   return true;
947 }
948
949 Vector3 WidgetView::GetNaturalSize()
950 {
951   Vector3 size;
952   size.x = mWidth;
953   size.y = mHeight;
954
955   if( size.x > 0 && size.y > 0 )
956   {
957     size.z = std::min( size.x, size.y );
958     return size;
959   }
960   else
961   {
962     return Control::GetNaturalSize();
963   }
964 }
965
966 float WidgetView::GetHeightForWidth( float width )
967 {
968   if( mWidth > 0 && mHeight > 0 )
969   {
970     return GetHeightForWidthBase( width );
971   }
972   else
973   {
974     return Control::GetHeightForWidthBase( width );
975   }
976 }
977
978 float WidgetView::GetWidthForHeight( float height )
979 {
980   if( mWidth > 0 && mHeight > 0 )
981   {
982     return GetWidthForHeightBase( height );
983   }
984   else
985   {
986     return Control::GetWidthForHeightBase( height );
987   }
988 }
989
990 void WidgetView::CloseRemoteSurface()
991 {
992   if( mWatcherHandle != NULL )
993   {
994     screen_connector_toolkit_remove( mWatcherHandle );
995     mWatcherHandle = NULL;
996   }
997   mRemoteSurface = NULL;
998   mPid = -1;
999 }
1000
1001 void WidgetView::ShowLoadingState( bool show )
1002 {
1003   if( mPreviewImage && mPreviewVisible )
1004   {
1005     mPreviewImage.SetVisible( show );
1006   }
1007
1008   if( mLoadingText && mLoadingTextVisible )
1009   {
1010     mLoadingText.SetProperty( Toolkit::TextLabel::Property::TEXT, GET_LOCALE_TEXT( "IDS_ST_POP_LOADING_ING" ) );
1011     mLoadingText.SetVisible( show );
1012   }
1013 }
1014
1015 void WidgetView::ShowRetryState( bool show )
1016 {
1017   if( mPreviewImage && mPreviewVisible )
1018   {
1019     mPreviewImage.SetVisible( false );
1020   }
1021
1022   if( mRetryText && mRetryTextVisible )
1023   {
1024     mRetryText.SetProperty( Toolkit::TextLabel::Property::TEXT, GET_LOCALE_TEXT( "IDS_HS_BODY_UNABLE_TO_LOAD_DATA_TAP_TO_RETRY" ) );
1025     mRetryText.SetVisible( show );
1026     mRetryState = show;
1027   }
1028 }
1029
1030 void WidgetView::SetLoadingTextPropertyMap( Property::Map map )
1031 {
1032   if( mLoadingText )
1033   {
1034     Property::Value* fontStyle = map.Find( FONT_STYLE );
1035     std::string style;
1036
1037     if( fontStyle && fontStyle->Get( style ) )
1038     {
1039       mLoadingText.SetProperty( Toolkit::TextLabel::Property::FONT_STYLE, style );
1040     }
1041
1042     Property::Value* textPointSize = map.Find( TEXT_POINT_SIZE );
1043     float size = 0.f;
1044
1045     if( textPointSize && textPointSize->Get( size ) )
1046     {
1047       mLoadingText.SetProperty( Toolkit::TextLabel::Property::POINT_SIZE, size );
1048     }
1049
1050     Property::Value* textColor = map.Find( TEXT_COLOR );
1051     Vector4 color;
1052
1053     if( textColor && textColor->Get( color ) )
1054     {
1055       mLoadingText.SetProperty( Toolkit::TextLabel::Property::TEXT_COLOR, color );
1056     }
1057   }
1058 }
1059
1060 float WidgetView::TextPixelToPointSize( int pixelSize )
1061 {
1062   Dali::Vector2 dpi = Dali::Stage::GetCurrent().GetDpi();
1063   float meanDpi = (dpi.height + dpi.width) / 2.0f;
1064
1065   return (pixelSize * 72.0f) / meanDpi;
1066 }
1067
1068 } // namespace Internal
1069
1070 } // namespace WidgetView
1071
1072 } // namespace Dali