[widget-viewer-dali] Add widget event notification
[platform/core/uifw/widget-viewer-dali.git] / internal / widget_view / widget_view_impl.cpp
1 /*
2  * Copyright (c) 2016 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
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/integration-api/debug.h>
25 #include <string.h>
26 #include <widget_service.h>
27 #include <widget_instance.h>
28 #include <tzplatform_config.h>
29
30 namespace Dali
31 {
32
33 namespace WidgetView
34 {
35
36 namespace Internal
37 {
38
39 namespace
40 {
41
42 #define WIDGET_VIEW_RESOURCE_DEFAULT_IMG "/widget_viewer_dali/images/unknown.png"
43
44 #if defined(DEBUG_ENABLED)
45 Integration::Log::Filter* gWidgetViewLogging  = Integration::Log::Filter::New( Debug::Verbose, false, "LOG_WIDGET_VIEW" );
46 #endif
47
48 } // unnamed namespace
49
50 Dali::WidgetView::WidgetView WidgetView::New( const std::string& widgetId, const std::string& contentInfo, int width, int height, double updatePeriod )
51 {
52   // Create the implementation, temporarily owned on stack
53   IntrusivePtr< WidgetView > internalWidgetView = new WidgetView( widgetId, contentInfo, width, height, updatePeriod );
54
55   // Pass ownership to CustomActor
56   Dali::WidgetView::WidgetView widgetView( *internalWidgetView );
57
58   // Second-phase init of the implementation
59   // This can only be done after the CustomActor connection has been made...
60   internalWidgetView->Initialize();
61
62   return widgetView;
63 }
64
65 WidgetView::WidgetView()
66 : Control( ControlBehaviour( REQUIRES_TOUCH_EVENTS ) ),
67   mWidgetId(),
68   mInstanceId(),
69   mContentInfo(),
70   mTitle(),
71   mBundle( NULL ),
72   mWidth( 0 ),
73   mHeight( 0 ),
74   mPid( 0 ),
75   mUpdatePeriod( 0.0 ),
76   mPreviewEnabled( true ),
77   mStateTextEnabled( true ),
78   mPermanentDelete( true )
79 {
80 }
81
82 WidgetView::WidgetView( const std::string& widgetId, const std::string& contentInfo, int width, int height, double updatePeriod )
83 : Control( ControlBehaviour( REQUIRES_TOUCH_EVENTS ) ),
84   mWidgetId( widgetId ),
85   mInstanceId(),
86   mContentInfo( contentInfo ),
87   mTitle(),
88   mBundle( NULL ),
89   mWidth( width ),
90   mHeight( height ),
91   mPid( 0 ),
92   mUpdatePeriod( updatePeriod ),
93   mPreviewEnabled( true ),
94   mStateTextEnabled( true ),
95   mPermanentDelete( true )
96 {
97 }
98
99 WidgetView::~WidgetView()
100 {
101   if( !mWidgetId.empty() && !mInstanceId.empty() )
102   {
103     widget_instance_terminate( mWidgetId.c_str(), mInstanceId.c_str() );
104
105     if( mPermanentDelete )
106     {
107       widget_instance_destroy( mWidgetId.c_str(), mInstanceId.c_str() );
108     }
109   }
110
111   if( mBundle )
112   {
113     bundle_free( mBundle );
114   }
115 }
116
117 const std::string& WidgetView::GetWidgetId() const
118 {
119   return mWidgetId;
120 }
121
122 const std::string& WidgetView::GetInstanceId() const
123 {
124   return mInstanceId;
125 }
126
127 const std::string& WidgetView::GetContentInfo()
128 {
129   widget_instance_h instance;
130   bundle* bundle = NULL;
131   bundle_raw* contentInfo = NULL;
132   int contentLength = 0;
133
134   mContentInfo.clear();
135
136   if( mWidgetId.empty() || mInstanceId.empty() )
137   {
138     DALI_LOG_INFO( gWidgetViewLogging, Debug::Verbose, "WidgetView::GetContentInfo: Widget id (%s) or instance id (%s) is invalid.\n", mWidgetId.c_str(), mInstanceId.c_str() );
139     return mContentInfo;
140   }
141
142   instance = widget_instance_get_instance( mWidgetId.c_str(), mInstanceId.c_str() );
143   if( !instance )
144   {
145     DALI_LOG_INFO( gWidgetViewLogging, Debug::Verbose, "WidgetView::GetContentInfo: widget_instance_get_instance is failed. [%s]\n", mInstanceId.c_str() );
146     return mContentInfo;
147   }
148
149   if( widget_instance_get_content( instance, &bundle ) < 0 )
150   {
151     DALI_LOG_INFO( gWidgetViewLogging, Debug::Verbose, "WidgetView::GetContentInfo: Failed to get content of widget. [%s]\n", mInstanceId.c_str() );
152     return mContentInfo;
153   }
154
155   if( !bundle )
156   {
157     DALI_LOG_INFO( gWidgetViewLogging, Debug::Verbose, "WidgetView::GetContentInfo: Cotent of widget [%s] is invalid.\n", mInstanceId.c_str() );
158     return mContentInfo;
159   }
160
161   if( bundle_encode( bundle, &contentInfo, &contentLength ) < 0 )
162   {
163     DALI_LOG_INFO( gWidgetViewLogging, Debug::Verbose, "WidgetView::GetContentInfo: bundle_encode is failed. [%s]\n", mInstanceId.c_str() );
164     return mContentInfo;
165   }
166
167   mContentInfo = reinterpret_cast< char* >( contentInfo );
168
169   return mContentInfo;
170 }
171
172 const std::string& WidgetView::GetTitle()
173 {
174   if( mObjectView )
175   {
176     mTitle = mObjectView.GetTitle();
177     if( mTitle.empty() )
178     {
179       mTitle = widget_service_get_name( mWidgetId.c_str(), NULL );
180     }
181   }
182
183   DALI_LOG_INFO( gWidgetViewLogging, Debug::Verbose, "WidgetView::GetTitle: title = %s\n", mTitle.c_str() );
184
185   return mTitle;
186 }
187
188 double WidgetView::GetUpdatePeriod() const
189 {
190   return mUpdatePeriod;
191 }
192
193 void WidgetView::Show()
194 {
195   if( mObjectView )
196   {
197     mObjectView.Show();
198   }
199 }
200
201 void WidgetView::Hide()
202 {
203   if( mObjectView )
204   {
205     mObjectView.Hide();
206   }
207 }
208
209 bool WidgetView::CancelTouchEvent()
210 {
211   if( mObjectView )
212   {
213     return mObjectView.CancelTouchEvent();
214   }
215
216   return false;
217 }
218
219 void WidgetView::SetPreviewEnabled( bool enabled )
220 {
221   mPreviewEnabled = enabled;
222
223   if( mPreviewImage )
224   {
225     mPreviewImage.SetVisible( enabled );
226   }
227 }
228
229 bool WidgetView::GetPreviewEnabled() const
230 {
231   return mPreviewEnabled;
232 }
233
234 void WidgetView::SetStateTextEnabled( bool enabled )
235 {
236   mStateTextEnabled = enabled;
237
238   if( mStateText )
239   {
240     mStateText.SetVisible( enabled );
241   }
242 }
243
244 bool WidgetView::GetStateTextEnabled() const
245 {
246   return mStateTextEnabled;
247 }
248
249 void WidgetView::ActivateFaultedWidget()
250 {
251   if( mPid < 0 )
252   {
253     // Esable preview and text
254     if( mPreviewEnabled )
255     {
256       mPreviewImage.SetVisible( true );
257     }
258
259     if( mStateTextEnabled )
260     {
261       mStateText.SetVisible( true );
262     }
263
264     // launch widget again
265     mPid = widget_instance_launch( mWidgetId.c_str(), mInstanceId.c_str(), mBundle, mWidth, mHeight );
266     if( mPid < 0)
267     {
268       DALI_LOG_INFO( gWidgetViewLogging, Debug::Verbose, "WidgetView::ActivateFaultedWidget: widget_instance_launch is failed. [%s]\n", mWidgetId.c_str() );
269       return;
270     }
271
272     DALI_LOG_INFO( gWidgetViewLogging, Debug::Verbose, "WidgetView::ActivateFaultedWidget: widget_instance_launch is called. [%s, mPid = %d]\n", mWidgetId.c_str(), mPid );
273   }
274 }
275
276 bool WidgetView::IsWidgetFaulted()
277 {
278   return mPid < 0 ? true : false;
279 }
280
281 void WidgetView::SetPermanentDelete( bool permanentDelete )
282 {
283   mPermanentDelete = permanentDelete;
284 }
285
286 void WidgetView::AddObjectView( Pepper::ObjectView objectView )
287 {
288   mObjectView = objectView;
289
290   mObjectView.SetParentOrigin( ParentOrigin::CENTER );
291   mObjectView.SetAnchorPoint( AnchorPoint::CENTER );
292
293   Self().Add( mObjectView );
294
295   // Disable preview and text
296   if( mPreviewEnabled )
297   {
298     mPreviewImage.SetVisible( false );
299   }
300
301   if( mStateTextEnabled )
302   {
303     mStateText.SetVisible( false );
304   }
305
306   // Emit signal
307   Dali::WidgetView::WidgetView handle( GetOwner() );
308   mWidgetAddedSignal.Emit( handle );
309
310   DALI_LOG_INFO( gWidgetViewLogging, Debug::Verbose, "WidgetView::AddObjectView: ObjectView is added.\n" );
311 }
312
313 void WidgetView::RemoveObjectView()
314 {
315   // Enable preview and text
316   if( mPreviewEnabled )
317   {
318     mPreviewImage.SetVisible( true );
319   }
320
321   if( mStateTextEnabled )
322   {
323     mStateText.SetVisible( true );
324   }
325
326   // Emit signal
327   Dali::WidgetView::WidgetView handle( GetOwner() );
328   mWidgetDeletedSignal.Emit( handle );
329
330   mObjectView.Reset();
331
332   DALI_LOG_INFO( gWidgetViewLogging, Debug::Verbose, "WidgetView::RemoveObjectView: ObjectView is removed.\n" );
333 }
334
335 void WidgetView::SendWidgetEvent( int event )
336 {
337   Dali::WidgetView::WidgetView handle( GetOwner() );
338
339   DALI_LOG_INFO( gWidgetViewLogging, Debug::Verbose, "WidgetView::SendWidgetEvent: event = %d widget = %s\n", event,  mWidgetId.c_str() );
340
341   // Emit signal
342   switch( event )
343   {
344     case WIDGET_INSTANCE_EVENT_UPDATE:
345     {
346       mWidgetContentUpdatedSignal.Emit( handle );
347       break;
348     }
349     case WIDGET_INSTANCE_EVENT_PERIOD_CHANGED:
350     {
351       mWidgetUpdatePeriodChangedSignal.Emit( handle );
352       break;
353     }
354     case WIDGET_INSTANCE_EVENT_SIZE_CHANGED:
355     {
356       mWidgetResizedSignal.Emit( handle );
357       break;
358     }
359     case WIDGET_INSTANCE_EVENT_EXTRA_UPDATED:
360     {
361       mWidgetExtraInfoUpdatedSignal.Emit( handle );
362       break;
363     }
364     default:
365     {
366       break;
367     }
368   }
369 }
370
371 Dali::WidgetView::WidgetView::WidgetViewSignalType& WidgetView::WidgetAddedSignal()
372 {
373   return mWidgetAddedSignal;
374 }
375
376 Dali::WidgetView::WidgetView::WidgetViewSignalType& WidgetView::WidgetDeletedSignal()
377 {
378   return mWidgetDeletedSignal;
379 }
380
381 Dali::WidgetView::WidgetView::WidgetViewSignalType& WidgetView::WidgetAbortedSignal()
382 {
383   return mWidgetAbortedSignal;
384 }
385
386 Dali::WidgetView::WidgetView::WidgetViewSignalType& WidgetView::WidgetResized()
387 {
388   return mWidgetResizedSignal;
389 }
390
391 Dali::WidgetView::WidgetView::WidgetViewSignalType& WidgetView::WidgetContentUpdated()
392 {
393   return mWidgetContentUpdatedSignal;
394 }
395
396 Dali::WidgetView::WidgetView::WidgetViewSignalType& WidgetView::WidgetExtraInfoUpdated()
397 {
398   return mWidgetExtraInfoUpdatedSignal;
399 }
400
401 Dali::WidgetView::WidgetView::WidgetViewSignalType& WidgetView::WidgetUpdatePeriodChanged()
402 {
403   return mWidgetUpdatePeriodChangedSignal;
404 }
405
406 void WidgetView::OnInitialize()
407 {
408   char* instanceId = NULL;
409   char* previewPath = NULL;
410   std::string previewImage;
411   widget_size_type_e sizeType;
412
413   if( !mContentInfo.empty() )
414   {
415     DALI_LOG_INFO( gWidgetViewLogging, Debug::Verbose, "WidgetView::OnInitialize: decode bundle\n" );
416
417     mBundle = bundle_decode( reinterpret_cast< const bundle_raw* >( mContentInfo.c_str() ), mContentInfo.length() );
418     if( !mBundle )
419     {
420       DALI_LOG_INFO( gWidgetViewLogging, Debug::Verbose, "WidgetView::OnInitialize: Invalid bundle data.\n" );
421       return;
422     }
423
424     bundle_get_str( mBundle, WIDGET_K_INSTANCE, &instanceId );
425   }
426
427   if( !instanceId )
428   {
429     int ret = widget_instance_create( mWidgetId.c_str(), &instanceId );
430     if( ret < 0 || !instanceId )
431     {
432       DALI_LOG_INFO( gWidgetViewLogging, Debug::Verbose, "WidgetView::OnInitialize: widget_instance_create is failed [%s].\n", mWidgetId.c_str() );
433       return;
434     }
435
436     DALI_LOG_INFO( gWidgetViewLogging, Debug::Verbose, "WidgetView::OnInitialize: widget_instance_create is called. [widget id = %s, instance id = %s]\n",
437                    mWidgetId.c_str(), instanceId );
438   }
439
440   mInstanceId = instanceId;
441
442   // Preview image
443   widget_service_get_size_type( mWidth, mHeight, &sizeType );
444
445   previewPath = widget_service_get_preview_image_path( mWidgetId.c_str(), sizeType );
446   if( previewPath )
447   {
448     previewImage = previewPath;
449     free( previewPath );
450   }
451   else
452   {
453     previewImage = tzplatform_getenv( TZ_SYS_SHARE );
454     previewImage.append( WIDGET_VIEW_RESOURCE_DEFAULT_IMG );
455   }
456
457   DALI_LOG_INFO( gWidgetViewLogging, Debug::Verbose, "WidgetView::OnInitialize: preview image path = %s\n", previewImage.c_str() );
458
459   mPreviewImage = Toolkit::ImageView::New( previewImage );
460
461   mPreviewImage.SetParentOrigin( ParentOrigin::CENTER );
462   mPreviewImage.SetAnchorPoint( AnchorPoint::CENTER );
463
464   if( !previewPath )
465   {
466     mPreviewImage.SetSize( mWidth, mHeight );
467   }
468
469   Self().SetResizePolicy( ResizePolicy::FIT_TO_CHILDREN, Dimension::ALL_DIMENSIONS );
470   Self().Add( mPreviewImage );
471
472   // State text
473   // TODO: use po files
474   mStateText = Toolkit::TextLabel::New( "Loading..." );
475
476   mStateText.SetParentOrigin( ParentOrigin::CENTER );
477   mStateText.SetAnchorPoint( AnchorPoint::CENTER );
478   mStateText.SetProperty( Toolkit::TextLabel::Property::HORIZONTAL_ALIGNMENT, "CENTER" );
479   mStateText.SetProperty( Toolkit::TextLabel::Property::VERTICAL_ALIGNMENT, "CENTER" );
480
481   mPreviewImage.Add( mStateText );
482
483   // launch widget
484   mPid = widget_instance_launch( mWidgetId.c_str(), instanceId, mBundle, mWidth, mHeight );
485   if( mPid < 0)
486   {
487     DALI_LOG_INFO( gWidgetViewLogging, Debug::Verbose, "WidgetView::OnInitialize: widget_instance_launch is failed. [%s]\n", mWidgetId.c_str() );
488
489     // Emit signal
490     Dali::WidgetView::WidgetView handle( GetOwner() );
491     mWidgetAbortedSignal.Emit( handle );
492
493     return;
494   }
495
496   DALI_LOG_INFO( gWidgetViewLogging, Debug::Verbose, "WidgetView::OnInitialize: widget_instance_launch is called. [%s, mPid = %d]\n", mWidgetId.c_str(), mPid );
497 }
498
499 } // namespace Internal
500
501 } // namespace WidgetView
502
503 } // namespace Dali