Updated demos to use DALi clang-format
[platform/core/uifw/dali-demo.git] / examples / image-policies / image-policies-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 #include <dali-toolkit/dali-toolkit.h>
19 #include <dali-toolkit/devel-api/controls/table-view/table-view.h>
20 #include <dali-toolkit/devel-api/visual-factory/visual-base.h>
21 #include <dali-toolkit/devel-api/visual-factory/visual-factory.h>
22 #include <dali-toolkit/devel-api/visuals/image-visual-properties-devel.h>
23 #include <dali/dali.h>
24 #include <string>
25 #include "shared/view.h"
26
27 using namespace Dali;
28 using namespace Toolkit;
29
30 namespace
31 {
32 const char* NEXT_BUTTON_IMAGE(DEMO_IMAGE_DIR "DarkStyleGreenArrowButton.png");
33 const char* NEXT_BUTTON_PRESSED_IMAGE(DEMO_IMAGE_DIR "DarkStyleGreyArrowButton.png");
34 const char* NEXT_BUTTON_DISABLED_IMAGE(DEMO_IMAGE_DIR "DarkStyleDisabledArrowButton.png");
35 const char* OK_IMAGE_IMAGE(DEMO_IMAGE_DIR "FontStyleButton_OK_02.png");
36 const char* LOADING_IMAGE(DEMO_IMAGE_DIR "animatedLoading.gif");
37
38 const char* IMAGE_PATH[] = {
39   DEMO_IMAGE_DIR "gallery-small-23.jpg",
40   DEMO_IMAGE_DIR "woodEffect.jpg",
41   DEMO_IMAGE_DIR "heartsframe.9.png",
42   DEMO_IMAGE_DIR "keyboard-Landscape.jpg",
43   DEMO_IMAGE_DIR "keyboard-LandscapeCopy.jpg",
44 };
45
46 /**
47  * Enums that refer to the row in the main table view.
48  * Aids in placement of content so easy to see which type of content belongs to each row.
49  */
50 enum TableRowPlacement
51 {
52   TITLE,
53   INSTRUCTIONS,
54   IMAGE,
55   NEXT_BUTTON,
56   LOADING_STATUS,
57   NUMBER_OF_ROWS
58 };
59
60 } // namespace
61
62 /**
63  * Examples showing the various polices of ImageVisual in use.
64  * image release polcy, image loading policy and exif data are currently demonstrated.
65  * Large images are used to cause loading time to be long enough to show differences.
66  * If hardware causes loading time improve then remote images or larger images may be required in future.
67  */
68 class ImagePolicies : public ConnectionTracker
69 {
70 public:
71   /**
72    * Constructor
73    */
74   ImagePolicies(Application& application)
75   : mApplication(application),
76     mExampleIndex(0)
77   {
78     // Connect to the Application's Init signal
79     mApplication.InitSignal().Connect(this, &ImagePolicies::Create);
80   }
81
82   /**
83    * To prevent the next button being pressed before an Image has loaded the Button can br disabled.
84    * This function allows the control (Image view in this case) to attached to the Image loading signal
85    * and re-enable the button after Image has loaded.
86    */
87   void ResourceReadySignal(Control control)
88   {
89     mNextButton.SetProperty(Button::Property::DISABLED, false);
90   }
91
92   /**
93    * Helper function to create ImageViews used by this example, preventing the duplication of code.
94    * param[in] correctionEnabled  Set true if Exif orientation correction should be applied.
95    * param[in] loadPolicy Which LoadPolicy to use.
96    * param[in] releasePolicy Which ReleasePolicy to use
97    * param[in] synchronousLoading If the Image should be loaded synchronously
98    * param[in] imageFilenameId Which image to load, referring to the array of filenames for this example.
99    * return An ImageView with the required set up
100    */
101   ImageView CreateImageView(bool correctionEnabled, ImageVisual::LoadPolicy::Type loadPolicy, ImageVisual::ReleasePolicy::Type releasePolicy, bool synchronousLoading, unsigned int imageFilenameId)
102   {
103     ImageView     imageView = ImageView::New();
104     Property::Map imagePropertyMap;
105     imagePropertyMap.Insert(Visual::Property::TYPE, Visual::IMAGE);
106     imagePropertyMap.Insert(ImageVisual::Property::URL, IMAGE_PATH[imageFilenameId]);
107     imagePropertyMap.Insert(ImageVisual::Property::ORIENTATION_CORRECTION, correctionEnabled);
108     imagePropertyMap.Insert(ImageVisual::Property::LOAD_POLICY, loadPolicy);
109     imagePropertyMap.Insert(ImageVisual::Property::RELEASE_POLICY, releasePolicy);
110     if(synchronousLoading)
111     {
112       imagePropertyMap.Insert(DevelImageVisual::Property::SYNCHRONOUS_LOADING, true);
113     }
114     imageView.SetProperty(ImageView::Property::IMAGE, imagePropertyMap);
115
116     imageView.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
117     imageView.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
118     imageView.SetResizePolicy(ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS);
119
120     return imageView;
121   }
122
123   /**
124    * To prevent the next button being pressed before an Image has loaded the Button can br disabled.
125    * This function will disable the next button.
126    * Connecting to the ResourceReady signal with ( ResourceReadySignal( Control control ) ) will allow enabling of the button again.
127    */
128
129   void DisableButtonWhilstLoading()
130   {
131     mNextButton.SetProperty(Button::Property::DISABLED, true);
132   }
133
134   /**
135    * Example shows loading an Image with exif orientation data but not applying automatic orientation correction
136    */
137   void OrientationCorrectionExampleNoCorrection()
138   {
139     mTitle.SetProperty(Toolkit::TextLabel::Property::TEXT, "Orientation Correction");
140     mInstructions.SetProperty(TextLabel::Property::TEXT, "Orientation Correction not applied");
141     mTable.RemoveChildAt(TableView::CellPosition(TableRowPlacement::IMAGE, 0));
142     DisableButtonWhilstLoading();
143     ImageView imageView01 = CreateImageView(false, ImageVisual::LoadPolicy::ATTACHED, ImageVisual::ReleasePolicy::DESTROYED, false, 3);
144     imageView01.ResourceReadySignal().Connect(this, &ImagePolicies::ResourceReadySignal);
145
146     mTable.AddChild(imageView01, TableView::CellPosition(TableRowPlacement::IMAGE, 0));
147   }
148
149   /**
150    * Example shows loading an Image with exif orientation data and automatically correcting the orientation to match the exif data.
151    */
152   void OrientationCorrectionExampleWithCorrection()
153   {
154     mInstructions.SetProperty(TextLabel::Property::TEXT, "Orientation Correction applied based on Exif data, now shown in landscape");
155     mTable.RemoveChildAt(TableView::CellPosition(TableRowPlacement::IMAGE, 0));
156     DisableButtonWhilstLoading();
157     ImageView imageView01 = CreateImageView(true, ImageVisual::LoadPolicy::ATTACHED, ImageVisual::ReleasePolicy::DESTROYED, false, 3);
158     imageView01.ResourceReadySignal().Connect(this, &ImagePolicies::ResourceReadySignal);
159     mTable.AddChild(imageView01, TableView::CellPosition(TableRowPlacement::IMAGE, 0));
160   }
161
162   /**
163    * Part One of the Immediate loading example, displays instructions on what will be shown and starts loading of the Immediate image before it
164    * is windowd.
165    */
166   void LoadPolicyImmediateExampleInstructions()
167   {
168     mTitle.SetProperty(Toolkit::TextLabel::Property::TEXT, "Immediate Loading Policy");
169     mTable.RemoveChildAt(TableView::CellPosition(TableRowPlacement::IMAGE, 0));
170     mInstructions.SetProperty(TextLabel::Property::TEXT, "Loading Image before staging, press next to see it in right column");
171     TableView dualImageViewTable = TableView::New(1, 2);
172     dualImageViewTable.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
173     dualImageViewTable.SetProperty(Dali::Actor::Property::NAME, "dualTable");
174     dualImageViewTable.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
175     dualImageViewTable.SetResizePolicy(ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS);
176     dualImageViewTable.SetCellPadding(Vector2(6.0f, 0.0f));
177     TextLabel attached = TextLabel::New("ATTACHED loaded image \nWill appear here");
178     attached.SetProperty(TextLabel::Property::MULTI_LINE, true);
179     TextLabel immediate = TextLabel::New("IMMEDIATE loaded image \nWill appear here");
180     immediate.SetProperty(TextLabel::Property::MULTI_LINE, true);
181
182     dualImageViewTable.AddChild(attached, TableView::CellPosition(0, 0));
183     dualImageViewTable.AddChild(immediate, TableView::CellPosition(0, 1));
184     mTable.AddChild(dualImageViewTable, TableView::CellPosition(TableRowPlacement::IMAGE, 0));
185
186     DisableButtonWhilstLoading();
187     mPersistantImageView = CreateImageView(true, ImageVisual::LoadPolicy::IMMEDIATE, ImageVisual::ReleasePolicy::DESTROYED, false, 4);
188     mPersistantImageView.ResourceReadySignal().Connect(this, &ImagePolicies::ResourceReadySignal);
189   }
190
191   /**
192    * Part Two of the Immediate loading example and here the Image is windowd, shown to be instant (if previously step gave enough time to load).
193    */
194   void LoadPolicyImmediateExample()
195   {
196     mInstructions.SetProperty(TextLabel::Property::TEXT, "Immediate loading policy on only second column hence image load was almost instant.");
197     DisableButtonWhilstLoading();
198     mTable.RemoveChildAt(TableView::CellPosition(TableRowPlacement::IMAGE, 0));
199
200     TableView dualImageViewTable = TableView::New(2, 2);
201     dualImageViewTable.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
202     dualImageViewTable.SetProperty(Dali::Actor::Property::NAME, "dualTable");
203     dualImageViewTable.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
204     dualImageViewTable.SetResizePolicy(ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS);
205     dualImageViewTable.SetCellPadding(Vector2(6.0f, 0.0f));
206
207     TextLabel attached  = TextLabel::New("ATTACHED");
208     TextLabel immediate = TextLabel::New("IMMEDIATE");
209     dualImageViewTable.AddChild(attached, TableView::CellPosition(1, 0));
210     dualImageViewTable.AddChild(immediate, TableView::CellPosition(1, 1));
211     dualImageViewTable.SetFitHeight(1);
212
213     mTable.AddChild(dualImageViewTable, TableView::CellPosition(TableRowPlacement::IMAGE, 0));
214
215     ImageView imageView02 = CreateImageView(true, ImageVisual::LoadPolicy::ATTACHED, ImageVisual::ReleasePolicy::DESTROYED, false, 3);
216     imageView02.ResourceReadySignal().Connect(this, &ImagePolicies::ResourceReadySignal);
217     dualImageViewTable.AddChild(imageView02, TableView::CellPosition(0, 0));
218     dualImageViewTable.AddChild(mPersistantImageView, TableView::CellPosition(0, 1));
219   }
220
221   /**
222    * Part one of an example of loading time when an Image is destroyed with the ReleasePolicy DESTROYED.
223    */
224   void LoadPolicyDestroyedExample()
225   {
226     mTitle.SetProperty(Toolkit::TextLabel::Property::TEXT, "Release Policy DESTROYED");
227     mTable.RemoveChildAt(TableView::CellPosition(TableRowPlacement::IMAGE, 0));
228     mPersistantImageView.Reset();
229     mInstructions.SetProperty(TextLabel::Property::TEXT, "ReleasePolicy::DESTROYED shown in first column, press next to destroy it.");
230     DisableButtonWhilstLoading();
231     TableView dualImageViewTable = TableView::New(1, 2);
232     dualImageViewTable.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
233     dualImageViewTable.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
234     dualImageViewTable.SetResizePolicy(ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS);
235     dualImageViewTable.SetCellPadding(Vector2(6.0f, 0.0f));
236
237     mTable.AddChild(dualImageViewTable, TableView::CellPosition(TableRowPlacement::IMAGE, 0));
238
239     ImageView imageView01 = CreateImageView(true, ImageVisual::LoadPolicy::ATTACHED, ImageVisual::ReleasePolicy::DESTROYED, false, 3);
240     imageView01.ResourceReadySignal().Connect(this, &ImagePolicies::ResourceReadySignal);
241
242     dualImageViewTable.AddChild(imageView01, TableView::CellPosition(0, 0));
243   }
244
245   /**
246    * Part two of the Destroyed example, the image is windowd again but to the second column, it shows the loading takes the same amount of time as
247    * when first loaded.
248    */
249   void LoadPolicyDestroyedExample02()
250   {
251     mInstructions.SetProperty(TextLabel::Property::TEXT, "Destroyed first image and reloaded in second column (loading took some time)");
252     mTable.RemoveChildAt(TableView::CellPosition(TableRowPlacement::IMAGE, 0));
253     DisableButtonWhilstLoading();
254     TableView dualImageViewTable = TableView::New(1, 2);
255     dualImageViewTable.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
256     dualImageViewTable.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
257     dualImageViewTable.SetResizePolicy(ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS);
258     dualImageViewTable.SetCellPadding(Vector2(6.0f, 0.0f));
259
260     mTable.AddChild(dualImageViewTable, TableView::CellPosition(TableRowPlacement::IMAGE, 0));
261
262     ImageView imageView01 = CreateImageView(true, ImageVisual::LoadPolicy::ATTACHED, ImageVisual::ReleasePolicy::DESTROYED, false, 3);
263     imageView01.ResourceReadySignal().Connect(this, &ImagePolicies::ResourceReadySignal);
264
265     dualImageViewTable.AddChild(imageView01, TableView::CellPosition(0, 1));
266   }
267
268   /**
269    * Part one the second Release policy example showing detachment of a visual with the Destroyed policy and loading instantly when re-used.
270    */
271   void ReleasePolicyDestroyedExample03()
272   {
273     mTitle.SetProperty(Toolkit::TextLabel::Property::TEXT, "Detaching with DESTROYED Policy");
274     mTable.RemoveChildAt(TableView::CellPosition(TableRowPlacement::IMAGE, 0));
275     mInstructions.SetProperty(TextLabel::Property::TEXT, "Image with ReleasePolicy::DESTROYED shown in first column, Image will be detached, reusing it will be fast");
276     DisableButtonWhilstLoading();
277     TableView dualImageViewTable = TableView::New(1, 2);
278     dualImageViewTable.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
279     dualImageViewTable.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
280     dualImageViewTable.SetResizePolicy(ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS);
281     dualImageViewTable.SetCellPadding(Vector2(6.0f, 0.0f));
282
283     mTable.AddChild(dualImageViewTable, TableView::CellPosition(TableRowPlacement::IMAGE, 0));
284
285     ImageView imageView01 = CreateImageView(true, ImageVisual::LoadPolicy::ATTACHED, ImageVisual::ReleasePolicy::DESTROYED, false, 3);
286     imageView01.ResourceReadySignal().Connect(this, &ImagePolicies::ResourceReadySignal);
287
288     dualImageViewTable.AddChild(imageView01, TableView::CellPosition(0, 0));
289   }
290
291   /**
292    * Second part of the second Release policy example, the detached visual is used again in the second column and shown nearly instantly.
293    */
294   void ReleasePolicyDestroyedExample04()
295   {
296     mInstructions.SetProperty(TextLabel::Property::TEXT, "Detached first image and reloaded in second column, loading should have seemed instant");
297     DisableButtonWhilstLoading();
298     TableView dualImageViewTable = TableView::DownCast(mTable.GetChildAt(TableView::CellPosition(TableRowPlacement::IMAGE, 0)));
299     ImageView imageViewDetached  = ImageView::DownCast(dualImageViewTable.GetChildAt(TableView::CellPosition(0, 0)));
300     dualImageViewTable.RemoveChildAt(TableView::CellPosition(0, 0));
301
302     ImageView imageView01 = CreateImageView(true, ImageVisual::LoadPolicy::ATTACHED, ImageVisual::ReleasePolicy::DESTROYED, false, 3);
303     imageView01.ResourceReadySignal().Connect(this, &ImagePolicies::ResourceReadySignal);
304
305     dualImageViewTable.AddChild(imageView01, TableView::CellPosition(0, 1));
306   }
307
308   /**
309    * Part one of an example of loading time when an Image is detached with the ReleasePolicy Detached.
310    */
311   void ReleasePolicyDestroyedExample05()
312   {
313     mTitle.SetProperty(Toolkit::TextLabel::Property::TEXT, "Detaching with DETACHED Policy");
314     mTable.RemoveChildAt(TableView::CellPosition(TableRowPlacement::IMAGE, 0));
315     mInstructions.SetProperty(TextLabel::Property::TEXT, "Image with ReleasePolicy::DETACHED shown in first column, will be detached and reloaded");
316     DisableButtonWhilstLoading();
317     TableView dualImageViewTable = TableView::New(1, 2);
318     dualImageViewTable.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
319     dualImageViewTable.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
320     dualImageViewTable.SetResizePolicy(ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS);
321     dualImageViewTable.SetCellPadding(Vector2(6.0f, 0.0f));
322
323     mTable.AddChild(dualImageViewTable, TableView::CellPosition(TableRowPlacement::IMAGE, 0));
324
325     ImageView imageView01 = CreateImageView(true, ImageVisual::LoadPolicy::ATTACHED, ImageVisual::ReleasePolicy::DETACHED, false, 3);
326     imageView01.ResourceReadySignal().Connect(this, &ImagePolicies::ResourceReadySignal);
327
328     dualImageViewTable.AddChild(imageView01, TableView::CellPosition(0, 0));
329   }
330
331   /**
332    * Part two of the Detached example, the image is windowd again but to the second column, it shows the loading takes the same amount of time as
333    * when first loaded.
334    */
335   void ReleasePolicyDestroyedExample06()
336   {
337     mInstructions.SetProperty(TextLabel::Property::TEXT, "Detached first image and reloaded in second column, loading took some time");
338     DisableButtonWhilstLoading();
339     TableView dualImageViewTable = TableView::DownCast(mTable.GetChildAt(TableView::CellPosition(TableRowPlacement::IMAGE, 0)));
340     ImageView imageViewDetached  = ImageView::DownCast(dualImageViewTable.GetChildAt(TableView::CellPosition(0, 0)));
341     dualImageViewTable.RemoveChildAt(TableView::CellPosition(0, 0));
342
343     ImageView imageView01 = CreateImageView(true, ImageVisual::LoadPolicy::ATTACHED, ImageVisual::ReleasePolicy::DESTROYED, false, 3);
344     imageView01.ResourceReadySignal().Connect(this, &ImagePolicies::ResourceReadySignal);
345
346     dualImageViewTable.AddChild(imageView01, TableView::CellPosition(0, 1));
347   }
348
349   /**
350    * Created a gradient property map that will produce a Gradient Visual
351    * param[out] gradientMap the output property map
352    */
353   void CreateGradient(Property::Map& gradientMap)
354   {
355     gradientMap.Insert(Toolkit::Visual::Property::TYPE, Visual::GRADIENT);
356
357     Property::Array stopOffsets;
358     stopOffsets.PushBack(0.0f);
359     stopOffsets.PushBack(0.6f);
360     stopOffsets.PushBack(1.0f);
361     gradientMap.Insert(GradientVisual::Property::STOP_OFFSET, stopOffsets);
362
363     Property::Array stopColors;
364     stopColors.PushBack(Vector4(54.f, 140.f, 207.f, 223.f) / 255.f);
365     stopColors.PushBack(Vector4(54.f, 170.f, 207.f, 123.f) / 255.f);
366     stopColors.PushBack(Vector4(54.f, 189.f, 207.f, 123.f) / 255.f);
367     gradientMap.Insert(GradientVisual::Property::STOP_COLOR, stopColors);
368
369     gradientMap.Insert(GradientVisual::Property::START_POSITION, Vector2(0.5f, 0.5f));
370     gradientMap.Insert(GradientVisual::Property::END_POSITION, Vector2(-0.5f, -0.5f));
371   }
372
373   /**
374    * Start of this example, called once when the application is initiated
375    */
376   void Create(Application& application)
377   {
378     Property::Map gradientBackground;
379     CreateGradient(gradientBackground);
380
381     // Get a handle to the window
382     Window window = application.GetWindow();
383
384     // Create default View.
385     Toolkit::Control view = Toolkit::Control::New();
386     view.SetProperty(Actor::Property::ANCHOR_POINT, Dali::AnchorPoint::CENTER);
387     view.SetProperty(Actor::Property::PARENT_ORIGIN, Dali::ParentOrigin::CENTER);
388     view.SetResizePolicy(Dali::ResizePolicy::FILL_TO_PARENT, Dali::Dimension::ALL_DIMENSIONS);
389     view.SetProperty(Toolkit::Control::Property::BACKGROUND, gradientBackground);
390     window.Add(view);
391
392     // Create a table view to show a pair of buttons above each image.
393     mTable = TableView::New(TableRowPlacement::NUMBER_OF_ROWS, 1);
394     mTable.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
395     mTable.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
396     mTable.SetResizePolicy(ResizePolicy::SIZE_RELATIVE_TO_PARENT, Dimension::ALL_DIMENSIONS);
397     Vector3 offset(0.9f, 0.90f, 0.0f);
398     mTable.SetProperty(Actor::Property::SIZE_MODE_FACTOR, offset);
399     mTable.SetFitHeight(TableRowPlacement::NEXT_BUTTON);
400     mTable.SetFitHeight(TableRowPlacement::LOADING_STATUS);
401     view.Add(mTable);
402
403     // Create Next button
404     mNextButton = PushButton::New();
405     Property::Map imagePropertyMap;
406     imagePropertyMap.Insert(Visual::Property::TYPE, Visual::IMAGE);
407     imagePropertyMap.Insert(ImageVisual::Property::URL, NEXT_BUTTON_IMAGE);
408     mNextButton.SetProperty(Button::Property::UNSELECTED_BACKGROUND_VISUAL, imagePropertyMap);
409     imagePropertyMap.Clear();
410     imagePropertyMap.Insert(Visual::Property::TYPE, Visual::IMAGE);
411     imagePropertyMap.Insert(ImageVisual::Property::URL, NEXT_BUTTON_PRESSED_IMAGE);
412     mNextButton.SetProperty(Button::Property::SELECTED_BACKGROUND_VISUAL, imagePropertyMap);
413     mNextButton.SetProperty(Button::Property::DISABLED_UNSELECTED_BACKGROUND_VISUAL, LOADING_IMAGE);
414     mNextButton.SetProperty(Button::Property::DISABLED_SELECTED_BACKGROUND_VISUAL, NEXT_BUTTON_DISABLED_IMAGE);
415     mNextButton.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::BOTTOM_CENTER);
416     mNextButton.SetProperty(Actor::Property::POSITION_Y, -50.0f);
417     mNextButton.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
418     mNextButton.ClickedSignal().Connect(this, &ImagePolicies::ChangeImageClicked);
419     mTable.AddChild(mNextButton, TableView::CellPosition(TableRowPlacement::NEXT_BUTTON, 0));
420     mTable.SetCellPadding(Vector2(2.0f, 2.0f));
421
422     window.KeyEventSignal().Connect(this, &ImagePolicies::OnKeyEvent);
423
424     // Outline Map for Labels
425     Property::Map outlineMap;
426     outlineMap["color"] = Color::BLACK;
427     outlineMap["width"] = 1.0f;
428
429     // Create Title Label
430     mTitle = TextLabel::New("Image Polices");
431     mTitle.SetProperty(TextLabel::Property::TEXT_COLOR, Color::CYAN);
432     mTable.AddChild(mTitle, TableView::CellPosition(TableRowPlacement::TITLE, 0));
433     mTable.SetFitHeight(TableRowPlacement::TITLE);
434
435     // Create Instructions label
436     mInstructions = TextLabel::New("This is an explaination of each example");
437     mInstructions.SetProperty(TextLabel::Property::MULTI_LINE, true);
438     mInstructions.SetProperty(TextLabel::Property::TEXT_COLOR, Color::WHITE);
439     mInstructions.SetProperty(TextLabel::Property::OUTLINE, outlineMap);
440     mInstructions.SetResizePolicy(ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS);
441     mTable.AddChild(mInstructions, TableView::CellPosition(TableRowPlacement::INSTRUCTIONS, 0));
442     float value = mInstructions.GetProperty<float>(TextLabel::Property::PIXEL_SIZE);
443     mTable.SetFixedHeight(TableRowPlacement::INSTRUCTIONS, value * 5); // Space allocated for example instructions
444
445     ChangeImageClicked(mNextButton); // Start examples ( 0 )
446   }
447
448 private:
449   /**
450    * Callback to the button clicked signal and starts the next example.
451    */
452   bool ChangeImageClicked(Button button)
453   {
454     switch(mExampleIndex++)
455     {
456       case 0:
457       {
458         OrientationCorrectionExampleNoCorrection();
459         break;
460       }
461       case 1:
462       {
463         OrientationCorrectionExampleWithCorrection();
464         break;
465       }
466       case 2:
467       {
468         LoadPolicyImmediateExampleInstructions();
469         break;
470       }
471       case 3:
472       {
473         LoadPolicyImmediateExample();
474         break;
475       }
476       case 4:
477       {
478         LoadPolicyDestroyedExample();
479         break;
480       }
481       case 5:
482       {
483         LoadPolicyDestroyedExample02();
484         break;
485       }
486       case 6:
487       {
488         ReleasePolicyDestroyedExample03();
489         break;
490       }
491       case 7:
492       {
493         ReleasePolicyDestroyedExample04();
494         break;
495       }
496       case 8:
497       {
498         ReleasePolicyDestroyedExample05();
499         break;
500       }
501       case 9:
502       {
503         ReleasePolicyDestroyedExample06();
504         // Change Next button to complete button ( will quit app once pressed )
505         button.SetProperty(Button::Property::UNSELECTED_BACKGROUND_VISUAL, OK_IMAGE_IMAGE);
506         button.SetProperty(Button::Property::SELECTED_BACKGROUND_VISUAL, OK_IMAGE_IMAGE);
507         break;
508       }
509       default:
510       {
511         mApplication.Quit();
512         break;
513       }
514     }
515     return true;
516   }
517
518   /**
519    * Main key event handler
520    */
521   void OnKeyEvent(const KeyEvent& event)
522   {
523     if(event.GetState() == KeyEvent::DOWN)
524     {
525       if(IsKey(event, DALI_KEY_ESCAPE) || IsKey(event, DALI_KEY_BACK))
526       {
527         mApplication.Quit();
528       }
529     }
530   }
531
532 private:
533   Application& mApplication;
534
535   TableView  mTable;
536   TextLabel  mInstructions;
537   TextLabel  mTitle;
538   PushButton mNextButton;
539   ImageView  mPersistantImageView;
540
541   unsigned int mExampleIndex;
542 };
543
544 int DALI_EXPORT_API main(int argc, char** argv)
545 {
546   Application   application = Application::New(&argc, &argv, DEMO_THEME_PATH);
547   ImagePolicies test(application);
548   application.MainLoop();
549   return 0;
550 }