Replace some Dali::Actor public APIs with new properties
[platform/core/uifw/dali-demo.git] / examples / text-memory-profiling / text-memory-profiling-example.cpp
1 /*
2  * Copyright (c) 2020 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 /**
19  * @file text-memory-profiling-example.cpp
20  * @brief Memory consumption profiling for TextLabel
21  */
22
23 // EXTERNAL INCLUDES
24 #include <dali/dali.h>
25 #include <dali-toolkit/dali-toolkit.h>
26 #include <dali-toolkit/devel-api/controls/navigation-view/navigation-view.h>
27
28 // INTERNAL INCLUDES
29 #include "shared/view.h"
30
31 using namespace Dali;
32 using namespace Dali::Toolkit;
33
34 namespace
35 {
36
37 enum TextType
38 {
39   SINGLE_COLOR_TEXT,
40   SINGLE_COLOR_TEXT_WITH_STYLE,
41   SINGLE_COLOR_TEXT_WITH_EMOJI,
42   SINGLE_COLOR_TEXT_WITH_STYLE_EMOJI,
43   MULTI_COLOR_TEXT,
44   MULTI_COLOR_TEXT_WITH_STYLE,
45   MULTI_COLOR_TEXT_WITH_EMOJI,
46   MULTI_COLOR_TEXT_WITH_STYLE_EMOJI,
47   SMALL_TEXT_IN_LARGE_TEXT_LABEL,
48   NUMBER_OF_TYPES
49 };
50
51 std::string TEXT_TYPE_STRING[ NUMBER_OF_TYPES ] =
52 {
53   "Single color text",
54   "Single color text with style",
55   "Single color text with emoji",
56   "Single color text with style and emoji",
57   "Multi color text",
58   "Multi color text with style",
59   "Multi color text with emoji",
60   "Multi color text with style and emoji",
61   "Small text in large Text Label"
62 };
63
64 const int NUMBER_OF_LABELS = 500;
65
66 const char* BACKGROUND_IMAGE( "" );
67 const char* TOOLBAR_IMAGE( DEMO_IMAGE_DIR "top-bar.png" );
68 const char* BACK_IMAGE( DEMO_IMAGE_DIR "icon-change.png" );
69 const char* BACK_IMAGE_SELECTED( DEMO_IMAGE_DIR "icon-change-selected.png" );
70 const char* INDICATOR_IMAGE( DEMO_IMAGE_DIR "loading.png" );
71
72 } // anonymous namespace
73
74 /**
75  * @brief The main class of the demo.
76  */
77 class TextMemoryProfilingExample : public ConnectionTracker, public Toolkit::ItemFactory
78 {
79 public:
80
81   TextMemoryProfilingExample( Application& application )
82   : mApplication( application ),
83     mCurrentTextStyle( SINGLE_COLOR_TEXT )
84   {
85     // Connect to the Application's Init signal
86     mApplication.InitSignal().Connect( this, &TextMemoryProfilingExample::Create );
87   }
88
89   ~TextMemoryProfilingExample()
90   {
91     // Nothing to do here.
92   }
93
94   /**
95    * @brief Create a text label in the given type
96    */
97   TextLabel SetupTextLabel( int type )
98   {
99     TextLabel label = TextLabel::New();
100     label.SetProperty( Actor::Property::ANCHOR_POINT, ParentOrigin::TOP_LEFT );
101     label.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT );
102     label.SetProperty( TextLabel::Property::TEXT_COLOR, Color::BLACK );
103     label.SetProperty( TextLabel::Property::POINT_SIZE, 12.0f );
104     Property::Map shadowMap;
105     shadowMap.Insert( "color", Color::YELLOW );
106     label.SetProperty( TextLabel::Property::SHADOW, shadowMap );
107     label.SetProperty( TextLabel::Property::ENABLE_MARKUP, true );
108
109     Vector2 stageSize = Stage::GetCurrent().GetSize();
110     label.SetProperty( Actor::Property::POSITION, Vector3( Random::Range( 0.0f, stageSize.x ), Random::Range( 0.0f, stageSize.y ), 0.0f) );
111
112     switch ( type )
113     {
114       case SINGLE_COLOR_TEXT:
115       {
116         label.SetProperty( TextLabel::Property::TEXT, "A Quick Brown Fox Jumps Over The Lazy Dog" );
117
118         shadowMap.Insert( "offset", Vector2( 0.0f, 0.0f ) );
119         label.SetProperty( TextLabel::Property::SHADOW, shadowMap );
120         break;
121       }
122       case SINGLE_COLOR_TEXT_WITH_STYLE:
123       {
124         label.SetProperty( TextLabel::Property::TEXT, "A Quick Brown Fox Jumps Over The Lazy Dog" );
125
126         shadowMap.Insert( "offset", Vector2( 2.0f, 2.0f ) );
127         label.SetProperty( TextLabel::Property::SHADOW, shadowMap );
128         break;
129       }
130       case SINGLE_COLOR_TEXT_WITH_EMOJI:
131       {
132         label.SetProperty( TextLabel::Property::TEXT, "\xF0\x9F\x98\x81 A Quick Brown Fox Jumps Over The Lazy Dog" );
133
134         shadowMap.Insert( "offset", Vector2( 0.0f, 0.0f ) );
135         label.SetProperty( TextLabel::Property::SHADOW, shadowMap );
136         break;
137       }
138       case SINGLE_COLOR_TEXT_WITH_STYLE_EMOJI:
139       {
140         label.SetProperty( TextLabel::Property::TEXT, "\xF0\x9F\x98\x81 A Quick Brown Fox Jumps Over The Lazy Dog" );
141
142         shadowMap.Insert( "offset", Vector2( 2.0f, 2.0f ) );
143         label.SetProperty( TextLabel::Property::SHADOW, shadowMap );
144         break;
145       }
146       case MULTI_COLOR_TEXT:
147       {
148         label.SetProperty( TextLabel::Property::TEXT, "A <color value='cyan'>Quick Brown Fox</color> Jumps Over The <color value='yellow'>Lazy Dog</color>" );
149
150         shadowMap.Insert( "offset", Vector2( 0.0f, 0.0f ) );
151         label.SetProperty( TextLabel::Property::SHADOW, shadowMap );
152         break;
153       }
154       case MULTI_COLOR_TEXT_WITH_STYLE:
155       {
156         label.SetProperty( TextLabel::Property::TEXT, "A <color value='cyan'>Quick Brown Fox</color> Jumps Over The <color value='yellow'>Lazy Dog</color>" );
157
158         shadowMap.Insert( "offset", Vector2( 2.0f, 2.0f ) );
159         label.SetProperty( TextLabel::Property::SHADOW, shadowMap );
160         break;
161       }
162       case MULTI_COLOR_TEXT_WITH_EMOJI:
163       {
164         label.SetProperty( TextLabel::Property::TEXT, " \xF0\x9F\x98\x81 A <color value='cyan'>Quick Brown Fox</color> Jumps Over The <color value='yellow'>Lazy Dog</color>" );
165
166         shadowMap.Insert( "offset", Vector2( 0.0f, 0.0f ) );
167         label.SetProperty( TextLabel::Property::SHADOW, shadowMap );
168         break;
169       }
170       case MULTI_COLOR_TEXT_WITH_STYLE_EMOJI:
171       {
172         label.SetProperty( TextLabel::Property::TEXT, " \xF0\x9F\x98\x81 A <color value='cyan'>Quick Brown Fox</color> Jumps Over The <color value='yellow'>Lazy Dog</color>" );
173
174         shadowMap.Insert( "offset", Vector2( 2.0f, 2.0f ) );
175         label.SetProperty( TextLabel::Property::SHADOW, shadowMap );
176         break;
177       }
178       case SMALL_TEXT_IN_LARGE_TEXT_LABEL:
179       {
180         label.SetProperty( TextLabel::Property::TEXT, "A Quick Brown Fox Jumps Over The Lazy Dog" );
181
182         shadowMap.Insert( "offset", Vector2( 0.0f, 0.0f ) );
183         label.SetProperty( TextLabel::Property::SHADOW, shadowMap );
184         label.SetProperty( Actor::Property::SIZE, Vector2(stageSize.x, stageSize.y * 0.25f) ); // Set the text label in larger size
185         break;
186       }
187       default:
188         break;
189     }
190
191     return label;
192   }
193
194   /**
195    * @brief Create the main menu
196    */
197   void CreateMainMenu()
198   {
199     Stage stage = Stage::GetCurrent();
200     Vector2 stageSize = stage.GetSize();
201
202     mTapDetector = TapGestureDetector::New();
203     mTapDetector.DetectedSignal().Connect( this, &TextMemoryProfilingExample::OnTap );
204
205     // Create an item view for the main menu
206     mItemView = ItemView::New( *this );
207
208     mItemView.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER );
209     mItemView.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER );
210
211     mLayout = DefaultItemLayout::New( DefaultItemLayout::LIST );
212     mLayout->SetItemSize( Vector3( stageSize.width, 60.0f, 0.0f ) );
213
214     mItemView.AddLayout( *mLayout );
215
216     // Activate the layout
217     mItemView.ActivateLayout( 0, Vector3( stageSize ), 0.0f );
218   }
219
220   /**
221    * @brief Return the number of items in the main menu
222    */
223   virtual unsigned int GetNumberOfItems()
224   {
225     return NUMBER_OF_TYPES;
226   }
227
228   /**
229    * @brief Create new item for the main menu
230    */
231   virtual Actor NewItem( unsigned int itemId )
232   {
233     TextLabel label = TextLabel::New( TEXT_TYPE_STRING[itemId] );
234     label.SetStyleName( "BuilderLabel" );
235     label.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::WIDTH );
236
237     // Hook up tap detector
238     mTapDetector.Attach( label );
239
240     return label;
241   }
242
243   /**
244    * @brief Create text labels for memory profiling
245    */
246   void CreateTextLabels( int type )
247   {
248     Stage stage = Stage::GetCurrent();
249
250     // Delete any existing text labels
251     unsigned int numChildren = mLayer.GetChildCount();
252
253     for( unsigned int i = 0; i < numChildren; ++i )
254     {
255       mLayer.Remove( mLayer.GetChildAt( 0 ) );
256     }
257
258     mLayer.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::BOTTOM_CENTER );
259     mLayer.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::BOTTOM_CENTER );
260     mLayer.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::WIDTH );
261     mLayer.SetResizePolicy( ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT, Dimension::HEIGHT );
262     mLayer.SetProperty( Actor::Property::SIZE_MODE_FACTOR, Vector3( 0.0f, -DemoHelper::DEFAULT_VIEW_STYLE.mToolBarHeight, 0.0f ) );
263
264     mNavigationView.Push( mLayer );
265
266     // Create new text labels
267     for ( int i = 0; i < NUMBER_OF_LABELS; i++ )
268     {
269       TextLabel label = SetupTextLabel( type );
270       mLayer.Add( label );
271     }
272
273     mTitle.SetProperty( TextLabel::Property::TEXT, "Run memps on target" );
274   }
275
276   /**
277    * @brief One-time setup in response to Application InitSignal.
278    */
279   void Create( Application& application )
280   {
281     Stage stage = Stage::GetCurrent();
282
283     stage.KeyEventSignal().Connect(this, &TextMemoryProfilingExample::OnKeyEvent);
284
285     Layer contents = DemoHelper::CreateView( mApplication,
286                                              mView,
287                                              mToolBar,
288                                              BACKGROUND_IMAGE,
289                                              TOOLBAR_IMAGE,
290                                              "" );
291
292     mTitle = DemoHelper::CreateToolBarLabel( "" );
293     mTitle.SetProperty( TextLabel::Property::TEXT, "Select the type of text" );
294
295     // Add title to the tool bar.
296     mToolBar.AddControl( mTitle, DemoHelper::DEFAULT_VIEW_STYLE.mToolBarTitlePercentage, Alignment::HorizontalCenter );
297
298     // Create a layer to contain dynamically created text labels
299     mLayer = Layer::New();
300
301     mIndicator = Toolkit::ImageView::New(INDICATOR_IMAGE);
302     mIndicator.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER );
303     mIndicator.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER );
304     mIndicator.SetProperty( Actor::Property::VISIBLE, false );
305
306     // Create a back button in the left of toolbar
307     PushButton backButton = PushButton::New();
308     backButton.SetProperty( Button::Property::UNSELECTED_BACKGROUND_VISUAL, BACK_IMAGE );
309     backButton.SetProperty( Button::Property::SELECTED_BACKGROUND_VISUAL, BACK_IMAGE_SELECTED );
310     backButton.ClickedSignal().Connect( this, &TextMemoryProfilingExample::OnBackButtonPressed );
311     backButton.SetProperty( Actor::Property::LEAVE_REQUIRED, true );
312     mToolBar.AddControl( backButton, DemoHelper::DEFAULT_VIEW_STYLE.mToolBarButtonPercentage, Alignment::HorizontalLeft, DemoHelper::DEFAULT_MODE_SWITCH_PADDING );
313
314     // Create a navigation view to navigate different types of text labels
315     mNavigationView = NavigationView::New();
316     mNavigationView.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS );
317     mNavigationView.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT );
318     mNavigationView.SetBackgroundColor( Color::WHITE );
319     stage.Add( mNavigationView );
320
321     CreateMainMenu();
322     mNavigationView.Push( mItemView );
323
324     mItemView.Add(mIndicator);
325
326     PropertyNotification notification = mIndicator.AddPropertyNotification( Actor::Property::VISIBLE, GreaterThanCondition(0.01f) );
327     notification.NotifySignal().Connect( this, &TextMemoryProfilingExample::OnIndicatorVisible );
328   }
329
330   /**
331    * @brief Main key event handler
332    */
333   void OnKeyEvent( const KeyEvent& event )
334   {
335     if( event.state == KeyEvent::Down )
336     {
337       if( IsKey( event, DALI_KEY_ESCAPE) || IsKey( event, DALI_KEY_BACK ) )
338       {
339         ReturnToPreviousScreen();
340       }
341     }
342   }
343
344   /**
345    * @brief Tap gesture handler
346    */
347   void OnTap( Actor actor, const TapGesture& tap )
348   {
349     mCurrentTextStyle = mItemView.GetItemId( actor );
350
351     // Show the loading indicator
352     mIndicator.SetProperty( Actor::Property::VISIBLE, true );
353
354     if ( mAnimation )
355     {
356       mAnimation.Clear();
357       mAnimation.Reset();
358     }
359
360     mAnimation = Animation::New( 0.8f );
361     mAnimation.AnimateBy( Property( mIndicator, Actor::Property::ORIENTATION ), Quaternion( Radian( Degree(180.0f) ), Vector3::ZAXIS ) );
362     mAnimation.SetLooping( true );
363     mAnimation.Play();
364   }
365
366   /**
367    * @brief Property notification handler
368    */
369   void OnIndicatorVisible( PropertyNotification& source )
370   {
371     CreateTextLabels( mCurrentTextStyle );
372
373     // Hide the loading indicator
374     mAnimation.Stop();
375     mIndicator.SetProperty( Actor::Property::VISIBLE, false );
376   }
377
378   /**
379    * @brief Button signal handler
380    */
381   bool OnBackButtonPressed( Toolkit::Button button )
382   {
383     ReturnToPreviousScreen();
384     return true;
385   }
386
387   /**
388    * @brief Returns to the previous screen
389    */
390   void ReturnToPreviousScreen()
391   {
392     if ( mItemView.GetProperty< bool >( Actor::Property::CONNECTED_TO_SCENE ) )
393     {
394       // Quit the application if it is in the main menu
395       mApplication.Quit();
396     }
397     else
398     {
399       // Return to the main menu
400       mNavigationView.Pop();
401
402       mTitle.SetProperty( TextLabel::Property::TEXT, "Select type of text to test" );
403     }
404   }
405
406 private:
407
408   Application& mApplication;
409
410   ItemLayoutPtr mLayout;
411   ItemView mItemView;
412   NavigationView mNavigationView;
413
414   Control mView;
415   ToolBar mToolBar;
416   TextLabel mTitle;
417   ImageView mIndicator;
418   Animation mAnimation;
419
420   Layer mLayer;
421
422   TapGestureDetector mTapDetector;
423
424   unsigned int mCurrentTextStyle;
425 };
426
427 int DALI_EXPORT_API main( int argc, char **argv )
428 {
429   Application application = Application::New( &argc, &argv, DEMO_THEME_PATH );
430   TextMemoryProfilingExample test( application );
431   application.MainLoop();
432   return 0;
433 }