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