[NUI] Remove build warning messages in NUI Samples (#4932)
[platform/core/csapi/tizenfx.git] / test / Tizen.NUI.Samples / Tizen.NUI.Samples / Samples / DaliDemo / DaliTableView.cs
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using Tizen.NUI.BaseComponents;
5 using Tizen.NUI.Components;
6
7 namespace Tizen.NUI.Samples
8 {
9     using tlog = Tizen.Log;
10
11     public class Example
12     {
13         public Example(string name, string title)
14         {
15             this.name = name;
16             this.title = title;
17         }
18
19         public Example()
20         {
21         }
22
23         private string name;
24         public string Name
25         {
26             get
27             {
28                 return name;
29             }
30         }
31
32         private string title;
33         public string Title
34         {
35             get
36             {
37                 return title;
38             }
39         }
40
41         static public int CompareByTitle(Example lhs, Example rhs)
42         {
43             return String.Compare(lhs.title, lhs.title);
44         }
45     };
46
47     public class DaliTableView
48     {
49         static readonly string tag = "NUITEST";
50
51         static private uint mCurPage = 0;
52
53         static public string DEMO_IMAGE_DIR = CommonResource.GetDaliResourcePath() + "DaliDemo/";
54         static public string LOGO_PATH = DEMO_IMAGE_DIR + "Logo-for-demo.png";
55
56         const float TILE_LABEL_PADDING = 8.0f;                          //  Border between edge of tile and the example text
57         const float BUTTON_PRESS_ANIMATION_TIME = 0.35f;                //  Time to perform button scale effect.
58         const float ROTATE_ANIMATION_TIME = 0.5f;                       //  Time to perform rotate effect.
59
60         const int EXAMPLES_PER_ROW = 3;
61         const int ROWS_PER_PAGE = 3;
62         const int EXAMPLES_PER_PAGE = EXAMPLES_PER_ROW * ROWS_PER_PAGE;
63
64         Vector3 TABLE_RELATIVE_SIZE = new Vector3(0.95f, 0.9f, 0.8f);          //  TableView's relative size to the entire stage. The Y value means sum of the logo and table relative heights.
65
66         Vector4[] BUBBLE_COLOR =
67         {
68           new Vector4( 0.3255f, 0.3412f, 0.6353f, 0.32f ),
69           new Vector4( 0.3647f, 0.7569f, 0.8157f, 0.32f ),
70           new Vector4( 0.3804f, 0.7412f, 0.6510f, 0.32f ),
71           new Vector4( 1.0f, 1.0f, 1.0f, 0.13f )
72         };
73
74         const int NUMBER_OF_BUBBLE_COLOR = 4;
75
76         string[] SHAPE_IMAGE_TABLE =
77         {
78           DEMO_IMAGE_DIR + "shape-circle.png",
79           DEMO_IMAGE_DIR + "shape-bubble.png"
80         };
81
82         const int NUMBER_OF_SHAPE_IMAGES = 2;
83         const int NUM_BACKGROUND_IMAGES = 18;
84         const float BACKGROUND_SPREAD_SCALE = 1.5f;
85         const uint BACKGROUND_ANIMATION_DURATION = 15000; // 15 secs
86
87         const float BUBBLE_MIN_Z = -1.0f;
88         const float BUBBLE_MAX_Z = 0.0f;
89
90         const uint CORE_MAJOR_VERSION = 1;
91         const uint CORE_MINOR_VERSION = 4;
92         const uint CORE_MICRO_VERSION = 50;
93
94         const uint ADAPTOR_MAJOR_VERSION = 1;
95         const uint ADAPTOR_MINOR_VERSION = 4;
96         const uint ADAPTOR_MICRO_VERSION = 50;
97
98         const uint TOOLKIT_MAJOR_VERSION = 1;
99         const uint TOOLKIT_MINOR_VERSION = 4;
100         const uint TOOLKIT_MICRO_VERSION = 50;
101
102         public void AddExample(Example example)
103         {
104             mExampleList.Add(example);
105         }
106
107         public void SortAlphabetically(bool sortAlphabetically)
108         {
109             mSortAlphabetically = sortAlphabetically;
110         }
111
112         private const uint FOCUS_ANIMATION_ACTOR_NUMBER = 2;
113
114         public delegate void ExampleClicked(string name);
115
116         private ExampleClicked onClicked;
117
118         public DaliTableView(ExampleClicked onClicked)
119         {
120             this.onClicked = onClicked;
121         }
122
123         public void Initialize()
124         {
125             NUIApplication.GetDefaultWindow().KeyEvent += OnKeyEvent;
126
127             Size2D stageSize = NUIApplication.GetDefaultWindow().WindowSize;
128
129             // Background
130             mRootActor = CreateBackground("LauncherBackground");
131
132             // Add logo
133             ImageView logo = new ImageView(LOGO_PATH);
134             logo.Name = "LOGO_IMAGE";
135             logo.PositionUsesPivotPoint = true;
136             logo.PivotPoint = PivotPoint.TopCenter;
137             logo.ParentOrigin = new Position(0.5f, 0.1f, 0.5f);
138             logo.WidthResizePolicy = ResizePolicyType.UseNaturalSize;
139             logo.HeightResizePolicy = ResizePolicyType.UseNaturalSize;
140             float logoScale = (float)(NUIApplication.GetDefaultWindow().Size.Height) / 1080.0f;
141             logo.Scale = new Vector3(logoScale, logoScale, 0);
142
143             //// The logo should appear on top of everything.
144             mRootActor.Add(logo);
145
146             // Scrollview occupying the majority of the screen
147             mScrollView = new ScrollView();
148             mScrollView.PositionUsesPivotPoint = true;
149             mScrollView.PivotPoint = PivotPoint.BottomCenter;
150             mScrollView.ParentOrigin = new Vector3(0.5f, 1.0f - 0.05f, 0.5f);
151             mScrollView.WidthResizePolicy = ResizePolicyType.FillToParent;
152             mScrollView.HeightResizePolicy = ResizePolicyType.SizeRelativeToParent;
153             mScrollView.SetSizeModeFactor(new Vector3(0.0f, 0.6f, 0.0f));
154
155             ushort buttonsPageMargin = (ushort)((1.0f - TABLE_RELATIVE_SIZE.X) * 0.5f * stageSize.Width);
156             mScrollView.SetPadding(new PaddingType(buttonsPageMargin, buttonsPageMargin, 0, 0));
157
158             mScrollView.ScrollCompleted += OnScrollComplete;
159             mScrollView.ScrollStarted += OnScrollStart;
160
161             mPageWidth = stageSize.Width * TABLE_RELATIVE_SIZE.X * 0.5f;
162
163             // Populate background and bubbles - needs to be scrollViewLayer so scroll ends show
164             View bubbleContainer = new View();
165             bubbleContainer.WidthResizePolicy = bubbleContainer.HeightResizePolicy = ResizePolicyType.FillToParent;
166             bubbleContainer.PositionUsesPivotPoint = true;
167             bubbleContainer.PivotPoint = PivotPoint.Center;
168             bubbleContainer.ParentOrigin = ParentOrigin.Center;
169             SetupBackground(bubbleContainer);
170
171             mRootActor.Add(bubbleContainer);
172             mRootActor.Add(mScrollView);
173
174             // Add scroll view effect and setup constraints on pages
175             ApplyScrollViewEffect();
176
177             // Add pages and tiles
178             Populate();
179
180             if (mCurPage != mScrollView.GetCurrentPage())
181             {
182                 mScrollView.ScrollTo(mCurPage, 0.0f);
183             }
184
185             // Remove constraints for inner cube effect
186             ApplyCubeEffectToPages();
187
188             // Set initial orientation
189             uint degrees = 0;
190             Rotate(degrees);
191
192             // Background animation
193             mAnimationTimer = new Timer(BACKGROUND_ANIMATION_DURATION);
194             mAnimationTimer.Tick += PauseBackgroundAnimation;
195             mAnimationTimer.Start();
196             mBackgroundAnimsPlaying = true;
197
198             tlog.Debug(tag, $"Initialize() end!");
199         }
200
201         private bool PauseBackgroundAnimation(object source, Timer.TickEventArgs e)
202         {
203             PauseAnimation();
204             return false;
205         }
206
207         private void PauseAnimation()
208         {
209             if (mBackgroundAnimsPlaying)
210             {
211                 foreach (Animation anim in mBackgroundAnimations)
212                 {
213                     anim.Stop();
214                 }
215
216                 mBackgroundAnimsPlaying = false;
217             }
218         }
219
220         private void PlayAnimation()
221         {
222             if (!mBackgroundAnimsPlaying)
223             {
224                 foreach (Animation anim in mBackgroundAnimations)
225                 {
226                     anim.Play();
227                 }
228
229                 mBackgroundAnimsPlaying = true;
230             }
231
232             mAnimationTimer.Interval = BACKGROUND_ANIMATION_DURATION;
233         }
234
235         private void OnKeyEvent(object sender, Window.KeyEventArgs e)
236         {
237             if (e.Key.State == Key.StateType.Down)
238             {
239
240             }
241         }
242
243         private void OnScrollStart(object source, Scrollable.StartedEventArgs e)
244         {
245             mScrolling = true;
246         }
247
248         private void OnScrollComplete(object source, Scrollable.CompletedEventArgs e)
249         {
250             // move focus to 1st item of new page
251             mScrolling = false;
252             mCurPage = mScrollView.GetCurrentPage();
253         }
254
255         // Creates the background image
256         private View CreateBackground(string stylename)
257         {
258             View background = new View();
259             NUIApplication.GetDefaultWindow().Add(background);
260             background.StyleName = stylename;
261             background.Name = "BACKGROUND";
262             background.PositionUsesPivotPoint = true;
263             background.PivotPoint = PivotPoint.Center;
264             background.ParentOrigin = ParentOrigin.Center;
265             background.WidthResizePolicy = ResizePolicyType.FillToParent;
266             background.HeightResizePolicy = ResizePolicyType.FillToParent;
267             return background;
268         }
269
270         private View CreateTile(string name, string title, Vector3 sizeMultiplier, Vector2 position)
271         {
272             ImageView focusableTile = new ImageView();
273
274             focusableTile.StyleName = "DemoTile";
275             focusableTile.ResourceUrl = CommonResource.GetDaliResourcePath() + "DaliDemo/demo-tile-texture.9.png";
276             focusableTile.PositionUsesPivotPoint = true;
277             focusableTile.ParentOrigin = ParentOrigin.Center;
278             focusableTile.WidthResizePolicy = focusableTile.HeightResizePolicy = ResizePolicyType.SizeRelativeToParent;
279             focusableTile.SetSizeModeFactor(sizeMultiplier);
280             focusableTile.Name = name;
281
282             // Set the tile to be keyboard focusable
283             focusableTile.Focusable = true;
284
285             // Register a property with the ImageView. This allows us to inject the scroll-view position into the shader.
286             PropertyValue value = new PropertyValue(new Vector3(0.0f, 0.0f, 0.0f));
287             int propertyIndex = focusableTile.RegisterProperty("uCustomPosition", value);
288
289             // Create an ImageView for the 9-patch border around the tile.
290             ImageView borderImage = new ImageView();
291             borderImage.ResourceUrl = CommonResource.GetDaliResourcePath() + "DaliDemo/item-background.9.png";
292             borderImage.PositionUsesPivotPoint = true;
293             borderImage.PivotPoint = PivotPoint.Center;
294             borderImage.ParentOrigin = ParentOrigin.Center;
295             borderImage.WidthResizePolicy = borderImage.HeightResizePolicy = ResizePolicyType.FillToParent;
296             borderImage.Opacity = 0.8f;
297             focusableTile.Add(borderImage);
298
299             TextLabel label = new TextLabel();
300             label.PositionUsesPivotPoint = true;
301             label.PivotPoint = PivotPoint.Center;
302             label.ParentOrigin = ParentOrigin.Center;
303             label.StyleName = "LauncherLabel";
304             label.MultiLine = true;
305             label.Text = title;
306             label.HorizontalAlignment = HorizontalAlignment.Center;
307             label.VerticalAlignment = VerticalAlignment.Center;
308             label.WidthResizePolicy = ResizePolicyType.FillToParent;
309             label.HeightResizePolicy = ResizePolicyType.FillToParent;
310
311             var fit = new PropertyMap();
312             fit.Add("enable", new PropertyValue(true)).Add("minSize", new PropertyValue(5.0f)).Add("maxSize", new PropertyValue(50.0f));
313             label.TextFit = fit;
314
315             // Pad around the label as its size is the same as the 9-patch border. It will overlap it without padding.
316             label.SetPadding(new PaddingType((int)TILE_LABEL_PADDING, (int)TILE_LABEL_PADDING, (int)TILE_LABEL_PADDING, (int)TILE_LABEL_PADDING));
317
318             focusableTile.Add(label);
319
320             // Connect to the touch events
321             focusableTile.TouchEvent += OnTilePressed;
322
323             return focusableTile;
324         }
325
326         private bool DoTilePress(View actor, PointStateType pointState)
327         {
328             bool consumed = false;
329
330             if (PointStateType.Down == pointState)
331             {
332                 mPressedActor = actor;
333                 consumed = true;
334             }
335
336             // A button press is only valid if the Down & Up events
337             // both occurred within the button.
338             if ((PointStateType.Up == pointState) &&
339                 (mPressedActor == actor))
340             {
341                 // ignore Example button presses when scrolling or button animating.
342                 if ((!mScrolling) && (!mPressedAnimation))
343                 {
344                     string name = actor.Name;
345                     foreach (Example example in mExampleList)
346                     {
347                         if (example.Name == name)
348                         {
349                             consumed = true;
350                             break;
351                         }
352                     }
353                 }
354
355                 if (consumed)
356                 {
357                     mPressedAnimation = new Animation((int)(BUTTON_PRESS_ANIMATION_TIME * 1000.0));
358                     mPressedAnimation.EndAction = Animation.EndActions.Discard;
359
360                     // scale the content actor within the Tile, as to not affect the placement within the Table.
361                     View content = actor.GetChildAt(0);
362                     mPressedAnimation.AnimateTo(content, "Scale", new Vector3(0.7f, 0.7f, 1.0f), 0, (int)((BUTTON_PRESS_ANIMATION_TIME * 0.5f) * 1000.0), new AlphaFunction(AlphaFunction.BuiltinFunctions.EaseOut));
363                     mPressedAnimation.AnimateTo(content, "Scale", Vector3.One, (int)((BUTTON_PRESS_ANIMATION_TIME * 0.5f) * 1000.0), (int)((BUTTON_PRESS_ANIMATION_TIME * 0.5f) * 1000.0), new AlphaFunction(AlphaFunction.BuiltinFunctions.EaseOut));
364                     mPressedAnimation.AnimateTo(content, "Orientation", new Rotation(new Radian(new Degree(180)), new Vector3(0, 1, 0)));
365                     mPressedAnimation.Play();
366                     mPressedAnimation.Finished += OnPressedAnimationFinished;
367                 }
368             }
369             return consumed;
370         }
371
372         private void OnPressedAnimationFinished(object sender, EventArgs e)
373         {
374             string name = mPressedActor?.Name;
375
376             mPressedAnimation = null;
377             mPressedActor = null;
378
379             onClicked(name);
380         }
381
382         private bool OnTilePressed(object source, View.TouchEventArgs e)
383         {
384             return DoTilePress(source as View, e.Touch.GetState(0));
385         }
386
387         private List<View> tiles = new List<View>();
388
389         private void Populate()
390         {
391             Vector2 stageSize = NUIApplication.GetDefaultWindow().WindowSize;
392
393             mTotalPages = (uint)((mExampleList.Count() + EXAMPLES_PER_PAGE - 1) / EXAMPLES_PER_PAGE);
394
395             // Populate ScrollView.
396             if (mExampleList.Count() > 0)
397             {
398                 if (mSortAlphabetically)
399                 {
400                     mExampleList.Sort(Example.CompareByTitle);
401                 }
402
403                 int pageCount = mExampleList.Count / (ROWS_PER_PAGE * EXAMPLES_PER_ROW) + ((0 == mExampleList.Count % (ROWS_PER_PAGE * EXAMPLES_PER_ROW)) ? 0 : 1);
404                 mPages = new View[pageCount];
405
406                 int pageIndex = 0;
407
408                 uint exampleCount = 0;
409
410                 for (int t = 0; t < mTotalPages; t++)
411                 {
412                     // Create Table
413                     TableView page = new TableView(ROWS_PER_PAGE, EXAMPLES_PER_ROW);
414                     page.PositionUsesPivotPoint = true;
415                     page.PivotPoint = PivotPoint.Center;
416                     page.ParentOrigin = ParentOrigin.Center;
417                     page.WidthResizePolicy = page.HeightResizePolicy = ResizePolicyType.FillToParent;
418                     mScrollView.Add(page);
419
420                     // Calculate the number of images going across (columns) within a page, according to the screen resolution and dpi.
421                     const float margin = 2.0f;
422                     const float tileParentMultiplier = 1.0f / EXAMPLES_PER_ROW;
423
424                     for (uint row = 0; row < ROWS_PER_PAGE; row++)
425                     {
426                         for (uint column = 0; column < EXAMPLES_PER_ROW; column++)
427                         {
428                             Example example = mExampleList.ElementAt((int)exampleCount++);
429
430                             // Calculate the tiles relative position on the page (between 0 & 1 in each dimension).
431                             Vector2 position = new Vector2((float)(column) / (EXAMPLES_PER_ROW - 1.0f), (float)(row) / (EXAMPLES_PER_ROW - 1.0f));
432                             View tile = CreateTile(example.Name, example.Title, new Vector3(tileParentMultiplier, tileParentMultiplier, 1.0f), position);
433
434                             tile.SetPadding(new PaddingType((int)margin, (int)margin, (int)margin, (int)margin));
435                             page.AddChild(tile, new TableView.CellPosition(row, column));
436
437                             tiles.Add(tile);
438
439                             if (exampleCount == mExampleList.Count)
440                             {
441                                 break;
442                             }
443                         }
444
445                         if (exampleCount == mExampleList.Count)
446                         {
447                             break;
448                         }
449                     }
450
451                     mPages[pageIndex++] = page;
452
453                     if (exampleCount == mExampleList.Count)
454                     {
455                         break;
456                     }
457                 }
458             }
459
460             // Update Ruler info.
461             mScrollRulerX = new RulerPtr(new FixedRuler(mPageWidth));
462             mScrollRulerY = new RulerPtr(new DefaultRuler());
463             mScrollRulerX.SetDomain(new RulerDomain(0.0f, (mTotalPages + 1) * stageSize.Width * TABLE_RELATIVE_SIZE.X * 0.5f, true));
464             mScrollRulerY.Disable();
465             mScrollView.SetRulerX(mScrollRulerX);
466             mScrollView.SetRulerY(mScrollRulerY);
467         }
468
469         private void SetupBackground(View bubbleContainer)
470         {
471             // Add bubbles to the bubbleContainer.
472             // Note: The bubbleContainer is parented externally to this function.
473             AddBackgroundActors(bubbleContainer, NUM_BACKGROUND_IMAGES);
474         }
475
476         private void AddBackgroundActors(View layer, int count)
477         {
478             int shapeType = 0;
479             Random sizeRandom = new Random(DateTime.Now.Millisecond);
480             Random shapeRandom = new Random(DateTime.Now.Millisecond);
481
482             for (int i = 0; i < count; ++i)
483             {
484                 int randSize = sizeRandom.Next(10, 400);
485                 shapeType = shapeRandom.Next(0, NUMBER_OF_SHAPE_IMAGES);
486
487                 Console.WriteLine("randSize is {0}, shapeType is {1}", randSize, shapeType);
488
489                 ImageView dfActor = new ImageView();
490                 dfActor.Size2D = new Vector2(randSize, randSize);
491                 dfActor.PositionUsesPivotPoint = true;
492                 dfActor.ParentOrigin = ParentOrigin.Center;
493
494                 // Set the Image URL and the custom shader at the same time
495                 PropertyMap effect = CreateDistanceFieldEffect();
496                 PropertyMap imageMap = new PropertyMap();
497                 imageMap.Insert(ImageVisualProperty.URL, new PropertyValue(SHAPE_IMAGE_TABLE[shapeType]));
498                 imageMap.Insert(Visual.Property.Shader, new PropertyValue(effect));
499                 imageMap.Insert(Visual.Property.MixColor, new PropertyValue(BUBBLE_COLOR[i % NUMBER_OF_BUBBLE_COLOR]));
500                 dfActor.ImageMap = imageMap;
501
502                 layer.Add(dfActor);
503             }
504
505             // Positioning will occur when the layer is relaid out
506             layer.Relayout += InitialiseBackgroundActors;
507         }
508
509         private void InitialiseBackgroundActors(object sender, EventArgs e)
510         {
511             // Delete current animations
512             mBackgroundAnimations.Clear();
513             View actor = sender as View;
514
515             // Create new animations
516             Size2D size = actor.Size2D;
517
518             Random childPosRandom = new Random(DateTime.Now.Millisecond);
519             Random animationDurationRandom = new Random(DateTime.Now.Millisecond);
520
521             for (uint i = 0, childCount = actor.GetChildCount(); i < childCount; ++i)
522             {
523                 View child = actor.GetChildAt(i);
524
525                 // Calculate a random position
526                 Vector3 childPos = new Vector3(childPosRandom.Next((int)(-size.Width * 0.5f * BACKGROUND_SPREAD_SCALE), (int)(size.Width * 0.85f * BACKGROUND_SPREAD_SCALE)),
527                                                childPosRandom.Next((int)(-size.Height), (int)(size.Height)),
528                                                childPosRandom.Next((int)BUBBLE_MIN_Z, (int)BUBBLE_MAX_Z));
529
530                 child.Position = childPos;
531
532                 // Kickoff animation
533                 Animation animation = new Animation(animationDurationRandom.Next(30, 160) * 1000);
534                 animation.AnimateBy(child, "Position", new Vector3(0.0f, -2000.0f, 0.0f), new AlphaFunction(AlphaFunction.BuiltinFunctions.Linear));
535                 animation.Looping = true;
536                 animation.Play();
537                 mBackgroundAnimations.Add(animation);
538             }
539         }
540
541         private PropertyMap CreateDistanceFieldEffect()
542         {
543             string fragmentShaderPrefix = "#extension GL_OES_standard_derivatives : enable\n";
544
545             string fragmentShader = "varying mediump vec2 vTexCoord;\n" +
546                 "\n" +
547                 "uniform mediump float uGlowBoundary;\n" +
548                 "uniform mediump vec2  uOutlineParams;\n" +
549                 "uniform lowp vec4  uOutlineColor;\n" +
550                 "uniform lowp vec4  uShadowColor;\n" +
551                 "uniform mediump vec2  uShadowOffset;\n" +
552                 "uniform lowp vec4  uGlowColor;\n" +
553                 "uniform lowp    float uDoOutline;\n" +
554                 "uniform lowp    float uDoShadow;\n" +
555                 "uniform lowp    float uDoGlow;\n" +
556                 "\n" +
557                 "uniform sampler2D sTexture;\n" +
558                 "uniform lowp vec4 uColor;\n" +
559                 "\n" +
560                 "void main()\n" +
561                 "{\n" +
562                 "// sample distance field\n" +
563                 "mediump float smoothing = 0.5;\n" +
564
565                 "mediump float distance = texture2D(sTexture, vTexCoord).a;\n" +
566                 "mediump float smoothWidth = fwidth(distance);\n" +
567                 "mediump float alphaFactor = smoothstep(smoothing - smoothWidth, smoothing + smoothWidth, distance);\n" +
568                 "lowp    vec4 color;\n" +
569                 "if (uDoShadow == 0.0)\n" +
570                 "{\n" +
571                 "mediump float alpha = uColor.a * alphaFactor;\n" +
572                 "lowp    vec4 rgb = uColor;\n" +
573                 "\n" +
574                 "if (uDoOutline > 0.0)\n" +
575                 "{\n" +
576                 "mediump float outlineWidth = uOutlineParams[1] + smoothWidth;\n" +
577                 "mediump float outlineBlend = smoothstep(uOutlineParams[0] - outlineWidth, uOutlineParams[0] + outlineWidth, distance);\n" +
578                 "alpha = smoothstep(smoothing - smoothWidth, smoothing + smoothWidth, distance);\n" +
579                 "rgb = mix(uOutlineColor, uColor, outlineBlend);\n" +
580                 "}\n" +
581                 "\n" +
582                 "if (uDoGlow > 0.0)\n" +
583                 "{\n" +
584                 "rgb = mix(uGlowColor, rgb, alphaFactor);\n" +
585                 "alpha = smoothstep(uGlowBoundary, smoothing, distance);\n" +
586                 "}\n" +
587                 "\n" +
588                 "// set fragment color\n" +
589                 "color = vec4(rgb.rgb, alpha);\n" +
590                 "}\n" +
591                 "\n" +
592                 "else // (uDoShadow > 0.0)\n" +
593                 "{\n" +
594                 "mediump float shadowDistance = texture2D(sTexture, vTexCoord - uShadowOffset).a;\n" +
595                 "mediump float inText = alphaFactor;\n" +
596                 "mediump float inShadow = smoothstep(smoothing - smoothWidth, smoothing + smoothWidth, shadowDistance);\n" +
597                 "\n" +
598                 "// inside object, outside shadow\n" +
599                 "if (inText == 1.0)\n" +
600                 "{\n" +
601                 "color = uColor;\n" +
602                 "}\n" +
603                 "// inside object, outside shadow\n" +
604                 "else if ((inText != 0.0) && (inShadow == 0.0))\n" +
605                 "{\n" +
606                 "color = uColor;\n" +
607                 "color.a *= inText;\n" +
608                 "}\n" +
609                 "// outside object, completely inside shadow\n" +
610                 "else if ((inText == 0.0) && (inShadow == 1.0))\n" +
611                 "{\n" +
612                 "color = uShadowColor;\n" +
613                 "}\n" +
614                 "// inside object, completely inside shadow\n" +
615                 "else if ((inText != 0.0) && (inShadow == 1.0))\n" +
616                 "{\n" +
617                 "color = mix(uShadowColor, uColor, inText);\n" +
618                 "color.a = uShadowColor.a;\n" +
619                 "}\n" +
620                 "// inside object, inside shadow's border\n" +
621                 "else if ((inText != 0.0) && (inShadow != 0.0))\n" +
622                 "{\n" +
623                 "color = mix(uShadowColor, uColor, inText);\n" +
624                 "color.a *= max(inText, inShadow);\n" +
625                 "}\n" +
626                 "// inside shadow's border\n" +
627                 "else if (inShadow != 0.0)\n" +
628                 "{\n" +
629                 "color = uShadowColor;\n" +
630                 "color.a *= inShadow;\n" +
631                 "}\n" +
632                 "// outside shadow and object\n" +
633                 "else \n" +
634                 "{\n" +
635                 "color.a = 0.0;\n" +
636                 "}\n" +
637                 "\n" +
638                 "}\n" +
639                 "\n" +
640                 "gl_FragColor = color;\n" +
641                 "\n" +
642                 "}";
643
644             PropertyMap map = new PropertyMap();
645
646             PropertyMap customShader = new PropertyMap();
647
648             string fragmentShaderString;
649             fragmentShaderString = fragmentShaderPrefix + fragmentShader;
650
651             customShader.Insert(Visual.ShaderProperty.FragmentShader, new PropertyValue(fragmentShaderString));
652             customShader.Insert(Visual.ShaderProperty.ShaderHints, new PropertyValue((int)Shader.Hint.Value.OUTPUT_IS_TRANSPARENT));
653
654             map.Insert(Visual.Property.Shader, new PropertyValue(customShader));
655             return map;
656         }
657
658         private void ApplyScrollViewEffect()
659         {
660             // Remove old effect if exists.
661             if (mScrollViewEffect)
662             {
663                 mScrollView.RemoveEffect(mScrollViewEffect);
664             }
665
666             // Just one effect for now
667             SetupInnerPageCubeEffect();
668
669             mScrollView.ApplyEffect(mScrollViewEffect);
670         }
671
672         private void SetupInnerPageCubeEffect()
673         {
674             Vector2 stageSize = NUIApplication.GetDefaultWindow().WindowSize;
675
676             Path path = new Path();
677             PropertyArray points = new PropertyArray();
678             points.PushBack(new PropertyValue(new Vector3(stageSize.X * 0.5f, 0.0f, stageSize.X * 0.5f)));
679             points.PushBack(new PropertyValue(new Vector3(0.0f, 0.0f, 0.0f)));
680             points.PushBack(new PropertyValue(new Vector3(-stageSize.X * 0.5f, 0.0f, stageSize.X * 0.5f)));
681             path.Points = points;
682
683             PropertyArray controlPoints = new PropertyArray();
684             controlPoints.PushBack(new PropertyValue(new Vector3(stageSize.X * 0.5f, 0.0f, stageSize.X * 0.3f)));
685             controlPoints.PushBack(new PropertyValue(new Vector3(stageSize.X * 0.3f, 0.0f, 0.0f)));
686             controlPoints.PushBack(new PropertyValue(new Vector3(-stageSize.X * 0.3f, 0.0f, 0.0f)));
687             controlPoints.PushBack(new PropertyValue(new Vector3(-stageSize.X * 0.5f, 0.0f, stageSize.X * 0.3f)));
688             path.ControlPoints = controlPoints;
689
690             mScrollViewEffect = new ScrollViewPagePathEffect(path,
691                                                              new Vector3(-1.0f, 0.0f, 0.0f),
692                                                              ScrollView.Property.ScrollFinalX,
693                                                              new Vector3(stageSize.X * TABLE_RELATIVE_SIZE.X, stageSize.Y * TABLE_RELATIVE_SIZE.Y, 0.0f), mTotalPages);
694         }
695
696         void ApplyCubeEffectToPages()
697         {
698             uint pageCount = 0;
699
700             for (int i = 0; i < mPages.Count(); i++)
701             {
702                 View page = mPages[i];
703                 mScrollViewEffect.ApplyToPage(page, pageCount++);
704             }
705         }
706
707         void Rotate(uint degrees)
708         {
709             // Resize the root actor
710             Vector2 stageSize = NUIApplication.GetDefaultWindow().WindowSize;
711             Vector3 targetSize = new Vector3(stageSize.X, stageSize.Y, 1.0f);
712
713             if (degrees == 90 || degrees == 270)
714             {
715                 targetSize = new Vector3(stageSize.Y, stageSize.X, 1.0f);
716             }
717
718             if (mRotateAnimation)
719             {
720                 mRotateAnimation.Stop();
721                 mRotateAnimation.Clear();
722             }
723
724             mRotateAnimation = new Animation((int)(ROTATE_ANIMATION_TIME * 1000.0));
725             mRotateAnimation.AnimateTo(mRootActor, "Orientation", new Rotation(new Radian(new Degree(360 - degrees)), new Vector3(0, 0, 1)), new AlphaFunction(AlphaFunction.BuiltinFunctions.EaseOut));
726             mRotateAnimation.AnimateTo(mRootActor, "Size", targetSize, new AlphaFunction(AlphaFunction.BuiltinFunctions.EaseOut));
727             mRotateAnimation.Play();
728         }
729
730         internal View mRootActor;                //  All content (excluding background is anchored to this Actor)
731         private Animation mRotateAnimation;          //  Animation to rotate and resize mRootActor.
732         private Animation mPressedAnimation;         //  Button press scaling animation.
733         private ScrollView mScrollView;               //  ScrollView container (for all Examples)
734         private ScrollViewPagePathEffect mScrollViewEffect;         //  Effect to be applied to the scroll view
735         private RulerPtr mScrollRulerX;             //  ScrollView X (horizontal) ruler
736         private RulerPtr mScrollRulerY;             //  ScrollView Y (vertical) ruler
737         private View mPressedActor;             //  The currently pressed actor.
738         private Timer mAnimationTimer;           //  Timer used to turn off animation after a specific time period
739
740         // This struct encapsulates all data relevant to each of the elements used within the custom keyboard focus effect.
741         private struct FocusEffect
742         {
743             public Animation animation;               //  The animation for the parent keyboard focus highlight actor
744         };
745         FocusEffect[] mFocusEffect = new FocusEffect[FOCUS_ANIMATION_ACTOR_NUMBER];    //  The elements used to create the custom focus effect
746
747         private View[] mPages;                    //  List of pages.
748         private List<Animation> mBackgroundAnimations = new List<Animation>();     //  List of background bubble animations
749         private List<Example> mExampleList = new List<Example>();              //  List of examples.
750
751         private float mPageWidth;                //  The width of a page within the scroll-view, used to calculate the domain
752         private uint mTotalPages;               //  Total pages within scrollview.
753
754         private bool mScrolling;              //  Flag indicating whether view is currently being scrolled
755         private bool mSortAlphabetically;     //  Sort examples alphabetically.
756         private bool mBackgroundAnimsPlaying; //  Are background animations playing
757     }
758 }