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