[dali_1.1.32] Merge branch 'devel/master'
[platform/core/uifw/dali-demo.git] / examples / item-view / item-view-example.cpp
1 /*
2  * Copyright (c) 2014 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 #include <sstream>
19 #include "shared/view.h"
20
21 #include <dali/dali.h>
22 #include <dali-toolkit/dali-toolkit.h>
23
24 using namespace Dali;
25 using namespace Dali::Toolkit;
26
27 namespace
28 {
29
30 enum AllImagesLayouts
31 {
32   SPIRAL_LAYOUT,
33   DEPTH_LAYOUT,
34   GRID_LAYOUT,
35
36   NUMBER_OF_LAYOUTS
37 };
38
39 const char* IMAGE_PATHS[] = {
40     DEMO_IMAGE_DIR "gallery-medium-1.jpg",
41     DEMO_IMAGE_DIR "gallery-medium-2.jpg",
42     DEMO_IMAGE_DIR "gallery-medium-3.jpg",
43     DEMO_IMAGE_DIR "gallery-medium-4.jpg",
44     DEMO_IMAGE_DIR "gallery-medium-5.jpg",
45     DEMO_IMAGE_DIR "gallery-medium-6.jpg",
46     DEMO_IMAGE_DIR "gallery-medium-7.jpg",
47     DEMO_IMAGE_DIR "gallery-medium-8.jpg",
48     DEMO_IMAGE_DIR "gallery-medium-9.jpg",
49     DEMO_IMAGE_DIR "gallery-medium-10.jpg",
50     DEMO_IMAGE_DIR "gallery-medium-11.jpg",
51     DEMO_IMAGE_DIR "gallery-medium-12.jpg",
52     DEMO_IMAGE_DIR "gallery-medium-13.jpg",
53     DEMO_IMAGE_DIR "gallery-medium-14.jpg",
54     DEMO_IMAGE_DIR "gallery-medium-15.jpg",
55     DEMO_IMAGE_DIR "gallery-medium-16.jpg",
56     DEMO_IMAGE_DIR "gallery-medium-17.jpg",
57     DEMO_IMAGE_DIR "gallery-medium-18.jpg",
58     DEMO_IMAGE_DIR "gallery-medium-19.jpg",
59     DEMO_IMAGE_DIR "gallery-medium-20.jpg",
60     DEMO_IMAGE_DIR "gallery-medium-21.jpg",
61     DEMO_IMAGE_DIR "gallery-medium-22.jpg",
62     DEMO_IMAGE_DIR "gallery-medium-23.jpg",
63     DEMO_IMAGE_DIR "gallery-medium-24.jpg",
64     DEMO_IMAGE_DIR "gallery-medium-25.jpg",
65     DEMO_IMAGE_DIR "gallery-medium-26.jpg",
66     DEMO_IMAGE_DIR "gallery-medium-27.jpg",
67     DEMO_IMAGE_DIR "gallery-medium-28.jpg",
68     DEMO_IMAGE_DIR "gallery-medium-29.jpg",
69     DEMO_IMAGE_DIR "gallery-medium-30.jpg",
70     DEMO_IMAGE_DIR "gallery-medium-31.jpg",
71     DEMO_IMAGE_DIR "gallery-medium-32.jpg",
72     DEMO_IMAGE_DIR "gallery-medium-33.jpg",
73     DEMO_IMAGE_DIR "gallery-medium-34.jpg",
74     DEMO_IMAGE_DIR "gallery-medium-35.jpg",
75     DEMO_IMAGE_DIR "gallery-medium-36.jpg",
76     DEMO_IMAGE_DIR "gallery-medium-37.jpg",
77     DEMO_IMAGE_DIR "gallery-medium-38.jpg",
78     DEMO_IMAGE_DIR "gallery-medium-39.jpg",
79     DEMO_IMAGE_DIR "gallery-medium-40.jpg",
80     DEMO_IMAGE_DIR "gallery-medium-41.jpg",
81     DEMO_IMAGE_DIR "gallery-medium-42.jpg",
82     DEMO_IMAGE_DIR "gallery-medium-43.jpg",
83     DEMO_IMAGE_DIR "gallery-medium-44.jpg",
84     DEMO_IMAGE_DIR "gallery-medium-45.jpg",
85     DEMO_IMAGE_DIR "gallery-medium-46.jpg",
86     DEMO_IMAGE_DIR "gallery-medium-47.jpg",
87     DEMO_IMAGE_DIR "gallery-medium-48.jpg",
88     DEMO_IMAGE_DIR "gallery-medium-49.jpg",
89     DEMO_IMAGE_DIR "gallery-medium-50.jpg",
90     DEMO_IMAGE_DIR "gallery-medium-51.jpg",
91     DEMO_IMAGE_DIR "gallery-medium-52.jpg",
92     DEMO_IMAGE_DIR "gallery-medium-53.jpg",
93 };
94
95 const unsigned int NUM_IMAGES = sizeof(IMAGE_PATHS) / sizeof(char*);
96
97 const char* BACKGROUND_IMAGE( "" );
98 const char* TOOLBAR_IMAGE( DEMO_IMAGE_DIR "top-bar.png" );
99 const char* EDIT_IMAGE( DEMO_IMAGE_DIR "icon-edit.png" );
100 const char* EDIT_IMAGE_SELECTED( DEMO_IMAGE_DIR "icon-edit-selected.png" );
101 const char* SPIRAL_LAYOUT_IMAGE( DEMO_IMAGE_DIR "icon-item-view-layout-spiral.png" );
102 const char* SPIRAL_LAYOUT_IMAGE_SELECTED( DEMO_IMAGE_DIR "icon-item-view-layout-spiral-selected.png" );
103 const char* GRID_LAYOUT_IMAGE( DEMO_IMAGE_DIR "icon-item-view-layout-grid.png" );
104 const char* GRID_LAYOUT_IMAGE_SELECTED( DEMO_IMAGE_DIR "icon-item-view-layout-grid-selected.png" );
105 const char* DEPTH_LAYOUT_IMAGE( DEMO_IMAGE_DIR "icon-item-view-layout-depth.png" );
106 const char* DEPTH_LAYOUT_IMAGE_SELECTED( DEMO_IMAGE_DIR "icon-item-view-layout-depth-selected.png" );
107 const char* DELETE_IMAGE( DEMO_IMAGE_DIR "icon-delete.png" );
108 const char* DELETE_IMAGE_SELECTED( DEMO_IMAGE_DIR "icon-delete-selected.png" );
109 const char* REPLACE_IMAGE( DEMO_IMAGE_DIR "icon-replace.png" );
110 const char* REPLACE_IMAGE_SELECTED( DEMO_IMAGE_DIR "icon-replace-selected.png" );
111 const char* INSERT_IMAGE( DEMO_IMAGE_DIR "icon-insert.png" );
112 const char* INSERT_IMAGE_SELECTED( DEMO_IMAGE_DIR "icon-insert-selected.png" );
113 const char* SELECTED_IMAGE( DEMO_IMAGE_DIR "item-select-check.png" );
114 const char* APPLICATION_TITLE( "ItemView" );
115
116 const char* SPIRAL_LABEL("Spiral");
117 const char* GRID_LABEL("Grid");
118 const char* DEPTH_LABEL("Depth");
119
120 const float ITEM_BORDER_SIZE = 2.0f;
121
122 const float DEPTH_LAYOUT_ITEM_SIZE_FACTOR_PORTRAIT = 1.0f;
123 const float DEPTH_LAYOUT_ITEM_SIZE_FACTOR_LANDSCAPE = 0.8f;
124 const float DEPTH_LAYOUT_COLUMNS = 3.0f;
125
126 const float MIN_SWIPE_DISTANCE = 15.0f;
127 const float MIN_SWIPE_SPEED = 5.0f;
128
129 const float SELECTION_BORDER_WIDTH = 3.0f;
130 const float BUTTON_BORDER = -10.0f;
131 const float MENU_OPTION_HEIGHT(140.0f);
132 const float LABEL_TEXT_SIZE_Y = 20.0f;
133
134 const Vector3 INITIAL_OFFSCREEN_POSITION( 1000.0f, 0, -1000.0f );
135
136 static Vector3 DepthLayoutItemSizeFunctionPortrait( float layoutWidth )
137 {
138   float width = ( layoutWidth / ( DEPTH_LAYOUT_COLUMNS + 1.0f ) ) * DEPTH_LAYOUT_ITEM_SIZE_FACTOR_PORTRAIT;
139
140   // 1x1 aspect ratio
141   return Vector3(width, width, width);
142 }
143
144 static Vector3 DepthLayoutItemSizeFunctionLandscape( float layoutWidth )
145 {
146   float width = ( layoutWidth / ( DEPTH_LAYOUT_COLUMNS + 1.0f ) ) * DEPTH_LAYOUT_ITEM_SIZE_FACTOR_LANDSCAPE;
147
148   // 1x1 aspect ratio
149   return Vector3(width, width, width);
150 }
151
152 } // unnamed namespace
153
154 /**
155  * This example shows how to use ItemView UI control.
156  * There are three layouts created for ItemView, i.e., Spiral, Depth and Grid.
157  * There is one button in the upper-left corner for quitting the application and
158  * another button in the upper-right corner for switching between different layouts.
159  */
160 class ItemViewExample : public ConnectionTracker, public ItemFactory
161 {
162 public:
163
164   enum Mode
165   {
166     MODE_NORMAL,
167     MODE_REMOVE,
168     MODE_REMOVE_MANY,
169     MODE_INSERT,
170     MODE_INSERT_MANY,
171     MODE_REPLACE,
172     MODE_REPLACE_MANY,
173     MODE_LAST
174   };
175
176   /**
177    * Constructor
178    * @param application class, stored as reference
179    */
180   ItemViewExample( Application& application )
181   : mApplication( application ),
182     mMode( MODE_NORMAL ),
183     mOrientation( 0 ),
184     mCurrentLayout( SPIRAL_LAYOUT ),
185     mDurationSeconds( 0.25f )
186   {
187     // Connect to the Application's Init signal
188     mApplication.InitSignal().Connect(this, &ItemViewExample::OnInit);
189   }
190
191   /**
192    * This method gets called once the main loop of application is up and running
193    */
194   void OnInit(Application& app)
195   {
196     Stage stage = Dali::Stage::GetCurrent();
197     stage.KeyEventSignal().Connect(this, &ItemViewExample::OnKeyEvent);
198     stage.GetRootLayer().SetBehavior(Layer::LAYER_3D);
199
200     Vector2 stageSize = Stage::GetCurrent().GetSize();
201
202     // Creates a default view with a default tool bar.
203     // The view is added to the stage.
204
205     Layer contents = DemoHelper::CreateView( mApplication,
206                                              mView,
207                                              mToolBar,
208                                              BACKGROUND_IMAGE,
209                                              TOOLBAR_IMAGE,
210                                              "" );
211
212     // Create an edit mode button. (left of toolbar)
213     Toolkit::PushButton editButton = Toolkit::PushButton::New();
214     editButton.SetUnselectedImage( EDIT_IMAGE );
215     editButton.SetSelectedImage( EDIT_IMAGE_SELECTED );
216     editButton.ClickedSignal().Connect( this, &ItemViewExample::OnModeButtonClicked);
217     editButton.SetLeaveRequired( true );
218     mToolBar.AddControl( editButton, DemoHelper::DEFAULT_VIEW_STYLE.mToolBarButtonPercentage, Toolkit::Alignment::HorizontalLeft, DemoHelper::DEFAULT_MODE_SWITCH_PADDING  );
219
220     // Create a layout toggle button. (right of toolbar)
221     mLayoutButton = Toolkit::PushButton::New();
222     mLayoutButton.SetUnselectedImage( SPIRAL_LAYOUT_IMAGE );
223     mLayoutButton.SetSelectedImage(SPIRAL_LAYOUT_IMAGE_SELECTED );
224     mLayoutButton.ClickedSignal().Connect( this, &ItemViewExample::OnLayoutButtonClicked);
225     mLayoutButton.SetLeaveRequired( true );
226     mToolBar.AddControl( mLayoutButton, DemoHelper::DEFAULT_VIEW_STYLE.mToolBarButtonPercentage, Toolkit::Alignment::HorizontalRight, DemoHelper::DEFAULT_MODE_SWITCH_PADDING  );
227
228     // Create a delete button (bottom right of screen)
229     mDeleteButton = Toolkit::PushButton::New();
230     mDeleteButton.SetParentOrigin(ParentOrigin::BOTTOM_RIGHT);
231     mDeleteButton.SetAnchorPoint(AnchorPoint::BOTTOM_RIGHT);
232     mDeleteButton.SetPosition( BUTTON_BORDER, BUTTON_BORDER );
233     mDeleteButton.SetDrawMode( DrawMode::OVERLAY_2D );
234     mDeleteButton.SetUnselectedImage( DELETE_IMAGE );
235     mDeleteButton.SetSelectedImage( DELETE_IMAGE_SELECTED );
236     mDeleteButton.SetBackgroundImage( TOOLBAR_IMAGE );
237     mDeleteButton.SetSize( Vector2( stageSize.width * 0.15f, stageSize.width * 0.15f ) );
238     mDeleteButton.ClickedSignal().Connect( this, &ItemViewExample::OnDeleteButtonClicked);
239     mDeleteButton.SetLeaveRequired( true );
240     mDeleteButton.SetVisible( false );
241     stage.Add( mDeleteButton );
242
243     // Create an insert button (bottom right of screen)
244     mInsertButton = Toolkit::PushButton::New();
245     mInsertButton.SetParentOrigin(ParentOrigin::BOTTOM_RIGHT);
246     mInsertButton.SetAnchorPoint(AnchorPoint::BOTTOM_RIGHT);
247     mInsertButton.SetPosition( BUTTON_BORDER, BUTTON_BORDER );
248     mInsertButton.SetDrawMode( DrawMode::OVERLAY_2D );
249     mInsertButton.SetUnselectedImage( INSERT_IMAGE );
250     mInsertButton.SetSelectedImage( INSERT_IMAGE_SELECTED );
251     mInsertButton.SetBackgroundImage( TOOLBAR_IMAGE );
252     mInsertButton.SetSize( stageSize.width * 0.15f, stageSize.width * 0.15f );
253     mInsertButton.ClickedSignal().Connect( this, &ItemViewExample::OnInsertButtonClicked);
254     mInsertButton.SetLeaveRequired( true );
255     mInsertButton.SetVisible( false );
256     stage.Add( mInsertButton );
257
258     // Create an replace button (bottom right of screen)
259     mReplaceButton = Toolkit::PushButton::New();
260     mReplaceButton.SetParentOrigin(ParentOrigin::BOTTOM_RIGHT);
261     mReplaceButton.SetAnchorPoint(AnchorPoint::BOTTOM_RIGHT);
262     mReplaceButton.SetPosition( BUTTON_BORDER, BUTTON_BORDER );
263     mReplaceButton.SetDrawMode( DrawMode::OVERLAY_2D );
264     mReplaceButton.SetUnselectedImage( REPLACE_IMAGE );
265     mReplaceButton.SetSelectedImage( REPLACE_IMAGE_SELECTED );
266     mReplaceButton.SetBackgroundImage( TOOLBAR_IMAGE );
267     mReplaceButton.SetSize( stageSize.width * 0.15f, stageSize.width * 0.15f );
268     mReplaceButton.ClickedSignal().Connect( this, &ItemViewExample::OnReplaceButtonClicked);
269     mReplaceButton.SetLeaveRequired( true );
270     mReplaceButton.SetVisible( false );
271     stage.Add( mReplaceButton );
272
273     // Create the item view actor
274     mItemView = ItemView::New(*this);
275     mItemView.SetParentOrigin(ParentOrigin::CENTER);
276     mItemView.SetAnchorPoint(AnchorPoint::CENTER);
277
278     // Display item view on the stage
279     stage.Add( mItemView );
280     stage.GetRootLayer().SetBehavior( Layer::LAYER_3D );
281
282     // Create the layouts
283     mSpiralLayout = DefaultItemLayout::New( DefaultItemLayout::SPIRAL );
284     mDepthLayout = DefaultItemLayout::New( DefaultItemLayout::DEPTH );
285     mGridLayout = DefaultItemLayout::New( DefaultItemLayout::GRID );
286
287     // Add the layouts to item view
288     mItemView.AddLayout(*mSpiralLayout);
289     mItemView.AddLayout(*mDepthLayout);
290     mItemView.AddLayout(*mGridLayout);
291
292     mItemView.SetMinimumSwipeDistance(MIN_SWIPE_DISTANCE);
293     mItemView.SetMinimumSwipeSpeed(MIN_SWIPE_SPEED);
294
295     // Activate the spiral layout
296     SetLayout( mCurrentLayout );
297     mItemView.SetKeyboardFocusable( true );
298     KeyboardFocusManager::Get().PreFocusChangeSignal().Connect( this, &ItemViewExample::OnKeyboardPreFocusChange );
299
300     // Set the title and icon to the current layout
301     SetLayoutTitle();
302     SetLayoutImage();
303   }
304
305   Actor OnKeyboardPreFocusChange( Actor current, Actor proposed, Control::KeyboardFocus::Direction direction )
306   {
307     if ( !current && !proposed  )
308     {
309       return mItemView;
310     }
311
312     return proposed;
313   }
314
315   /**
316    * Animate to a different layout
317    */
318   void ChangeLayout()
319   {
320     Animation animation = Animation::New( mDurationSeconds );
321     animation.FinishedSignal().Connect( this, &ItemViewExample::AnimationFinished );
322     animation.AnimateTo( Property( mItemView, Actor::Property::COLOR_ALPHA ), 0.0f );
323     animation.Play();
324   }
325
326   void AnimationFinished( Animation& )
327   {
328     SetLayout( mCurrentLayout );
329
330     Animation animation = Animation::New( mDurationSeconds );
331     animation.AnimateTo( Property( mItemView, Actor::Property::COLOR_ALPHA ), 1.0f );
332     animation.Play();
333   }
334
335   /**
336    * Switch to a different item view layout
337    */
338   void SetLayout( int layoutId )
339   {
340     Stage stage = Dali::Stage::GetCurrent();
341     switch( mCurrentLayout )
342     {
343       case SPIRAL_LAYOUT:
344       case DEPTH_LAYOUT:
345       {
346         stage.GetRootLayer().SetBehavior(Layer::LAYER_3D);
347         break;
348       }
349       case GRID_LAYOUT:
350       {
351         stage.GetRootLayer().SetBehavior(Layer::LAYER_2D);
352         break;
353       }
354     }
355
356     // Set the new orientation to the layout
357     mItemView.GetLayout(layoutId)->SetOrientation(static_cast<ControlOrientation::Type>(mOrientation / 90));
358
359     Vector2 stageSize = Stage::GetCurrent().GetSize();
360
361     if(layoutId == DEPTH_LAYOUT)
362     {
363       // Set up the depth layout according to the new orientation
364       if(Toolkit::IsVertical(mDepthLayout->GetOrientation()))
365       {
366         mDepthLayout->SetItemSize( DepthLayoutItemSizeFunctionPortrait( stageSize.width ) );
367       }
368       else
369       {
370         mDepthLayout->SetItemSize( DepthLayoutItemSizeFunctionLandscape( stageSize.height ) );
371       }
372     }
373
374     // Enable anchoring for depth layout only
375     mItemView.SetAnchoring(layoutId == DEPTH_LAYOUT);
376
377     // Activate the layout
378     mItemView.ActivateLayout( layoutId, Vector3(stageSize.x, stageSize.y, stageSize.x), 0.0f );
379   }
380
381   bool OnLayoutButtonClicked( Toolkit::Button button )
382   {
383     // Switch to the next layout
384     mCurrentLayout = (mCurrentLayout + 1) % mItemView.GetLayoutCount();
385
386     ChangeLayout();
387
388     SetLayoutTitle();
389     SetLayoutImage();
390
391     return true;
392   }
393
394   bool OnModeButtonClicked( Toolkit::Button button )
395   {
396     SwitchToNextMode();
397
398     return true;
399   }
400
401   void SwitchToNextMode()
402   {
403     switch( mMode )
404     {
405       case MODE_REMOVE:
406       {
407         ExitRemoveMode();
408         mMode = MODE_REMOVE_MANY;
409         EnterRemoveManyMode();
410         break;
411       }
412
413       case MODE_REMOVE_MANY:
414       {
415         ExitRemoveManyMode();
416         mMode = MODE_INSERT;
417         EnterInsertMode();
418         break;
419       }
420
421       case MODE_INSERT:
422       {
423         ExitInsertMode();
424         mMode = MODE_INSERT_MANY;
425         EnterInsertManyMode();
426         break;
427       }
428
429       case MODE_INSERT_MANY:
430       {
431         ExitInsertManyMode();
432         mMode = MODE_REPLACE;
433         EnterReplaceMode();
434         break;
435       }
436
437       case MODE_REPLACE:
438       {
439         ExitReplaceMode();
440         mMode = MODE_REPLACE_MANY;
441         EnterReplaceManyMode();
442         break;
443       }
444
445       case MODE_REPLACE_MANY:
446       {
447         ExitReplaceManyMode();
448         mMode = MODE_NORMAL;
449         SetLayoutTitle();
450         break;
451       }
452
453       case MODE_NORMAL:
454       default:
455       {
456         mMode = MODE_REMOVE;
457         EnterRemoveMode();
458         break;
459       }
460     }
461   }
462
463   void EnterRemoveMode()
464   {
465     SetTitle("Edit: Remove");
466
467     mTapDetector = TapGestureDetector::New();
468
469     for( unsigned int i = 0u; i < mItemView.GetChildCount(); ++i )
470     {
471       mTapDetector.Attach(mItemView.GetChildAt(i));
472     }
473
474     mTapDetector.DetectedSignal().Connect( this, &ItemViewExample::RemoveOnTap );
475   }
476
477   void ExitRemoveMode()
478   {
479     mTapDetector.Reset();
480   }
481
482   void RemoveOnTap( Actor actor, const TapGesture& tap )
483   {
484     mItemView.RemoveItem( mItemView.GetItemId(actor), 0.5f );
485   }
486
487   void EnterRemoveManyMode()
488   {
489     SetTitle("Edit: Remove Many");
490
491     mDeleteButton.SetVisible( true );
492
493     mTapDetector = TapGestureDetector::New();
494
495     for( unsigned int i = 0u; i < mItemView.GetChildCount(); ++i )
496     {
497       Actor child = mItemView.GetChildAt( i );
498       Actor box = child.FindChildByName( "CheckBox" );
499
500       if( box )
501       {
502         mTapDetector.Attach( child );
503         box.SetVisible( true );
504       }
505     }
506
507     mTapDetector.DetectedSignal().Connect( this, &ItemViewExample::SelectOnTap );
508   }
509
510   void ExitRemoveManyMode()
511   {
512     for( unsigned int i = 0u; i < mItemView.GetChildCount(); ++i )
513     {
514       Actor child = mItemView.GetChildAt( i );
515       Actor box = child.FindChildByName( "CheckBox" );
516
517       if( box )
518       {
519         box.SetVisible( false );
520
521         Actor tick = box.FindChildByName( "Tick" );
522         if( tick )
523         {
524           tick.SetVisible( false );
525         }
526       }
527     }
528
529     mTapDetector.Reset();
530
531     mDeleteButton.SetVisible( false );
532   }
533
534   void SelectOnTap( Actor actor, const TapGesture& tap )
535   {
536     Actor tick = actor.FindChildByName( "Tick" );
537     if( tick )
538     {
539       tick.SetVisible( !tick.IsVisible() );
540     }
541   }
542
543   bool OnDeleteButtonClicked( Toolkit::Button button )
544   {
545     ItemIdContainer removeList;
546
547     for( unsigned int i = 0u; i < mItemView.GetChildCount(); ++i )
548     {
549       Actor child = mItemView.GetChildAt( i );
550       Actor tick = child.FindChildByName( "Tick" );
551
552       if( tick && tick.IsVisible() )
553       {
554         removeList.push_back( mItemView.GetItemId(child) );
555       }
556     }
557
558     if( ! removeList.empty() )
559     {
560       mItemView.RemoveItems( removeList, 0.5f );
561     }
562
563     return true;
564   }
565
566   void EnterInsertMode()
567   {
568     SetTitle("Edit: Insert");
569
570     mTapDetector = TapGestureDetector::New();
571
572     for( unsigned int i = 0u; i < mItemView.GetChildCount(); ++i )
573     {
574       mTapDetector.Attach( mItemView.GetChildAt(i) );
575     }
576
577     mTapDetector.DetectedSignal().Connect( this, &ItemViewExample::InsertOnTap );
578   }
579
580   void ExitInsertMode()
581   {
582     mTapDetector.Reset();
583   }
584
585   void InsertOnTap( Actor actor, const TapGesture& tap )
586   {
587     ItemId id = mItemView.GetItemId( actor );
588
589     Actor newActor = NewItem( rand() );
590
591     mItemView.InsertItem( Item(id,newActor), 0.5f );
592   }
593
594   void EnterInsertManyMode()
595   {
596     SetTitle("Edit: Insert Many");
597
598     mInsertButton.SetVisible( true );
599
600     mTapDetector = TapGestureDetector::New();
601
602     for( unsigned int i = 0u; i < mItemView.GetChildCount(); ++i )
603     {
604       Actor child = mItemView.GetChildAt( i );
605       Actor box = child.FindChildByName( "CheckBox" );
606
607       if( box )
608       {
609         mTapDetector.Attach( child );
610         box.SetVisible( true );
611       }
612     }
613
614     mTapDetector.DetectedSignal().Connect( this, &ItemViewExample::SelectOnTap );
615   }
616
617   void ExitInsertManyMode()
618   {
619     for( unsigned int i = 0u; i < mItemView.GetChildCount(); ++i )
620     {
621       Actor child = mItemView.GetChildAt( i );
622       Actor box = child.FindChildByName( "CheckBox" );
623
624       if( box )
625       {
626         box.SetVisible( false );
627
628         Actor tick = box.FindChildByName( "Tick" );
629         if( tick )
630         {
631           tick.SetVisible( false );
632         }
633       }
634     }
635
636     mTapDetector.Reset();
637
638     mInsertButton.SetVisible( false );
639   }
640
641   bool OnInsertButtonClicked( Toolkit::Button button )
642   {
643     ItemContainer insertList;
644
645     for( unsigned int i = 0u; i < mItemView.GetChildCount(); ++i )
646     {
647       Actor child = mItemView.GetChildAt( i );
648       Actor tick = child.FindChildByName( "Tick" );
649
650       if( tick && tick.IsVisible() )
651       {
652         insertList.push_back( Item( mItemView.GetItemId(child), NewItem(rand()) ) );
653       }
654     }
655
656     if( ! insertList.empty() )
657     {
658       mItemView.InsertItems( insertList, 0.5f );
659     }
660
661     return true;
662   }
663
664   void EnterReplaceMode()
665   {
666     SetTitle("Edit: Replace");
667
668     mTapDetector = TapGestureDetector::New();
669
670     for( unsigned int i = 0u; i < mItemView.GetChildCount(); ++i )
671     {
672       mTapDetector.Attach(mItemView.GetChildAt(i));
673     }
674
675     mTapDetector.DetectedSignal().Connect( this, &ItemViewExample::ReplaceOnTap );
676   }
677
678   void ReplaceOnTap( Actor actor, const TapGesture& tap )
679   {
680     mItemView.ReplaceItem( Item( mItemView.GetItemId(actor), NewItem(rand()) ), 0.5f );
681   }
682
683   void ExitReplaceMode()
684   {
685     mTapDetector.Reset();
686   }
687
688   void EnterReplaceManyMode()
689   {
690     SetTitle("Edit: Replace Many");
691
692     mReplaceButton.SetVisible( true );
693
694     mTapDetector = TapGestureDetector::New();
695
696     for( unsigned int i = 0u; i < mItemView.GetChildCount(); ++i )
697     {
698       Actor child = mItemView.GetChildAt( i );
699       Actor box = child.FindChildByName( "CheckBox" );
700
701       if( box )
702       {
703         mTapDetector.Attach( child );
704         box.SetVisible( true );
705       }
706     }
707
708     mTapDetector.DetectedSignal().Connect( this, &ItemViewExample::SelectOnTap );
709   }
710
711   void ExitReplaceManyMode()
712   {
713     for( unsigned int i = 0u; i < mItemView.GetChildCount(); ++i )
714     {
715       Actor child = mItemView.GetChildAt( i );
716       Actor box = child.FindChildByName( "CheckBox" );
717
718       if( box )
719       {
720         box.SetVisible( false );
721
722         Actor tick = box.FindChildByName( "Tick" );
723         if( tick )
724         {
725           tick.SetVisible( false );
726         }
727       }
728     }
729
730     mTapDetector.Reset();
731
732     mReplaceButton.SetVisible( false );
733   }
734
735   bool OnReplaceButtonClicked( Toolkit::Button button )
736   {
737     ItemContainer replaceList;
738
739     for( unsigned int i = 0u; i < mItemView.GetChildCount(); ++i )
740     {
741       Actor child = mItemView.GetChildAt( i );
742       Actor tick = child.FindChildByName( "Tick" );
743
744       if( tick && tick.IsVisible() )
745       {
746         replaceList.push_back( Item( mItemView.GetItemId(child), NewItem(rand()) ) );
747       }
748     }
749
750     if( ! replaceList.empty() )
751     {
752       mItemView.ReplaceItems( replaceList, 0.5f );
753     }
754
755     return true;
756   }
757
758   void SetLayoutTitle()
759   {
760     if( MODE_NORMAL == mMode )
761     {
762       std::stringstream ss(APPLICATION_TITLE);
763       switch(mCurrentLayout)
764       {
765       case SPIRAL_LAYOUT:
766         ss << APPLICATION_TITLE << ": " << SPIRAL_LABEL;
767         break;
768       case GRID_LAYOUT:
769         ss << APPLICATION_TITLE << ": " << GRID_LABEL;
770         break;
771       case DEPTH_LAYOUT:
772         ss << APPLICATION_TITLE << ": " << DEPTH_LABEL;
773         break;
774       default:
775         break;
776       }
777       SetTitle(ss.str());
778     }
779   }
780
781   void SetLayoutImage()
782   {
783     if( mLayoutButton )
784     {
785       switch( mCurrentLayout )
786       {
787         case SPIRAL_LAYOUT:
788         {
789           mLayoutButton.SetUnselectedImage( SPIRAL_LAYOUT_IMAGE );
790           mLayoutButton.SetSelectedImage( SPIRAL_LAYOUT_IMAGE_SELECTED );
791           break;
792         }
793
794         case GRID_LAYOUT:
795         {
796           mLayoutButton.SetUnselectedImage( GRID_LAYOUT_IMAGE );
797           mLayoutButton.SetSelectedImage( GRID_LAYOUT_IMAGE_SELECTED );
798           break;
799         }
800
801         case DEPTH_LAYOUT:
802         {
803           mLayoutButton.SetUnselectedImage( DEPTH_LAYOUT_IMAGE );
804           mLayoutButton.SetSelectedImage( DEPTH_LAYOUT_IMAGE_SELECTED );
805           break;
806         }
807
808         default:
809           break;
810       }
811     }
812   }
813
814 public: // From ItemFactory
815
816   /**
817    * Query the number of items available from the factory.
818    * The maximum available item has an ID of GetNumberOfItems() - 1.
819    */
820   virtual unsigned int GetNumberOfItems()
821   {
822     return NUM_IMAGES * 10;
823   }
824
825   /**
826    * Create an Actor to represent a visible item.
827    * @param itemId
828    * @return the created actor.
829    */
830   virtual Actor NewItem(unsigned int itemId)
831   {
832     // Create an image view for this item
833     ImageView actor = ImageView::New( IMAGE_PATHS[ itemId % NUM_IMAGES ] );
834     actor.SetZ( 0.0f );
835     actor.SetPosition( INITIAL_OFFSCREEN_POSITION );
836
837     // Add a border image child actor
838     ImageView borderActor = ImageView::New();
839     borderActor.SetParentOrigin( ParentOrigin::CENTER );
840     borderActor.SetAnchorPoint( AnchorPoint::CENTER );
841     borderActor.SetResizePolicy( ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT, Dimension::ALL_DIMENSIONS );
842     borderActor.SetSizeModeFactor( Vector3( 2.0f * ITEM_BORDER_SIZE, 2.0f * ITEM_BORDER_SIZE, 0.0f ) );
843     borderActor.SetColorMode( USE_PARENT_COLOR );
844
845     Property::Map borderProperty;
846     borderProperty.Insert( "rendererType", "border" );
847     borderProperty.Insert( "borderColor", Color::WHITE );
848     borderProperty.Insert( "borderSize", ITEM_BORDER_SIZE );
849     borderProperty.Insert( "antiAliasing", true );
850     borderActor.SetProperty( ImageView::Property::IMAGE, borderProperty );
851
852     actor.Add(borderActor);
853
854     actor.SetKeyboardFocusable( true );
855
856     Vector3 spiralItemSize;
857     static_cast<ItemLayout&>(*mSpiralLayout).GetItemSize( 0u, Vector3( Stage::GetCurrent().GetSize() ), spiralItemSize );
858
859     // Add a checkbox child actor; invisible until edit-mode is enabled
860     ImageView checkbox = ImageView::New();
861     checkbox.SetName( "CheckBox" );
862     checkbox.SetColorMode( USE_PARENT_COLOR );
863     checkbox.SetParentOrigin( ParentOrigin::TOP_RIGHT );
864     checkbox.SetAnchorPoint( AnchorPoint::TOP_RIGHT );
865     checkbox.SetSize( spiralItemSize.width * 0.2f, spiralItemSize.width * 0.2f );
866     checkbox.SetPosition( -SELECTION_BORDER_WIDTH, SELECTION_BORDER_WIDTH );
867     checkbox.SetZ( 0.1f );
868
869     Property::Map solidColorProperty;
870     solidColorProperty.Insert( "rendererType", "color" );
871     solidColorProperty.Insert( "blendColor", Vector4(0.f, 0.f, 0.f, 0.6f) );
872     checkbox.SetProperty( ImageView::Property::IMAGE, solidColorProperty );
873
874     if( MODE_REMOVE_MANY  != mMode &&
875         MODE_INSERT_MANY  != mMode &&
876         MODE_REPLACE_MANY != mMode )
877     {
878       checkbox.SetVisible( false );
879     }
880     borderActor.Add( checkbox );
881
882     ImageView tick = ImageView::New( SELECTED_IMAGE );
883     tick.SetName( "Tick" );
884     tick.SetColorMode( USE_PARENT_COLOR );
885     tick.SetParentOrigin( ParentOrigin::TOP_RIGHT );
886     tick.SetAnchorPoint( AnchorPoint::TOP_RIGHT );
887     tick.SetSize( spiralItemSize.width * 0.2f, spiralItemSize.width * 0.2f );
888     tick.SetZ( 0.2f );
889     tick.SetVisible( false );
890     checkbox.Add( tick );
891
892     // Connect new items for various editing modes
893     if( mTapDetector )
894     {
895       mTapDetector.Attach( actor );
896     }
897
898     return actor;
899   }
900
901 private:
902
903   /**
904    * Sets/Updates the title of the View
905    * @param[in] title The new title for the view.
906    */
907   void SetTitle(const std::string& title)
908   {
909     if(!mTitleActor)
910     {
911       mTitleActor = DemoHelper::CreateToolBarLabel( "" );
912       // Add title to the tool bar.
913       mToolBar.AddControl( mTitleActor, DemoHelper::DEFAULT_VIEW_STYLE.mToolBarTitlePercentage, Alignment::HorizontalCenter );
914     }
915
916     mTitleActor.SetProperty( TextLabel::Property::TEXT, title );
917   }
918
919   /**
920    * Main key event handler
921    */
922   void OnKeyEvent(const KeyEvent& event)
923   {
924     if(event.state == KeyEvent::Down)
925     {
926       if( IsKey( event, DALI_KEY_ESCAPE) || IsKey( event, DALI_KEY_BACK ) )
927       {
928         mApplication.Quit();
929       }
930     }
931   }
932
933 private:
934
935   Application& mApplication;
936   Mode mMode;
937
938   Toolkit::Control mView;
939   unsigned int mOrientation;
940
941   Toolkit::ToolBar mToolBar;
942   TextLabel mTitleActor;             ///< The Toolbar's Title.
943
944   ItemView mItemView;
945   unsigned int mCurrentLayout;
946   float mDurationSeconds;
947
948   ItemLayoutPtr mSpiralLayout;
949   ItemLayoutPtr mDepthLayout;
950   ItemLayoutPtr mGridLayout;
951
952   TapGestureDetector mTapDetector;
953   Toolkit::PushButton mLayoutButton;
954   Toolkit::PushButton mDeleteButton;
955   Toolkit::PushButton mInsertButton;
956   Toolkit::PushButton mReplaceButton;
957 };
958
959 void RunTest(Application& app)
960 {
961   ItemViewExample test(app);
962
963   app.MainLoop();
964 }
965
966 int DALI_EXPORT_API main(int argc, char **argv)
967 {
968   Application app = Application::New(&argc, &argv, DEMO_THEME_PATH);
969
970   RunTest(app);
971
972   return 0;
973 }