37d45a5f0cb16e963734157747928df2bc62e5f8
[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 windowSize = mApplication.GetWindow().GetSize();
110     label.SetProperty( Actor::Property::POSITION, Vector3( Random::Range( 0.0f, windowSize.x ), Random::Range( 0.0f, windowSize.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(windowSize.x, windowSize.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     Vector2 windowSize = mApplication.GetWindow().GetSize();
200
201     mTapDetector = TapGestureDetector::New();
202     mTapDetector.DetectedSignal().Connect( this, &TextMemoryProfilingExample::OnTap );
203
204     // Create an item view for the main menu
205     mItemView = ItemView::New( *this );
206
207     mItemView.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER );
208     mItemView.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER );
209
210     mLayout = DefaultItemLayout::New( DefaultItemLayout::LIST );
211     mLayout->SetItemSize( Vector3( windowSize.width, 60.0f, 0.0f ) );
212
213     mItemView.AddLayout( *mLayout );
214
215     // Activate the layout
216     mItemView.ActivateLayout( 0, Vector3( windowSize ), 0.0f );
217   }
218
219   /**
220    * @brief Return the number of items in the main menu
221    */
222   virtual unsigned int GetNumberOfItems()
223   {
224     return NUMBER_OF_TYPES;
225   }
226
227   /**
228    * @brief Create new item for the main menu
229    */
230   virtual Actor NewItem( unsigned int itemId )
231   {
232     TextLabel label = TextLabel::New( TEXT_TYPE_STRING[itemId] );
233     label.SetStyleName( "BuilderLabel" );
234     label.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::WIDTH );
235
236     // Hook up tap detector
237     mTapDetector.Attach( label );
238
239     return label;
240   }
241
242   /**
243    * @brief Create text labels for memory profiling
244    */
245   void CreateTextLabels( int type )
246   {
247     // Delete any existing text labels
248     unsigned int numChildren = mLayer.GetChildCount();
249
250     for( unsigned int i = 0; i < numChildren; ++i )
251     {
252       mLayer.Remove( mLayer.GetChildAt( 0 ) );
253     }
254
255     mLayer.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::BOTTOM_CENTER );
256     mLayer.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::BOTTOM_CENTER );
257     mLayer.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::WIDTH );
258     mLayer.SetResizePolicy( ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT, Dimension::HEIGHT );
259     mLayer.SetProperty( Actor::Property::SIZE_MODE_FACTOR, Vector3( 0.0f, -DemoHelper::DEFAULT_VIEW_STYLE.mToolBarHeight, 0.0f ) );
260
261     mNavigationView.Push( mLayer );
262
263     // Create new text labels
264     for ( int i = 0; i < NUMBER_OF_LABELS; i++ )
265     {
266       TextLabel label = SetupTextLabel( type );
267       mLayer.Add( label );
268     }
269
270     mTitle.SetProperty( TextLabel::Property::TEXT, "Run memps on target" );
271   }
272
273   /**
274    * @brief One-time setup in response to Application InitSignal.
275    */
276   void Create( Application& application )
277   {
278     Window window = application.GetWindow();
279
280     window.KeyEventSignal().Connect(this, &TextMemoryProfilingExample::OnKeyEvent);
281
282     Layer contents = DemoHelper::CreateView( mApplication,
283                                              mView,
284                                              mToolBar,
285                                              BACKGROUND_IMAGE,
286                                              TOOLBAR_IMAGE,
287                                              "" );
288
289     mTitle = DemoHelper::CreateToolBarLabel( "" );
290     mTitle.SetProperty( TextLabel::Property::TEXT, "Select the type of text" );
291
292     // Add title to the tool bar.
293     mToolBar.AddControl( mTitle, DemoHelper::DEFAULT_VIEW_STYLE.mToolBarTitlePercentage, Alignment::HorizontalCenter );
294
295     // Create a layer to contain dynamically created text labels
296     mLayer = Layer::New();
297
298     mIndicator = Toolkit::ImageView::New(INDICATOR_IMAGE);
299     mIndicator.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER );
300     mIndicator.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER );
301     mIndicator.SetProperty( Actor::Property::VISIBLE, false );
302
303     // Create a back button in the left of toolbar
304     PushButton backButton = PushButton::New();
305     backButton.SetProperty( Button::Property::UNSELECTED_BACKGROUND_VISUAL, BACK_IMAGE );
306     backButton.SetProperty( Button::Property::SELECTED_BACKGROUND_VISUAL, BACK_IMAGE_SELECTED );
307     backButton.ClickedSignal().Connect( this, &TextMemoryProfilingExample::OnBackButtonPressed );
308     backButton.SetProperty( Actor::Property::LEAVE_REQUIRED, true );
309     mToolBar.AddControl( backButton, DemoHelper::DEFAULT_VIEW_STYLE.mToolBarButtonPercentage, Alignment::HorizontalLeft, DemoHelper::DEFAULT_MODE_SWITCH_PADDING );
310
311     // Create a navigation view to navigate different types of text labels
312     mNavigationView = NavigationView::New();
313     mNavigationView.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS );
314     mNavigationView.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT );
315     mNavigationView.SetBackgroundColor( Color::WHITE );
316     window.Add( mNavigationView );
317
318     CreateMainMenu();
319     mNavigationView.Push( mItemView );
320
321     mItemView.Add(mIndicator);
322
323     PropertyNotification notification = mIndicator.AddPropertyNotification( Actor::Property::VISIBLE, GreaterThanCondition(0.01f) );
324     notification.NotifySignal().Connect( this, &TextMemoryProfilingExample::OnIndicatorVisible );
325   }
326
327   /**
328    * @brief Main key event handler
329    */
330   void OnKeyEvent( const KeyEvent& event )
331   {
332     if( event.state == KeyEvent::Down )
333     {
334       if( IsKey( event, DALI_KEY_ESCAPE) || IsKey( event, DALI_KEY_BACK ) )
335       {
336         ReturnToPreviousScreen();
337       }
338     }
339   }
340
341   /**
342    * @brief Tap gesture handler
343    */
344   void OnTap( Actor actor, const TapGesture& tap )
345   {
346     mCurrentTextStyle = mItemView.GetItemId( actor );
347
348     // Show the loading indicator
349     mIndicator.SetProperty( Actor::Property::VISIBLE, true );
350
351     if ( mAnimation )
352     {
353       mAnimation.Clear();
354       mAnimation.Reset();
355     }
356
357     mAnimation = Animation::New( 0.8f );
358     mAnimation.AnimateBy( Property( mIndicator, Actor::Property::ORIENTATION ), Quaternion( Radian( Degree(180.0f) ), Vector3::ZAXIS ) );
359     mAnimation.SetLooping( true );
360     mAnimation.Play();
361   }
362
363   /**
364    * @brief Property notification handler
365    */
366   void OnIndicatorVisible( PropertyNotification& source )
367   {
368     CreateTextLabels( mCurrentTextStyle );
369
370     // Hide the loading indicator
371     mAnimation.Stop();
372     mIndicator.SetProperty( Actor::Property::VISIBLE, false );
373   }
374
375   /**
376    * @brief Button signal handler
377    */
378   bool OnBackButtonPressed( Toolkit::Button button )
379   {
380     ReturnToPreviousScreen();
381     return true;
382   }
383
384   /**
385    * @brief Returns to the previous screen
386    */
387   void ReturnToPreviousScreen()
388   {
389     if ( mItemView.GetProperty< bool >( Actor::Property::CONNECTED_TO_SCENE ) )
390     {
391       // Quit the application if it is in the main menu
392       mApplication.Quit();
393     }
394     else
395     {
396       // Return to the main menu
397       mNavigationView.Pop();
398
399       mTitle.SetProperty( TextLabel::Property::TEXT, "Select type of text to test" );
400     }
401   }
402
403 private:
404
405   Application& mApplication;
406
407   ItemLayoutPtr mLayout;
408   ItemView mItemView;
409   NavigationView mNavigationView;
410
411   Control mView;
412   ToolBar mToolBar;
413   TextLabel mTitle;
414   ImageView mIndicator;
415   Animation mAnimation;
416
417   Layer mLayer;
418
419   TapGestureDetector mTapDetector;
420
421   unsigned int mCurrentTextStyle;
422 };
423
424 int DALI_EXPORT_API main( int argc, char **argv )
425 {
426   Application application = Application::New( &argc, &argv, DEMO_THEME_PATH );
427   TextMemoryProfilingExample test( application );
428   application.MainLoop();
429   return 0;
430 }