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