2 * Copyright (c) 2016 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>
24 using Dali::Toolkit::TextLabel;
29 const char* IMAGE_PATH_PREFIX ( DEMO_IMAGE_DIR "application-icon-" );
30 const char* IMAGE_PATH_POSTFIX ( ".png" );
31 const int TOTAL_ICON_DEFINITIONS ( 147 );
33 const char* BACKGROUND_IMAGE ( DEMO_IMAGE_DIR "background-3.jpg" );
34 const float PAGE_SCALE_FACTOR_X ( 0.95f );
35 const float PAGE_SCALE_FACTOR_Y ( 0.95f );
36 const float PAGE_DURATION_SCALE_FACTOR ( 10.0f ); ///< Time-scale factor, larger = animation is slower
38 const float DEFAULT_OPT_ROW_COUNT ( 5 );
39 const float DEFAULT_OPT_COL_COUNT ( 4 );
40 const float DEFAULT_OPT_PAGE_COUNT ( 10 );
41 const bool DEFAULT_OPT_USE_TABLEVIEW ( true );
42 const bool DEFAULT_OPT_BATCHING_ENABLED ( true );
43 const bool DEFAULT_OPT_ICON_LABELS ( true );
45 // The image/label area tries to make sure the positioning will be relative to previous sibling
46 const float IMAGE_AREA ( 0.60f );
47 const float LABEL_AREA ( 0.50f );
50 * Random words used as unique application names.
51 * The number matches the value of TOTAL_ICON_DEFINITIONS.
53 const char* DEMO_APPS_NAMES[] =
55 "Achdyer", "Aughm", "Cerl", "Daril", "Emgha", "Ghatan", "Issum", "Lertan", "Mosorrad",
56 "Achtortor", "Aughtheryer", "Certin", "Darpban", "Emiton", "Gibanis", "Itenthbel", "Liadem", "Mosraye",
57 "Ackirlor", "Awitad", "Checerper", "Dasrad", "Emworeng", "Hatdyn", "K'ackves", "Liathar", "Mosth",
58 "Ackptin", "Banengon", "Chegit", "Deeqskel", "Endnys", "Heesban", "Kagdra", "Liephden", "Neabar",
59 "Aighte", "Banhinat", "Cheirat", "Delurnther", "Enessray", "Hesub", "Kalbankim", "Likellor", "Neerdem",
60 "Akala", "Belrisash", "Che'rak", "Denalda", "Engyer", "Hinkelenth", "Kal'enda", "Loightmos", "Nichqua",
61 "Alealdny", "Bilorm", "Cheves", "Derynkel", "En'rady", "Hirryer", "Kimest", "Loromum", "Nudraough",
62 "Angash", "Bleustcer", "Chiperath", "Deurnos", "Enthount", "Ideinta", "Kimundeng", "Lorr", "Nuyim",
63 "Anglor", "Bliagelor", "Chralerack", "Doyaryke", "Enundem", "Im'eld", "Koachlor", "Lortas", "Nycha",
64 "Anveraugh", "Blorynton", "Chram", "Draithon", "Essina", "Ina'ir", "Kuren", "Lyerr", "Nyia",
65 "Ardangas", "Booten", "Clyimen", "Drantess", "Faughald", "Ing'moro", "Kygver", "Maustbur", "Nyjac",
66 "Ardug", "Bripolqua", "Coqueang", "Druardny", "Fiummos", "Ingormess", "Kyning", "Menvor", "Nystondar",
67 "Ardworu", "Bryray", "Craennther", "Dynsaytor", "Garash", "Ingshy", "Laiyach", "Meusten", "Okine",
68 "Ascerald", "Burust", "Cykage", "Dytinris", "Garight", "Issath", "Lasuzu", "Mirodskel", "Oldit",
69 "Ash'ach", "Cataikel", "Dalek", "Eeni", "Garrynath", "Issendris", "Lekew", "Morhatrod", "Om'mose",
70 "Athiund", "Cerilwar", "Darhkel", "Elmryn", "Ghalora", "Issey", "Lerengom", "Moserbel", "Onye",
71 "Ososrak", "Pecertin", "Perrd"
74 // This code comes from command-line-options.cpp. the reason it's here is to
75 // keep consistent the extra-help formatting when '--help' used.
76 void PrintHelp( const char * const opt, const char * const optDescription)
78 const std::ios_base::fmtflags flags = std::cout.flags();
79 std::cout << std::left << " -";
80 std::cout.width( 18 );
82 std::cout << optDescription;
83 std::cout << std::endl;
84 std::cout.flags( flags );
90 * @brief This example is a benchmark that mimics the paged applications list of the homescreen application.
92 class HomescreenBenchmark : public ConnectionTracker
96 // Config structure passed to the constructor. It makes easier to increase number
97 // of setup parameters if needed.
101 mRows( DEFAULT_OPT_ROW_COUNT ),
102 mCols( DEFAULT_OPT_COL_COUNT ),
103 mPageCount( DEFAULT_OPT_PAGE_COUNT ),
104 mTableViewEnabled( DEFAULT_OPT_USE_TABLEVIEW ),
105 mBatchingEnabled( DEFAULT_OPT_BATCHING_ENABLED ),
106 mIconLabelsEnabled( DEFAULT_OPT_ICON_LABELS )
113 bool mTableViewEnabled;
114 bool mBatchingEnabled;
115 bool mIconLabelsEnabled;
118 // animation script data
121 ScriptData( int pages, float duration, bool flick )
123 mDuration( duration ),
128 int mPages; ///< Number of pages to scroll
129 float mDuration; ///< Duration
130 bool mFlick; ///< Use flick or 'one-by-one' scroll
133 HomescreenBenchmark( Application& application, const Config& config )
134 : mApplication( application ),
139 // Connect to the Application's Init signal.
140 mApplication.InitSignal().Connect( this, &HomescreenBenchmark::Create );
143 ~HomescreenBenchmark()
147 // The Init signal is received once (only) during the Application lifetime.
148 void Create( Application& application )
150 // Create benchmark script
153 // Get a handle to the stage
154 Stage stage = Stage::GetCurrent();
156 mScrollParent = Actor::New();
157 mScrollParent.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS );
158 mScrollParent.SetAnchorPoint( AnchorPoint::CENTER );
159 mScrollParent.SetParentOrigin( ParentOrigin::CENTER );
162 Toolkit::ImageView background = Toolkit::ImageView::New( BACKGROUND_IMAGE );
163 Stage::GetCurrent().Add( background );
164 background.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS );
165 background.SetAnchorPoint( AnchorPoint::CENTER );
166 background.SetParentOrigin( ParentOrigin::CENTER );
170 stage.Add( mScrollParent );
172 // Respond to a click anywhere on the stage.
173 stage.GetRootLayer().TouchSignal().Connect( this, &HomescreenBenchmark::OnTouch );
176 bool OnTouch( Actor actor, const TouchData& touch )
178 // Quit the application.
185 // Create root page actor.
188 if( mConfig.mTableViewEnabled )
190 Toolkit::TableView tableView = Toolkit::TableView::New( mConfig.mRows, mConfig.mCols );
192 // Create geometry batcher for table view.
193 tableView.SetBackgroundColor( Vector4( 0.0f, 0.0f, 0.0f, 0.5f ) );
194 pageActor = tableView;
198 pageActor = Toolkit::Control::New();
199 pageActor.SetProperty( Toolkit::Control::Property::BACKGROUND_COLOR, Vector4( 0.0f, 0.0f, 0.0f, 0.5f ) );
202 pageActor.SetParentOrigin( ParentOrigin::CENTER );
203 pageActor.SetAnchorPoint( AnchorPoint::CENTER );
204 pageActor.SetResizePolicy( ResizePolicy::SIZE_RELATIVE_TO_PARENT, Dimension::ALL_DIMENSIONS );
205 pageActor.SetSizeModeFactor( Vector3( PAGE_SCALE_FACTOR_X, PAGE_SCALE_FACTOR_Y, 1.0f ) );
209 void AddIconsToPage( Actor page )
211 Size stageSize( Stage::GetCurrent().GetSize() );
212 const float scaledHeight = stageSize.y * PAGE_SCALE_FACTOR_Y;
213 const float scaledWidth = stageSize.x * PAGE_SCALE_FACTOR_X;
214 const float PADDING = stageSize.y / 64.0f;
215 const float ROW_HEIGHT = ( scaledHeight - (PADDING*2.0f) ) / static_cast<float>( mConfig.mRows );
216 const float COL_WIDTH = ( scaledWidth - (PADDING*2.0f) ) / static_cast<float>( mConfig.mCols );
218 Vector2 dpi = Stage::GetCurrent().GetDpi();
220 static int currentIconIndex = 0;
222 for( int y = 0; y < mConfig.mRows; ++y )
224 for( int x = 0; x < mConfig.mCols; ++x )
226 // Create parent icon view
227 Toolkit::Control iconView = Toolkit::Control::New();
228 iconView.SetAnchorPoint( AnchorPoint::TOP_LEFT );
229 iconView.SetParentOrigin( ParentOrigin::TOP_LEFT );
231 if( !mConfig.mTableViewEnabled )
233 float rowX = x * COL_WIDTH + PADDING;
234 float rowY = y * ROW_HEIGHT + PADDING;
235 iconView.SetSize( Vector3( COL_WIDTH, ROW_HEIGHT, 1.0f ) );
236 iconView.SetPosition( Vector3( rowX, rowY, 0.0f ) );
240 iconView.SetResizePolicy( ResizePolicy::SIZE_RELATIVE_TO_PARENT, Dimension::ALL_DIMENSIONS );
241 iconView.SetSizeScalePolicy( SizeScalePolicy::FIT_WITH_ASPECT_RATIO );
244 // Create empty image to avoid early renderer creation
245 Toolkit::ImageView imageView = Toolkit::ImageView::New();
247 // Auto-generate the Icons image URL.
249 std::stringstream imagePath;
250 imagePath << IMAGE_PATH_PREFIX << currentIconIndex << IMAGE_PATH_POSTFIX;
251 map[ Dali::Toolkit::BatchImageVisual::Property::URL ] = imagePath.str();
253 // Enable/disable batching
254 map[ Toolkit::Visual::Property::BATCHING_ENABLED ] = mConfig.mBatchingEnabled;
256 imageView.SetProperty( Toolkit::ImageView::Property::IMAGE, map );
257 imageView.SetResizePolicy( ResizePolicy::SIZE_RELATIVE_TO_PARENT, Dimension::ALL_DIMENSIONS );
258 imageView.SetSizeScalePolicy( SizeScalePolicy::FIT_WITH_ASPECT_RATIO );
259 imageView.SetAnchorPoint( AnchorPoint::CENTER );
260 imageView.SetParentOrigin( ParentOrigin::CENTER );
261 imageView.SetSizeModeFactor( Vector3( IMAGE_AREA, IMAGE_AREA, 1.0f ) );
263 if( mConfig.mIconLabelsEnabled )
266 Toolkit::TextLabel textLabel = Toolkit::TextLabel::New( DEMO_APPS_NAMES[currentIconIndex] );
267 textLabel.SetAnchorPoint( AnchorPoint::TOP_CENTER );
268 textLabel.SetParentOrigin( ParentOrigin::BOTTOM_CENTER );
269 textLabel.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS );
270 textLabel.SetProperty( Toolkit::TextLabel::Property::TEXT_COLOR, Vector4( 1.0f, 1.0f, 1.0f, 1.0f ) ); // White.
271 textLabel.SetProperty( Toolkit::TextLabel::Property::POINT_SIZE, ( ( static_cast<float>( ROW_HEIGHT * LABEL_AREA ) * 72.0f ) / dpi.y ) * 0.25f );
272 textLabel.SetProperty( Toolkit::TextLabel::Property::HORIZONTAL_ALIGNMENT, "CENTER" );
273 textLabel.SetProperty( Toolkit::TextLabel::Property::VERTICAL_ALIGNMENT, "TOP" );
274 imageView.Add( textLabel );
277 iconView.Add( imageView );
278 page.Add( iconView );
280 // We only have images and names for a certain number of icons.
281 // Wrap around if we have used them all.
282 if( ++currentIconIndex == TOTAL_ICON_DEFINITIONS )
284 currentIconIndex = 0;
292 const int lastPage = mConfig.mPageCount - 1;
293 const int halfA = lastPage / 2;
294 const int halfB = lastPage / 2 + lastPage % 2;
295 mScriptFrameData.push_back( ScriptData( lastPage, 1.5f, true ) );
296 mScriptFrameData.push_back( ScriptData( -lastPage, 1.5f, true ) );
297 mScriptFrameData.push_back( ScriptData( halfA, 1.0f, true ) );
298 mScriptFrameData.push_back( ScriptData( halfB, 1.0f, true ) );
299 mScriptFrameData.push_back( ScriptData( -lastPage, 0.5f, false ) );
300 mScriptFrameData.push_back( ScriptData( halfA, 0.5f, false ) );
301 mScriptFrameData.push_back( ScriptData( halfB, 1.0f, true ) );
302 mScriptFrameData.push_back( ScriptData( -halfA, 1.0f, true ) );
303 mScriptFrameData.push_back( ScriptData( 1, 0.1f, true ) );
304 mScriptFrameData.push_back( ScriptData( -1, 0.1f, true ) );
305 mScriptFrameData.push_back( ScriptData( 1, 0.1f, true ) );
306 mScriptFrameData.push_back( ScriptData( -1, 0.1f, true ) );
307 mScriptFrameData.push_back( ScriptData( 1, 0.1f, true ) );
308 mScriptFrameData.push_back( ScriptData( -1, 0.1f, true ) );
309 mScriptFrameData.push_back( ScriptData( halfA, 1.0f, true ) );
314 Vector3 stageSize( Stage::GetCurrent().GetSize() );
316 for( int i = 0; i < mConfig.mPageCount; ++i )
319 Actor page = AddPage();
322 AddIconsToPage( page );
324 // Move page 'a little bit up'.
325 page.SetParentOrigin( ParentOrigin::CENTER );
326 page.SetAnchorPoint( AnchorPoint::CENTER );
327 page.SetPosition( Vector3( stageSize.x * i, 0.0f, 0.0f ) );
328 mScrollParent.Add( page );
330 if( mConfig.mTableViewEnabled && mConfig.mBatchingEnabled )
332 page.SetProperty( Actor::Property::BATCH_PARENT, true );
336 mScrollParent.SetOpacity( 1.0f );
337 mScrollParent.SetScale( Vector3::ONE );
345 mShowAnimation = Animation::New( 1.0f );
346 mShowAnimation.AnimateTo( Property( mScrollParent, Actor::Property::COLOR_ALPHA ), 1.0f, AlphaFunction::EASE_IN_OUT );
347 mShowAnimation.AnimateTo( Property( mScrollParent, Actor::Property::SCALE ), Vector3::ONE, AlphaFunction::EASE_IN_OUT );
348 mShowAnimation.FinishedSignal().Connect( this, &HomescreenBenchmark::OnAnimationEnd );
349 mShowAnimation.Play();
352 void ScrollPages(int pages, float duration, bool flick)
354 duration *= PAGE_DURATION_SCALE_FACTOR;
355 Vector3 stageSize( Stage::GetCurrent().GetSize() );
356 mScrollAnimation = Animation::New( duration );
359 mScrollAnimation.AnimateBy( Property( mScrollParent, Actor::Property::POSITION ), Vector3( -stageSize.x * pages, 0.0f, 0.0f ), AlphaFunction::EASE_IN_OUT );
363 int totalPages = abs( pages );
364 for( int i = 0; i < totalPages; ++i )
366 mScrollAnimation.AnimateBy( Property( mScrollParent, Actor::Property::POSITION ), Vector3( pages < 0 ? stageSize.x : -stageSize.x, 0.0f, 0.0f ), AlphaFunction::EASE_IN_OUT, TimePeriod( duration * i, duration ) );
369 mScrollAnimation.FinishedSignal().Connect( this, &HomescreenBenchmark::OnAnimationEnd );
370 mScrollAnimation.Play();
371 mCurrentPage += pages;
374 void OnAnimationEnd( Animation& source )
376 if( mScriptFrame < mScriptFrameData.size() )
378 ScriptData& frame = mScriptFrameData[mScriptFrame];
379 ScrollPages( frame.mPages, frame.mDuration, frame.mFlick );
390 Application& mApplication;
392 Animation mShowAnimation;
393 Animation mScrollAnimation;
395 std::vector<ScriptData> mScriptFrameData;
400 void RunTest( Application& application, const HomescreenBenchmark::Config& config, bool printHelpAndExit )
402 HomescreenBenchmark test( application, config );
404 if( printHelpAndExit )
406 PrintHelp( "c<num>", " Number of columns" );
407 PrintHelp( "r<num>", " Number of rows" );
408 PrintHelp( "p<num>", " Number of pages ( must be greater than 1 )" );
409 PrintHelp( "-disable-tableview", " Disables the use of TableView for layouting (must be enabled for batching)" );
410 PrintHelp( "-disable-batching", " Disables geometry batching" );
411 PrintHelp( "-disable-icon-labels", " Disables labels for each icon" );
415 application.MainLoop();
418 // Entry point for Linux & Tizen applications.
419 int DALI_EXPORT_API main( int argc, char **argv )
422 HomescreenBenchmark::Config config;
424 bool printHelpAndExit = false;
426 for( int i = 1 ; i < argc; ++i )
428 std::string arg( argv[i] );
429 if( arg.compare( 0, 2, "-r" ) == 0 )
431 config.mRows = atoi( arg.substr( 2 ).c_str() );
433 else if( arg.compare( 0, 2, "-c" ) == 0 )
435 config.mCols = atoi( arg.substr( 2 ).c_str() );
437 else if( arg.compare( 0, 2, "-p" ) == 0 )
439 config.mPageCount = atoi( arg.substr( 2 ).c_str() );
441 else if( arg.compare( "--disable-tableview" ) == 0 )
443 config.mTableViewEnabled = false;
445 else if( arg.compare( "--disable-batching" ) == 0 )
447 config.mBatchingEnabled = false;
449 else if( arg.compare( "--disable-icon-labels" ) == 0 )
451 config.mIconLabelsEnabled = false;
453 else if( arg.compare( "--help" ) == 0 )
455 printHelpAndExit = true;
459 Application application = Application::New( &argc, &argv );
461 RunTest( application, config, printHelpAndExit );