2 * Copyright (c) 2020 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #include <dali-toolkit/dali-toolkit.h>
20 #include <dali/devel-api/actors/actor-devel.h>
24 #include <dali-toolkit/devel-api/controls/table-view/table-view.h>
25 #include <dali-toolkit/devel-api/visual-factory/visual-factory.h>
28 using Dali::Toolkit::TextLabel;
38 const char* IMAGE_PATH_PREFIX(DEMO_IMAGE_DIR "application-icon-");
39 const char* IMAGE_PATH_POSTFIX(".png");
40 const int TOTAL_ICON_DEFINITIONS(147);
42 const char* BACKGROUND_IMAGE(DEMO_IMAGE_DIR "background-3.jpg");
43 const float PAGE_SCALE_FACTOR_X(0.95f);
44 const float PAGE_SCALE_FACTOR_Y(0.95f);
45 const float PAGE_DURATION_SCALE_FACTOR(10.0f); ///< Time-scale factor, larger = animation is slower
47 const float DEFAULT_OPT_ROW_COUNT(5);
48 const float DEFAULT_OPT_COL_COUNT(4);
49 const float DEFAULT_OPT_PAGE_COUNT(10);
50 const bool DEFAULT_OPT_USE_TABLEVIEW(true);
51 const bool DEFAULT_OPT_ICON_LABELS(true);
52 const IconType DEFAULT_OPT_ICON_TYPE(IMAGEVIEW);
53 const bool DEFAULT_OPT_USE_TEXT_LABEL(false);
55 // The image/label area tries to make sure the positioning will be relative to previous sibling
56 const float IMAGE_AREA(0.60f);
57 const float LABEL_AREA(0.50f);
60 * Random words used as unique application names.
61 * The number matches the value of TOTAL_ICON_DEFINITIONS.
63 const char* DEMO_APPS_NAMES[] =
65 "Achdyer", "Aughm", "Cerl", "Daril", "Emgha", "Ghatan", "Issum", "Lertan", "Mosorrad", "Achtortor", "Aughtheryer", "Certin", "Darpban", "Emiton", "Gibanis", "Itenthbel", "Liadem", "Mosraye", "Ackirlor", "Awitad", "Checerper", "Dasrad", "Emworeng", "Hatdyn", "K'ackves", "Liathar", "Mosth", "Ackptin", "Banengon", "Chegit", "Deeqskel", "Endnys", "Heesban", "Kagdra", "Liephden", "Neabar", "Aighte", "Banhinat", "Cheirat", "Delurnther", "Enessray", "Hesub", "Kalbankim", "Likellor", "Neerdem", "Akala", "Belrisash", "Che'rak", "Denalda", "Engyer", "Hinkelenth", "Kal'enda", "Loightmos", "Nichqua", "Alealdny", "Bilorm", "Cheves", "Derynkel", "En'rady", "Hirryer", "Kimest", "Loromum", "Nudraough", "Angash", "Bleustcer", "Chiperath", "Deurnos", "Enthount", "Ideinta", "Kimundeng", "Lorr", "Nuyim", "Anglor", "Bliagelor", "Chralerack", "Doyaryke", "Enundem", "Im'eld", "Koachlor", "Lortas", "Nycha", "Anveraugh", "Blorynton", "Chram", "Draithon", "Essina", "Ina'ir", "Kuren", "Lyerr", "Nyia", "Ardangas", "Booten", "Clyimen", "Drantess", "Faughald", "Ing'moro", "Kygver", "Maustbur", "Nyjac", "Ardug", "Bripolqua", "Coqueang", "Druardny", "Fiummos", "Ingormess", "Kyning", "Menvor", "Nystondar", "Ardworu", "Bryray", "Craennther", "Dynsaytor", "Garash", "Ingshy", "Laiyach", "Meusten", "Okine", "Ascerald", "Burust", "Cykage", "Dytinris", "Garight", "Issath", "Lasuzu", "Mirodskel", "Oldit", "Ash'ach", "Cataikel", "Dalek", "Eeni", "Garrynath", "Issendris", "Lekew", "Morhatrod", "Om'mose", "Athiund", "Cerilwar", "Darhkel", "Elmryn", "Ghalora", "Issey", "Lerengom", "Moserbel", "Onye", "Ososrak", "Pecertin", "Perrd"};
67 // This code comes from command-line-options.cpp. the reason it's here is to
68 // keep consistent the extra-help formatting when '--help' used.
69 void PrintHelp(const char* const opt, const char* const optDescription)
71 const std::ios_base::fmtflags flags = std::cout.flags();
72 std::cout << std::left << " -";
75 std::cout << optDescription;
76 std::cout << std::endl;
77 std::cout.flags(flags);
83 * @brief This example is a benchmark that mimics the paged applications list of the homescreen application.
85 class HomescreenBenchmark : public ConnectionTracker
88 // Config structure passed to the constructor. It makes easier to increase number
89 // of setup parameters if needed.
93 : mRows(DEFAULT_OPT_ROW_COUNT),
94 mCols(DEFAULT_OPT_COL_COUNT),
95 mPageCount(DEFAULT_OPT_PAGE_COUNT),
96 mTableViewEnabled(DEFAULT_OPT_USE_TABLEVIEW),
97 mIconLabelsEnabled(DEFAULT_OPT_ICON_LABELS),
98 mIconType(DEFAULT_OPT_ICON_TYPE),
99 mUseTextLabel(DEFAULT_OPT_USE_TEXT_LABEL)
106 bool mTableViewEnabled;
107 bool mIconLabelsEnabled;
112 // animation script data
115 ScriptData(int pages, float duration, bool flick)
122 int mPages; ///< Number of pages to scroll
123 float mDuration; ///< Duration
124 bool mFlick; ///< Use flick or 'one-by-one' scroll
127 HomescreenBenchmark(Application& application, const Config& config)
128 : mApplication(application),
133 // Connect to the Application's Init signal.
134 mApplication.InitSignal().Connect(this, &HomescreenBenchmark::Create);
137 ~HomescreenBenchmark()
141 // The Init signal is received once (only) during the Application lifetime.
142 void Create(Application& application)
144 // Create benchmark script
147 // Get a handle to the window
148 Window window = application.GetWindow();
150 mScrollParent = Actor::New();
151 mScrollParent.SetResizePolicy(ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS);
152 mScrollParent.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
153 mScrollParent.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
156 Toolkit::ImageView background = Toolkit::ImageView::New(BACKGROUND_IMAGE);
157 window.Add(background);
158 background.SetResizePolicy(ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS);
159 background.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
160 background.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
164 window.Add(mScrollParent);
166 // Respond to a click anywhere on the window.
167 window.GetRootLayer().TouchedSignal().Connect(this, &HomescreenBenchmark::OnTouch);
169 // Respond to key events
170 window.KeyEventSignal().Connect(this, &HomescreenBenchmark::OnKeyEvent);
173 bool OnTouch(Actor actor, const TouchEvent& touch)
175 // Quit the application.
182 // Create root page actor.
183 Toolkit::Control pageActor;
185 if(mConfig.mTableViewEnabled)
187 pageActor = Toolkit::TableView::New(mConfig.mRows, mConfig.mCols);
191 pageActor = Toolkit::Control::New();
194 pageActor.SetBackgroundColor(Vector4(0.0f, 0.0f, 0.0f, 0.5f));
195 pageActor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
196 pageActor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
197 pageActor.SetResizePolicy(ResizePolicy::SIZE_RELATIVE_TO_PARENT, Dimension::ALL_DIMENSIONS);
198 pageActor.SetProperty(Actor::Property::SIZE_MODE_FACTOR, Vector3(PAGE_SCALE_FACTOR_X, PAGE_SCALE_FACTOR_Y, 1.0f));
202 Toolkit::ImageView CreateImageView(const unsigned int currentIconIndex)
204 // Create empty image to avoid early renderer creation
205 Toolkit::ImageView imageView = Toolkit::ImageView::New();
207 // Auto-generate the Icons image URL.
209 std::stringstream imagePath;
210 imagePath << IMAGE_PATH_PREFIX << currentIconIndex << IMAGE_PATH_POSTFIX;
211 map[Dali::Toolkit::ImageVisual::Property::URL] = imagePath.str();
213 imageView.SetProperty(Toolkit::ImageView::Property::IMAGE, map);
214 imageView.SetResizePolicy(ResizePolicy::SIZE_RELATIVE_TO_PARENT, Dimension::ALL_DIMENSIONS);
215 imageView.SetProperty(Actor::Property::SIZE_SCALE_POLICY, SizeScalePolicy::FIT_WITH_ASPECT_RATIO);
216 imageView.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
217 imageView.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
218 imageView.SetProperty(Actor::Property::SIZE_MODE_FACTOR, Vector3(IMAGE_AREA, IMAGE_AREA, 1.0f));
223 Toolkit::Button CreateButton(const unsigned int currentIconIndex)
225 Toolkit::CheckBoxButton button = Toolkit::CheckBoxButton::New();
226 button.SetResizePolicy(ResizePolicy::SIZE_RELATIVE_TO_PARENT, Dimension::ALL_DIMENSIONS);
227 button.SetProperty(Actor::Property::SIZE_SCALE_POLICY, SizeScalePolicy::FIT_WITH_ASPECT_RATIO);
228 button.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
229 button.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
230 button.SetProperty(Toolkit::Button::Property::SELECTED, (currentIconIndex % 2 == 0)); // Select half the button
235 void AddIconsToPage(Actor page, bool useTextLabel)
237 Window window = mApplication.GetWindow();
239 Size windowSize(window.GetSize());
240 const float scaledHeight = windowSize.y * PAGE_SCALE_FACTOR_Y;
241 const float scaledWidth = windowSize.x * PAGE_SCALE_FACTOR_X;
242 const float PADDING = windowSize.y / 64.0f;
243 const float ROW_HEIGHT = (scaledHeight - (PADDING * 2.0f)) / static_cast<float>(mConfig.mRows);
244 const float COL_WIDTH = (scaledWidth - (PADDING * 2.0f)) / static_cast<float>(mConfig.mCols);
246 Vector2 dpi = window.GetDpi();
248 static int currentIconIndex = 0;
250 for(int y = 0; y < mConfig.mRows; ++y)
252 for(int x = 0; x < mConfig.mCols; ++x)
254 // Create parent icon view
255 Toolkit::Control iconView = Toolkit::Control::New();
256 iconView.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
257 iconView.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT);
259 if(!mConfig.mTableViewEnabled)
261 float rowX = x * COL_WIDTH + PADDING;
262 float rowY = y * ROW_HEIGHT + PADDING;
263 iconView.SetProperty(Actor::Property::SIZE, Vector3(COL_WIDTH, ROW_HEIGHT, 1.0f));
264 iconView.SetProperty(Actor::Property::POSITION, Vector3(rowX, rowY, 0.0f));
268 iconView.SetResizePolicy(ResizePolicy::SIZE_RELATIVE_TO_PARENT, Dimension::ALL_DIMENSIONS);
269 iconView.SetProperty(Actor::Property::SIZE_SCALE_POLICY, SizeScalePolicy::FIT_WITH_ASPECT_RATIO);
274 switch(mConfig.mIconType)
278 icon = CreateButton(currentIconIndex);
283 icon = CreateImageView(currentIconIndex);
288 if(mConfig.mIconLabelsEnabled)
293 Toolkit::TextLabel textLabel = Toolkit::TextLabel::New(DEMO_APPS_NAMES[currentIconIndex]);
294 textLabel.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_CENTER);
295 textLabel.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::BOTTOM_CENTER);
296 textLabel.SetResizePolicy(ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS);
297 textLabel.SetProperty(Toolkit::TextLabel::Property::TEXT_COLOR, Vector4(1.0f, 1.0f, 1.0f, 1.0f)); // White.
298 textLabel.SetProperty(Toolkit::TextLabel::Property::POINT_SIZE, ((static_cast<float>(ROW_HEIGHT * LABEL_AREA) * 72.0f) / dpi.y) * 0.25f);
299 textLabel.SetProperty(Toolkit::TextLabel::Property::HORIZONTAL_ALIGNMENT, "CENTER");
300 textLabel.SetProperty(Toolkit::TextLabel::Property::VERTICAL_ALIGNMENT, "TOP");
306 map.Add(Toolkit::Visual::Property::TYPE, Toolkit::Visual::TEXT).Add(Toolkit::TextVisual::Property::TEXT, DEMO_APPS_NAMES[currentIconIndex]).Add(Toolkit::TextVisual::Property::TEXT_COLOR, Color::WHITE).Add(Toolkit::TextVisual::Property::POINT_SIZE, ((static_cast<float>(ROW_HEIGHT * LABEL_AREA) * 72.0f) / dpi.y) * 0.25f).Add(Toolkit::TextVisual::Property::HORIZONTAL_ALIGNMENT, "CENTER").Add(Toolkit::TextVisual::Property::VERTICAL_ALIGNMENT, "TOP");
308 Toolkit::Control control = Toolkit::Control::New();
309 control.SetProperty(Toolkit::Control::Property::BACKGROUND, map);
310 control.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_CENTER);
311 control.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::BOTTOM_CENTER);
319 // We only have images and names for a certain number of icons.
320 // Wrap around if we have used them all.
321 if(++currentIconIndex == TOTAL_ICON_DEFINITIONS)
323 currentIconIndex = 0;
331 const int lastPage = mConfig.mPageCount - 1;
332 const int halfA = lastPage / 2;
333 const int halfB = lastPage / 2 + lastPage % 2;
334 mScriptFrameData.push_back(ScriptData(lastPage, 1.5f, true));
335 mScriptFrameData.push_back(ScriptData(-lastPage, 1.5f, true));
336 mScriptFrameData.push_back(ScriptData(halfA, 1.0f, true));
337 mScriptFrameData.push_back(ScriptData(halfB, 1.0f, true));
338 mScriptFrameData.push_back(ScriptData(-lastPage, 0.5f, false));
339 mScriptFrameData.push_back(ScriptData(halfA, 0.5f, false));
340 mScriptFrameData.push_back(ScriptData(halfB, 1.0f, true));
341 mScriptFrameData.push_back(ScriptData(-halfA, 1.0f, true));
342 mScriptFrameData.push_back(ScriptData(1, 0.1f, true));
343 mScriptFrameData.push_back(ScriptData(-1, 0.1f, true));
344 mScriptFrameData.push_back(ScriptData(1, 0.1f, true));
345 mScriptFrameData.push_back(ScriptData(-1, 0.1f, true));
346 mScriptFrameData.push_back(ScriptData(1, 0.1f, true));
347 mScriptFrameData.push_back(ScriptData(-1, 0.1f, true));
348 mScriptFrameData.push_back(ScriptData(halfA, 1.0f, true));
353 Vector3 windowSize(mApplication.GetWindow().GetSize());
355 for(int i = 0; i < mConfig.mPageCount; ++i)
358 Actor page = AddPage();
361 AddIconsToPage(page, mConfig.mUseTextLabel);
363 // Move page 'a little bit up'.
364 page.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
365 page.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
366 page.SetProperty(Actor::Property::POSITION, Vector3(windowSize.x * i, 0.0f, 0.0f));
367 mScrollParent.Add(page);
370 mScrollParent.SetProperty(Actor::Property::OPACITY, 1.0f);
371 mScrollParent.SetProperty(Actor::Property::SCALE, Vector3::ONE);
379 mShowAnimation = Animation::New(1.0f);
380 mShowAnimation.AnimateTo(Property(mScrollParent, Actor::Property::COLOR_ALPHA), 1.0f, AlphaFunction::EASE_IN_OUT);
381 mShowAnimation.AnimateTo(Property(mScrollParent, Actor::Property::SCALE), Vector3::ONE, AlphaFunction::EASE_IN_OUT);
382 mShowAnimation.FinishedSignal().Connect(this, &HomescreenBenchmark::OnAnimationEnd);
383 mShowAnimation.Play();
386 void ScrollPages(int pages, float duration, bool flick)
388 duration *= PAGE_DURATION_SCALE_FACTOR;
389 Vector3 windowSize(mApplication.GetWindow().GetSize());
390 mScrollAnimation = Animation::New(duration);
393 mScrollAnimation.AnimateBy(Property(mScrollParent, Actor::Property::POSITION), Vector3(-windowSize.x * pages, 0.0f, 0.0f), AlphaFunction::EASE_IN_OUT);
397 int totalPages = abs(pages);
398 for(int i = 0; i < totalPages; ++i)
400 mScrollAnimation.AnimateBy(Property(mScrollParent, Actor::Property::POSITION), Vector3(pages < 0 ? windowSize.x : -windowSize.x, 0.0f, 0.0f), AlphaFunction::EASE_IN_OUT, TimePeriod(duration * i, duration));
403 mScrollAnimation.FinishedSignal().Connect(this, &HomescreenBenchmark::OnAnimationEnd);
404 mScrollAnimation.Play();
405 mCurrentPage += pages;
408 void OnAnimationEnd(Animation& source)
410 if(mScriptFrame < mScriptFrameData.size())
412 ScriptData& frame = mScriptFrameData[mScriptFrame];
413 ScrollPages(frame.mPages, frame.mDuration, frame.mFlick);
422 void OnKeyEvent(const KeyEvent& event)
424 if(event.GetState() == KeyEvent::DOWN)
426 if(IsKey(event, Dali::DALI_KEY_ESCAPE) || IsKey(event, Dali::DALI_KEY_BACK))
434 Application& mApplication;
436 Animation mShowAnimation;
437 Animation mScrollAnimation;
439 std::vector<ScriptData> mScriptFrameData;
444 int DALI_EXPORT_API main(int argc, char** argv)
447 HomescreenBenchmark::Config config;
449 bool printHelpAndExit = false;
451 for(int i = 1; i < argc; ++i)
453 std::string arg(argv[i]);
454 if(arg.compare(0, 2, "-r") == 0)
456 config.mRows = atoi(arg.substr(2).c_str());
458 else if(arg.compare(0, 2, "-c") == 0)
460 config.mCols = atoi(arg.substr(2).c_str());
462 else if(arg.compare(0, 2, "-p") == 0)
464 config.mPageCount = atoi(arg.substr(2).c_str());
466 else if(arg.compare("--disable-tableview") == 0)
468 config.mTableViewEnabled = false;
470 else if(arg.compare("--disable-icon-labels") == 0)
472 config.mIconLabelsEnabled = false;
474 else if(arg.compare("--use-checkbox") == 0)
476 config.mIconType = CHECKBOX;
478 else if(arg.compare("--use-text-label") == 0)
480 config.mUseTextLabel = true;
482 else if(arg.compare("--help") == 0)
484 printHelpAndExit = true;
488 Application application = Application::New(&argc, &argv);
489 HomescreenBenchmark test(application, config);
493 PrintHelp("c<num>", " Number of columns");
494 PrintHelp("r<num>", " Number of rows");
495 PrintHelp("p<num>", " Number of pages ( must be greater than 1 )");
496 PrintHelp("-disable-tableview", " Disables the use of TableView for layouting");
497 PrintHelp("-disable-icon-labels", " Disables labels for each icon");
498 PrintHelp("-use-checkbox", " Uses checkboxes for icons");
499 PrintHelp("-use-text-label", " Uses TextLabel instead of a TextVisual");
503 application.MainLoop();