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