[NUI] TCSACR-226 code change (#1032)
[platform/core/csapi/tizenfx.git] / src / Tizen.NUI.Components / Controls / FlexibleView / FlexibleView.cs
1 /*
2  * Copyright(c) 2019 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 using System;
18 using System.ComponentModel;
19 using System.Collections.Generic;
20 using Tizen.NUI.BaseComponents;
21
22 namespace Tizen.NUI.Components
23 {
24     /// <summary>
25     /// A flexible view for providing a limited window into a large data set.
26     /// </summary>
27     /// <since_tizen> 6 </since_tizen>
28     /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
29     [EditorBrowsable(EditorBrowsableState.Never)]
30     public class FlexibleView : Control
31     {
32         /// <summary>
33         /// Constant value: -1.
34         /// </summary>
35         /// <since_tizen> 6 </since_tizen>
36         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
37         [EditorBrowsable(EditorBrowsableState.Never)]
38         public static readonly int NO_POSITION = -1;
39         /// <summary>
40         /// Constant value: -1.
41         /// </summary>
42         /// <since_tizen> 6 </since_tizen>
43         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
44         [EditorBrowsable(EditorBrowsableState.Never)]
45         public static readonly int INVALID_TYPE = -1;
46
47         private Adapter mAdapter;
48         private LayoutManager mLayout;
49         private Recycler mRecycler;
50         private RecycledViewPool mRecyclerPool;
51         private ChildHelper mChildHelper;
52
53         private PanGestureDetector mPanGestureDetector;
54
55         private int mFocusedItemIndex = NO_POSITION;
56
57         private AdapterHelper mAdapteHelper;
58
59         private ScrollBar mScrollBar = null;
60         private Timer mScrollBarShowTimer = null;
61
62         private EventHandler<ItemClickEventArgs> clickEventHandlers;
63         private EventHandler<ItemTouchEventArgs> touchEventHandlers;
64         private EventHandler<NUI.StyleManager.StyleChangedEventArgs> styleChangedEventHandlers;
65
66         /// <summary>
67         /// Creates a FlexibleView instance.
68         /// </summary>
69         /// <since_tizen> 6 </since_tizen>
70         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
71         [EditorBrowsable(EditorBrowsableState.Never)]
72         public FlexibleView()
73         {
74             mRecyclerPool = new RecycledViewPool(this);
75
76             mRecycler = new Recycler(this);
77             mRecycler.SetRecycledViewPool(mRecyclerPool);
78
79             mChildHelper = new ChildHelper(this);
80
81             mPanGestureDetector = new PanGestureDetector();
82             mPanGestureDetector.Attach(this);
83             mPanGestureDetector.Detected += OnPanGestureDetected;
84
85             mAdapteHelper = new AdapterHelper(this);
86
87             ClippingMode = ClippingModeType.ClipToBoundingBox;
88         }
89
90         /// <summary>
91         /// Item click event.
92         /// </summary>
93         /// <since_tizen> 6 </since_tizen>
94         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
95         [EditorBrowsable(EditorBrowsableState.Never)]
96         public event EventHandler<ItemClickEventArgs> ItemClickEvent
97         {
98             add
99             {
100                 clickEventHandlers += value;
101             }
102
103             remove
104             {
105                 clickEventHandlers -= value;
106             }
107         }
108
109
110         /// <summary>
111         /// Item touch event.
112         /// </summary>
113         /// <since_tizen> 6 </since_tizen>
114         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
115         [EditorBrowsable(EditorBrowsableState.Never)]
116         public event EventHandler<ItemTouchEventArgs> ItemTouchEvent
117         {
118             add
119             {
120                 touchEventHandlers += value;
121             }
122
123             remove
124             {
125                 touchEventHandlers -= value;
126             }
127         }
128
129         /// <summary>
130         /// Style changed, for example default font size.
131         /// </summary>
132         /// <since_tizen> 6 </since_tizen>
133         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
134         [EditorBrowsable(EditorBrowsableState.Never)]
135         public event EventHandler<NUI.StyleManager.StyleChangedEventArgs> StyleChanged
136         {
137             add
138             {
139                 styleChangedEventHandlers += value;
140             }
141
142             remove
143             {
144                 styleChangedEventHandlers -= value;
145             }
146         }
147
148         /// <summary>
149         /// overwrite the Padding.
150         /// </summary>
151         /// <since_tizen> 6 </since_tizen>
152         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
153         [EditorBrowsable(EditorBrowsableState.Never)]
154         public new Extents Padding
155         {
156             get;
157             set;
158         }
159
160         /// <summary>
161         /// Gets or sets the focused item index(adapter position).
162         /// </summary>
163         /// <since_tizen> 6 </since_tizen>
164         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
165         [EditorBrowsable(EditorBrowsableState.Never)]
166         public int FocusedItemIndex
167         {
168             get
169             {
170                 return mFocusedItemIndex;
171             }
172             set
173             {
174                 if (value == mFocusedItemIndex)
175                 {
176                     return;
177                 }
178
179                 if (mAdapter == null)
180                 {
181                     return;
182                 }
183
184                 if (mLayout == null)
185                 {
186                     return;
187                 }
188
189                 ViewHolder nextFocusView = FindViewHolderForAdapterPosition(value);
190                 if (nextFocusView == null)
191                 {
192                     mLayout.ScrollToPosition(value);
193                 }
194                 else
195                 {
196                     mLayout.RequestChildRectangleOnScreen(this, nextFocusView, mRecycler, true);
197                     DispatchFocusChanged(value);
198                 }
199             }
200         }
201
202         /// <summary>
203         /// Set a new adapter to provide child views on demand.
204         /// </summary>
205         /// <since_tizen> 6 </since_tizen>
206         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
207         [EditorBrowsable(EditorBrowsableState.Never)]
208         public void SetAdapter(Adapter adapter)
209         {
210             if (adapter == null)
211             {
212                 return;
213             }
214             mAdapter = adapter;
215
216             mAdapter.ItemEvent += OnItemEvent;
217         }
218
219         /// <summary>
220         /// Retrieves the previously set adapter or null if no adapter is set.
221         /// </summary>
222         /// <since_tizen> 6 </since_tizen>
223         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
224         [EditorBrowsable(EditorBrowsableState.Never)]
225         public Adapter GetAdapter()
226         {
227             return mAdapter;
228         }
229
230         /// <summary>
231         /// Set the FlexibleView.LayoutManager that this FlexibleView will use.
232         /// </summary>
233         /// <since_tizen> 6 </since_tizen>
234         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
235         [EditorBrowsable(EditorBrowsableState.Never)]
236         public void SetLayoutManager(LayoutManager layoutManager)
237         {
238             mLayout = layoutManager;
239
240             mLayout.SetRecyclerView(this);
241
242             if (mLayout.CanScrollHorizontally())
243             {
244                 mPanGestureDetector.AddDirection(PanGestureDetector.DirectionHorizontal);
245             }
246             else if (mLayout.CanScrollVertically())
247             {
248                 mPanGestureDetector.AddDirection(PanGestureDetector.DirectionVertical);
249             }
250         }
251
252         /// <summary>
253         /// Return the FlexibleView.LayoutManager currently responsible for layout policy for this FlexibleView.
254         /// </summary>
255         /// <since_tizen> 6 </since_tizen>
256         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
257         [EditorBrowsable(EditorBrowsableState.Never)]
258         public LayoutManager GetLayoutManager()
259         {
260             return mLayout;
261         }
262
263
264         /// <summary>
265         /// Convenience method to scroll to a certain position
266         /// </summary>
267         /// <param name="position">Adapter position</param>
268         /// <param name="offset">The distance (in pixels) between the start edge of the item view and start edge of the FlexibleView.</param>
269         /// <since_tizen> 6 </since_tizen>
270         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
271         [EditorBrowsable(EditorBrowsableState.Never)]
272         public void ScrollToPositionWithOffset(int position, int offset)
273         {
274             mLayout.ScrollToPositionWithOffset(position, offset);
275         }
276
277         /// <summary>
278         /// Move focus by direction.
279         /// </summary>
280         /// <param name="direction">Direction. Should be "Left", "Right", "Up" or "Down" </param>
281         /// <since_tizen> 6 </since_tizen>
282         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
283         [EditorBrowsable(EditorBrowsableState.Never)]
284         public void MoveFocus(FlexibleView.LayoutManager.Direction direction)
285         {
286             mLayout.MoveFocus(direction, mRecycler);
287         }
288
289         /// <summary>
290         /// Attach a scrollbar to this FlexibleView.
291         /// </summary>
292         /// <param name="scrollBar">ScrollBar</param>
293         /// <since_tizen> 6 </since_tizen>
294         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
295         [EditorBrowsable(EditorBrowsableState.Never)]
296         public void AttachScrollBar(ScrollBar scrollBar)
297         {
298             if (scrollBar == null)
299             {
300                 return;
301             }
302             mScrollBar = scrollBar;
303             Add(mScrollBar);
304         }
305
306         /// <summary>
307         /// Detach the scrollbar from this FlexibleView.
308         /// </summary>
309         /// <since_tizen> 6 </since_tizen>
310         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
311         [EditorBrowsable(EditorBrowsableState.Never)]
312         public void DetachScrollBar()
313         {
314             if (mScrollBar == null)
315             {
316                 return;
317             }
318             Remove(mScrollBar);
319             mScrollBar = null;
320         }
321
322         /// <summary>
323         /// Return the ViewHolder for the item in the given position of the data set as of the latest layout pass.
324         /// This method checks only the children of RecyclerView. If the item at the given position is not laid out, it will not create a new one.
325         /// </summary>
326         /// <param name="position">The position of the item in the data set of the adapter</param>
327         /// <since_tizen> 6 </since_tizen>
328         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
329         [EditorBrowsable(EditorBrowsableState.Never)]
330         public ViewHolder FindViewHolderForLayoutPosition(int position)
331         {
332             int childCount = mChildHelper.GetChildCount();
333             for (int i = 0; i < childCount; i++)
334             {
335                 if (mChildHelper.GetChildAt(i) is ViewHolder holder)
336                 {
337                     if (holder.LayoutPosition == position)
338                     {
339                         return holder;
340                     }
341                 }
342             }
343
344             return null;
345         }
346
347         /// <summary>
348         /// Return the ViewHolder for the item in the given position of the data set.
349         /// This method checks only the children of RecyclerView. If the item at the given position is not laid out, it will not create a new one.
350         /// </summary>
351         /// <param name="position">The position of the item in the data set of the adapter</param>
352         /// <since_tizen> 6 </since_tizen>
353         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
354         [EditorBrowsable(EditorBrowsableState.Never)]
355         public ViewHolder FindViewHolderForAdapterPosition(int position)
356         {
357             int childCount = mChildHelper.GetChildCount();
358             for (int i = 0; i < childCount; i++)
359             {
360                 if (mChildHelper.GetChildAt(i) is ViewHolder holder)
361                 {
362                     if (holder.AdapterPosition == position)
363                     {
364                         return holder;
365                     }
366                 }
367             }
368
369             return null;
370         }
371
372         /// <summary>
373         /// Return the recycler instance.
374         /// </summary>
375         /// <since_tizen> 6 </since_tizen>
376         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
377         [EditorBrowsable(EditorBrowsableState.Never)]
378         public Recycler GetRecycler()
379         {
380             return mRecycler;
381         }
382
383         /// <summary>
384         /// you can override it to clean-up your own resources.
385         /// </summary>
386         /// <param name="type">DisposeTypes</param>
387         /// <since_tizen> 6 </since_tizen>
388         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
389         [EditorBrowsable(EditorBrowsableState.Never)]
390         protected override void Dispose(DisposeTypes type)
391         {
392             if (disposed)
393             {
394                 return;
395             }
396
397             if (type == DisposeTypes.Explicit)
398             {
399                 mLayout.StopScroll();
400
401                 if (mAdapter != null)
402                 {
403                     mAdapter.ItemEvent -= OnItemEvent;
404                 }
405
406                 if (mPanGestureDetector != null)
407                 {
408                     mPanGestureDetector.Detected -= OnPanGestureDetected;
409                     mPanGestureDetector.Dispose();
410                     mPanGestureDetector = null;
411                 }
412
413                 if (mScrollBarShowTimer != null)
414                 {
415                     mScrollBarShowTimer.Tick -= OnShowTimerTick;
416                     mScrollBarShowTimer.Stop();
417                     mScrollBarShowTimer.Dispose();
418                     mScrollBarShowTimer = null;
419                 }
420
421                 if (mRecyclerPool != null)
422                 {
423                     mRecyclerPool.Clear();
424                     mRecyclerPool = null;
425                 }
426
427                 if (mChildHelper != null)
428                 {
429                     mChildHelper.Clear();
430                     mChildHelper = null;
431                 }
432             }
433             base.Dispose(type);
434         }
435
436         /// <summary>
437         /// you can override it to create your own default attributes.
438         /// </summary>
439         /// <since_tizen> 6 </since_tizen>
440         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
441         [EditorBrowsable(EditorBrowsableState.Never)]
442         protected override Attributes GetAttributes()
443         {
444             return null;
445         }
446
447         /// <summary>
448         /// you can override it to relayout elements.
449         /// </summary>
450         /// <since_tizen> 6 </since_tizen>
451         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
452         [EditorBrowsable(EditorBrowsableState.Never)]
453         public override void OnRelayout(Vector2 size, RelayoutContainer container)
454         {
455             if (mAdapter == null)
456             {
457                 return;
458             }
459
460             if (mLayout == null)
461             {
462                 return;
463             }
464
465             DispatchLayoutStep1();
466
467             mLayout.OnLayoutChildren(mRecycler);
468
469             RemoveAndRecycleScrapInt();
470         }
471
472         /// <summary>
473         /// you can override it to do something for style change.
474         /// </summary>
475         /// <since_tizen> 6 </since_tizen>
476         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
477         [EditorBrowsable(EditorBrowsableState.Never)]
478         public override void OnStyleChange(NUI.StyleManager styleManager, StyleChangeType change)
479         {
480             if (change == StyleChangeType.DefaultFontSizeChange)
481             {
482                 NUI.StyleManager.StyleChangedEventArgs args = new NUI.StyleManager.StyleChangedEventArgs();
483                 args.StyleManager = styleManager;
484                 args.StyleChange = change;
485
486                 styleChangedEventHandlers?.Invoke(this, args);
487
488                 RelayoutRequest();
489             }
490         }
491
492         private void DispatchLayoutStep1()
493         {
494             ProcessAdapterUpdates();
495             SaveOldPositions();
496             ClearOldPositions();
497         }
498
499         private void ProcessAdapterUpdates()
500         {
501             mAdapteHelper.PreProcess();
502         }
503
504         private void OffsetPositionRecordsForInsert(int positionStart, int itemCount)
505         {
506             int childCount = mChildHelper.GetChildCount();
507             for (int i = 0; i < childCount; i++)
508             {
509                 ViewHolder holder = mChildHelper.GetChildAt(i);
510                 if (holder != null && holder.AdapterPosition >= positionStart)
511                 {
512                     holder.OffsetPosition(itemCount, false);
513                 }
514             }
515
516             if (positionStart <= mFocusedItemIndex)
517             {
518                 mFocusedItemIndex += itemCount;
519             }
520         }
521
522         private void OffsetPositionRecordsForRemove(int positionStart, int itemCount, bool applyToPreLayout)
523         {
524             int positionEnd = positionStart + itemCount;
525             int childCount = mChildHelper.GetChildCount();
526             for (int i = 0; i < childCount; i++)
527             {
528                 ViewHolder holder = mChildHelper.GetChildAt(i);
529                 if (holder != null)
530                 {
531                     if (holder.AdapterPosition >= positionEnd)
532                     {
533                         holder.OffsetPosition(-itemCount, applyToPreLayout);
534                     }
535                     else if (holder.AdapterPosition >= positionStart)
536                     {
537                         holder.FlagRemovedAndOffsetPosition(positionStart - 1, -itemCount, applyToPreLayout);
538                     }
539                 }
540             }
541
542             if (positionEnd <= mFocusedItemIndex)
543             {
544                 mFocusedItemIndex -= itemCount;
545             }
546             else if (positionStart <= mFocusedItemIndex)
547             {
548                 mFocusedItemIndex = positionStart;
549                 if (mFocusedItemIndex >= mAdapter.GetItemCount())
550                 {
551                     mFocusedItemIndex = mAdapter.GetItemCount() - 1;
552                 }
553             }
554         }
555
556         private void SaveOldPositions()
557         {
558             int childCount = mChildHelper.GetChildCount();
559             for (int i = 0; i < childCount; i++)
560             {
561                 ViewHolder holder = mChildHelper.GetChildAt(i);
562                 holder.SaveOldPosition();
563             }
564         }
565
566         private void ClearOldPositions()
567         {
568             int childCount = mChildHelper.GetChildCount();
569             for (int i = 0; i < childCount; i++)
570             {
571                 ViewHolder holder = mChildHelper.GetChildAt(i);
572                 holder.ClearOldPosition();
573             }
574         }
575
576         private void RemoveAndRecycleScrapInt()
577         {
578             int scrapCount = mRecycler.GetScrapCount();
579             for (int i = 0; i < scrapCount; i++)
580             {
581                 ViewHolder scrap = mRecycler.GetScrapViewAt(i);
582                 mChildHelper.RemoveView(scrap);
583                 mRecycler.RecycleView(scrap);
584             }
585             mRecycler.Clear();
586         }
587
588         private void ShowScrollBar(uint millisecond = 700, bool flagAni = false)
589         {
590             if (mScrollBar == null || mLayout == null)
591             {
592                 return;
593             }
594
595             float extent = mLayout.ComputeScrollExtent();
596             float range = mLayout.ComputeScrollRange();
597             if(range == 0)
598             {
599                 return;
600             }
601             float offset = mLayout.ComputeScrollOffset();
602
603             float size = mScrollBar.Direction == ScrollBar.DirectionType.Vertical ? mScrollBar.SizeHeight : mScrollBar.SizeWidth;
604             float thickness = mScrollBar.Direction == ScrollBar.DirectionType.Vertical ? mScrollBar.SizeWidth : mScrollBar.SizeHeight;
605             float length = (float)Math.Round(size * extent / range);
606
607             // avoid the tiny thumb
608             float minLength = thickness * 2;
609             if (length < minLength)
610             {
611                 length = minLength;
612             }
613             // avoid the too-big thumb
614             if (offset > range - extent)
615             {
616                 offset = range - extent;
617             }
618             if (mScrollBar.Direction == ScrollBar.DirectionType.Vertical)
619             {
620                 mScrollBar.ThumbSize = new Size2D((int)thickness, (int)length);
621             }
622             else
623             {
624                 mScrollBar.ThumbSize = new Size2D((int)length, (int)thickness);
625             }
626             mScrollBar.MinValue = 0;
627             mScrollBar.MaxValue = (int)(range - extent);
628             mScrollBar.SetCurrentValue((int)offset, flagAni);
629             mScrollBar.Show();
630             if (mScrollBarShowTimer == null)
631             {
632                 mScrollBarShowTimer = new Timer(millisecond);
633                 mScrollBarShowTimer.Tick += OnShowTimerTick;
634             }
635             else
636             {
637                 mScrollBarShowTimer.Interval = millisecond;
638             }
639             mScrollBarShowTimer.Start();
640         }
641
642         private bool OnShowTimerTick(object source, EventArgs e)
643         {
644             if (mScrollBar != null)
645             {
646                 mScrollBar.Hide();
647             }
648
649             return false;
650         }
651
652         private void DispatchFocusChanged(int nextFocusPosition)
653         {
654             mAdapter.OnFocusChange(this, mFocusedItemIndex, nextFocusPosition);
655
656             mFocusedItemIndex = nextFocusPosition;
657  
658            ShowScrollBar();
659         }
660
661         private void DispatchChildAttached(ViewHolder holder)
662         {
663             if (mAdapter != null && holder != null)
664             {
665                 mAdapter.OnViewAttachedToWindow(holder);
666             }
667         }
668
669         private void DispatchChildDetached(ViewHolder holder)
670         {
671             if (mAdapter != null && holder != null)
672             {
673                 mAdapter.OnViewDetachedFromWindow(holder);
674             }
675         }
676
677         private void DispatchChildDestroyed(ViewHolder holder)
678         {
679             if (mAdapter != null && holder != null)
680             {
681                 mAdapter.OnDestroyViewHolder(holder);
682             }
683         }
684
685         private void DispatchItemClicked(ViewHolder clickedHolder)
686         {
687             ItemClickEventArgs args = new ItemClickEventArgs();
688             args.ClickedView = clickedHolder;
689             OnClickEvent(this, args);
690         }
691
692         private void DispatchItemTouched(ViewHolder touchedHolder, Touch touchEvent)
693         {
694             ItemTouchEventArgs args = new ItemTouchEventArgs();
695             args.TouchedView = touchedHolder;
696             args.Touch = touchEvent;
697             OnTouchEvent(this, args);
698         }
699
700         private void OnPanGestureDetected(object source, PanGestureDetector.DetectedEventArgs e)
701         {
702             if (e.PanGesture.State == Gesture.StateType.Started)
703             {
704                 mLayout.StopScroll();
705             }
706             else if (e.PanGesture.State == Gesture.StateType.Continuing)
707             {
708                 if (mLayout.CanScrollVertically())
709                 {
710                     mLayout.ScrollVerticallyBy(e.PanGesture.Displacement.Y, mRecycler, true);
711                 }
712                 else if (mLayout.CanScrollHorizontally())
713                 {
714                     mLayout.ScrollHorizontallyBy(e.PanGesture.Displacement.X, mRecycler, true);
715                 }
716
717                 ShowScrollBar();
718             }
719             else if (e.PanGesture.State == Gesture.StateType.Finished)
720             {
721                 if (mLayout.CanScrollVertically())
722                 {
723                     mLayout.ScrollVerticallyBy(e.PanGesture.Velocity.Y * 600, mRecycler, false);
724                 }
725                 else if (mLayout.CanScrollHorizontally())
726                 {
727                     mLayout.ScrollHorizontallyBy(e.PanGesture.Velocity.X * 600, mRecycler, false);
728                 }
729                 ShowScrollBar(1200, true);
730             }
731         }
732
733
734         private void OnItemEvent(object sender, Adapter.ItemEventArgs e)
735         {
736             switch (e.EventType)
737             {
738                 case Adapter.ItemEventType.Insert:
739                     mAdapteHelper.OnItemRangeInserted(e.param[0], e.param[1]);
740                     ShowScrollBar();
741                     break;
742                 case Adapter.ItemEventType.Remove:
743                     mAdapteHelper.OnItemRangeRemoved(e.param[0], e.param[1]);
744                     ShowScrollBar();
745                     break;
746                 case Adapter.ItemEventType.Move:
747                     break;
748                 case Adapter.ItemEventType.Change:
749                     break;
750                 default:
751                     return;
752             }
753             RelayoutRequest();
754         }
755
756
757         private void OnClickEvent(object sender, ItemClickEventArgs e)
758         {
759             clickEventHandlers?.Invoke(sender, e);
760         }
761
762         private void OnTouchEvent(object sender, ItemTouchEventArgs e)
763         {
764             touchEventHandlers?.Invoke(sender, e);
765         }
766
767         /// <summary>
768         /// ItemClick Event Arguments.
769         /// </summary>
770         /// <since_tizen> 6 </since_tizen>
771         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
772         [EditorBrowsable(EditorBrowsableState.Never)]
773         public class ItemClickEventArgs : EventArgs
774         {
775             /// <summary>
776             /// The clicked ViewHolder.
777             /// </summary>
778             /// <since_tizen> 6 </since_tizen>
779             /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
780             [EditorBrowsable(EditorBrowsableState.Never)]
781             public ViewHolder ClickedView;
782         }
783
784         /// <summary>
785         /// ItemTouch Event Arguments.
786         /// </summary>
787         /// <since_tizen> 6 </since_tizen>
788         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
789         [EditorBrowsable(EditorBrowsableState.Never)]
790         public class ItemTouchEventArgs : TouchEventArgs
791         {
792             /// <summary>
793             /// The touched ViewHolder.
794             /// </summary>
795             /// <since_tizen> 6 </since_tizen>
796             /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
797             [EditorBrowsable(EditorBrowsableState.Never)]
798             public ViewHolder TouchedView;
799         }
800
801         /// <summary>
802         /// Adapters provide a binding from an app-specific data set to views that are displayed within a FlexibleView.
803         /// </summary>
804         /// <since_tizen> 6 </since_tizen>
805         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
806         [EditorBrowsable(EditorBrowsableState.Never)]
807         public abstract class Adapter
808         {
809             private EventHandler<ItemEventArgs> itemEventHandlers;
810
811             internal event EventHandler<ItemEventArgs> ItemEvent
812             {
813                 add
814                 {
815                     itemEventHandlers += value;
816                 }
817
818                 remove
819                 {
820                     itemEventHandlers -= value;
821                 }
822             }
823
824             internal enum ItemEventType
825             {
826                 Insert = 0,
827                 Remove,
828                 Move,
829                 Change
830             }
831
832             /// <summary>
833             /// Called when FlexibleView needs a new FlexibleView.ViewHolder of the given type to represent an item.
834             /// </summary>
835             /// <param name="viewType">The view type of the new View</param>
836             /// <since_tizen> 6 </since_tizen>
837             /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
838             [EditorBrowsable(EditorBrowsableState.Never)]
839             public abstract ViewHolder OnCreateViewHolder(int viewType);
840
841             /// <summary>
842             /// Called by FlexibleView to display the data at the specified position.
843             /// </summary>
844             /// <param name="holder">The ViewHolder which should be updated to represent the contents of the item at the given position in the data set.</param>
845             /// <param name="position">The position of the item within the adapter's data set.</param>
846             /// <since_tizen> 6 </since_tizen>
847             /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
848             [EditorBrowsable(EditorBrowsableState.Never)]
849             public abstract void OnBindViewHolder(ViewHolder holder, int position);
850
851             /// <summary>
852             /// Called when a ViewHolder is never used.
853             /// </summary>
854             /// <param name="holder">The ViewHolder which need to be disposed</param>
855             /// <since_tizen> 6 </since_tizen>
856             /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
857             [EditorBrowsable(EditorBrowsableState.Never)]
858             public abstract void OnDestroyViewHolder(ViewHolder holder);
859
860             /// <summary>
861             /// Returns the total number of items in the data set held by the adapter.
862             /// </summary>
863             /// <since_tizen> 6 </since_tizen>
864             /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
865             [EditorBrowsable(EditorBrowsableState.Never)]
866             public abstract int GetItemCount();
867
868             /// <summary>
869             /// Return the view type of the item at position for the purposes of view recycling.
870             /// </summary>
871             /// <param name="position">The position of the item within the adapter's data set.</param>
872             /// <since_tizen> 6 </since_tizen>
873             /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
874             [EditorBrowsable(EditorBrowsableState.Never)]
875             public virtual int GetItemViewType(int position)
876             {
877                 return 0;
878             }
879
880             /// <summary>
881             /// Called by FlexibleView when it starts observing this Adapter.
882             /// Keep in mind that same adapter may be observed by multiple FlexibleView.
883             /// </summary>
884             /// <param name="flexibleView">The FlexibleView instance which started observing this adapter.</param>
885             /// <since_tizen> 6 </since_tizen>
886             /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
887             [EditorBrowsable(EditorBrowsableState.Never)]
888             public virtual void OnAttachedToRecyclerView(FlexibleView flexibleView)
889             {
890             }
891
892             /// <summary>
893             /// Called by FlexibleView when it stops observing this Adapter.
894             /// </summary>
895             /// <param name="flexibleView">The FlexibleView instance which stopped observing this adapter.</param>
896             /// <since_tizen> 6 </since_tizen>
897             /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
898             [EditorBrowsable(EditorBrowsableState.Never)]
899             public virtual void OnDetachedFromRecyclerView(FlexibleView flexibleView)
900             {
901             }
902
903             /// <summary>
904             /// Called when FlexibleView focus changed.
905             /// </summary>
906             /// <param name="flexibleView">The FlexibleView into which the focus ViewHolder changed.</param>
907             /// <param name="previousFocus">The position of previous focus</param>
908             /// <param name="currentFocus">The position of current focus</param>
909             /// <since_tizen> 6 </since_tizen>
910             /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
911             [EditorBrowsable(EditorBrowsableState.Never)]
912             public virtual void OnFocusChange(FlexibleView flexibleView, int previousFocus, int currentFocus)
913             {
914             }
915
916             /// <summary>
917             /// Called when a view created by this adapter has been recycled.
918             /// If an item view has large or expensive data bound to it such as large bitmaps, this may be a good place to release those resources
919             /// </summary>
920             /// <param name="holder">The ViewHolder will be recycled.</param>
921             /// <since_tizen> 6 </since_tizen>
922             /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
923             [EditorBrowsable(EditorBrowsableState.Never)]
924             public virtual void OnViewRecycled(ViewHolder holder)
925             {
926             }
927
928             /// <summary>
929             /// Called when a view created by this adapter has been attached to a window.
930             /// This can be used as a reasonable signal that the view is about to be seen by the user.
931             /// </summary>
932             /// <param name="holder">Holder of the view being attached.</param>
933             /// <since_tizen> 6 </since_tizen>
934             /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
935             [EditorBrowsable(EditorBrowsableState.Never)]
936             public virtual void OnViewAttachedToWindow(ViewHolder holder)
937             {
938             }
939
940             /// <summary>
941             /// Called when a view created by this adapter has been detached from its window.
942             /// </summary>
943             /// <param name="holder">Holder of the view being detached.</param>
944             /// <since_tizen> 6 </since_tizen>
945             /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
946             [EditorBrowsable(EditorBrowsableState.Never)]
947             public virtual void OnViewDetachedFromWindow(ViewHolder holder)
948             {
949             }
950
951             /// <summary>
952             /// Notify any registered observers that the data set has changed.
953             /// </summary>
954             /// <since_tizen> 6 </since_tizen>
955             /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
956             [EditorBrowsable(EditorBrowsableState.Never)]
957             public void NotifyDataSetChanged()
958             {
959             }
960
961             /// <summary>
962             /// Notify any registered observers that the data set has changed.
963             /// It indicates that any reflection of the data at position is out of date and should be updated.
964             /// </summary>
965             /// <param name="position">Position of the item that has changed</param>
966             /// <since_tizen> 6 </since_tizen>
967             /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
968             [EditorBrowsable(EditorBrowsableState.Never)]
969             public void NotifyItemChanged(int position)
970             {
971                 ItemEventArgs args = new ItemEventArgs
972                 {
973                     EventType = ItemEventType.Change,
974                 };
975                 args.param[0] = position;
976                 args.param[1] = 1;
977                 OnItemEvent(this, args);
978             }
979
980             /// <summary>
981             /// Notify any registered observers that the itemCount items starting at position positionStart have changed.
982             /// An optional payload can be passed to each changed item.
983             /// </summary>
984             /// <param name="positionStart">Position of the first item that has changed</param>
985             /// <param name="itemCount">Number of items that have changed</param>
986             /// <since_tizen> 6 </since_tizen>
987             /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
988             [EditorBrowsable(EditorBrowsableState.Never)]
989             public void NotifyItemRangeChanged(int positionStart, int itemCount)
990             {
991             }
992
993             /// <summary>
994             /// Notify any registered observers that the data set has been newly inserted.
995             /// It indicates that any reflection of the data at position is out of date and should be updated.
996             /// </summary>
997             /// <param name="position">Position of the item that has been newly inserted</param>
998             /// <since_tizen> 6 </since_tizen>
999             /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
1000             [EditorBrowsable(EditorBrowsableState.Never)]
1001             public void NotifyItemInserted(int position)
1002             {
1003                 NotifyItemRangeInserted(position, 1);
1004             }
1005
1006             /// <summary>
1007             /// Notify any registered observers that the itemCount items starting at position positionStart have been newly inserted.
1008             /// </summary>
1009             /// <param name="positionStart">Position of the first item that was inserted</param>
1010             /// <param name="itemCount">Number of items inserted</param>
1011             /// <since_tizen> 6 </since_tizen>
1012             /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
1013             [EditorBrowsable(EditorBrowsableState.Never)]
1014             public void NotifyItemRangeInserted(int positionStart, int itemCount)
1015             {
1016                 ItemEventArgs args = new ItemEventArgs
1017                 {
1018                     EventType = ItemEventType.Insert,
1019                 };
1020                 args.param[0] = positionStart;
1021                 args.param[1] = itemCount;
1022                 OnItemEvent(this, args);
1023             }
1024
1025             /// <summary>
1026             /// Notify any registered observers that the item previously located at position has been removed from the data set. 
1027             /// </summary>
1028             /// <param name="position">Previous position of the first item that was removed</param>
1029             /// <since_tizen> 6 </since_tizen>
1030             /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
1031             [EditorBrowsable(EditorBrowsableState.Never)]
1032             public void NotifyItemRemoved(int position)
1033             {
1034                 NotifyItemRangeRemoved(position, 1);
1035             }
1036
1037             /// <summary>
1038             /// Notify any registered observers that the itemCount items previously located at positionStart have been removed from the data set.
1039             /// </summary>
1040             /// <param name="positionStart">Previous position of the first item that was removed</param>
1041             /// <param name="itemCount">Number of items removed from the data set </param>
1042             /// <since_tizen> 6 </since_tizen>
1043             /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
1044             [EditorBrowsable(EditorBrowsableState.Never)]
1045             public void NotifyItemRangeRemoved(int positionStart, int itemCount)
1046             {
1047                 ItemEventArgs args = new ItemEventArgs
1048                 {
1049                     EventType = ItemEventType.Remove,
1050                 };
1051                 args.param[0] = positionStart;
1052                 args.param[1] = itemCount;
1053                 OnItemEvent(this, args);
1054             }
1055
1056             /// <summary>
1057             /// Notify any registered observers that the item reflected at fromPosition has been moved to toPosition.
1058             /// </summary>
1059             /// <param name="fromPosition">Previous position of the item</param>
1060             /// <param name="toPosition">New position of the item. </param>
1061             /// <since_tizen> 6 </since_tizen>
1062             /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
1063             [EditorBrowsable(EditorBrowsableState.Never)]
1064             public void NotifyItemMoved(int fromPosition, int toPosition)
1065             {
1066                
1067             }
1068
1069             private void OnItemEvent(object sender, ItemEventArgs e)
1070             {
1071                 itemEventHandlers?.Invoke(sender, e);
1072             }
1073
1074             internal class ItemEventArgs : EventArgs
1075             {
1076
1077                 /// <summary>
1078                 /// Data change event parameters.
1079                 /// </summary>
1080                 public int[] param = new int[4];
1081
1082                 /// <summary>
1083                 /// Data changed event type.
1084                 /// </summary>
1085                 public ItemEventType EventType
1086                 {
1087                     get;
1088                     set;
1089                 }
1090             }
1091         }
1092
1093         /// <summary>
1094         /// A LayoutManager is responsible for measuring and positioning item views within a FlexibleView
1095         /// as well as determining the policy for when to recycle item views that are no longer visible to the user.
1096         /// </summary>
1097         /// <since_tizen> 6 </since_tizen>
1098         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
1099         [EditorBrowsable(EditorBrowsableState.Never)]
1100         public abstract class LayoutManager
1101         {
1102             /// <summary>
1103             /// Direction
1104             /// </summary>
1105             public enum Direction
1106             {
1107                 /// <summary>
1108                 /// Left
1109                 /// </summary>
1110                 Left,
1111
1112                 /// <summary>
1113                 /// Right
1114                 /// </summary>
1115                 Right,
1116
1117                 /// <summary>
1118                 /// Up
1119                 /// </summary>
1120                 Up,
1121
1122                 /// <summary>
1123                 /// Down
1124                 /// </summary>
1125                 Down
1126             }
1127
1128             private FlexibleView mFlexibleView;
1129             private ChildHelper mChildHelper;
1130
1131             private List<ViewHolder> mPendingRecycleViews = new List<ViewHolder>();
1132
1133             private Animation mScrollAni;
1134
1135             /// <summary>
1136             /// Layout all relevant child views from the given adapter.
1137             /// </summary>
1138             /// <param name="recycler">Recycler to use for fetching potentially cached views for a position</param>
1139             /// <since_tizen> 6 </since_tizen>
1140             /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
1141             [EditorBrowsable(EditorBrowsableState.Never)]
1142             public abstract void OnLayoutChildren(Recycler recycler);
1143
1144             /// <summary>
1145             /// Called after a full layout calculation is finished.
1146             /// </summary>
1147             /// <since_tizen> 6 </since_tizen>
1148             /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
1149             [EditorBrowsable(EditorBrowsableState.Never)]
1150             public virtual void OnLayoutCompleted()
1151             {
1152             }
1153
1154
1155             /// <summary>
1156             /// Gets the current focus position in adapter.
1157             /// </summary>
1158             /// <since_tizen> 6 </since_tizen>
1159             /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
1160             [EditorBrowsable(EditorBrowsableState.Never)]
1161             public int FocusPosition
1162             {
1163                 get
1164                 {
1165                     return mFlexibleView.mFocusedItemIndex;
1166                 }
1167             }
1168
1169             /// <summary>
1170             /// Gets the datas count in data sets.
1171             /// </summary>
1172             /// <since_tizen> 6 </since_tizen>
1173             /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
1174             [EditorBrowsable(EditorBrowsableState.Never)]
1175             public int ItemCount
1176             {
1177                 get
1178                 {
1179                     Adapter b = mFlexibleView != null ? mFlexibleView.mAdapter : null;
1180
1181                     return b != null ? b.GetItemCount() : 0;
1182                 }
1183             }
1184
1185             /// <summary>
1186             /// Query if horizontal scrolling is currently supported. The default implementation returns false.
1187             /// </summary>
1188             /// <since_tizen> 6 </since_tizen>
1189             /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
1190             [EditorBrowsable(EditorBrowsableState.Never)]
1191             public virtual bool CanScrollHorizontally()
1192             {
1193                 return false;
1194             }
1195
1196             /// <summary>
1197             /// Query if vertical scrolling is currently supported. The default implementation returns false.
1198             /// </summary>
1199             /// <since_tizen> 6 </since_tizen>
1200             /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
1201             [EditorBrowsable(EditorBrowsableState.Never)]
1202             public virtual bool CanScrollVertically()
1203             {
1204                 return false;
1205             }
1206
1207             /// <summary>
1208             /// Scroll horizontally by dy pixels in screen coordinates.
1209             /// </summary>
1210             /// <param name="dy">distance to scroll in pixels. Y increases as scroll position approaches the top.</param>
1211             /// <param name="recycler">Recycler to use for fetching potentially cached views for a position</param>
1212             /// <param name="immediate">Specify if the scroll need animation</param>
1213             /// <since_tizen> 6 </since_tizen>
1214             /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
1215             [EditorBrowsable(EditorBrowsableState.Never)]
1216             public virtual float ScrollHorizontallyBy(float dy, Recycler recycler, bool immediate)
1217             {
1218                 return 0;
1219             }
1220
1221             /// <summary>
1222             /// Scroll vertically by dy pixels in screen coordinates.
1223             /// </summary>
1224             /// <param name="dy">distance to scroll in pixels. Y increases as scroll position approaches the top.</param>
1225             /// <param name="recycler">Recycler to use for fetching potentially cached views for a position</param>
1226             /// <param name="immediate">Specify if the scroll need animation</param>
1227             /// <since_tizen> 6 </since_tizen>
1228             /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
1229             [EditorBrowsable(EditorBrowsableState.Never)]
1230             public virtual float ScrollVerticallyBy(float dy, Recycler recycler, bool immediate)
1231             {
1232                 return 0;
1233             }
1234
1235             /// <summary>
1236             /// Compute the extent of the scrollbar's thumb within the range.
1237             /// </summary>
1238             /// <since_tizen> 6 </since_tizen>
1239             /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
1240             [EditorBrowsable(EditorBrowsableState.Never)]
1241             public virtual float ComputeScrollExtent()
1242             {
1243                 return 0;
1244             }
1245
1246             /// <summary>
1247             /// Compute the offset of the scrollbar's thumb within the range.
1248             /// </summary>
1249             /// <since_tizen> 6 </since_tizen>
1250             /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
1251             [EditorBrowsable(EditorBrowsableState.Never)]
1252             public virtual float ComputeScrollOffset()
1253             {
1254                 return 0;
1255             }
1256
1257             /// <summary>
1258             /// Compute the range that the scrollbar represents.
1259             /// </summary>
1260             /// <since_tizen> 6 </since_tizen>
1261             /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
1262             [EditorBrowsable(EditorBrowsableState.Never)]
1263             public virtual float ComputeScrollRange()
1264             {
1265                 return 0;
1266             }
1267
1268             /// <summary>
1269             /// Scroll the FlexibleView to make the position visible.
1270             /// </summary>
1271             /// <param name="position">Scroll to this adapter position</param>
1272             /// <since_tizen> 6 </since_tizen>
1273             /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
1274             [EditorBrowsable(EditorBrowsableState.Never)]
1275             public virtual void ScrollToPosition(int position)
1276             {
1277
1278             }
1279
1280             /// <summary>
1281             /// Scroll to the specified adapter position with the given offset from resolved layout start.
1282             /// </summary>
1283             /// <param name="position">Scroll to this adapter position</param>
1284             /// <param name="offset">The distance (in pixels) between the start edge of the item view and start edge of the FlexibleView.</param>
1285             /// <since_tizen> 6 </since_tizen>
1286             /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
1287             [EditorBrowsable(EditorBrowsableState.Never)]
1288             public virtual void ScrollToPositionWithOffset(int position, int offset)
1289             {
1290
1291             }
1292
1293             internal void MoveFocus(FlexibleView.LayoutManager.Direction direction, Recycler recycler)
1294             {
1295                 int prevFocusPosition = FocusPosition;
1296                 int nextFocusPosition = GetNextPosition(FocusPosition, direction);
1297                 if (nextFocusPosition == NO_POSITION)
1298                 {
1299                     return;
1300                 }
1301
1302                 FlexibleView.ViewHolder nextFocusChild = FindItemViewByPosition(nextFocusPosition);
1303                 if (nextFocusChild == null)
1304                 {
1305                     nextFocusChild = OnFocusSearchFailed(null, direction, recycler);
1306                 }
1307
1308                 if (nextFocusChild != null)
1309                 {
1310                     RequestChildRectangleOnScreen(mFlexibleView, nextFocusChild, recycler, false);
1311
1312                     ChangeFocus(nextFocusPosition);
1313                 }
1314             }
1315
1316             /**
1317              * Requests that the given child of the RecyclerView be positioned onto the screen. This
1318              * method can be called for both unfocusable and focusable child views. For unfocusable
1319              * child views, focusedChildVisible is typically true in which case, layout manager
1320              * makes the child view visible only if the currently focused child stays in-bounds of RV.
1321              * @param parent The parent RecyclerView.
1322              * @param child The direct child making the request.
1323              * @param rect The rectangle in the child's coordinates the child
1324              *              wishes to be on the screen.
1325              * @param immediate True to forbid animated or delayed scrolling,
1326              *                  false otherwise
1327              * @param focusedChildVisible Whether the currently focused view must stay visible.
1328              * @return Whether the group scrolled to handle the operation
1329              */
1330             internal bool RequestChildRectangleOnScreen(FlexibleView parent, FlexibleView.ViewHolder child, Recycler recycler, bool immediate)
1331             {
1332                 Vector2 scrollAmount = GetChildRectangleOnScreenScrollAmount(parent, child);
1333                 float dx = scrollAmount[0];
1334                 float dy = scrollAmount[1];
1335                 if (dx != 0 || dy != 0)
1336                 {
1337                     if (dx != 0 && CanScrollHorizontally())
1338                     {
1339                         ScrollHorizontallyBy(dx, recycler, immediate);
1340                     }
1341                     else if (dy != 0 && CanScrollVertically())
1342                     {
1343                         ScrollVerticallyBy(dy, recycler, immediate);
1344                     }
1345                     return true;
1346                 }
1347                 return false;
1348             }
1349
1350             /// <summary>
1351             /// Calls {@code FlexibleView#RelayoutRequest} on the underlying FlexibleView.
1352             /// </summary>
1353             /// <since_tizen> 6 </since_tizen>
1354             /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
1355             [EditorBrowsable(EditorBrowsableState.Never)]
1356             public void RelayoutRequest()
1357             {
1358                 if (mFlexibleView != null)
1359                 {
1360                     mFlexibleView.RelayoutRequest();
1361                 }
1362             }
1363
1364             /// <summary>
1365             /// Lay out the given child view within the FlexibleView using coordinates that include view margins.
1366             /// </summary>
1367             /// <param name="child">Child to lay out</param>
1368             /// <param name="left">Left edge, with item view left margin included</param>
1369             /// <param name="top">Top edge, with item view top margin included</param>
1370             /// <param name="width">Width, with item view left and right margin included</param>
1371             /// <param name="height">Height, with item view top and bottom margin included</param>
1372             /// <since_tizen> 6 </since_tizen>
1373             /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
1374             [EditorBrowsable(EditorBrowsableState.Never)]
1375             public void LayoutChild(ViewHolder child, float left, float top, float width, float height)
1376             {
1377                 View itemView = child.ItemView;
1378                 itemView.SizeWidth = width - itemView.Margin.Start - itemView.Margin.End;
1379                 itemView.SizeHeight = height - itemView.Margin.Top - itemView.Margin.Bottom;
1380                 itemView.PositionX = left + itemView.Margin.Start;
1381                 itemView.PositionY = top + itemView.Margin.Top;
1382             }
1383
1384             /// <summary>
1385             /// Change the ViewHolder with focusPosition to focus.
1386             /// </summary>
1387             /// <param name="focusPosition">the newly focus position</param>
1388             /// <since_tizen> 6 </since_tizen>
1389             /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
1390             [EditorBrowsable(EditorBrowsableState.Never)]
1391             public void ChangeFocus(int focusPosition)
1392             {
1393                 if (mFlexibleView != null)
1394                 {
1395                     mFlexibleView.DispatchFocusChanged(focusPosition);
1396                 }
1397             }
1398
1399             /// <summary>
1400             /// Return the current number of child views attached to the parent FlexibleView.
1401             /// </summary>
1402             /// <since_tizen> 6 </since_tizen>
1403             /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
1404             [EditorBrowsable(EditorBrowsableState.Never)]
1405             public int GetChildCount()
1406             {
1407                 return mChildHelper != null ? mChildHelper.GetChildCount() : 0;
1408             }
1409
1410             /// <summary>
1411             /// Return the child view at the given index.
1412             /// </summary>
1413             /// <param name="index">child index</param>
1414             /// <since_tizen> 6 </since_tizen>
1415             /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
1416             [EditorBrowsable(EditorBrowsableState.Never)]
1417             public ViewHolder GetChildAt(int index)
1418             {
1419                 return mChildHelper != null ? mChildHelper.GetChildAt(index) : null;
1420             }
1421
1422             /// <summary>
1423             /// Finds the view which represents the given adapter position.
1424             /// </summary>
1425             /// <param name="position">adapter position</param>
1426             /// <since_tizen> 6 </since_tizen>
1427             /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
1428             [EditorBrowsable(EditorBrowsableState.Never)]
1429             public ViewHolder FindItemViewByPosition(int position)
1430             {
1431                 return mFlexibleView.FindViewHolderForLayoutPosition(position);
1432             }
1433
1434             /// <summary>
1435             /// Offset all child views attached to the parent FlexibleView by dx pixels along the horizontal axis.
1436             /// </summary>
1437             /// <param name="dx">Pixels to offset by </param>
1438             /// <param name="immediate">specify if the offset need animation</param>
1439             /// <since_tizen> 6 </since_tizen>
1440             /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
1441             [EditorBrowsable(EditorBrowsableState.Never)]
1442             public void OffsetChildrenHorizontal(float dx, bool immediate)
1443             {
1444                 if (mChildHelper == null)
1445                 {
1446                     return;
1447                 }
1448
1449                 if (mScrollAni == null)
1450                 {
1451                     mScrollAni = new Animation();
1452                     mScrollAni.Finished += OnScrollAnimationFinished;
1453                 }
1454                 else if (mScrollAni.State == Animation.States.Playing)
1455                 {
1456                     //StopScroll();
1457                     mScrollAni.Stop(Animation.EndActions.StopFinal);
1458                 }
1459                 mScrollAni.Duration = 500;
1460                 mScrollAni.DefaultAlphaFunction = new AlphaFunction(AlphaFunction.BuiltinFunctions.EaseOutSquare);
1461
1462                 mScrollAni.Clear();
1463
1464                 int childCount = mChildHelper.GetChildCount();
1465                 if (immediate == true)
1466                 {
1467                     for (int i = childCount - 1; i >= 0; i--)
1468                     {
1469                         ViewHolder v = mChildHelper.GetChildAt(i);
1470                         v.ItemView.PositionX += dx;
1471                     }
1472                 }
1473                 else
1474                 {
1475                     for (int i = childCount - 1; i >= 0; i--)
1476                     {
1477                         ViewHolder v = mChildHelper.GetChildAt(i);
1478                         mScrollAni.AnimateTo(v.ItemView, "PositionX", v.ItemView.PositionX + dx);
1479                     }
1480                     mScrollAni.Play();
1481                 }
1482             }
1483
1484             /// <summary>
1485             /// Offset all child views attached to the parent FlexibleView by dy pixels along the vertical axis.
1486             /// </summary>
1487             /// <param name="dy">Pixels to offset by </param>
1488             /// <param name="immediate">specify if the offset need animation</param>
1489             /// <since_tizen> 6 </since_tizen>
1490             /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
1491             [EditorBrowsable(EditorBrowsableState.Never)]
1492             public void OffsetChildrenVertical(float dy, bool immediate)
1493             {
1494                 if (mChildHelper == null)
1495                 {
1496                     return;
1497                 }
1498
1499                 if (mScrollAni == null)
1500                 {
1501                     mScrollAni = new Animation();
1502                     mScrollAni.Finished += OnScrollAnimationFinished;
1503                 }
1504                 else if (mScrollAni.State == Animation.States.Playing)
1505                 {
1506                     //StopScroll();
1507                     mScrollAni.Stop(Animation.EndActions.StopFinal);
1508                 }
1509                 mScrollAni.Duration = 500;
1510                 mScrollAni.DefaultAlphaFunction = new AlphaFunction(AlphaFunction.BuiltinFunctions.EaseOutSquare);
1511
1512                 mScrollAni.Clear();
1513
1514                 int childCount = mChildHelper.GetChildCount();
1515                 if (immediate == true)
1516                 {
1517                     for (int i = childCount - 1; i >= 0; i--)
1518                     {
1519                         ViewHolder v = mChildHelper.GetChildAt(i);
1520                         v.ItemView.PositionY += dy;
1521                     }
1522                 }
1523                 else
1524                 {
1525                     for (int i = childCount - 1; i >= 0; i--)
1526                     {
1527                         ViewHolder v = mChildHelper.GetChildAt(i);
1528                         mScrollAni.AnimateTo(v.ItemView, "PositionY", v.ItemView.PositionY + dy);
1529                     }
1530                     mScrollAni.Play();
1531                 }
1532             }
1533
1534             /// <summary>
1535             /// Return the width of the parent FlexibleView.
1536             /// </summary>
1537             /// <since_tizen> 6 </since_tizen>
1538             /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
1539             [EditorBrowsable(EditorBrowsableState.Never)]
1540             public float GetWidth()
1541             {
1542                 return mFlexibleView != null ? mFlexibleView.SizeWidth : 0;
1543             }
1544
1545             /// <summary>
1546             /// Return the height of the parent FlexibleView.
1547             /// </summary>
1548             /// <since_tizen> 6 </since_tizen>
1549             /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
1550             [EditorBrowsable(EditorBrowsableState.Never)]
1551             public float GetHeight()
1552             {
1553                 return mFlexibleView != null ? mFlexibleView.SizeHeight : 0;
1554             }
1555
1556             /// <summary>
1557             /// Return the left padding of the parent FlexibleView.
1558             /// </summary>
1559             /// <since_tizen> 6 </since_tizen>
1560             /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
1561             [EditorBrowsable(EditorBrowsableState.Never)]
1562             public int GetPaddingLeft()
1563             {
1564                 return mFlexibleView != null ? mFlexibleView.Padding.Start : 0;
1565             }
1566
1567             /// <summary>
1568             /// Return the top padding of the parent FlexibleView.
1569             /// </summary>
1570             /// <since_tizen> 6 </since_tizen>
1571             /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
1572             [EditorBrowsable(EditorBrowsableState.Never)]
1573             public int GetPaddingTop()
1574             {
1575                 return mFlexibleView != null ? mFlexibleView.Padding.Top : 0;
1576             }
1577
1578             /// <summary>
1579             /// Return the right padding of the parent FlexibleView.
1580             /// </summary>
1581             /// <since_tizen> 6 </since_tizen>
1582             /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
1583             [EditorBrowsable(EditorBrowsableState.Never)]
1584             public int GetPaddingRight()
1585             {
1586                 return mFlexibleView != null ? mFlexibleView.Padding.End : 0;
1587             }
1588
1589             /// <summary>
1590             /// Return the bottom padding of the parent FlexibleView.
1591             /// </summary>
1592             /// <since_tizen> 6 </since_tizen>
1593             /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
1594             [EditorBrowsable(EditorBrowsableState.Never)]
1595             public int GetPaddingBottom()
1596             {
1597                 return mFlexibleView != null ? mFlexibleView.Padding.Bottom : 0;
1598             }
1599
1600             /// <summary>
1601             /// Add a view to the currently attached FlexibleView if needed.<br />
1602             /// LayoutManagers should use this method to add views obtained from a FlexibleView.Recycler using getViewForPosition(int).<br />
1603             /// </summary>
1604             /// <param name="holder">view to add</param>
1605             /// <since_tizen> 6 </since_tizen>
1606             /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
1607             [EditorBrowsable(EditorBrowsableState.Never)]
1608             public void AddView(ViewHolder holder)
1609             {
1610                 AddView(holder, -1);
1611             }
1612
1613             /// <summary>
1614             /// Add a view to the currently attached FlexibleView if needed.<br />
1615             /// LayoutManagers should use this method to add views obtained from a FlexibleView.Recycler using getViewForPosition(int).<br />
1616             /// </summary>
1617             /// <param name="holder">view to add</param>
1618             /// <param name="index">index to add child at</param>
1619             /// <since_tizen> 6 </since_tizen>
1620             /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
1621             [EditorBrowsable(EditorBrowsableState.Never)]
1622             public void AddView(ViewHolder holder, int index)
1623             {
1624                 AddViewInternal(holder, index, false);
1625             }
1626
1627             /// <summary>
1628             /// Temporarily detach and scrap all currently attached child views.
1629             /// Views will be scrapped into the given Recycler.
1630             /// The Recycler may prefer to reuse scrap views before other views that were previously recycled.
1631             /// </summary>
1632             /// <param name="recycler">Recycler to scrap views into</param>
1633             /// <since_tizen> 6 </since_tizen>
1634             /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
1635             [EditorBrowsable(EditorBrowsableState.Never)]
1636             public void ScrapAttachedViews(Recycler recycler)
1637             {
1638                 if (mChildHelper == null)
1639                 {
1640                     return;
1641                 }
1642
1643                 recycler.Clear();
1644
1645                 mChildHelper.ScrapViews(recycler);
1646             }
1647
1648             /**
1649              * Remove a child view and recycle it using the given Recycler.
1650              *
1651              * @param index Index of child to remove and recycle
1652              * @param recycler Recycler to use to recycle child
1653              */
1654             /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
1655             [EditorBrowsable(EditorBrowsableState.Never)]
1656             public void RemoveAndRecycleViewAt(int index, Recycler recycler)
1657             {
1658                 ViewHolder v = mChildHelper.GetChildAt(index);
1659                 mChildHelper.RemoveViewAt(index);
1660                 recycler.RecycleView(v);
1661             }
1662
1663             /// <summary>
1664             /// ecycles children between given indices..
1665             /// </summary>
1666             /// <param name="recycler">Recycler to recycle views into</param>
1667             /// <param name="startIndex">inclusive</param>
1668             /// <param name="endIndex">exclusive</param>
1669             /// <param name="immediate">recycle immediately or add to pending list and recycle later.</param>
1670             /// <since_tizen> 6 </since_tizen>
1671             /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
1672             [EditorBrowsable(EditorBrowsableState.Never)]
1673             public void RecycleChildren(FlexibleView.Recycler recycler, int startIndex, int endIndex, bool immediate)
1674             {
1675                 if (startIndex == endIndex)
1676                 {
1677                     return;
1678                 }
1679                 if (endIndex > startIndex)
1680                 {
1681                     for (int i = startIndex; i < endIndex; i++)
1682                     {
1683                         ViewHolder v = mChildHelper.GetChildAt(i);
1684                         if (v.PendingRecycle == false)
1685                         {
1686                             v.PendingRecycle = true;
1687                             mPendingRecycleViews.Add(v);
1688                         }
1689                     }
1690                 }
1691                 else
1692                 {
1693                     for (int i = startIndex; i > endIndex; i--)
1694                     {
1695                         ViewHolder v = mChildHelper.GetChildAt(i);
1696                         if (v.PendingRecycle == false)
1697                         {
1698                             v.PendingRecycle = true;
1699                             mPendingRecycleViews.Add(v);
1700                         }
1701                     }
1702                 }
1703                 if (immediate == true)
1704                 {
1705                     RecycleChildrenInt(recycler);
1706                 }
1707             }
1708
1709             /// <summary>
1710             /// Retrieves a position that neighbor to current position by direction.
1711             /// </summary>
1712             /// <param name="position">The anchor adapter position</param>
1713             /// <param name="direction">The direction.</param>
1714             /// <since_tizen> 6 </since_tizen>
1715             /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
1716             [EditorBrowsable(EditorBrowsableState.Never)]
1717             protected abstract int GetNextPosition(int position, FlexibleView.LayoutManager.Direction direction);
1718
1719             internal virtual ViewHolder OnFocusSearchFailed(FlexibleView.ViewHolder focused, LayoutManager.Direction direction, Recycler recycler)
1720             {
1721                 return null;
1722             }
1723
1724             internal void SetRecyclerView(FlexibleView recyclerView)
1725             {
1726                 mFlexibleView = recyclerView;
1727                 mChildHelper = recyclerView.mChildHelper;
1728             }
1729
1730             internal void StopScroll()
1731             {
1732                 if (mScrollAni != null && mScrollAni.State == Animation.States.Playing)
1733                 {
1734                     mScrollAni.Stop(Animation.EndActions.StopFinal);
1735                     mScrollAni.Clear();
1736                     OnScrollAnimationFinished(mScrollAni, null);
1737                 }
1738             }
1739
1740             /**
1741              * Returns the scroll amount that brings the given rect in child's coordinate system within
1742              * the padded area of RecyclerView.
1743              * @param parent The parent RecyclerView.
1744              * @param child The direct child making the request.
1745              * @param rect The rectangle in the child's coordinates the child
1746              *             wishes to be on the screen.
1747              * @param immediate True to forbid animated or delayed scrolling,
1748              *                  false otherwise
1749              * @return The array containing the scroll amount in x and y directions that brings the
1750              * given rect into RV's padded area.
1751              */
1752             private Vector2 GetChildRectangleOnScreenScrollAmount(FlexibleView parent, FlexibleView.ViewHolder child)
1753             {
1754                 Vector2 ret = new Vector2(0, 0);
1755                 int parentLeft = GetPaddingLeft();
1756                 int parentTop = GetPaddingTop();
1757                 int parentRight = (int)GetWidth() - GetPaddingRight();
1758                 int parentBottom = (int)GetHeight() - GetPaddingBottom();
1759                 int childLeft = (int)child.Left;
1760                 int childTop = (int)child.Top;
1761                 int childRight = (int)child.Right;
1762                 int childBottom = (int)child.Bottom;
1763
1764                 int offScreenLeft = Math.Min(0, childLeft - parentLeft);
1765                 int offScreenTop = Math.Min(0, childTop - parentTop);
1766                 int offScreenRight = Math.Max(0, childRight - parentRight);
1767                 int offScreenBottom = Math.Max(0, childBottom - parentBottom);
1768
1769                 // Favor the "start" layout direction over the end when bringing one side or the other
1770                 // of a large rect into view. If we decide to bring in end because start is already
1771                 // visible, limit the scroll such that start won't go out of bounds.
1772                 int dx= offScreenLeft != 0 ? offScreenLeft
1773                             : Math.Min(childLeft - parentLeft, offScreenRight);
1774
1775                 // Favor bringing the top into view over the bottom. If top is already visible and
1776                 // we should scroll to make bottom visible, make sure top does not go out of bounds.
1777                 int dy = offScreenTop != 0 ? offScreenTop
1778                         : Math.Min(childTop - parentTop, offScreenBottom);
1779
1780                 ret.X = -dx;
1781                 ret.Y = -dy;
1782
1783                 return ret;
1784             }
1785
1786             private void OnScrollAnimationFinished(object sender, EventArgs e)
1787             {
1788                 RecycleChildrenInt(mFlexibleView.mRecycler);
1789             }
1790
1791             private void AddViewInternal(ViewHolder holder, int index, bool disappearing)
1792             {
1793                 if (holder.IsScrap())
1794                 {
1795                     holder.Unscrap();
1796                     mChildHelper.AttachView(holder, index);
1797                 }
1798                 else
1799                 {
1800                     mChildHelper.AddView(holder, index);
1801                 }
1802             }
1803
1804             private void RecycleChildrenInt(FlexibleView.Recycler recycler)
1805             {
1806                 foreach(ViewHolder holder in mPendingRecycleViews)
1807                 {
1808                     holder.PendingRecycle = false;
1809                     recycler.RecycleView(holder);
1810                     mChildHelper.RemoveView(holder);
1811                 }
1812                 mPendingRecycleViews.Clear();
1813             }
1814
1815             private void ScrapOrRecycleView(Recycler recycler, ViewHolder itemView)
1816             {
1817                 recycler.ScrapView(itemView);
1818             }
1819
1820         }
1821
1822         /// <summary>
1823         /// A ViewHolder describes an item view and metadata about its place within the FlexibleView.
1824         /// </summary>
1825         /// <since_tizen> 6 </since_tizen>
1826         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
1827         [EditorBrowsable(EditorBrowsableState.Never)]
1828         public class ViewHolder
1829         {
1830             /**
1831              * This ViewHolder has been bound to a position; AdapterPosition, mItemId and mItemViewType
1832              * are all valid.
1833              */
1834             //static readonly int FLAG_BOUND = 1 << 0;
1835
1836             /**
1837              * The data this ViewHolder's view reflects is stale and needs to be rebound
1838              * by the adapter. AdapterPosition and mItemId are consistent.
1839              */
1840             //static readonly int FLAG_UPDATE = 1 << 1;
1841
1842             /**
1843              * This ViewHolder's data is invalid. The identity implied by AdapterPosition and mItemId
1844              * are not to be trusted and may no longer match the item view type.
1845              * This ViewHolder must be fully rebound to different data.
1846              */
1847             //static readonly int FLAG_INVALID = 1 << 2;
1848
1849             /**
1850              * This ViewHolder points at data that represents an item previously removed from the
1851              * data set. Its view may still be used for things like outgoing animations.
1852              */
1853             //static readonly int FLAG_REMOVED = 1 << 3;
1854
1855             /**
1856              * This ViewHolder should not be recycled. This flag is set via setIsRecyclable()
1857              * and is intended to keep views around during animations.
1858              */
1859             //static readonly int FLAG_NOT_RECYCLABLE = 1 << 4;
1860
1861             /**
1862              * This ViewHolder is returned from scrap which means we are expecting an addView call
1863              * for this itemView. When returned from scrap, ViewHolder stays in the scrap list until
1864              * the end of the layout pass and then recycled by RecyclerView if it is not added back to
1865              * the RecyclerView.
1866              */
1867             //static readonly int FLAG_RETURNED_FROM_SCRAP = 1 << 5;
1868
1869             /**
1870              * This ViewHolder is fully managed by the LayoutManager. We do not scrap, recycle or remove
1871              * it unless LayoutManager is replaced.
1872              * It is still fully visible to the LayoutManager.
1873              */
1874             //static readonly int FLAG_IGNORE = 1 << 7;
1875
1876             private int mFlags;
1877             private int mPreLayoutPosition = NO_POSITION;
1878
1879             /// <summary>
1880             /// ViewHolder constructor.
1881             /// </summary>
1882             /// <param name="itemView">View</param>
1883             /// <since_tizen> 6 </since_tizen>
1884             /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
1885             [EditorBrowsable(EditorBrowsableState.Never)]
1886             public ViewHolder(View itemView)
1887             {
1888                 if (itemView == null)
1889                 {
1890                     throw new ArgumentNullException("itemView may not be null");
1891                 }
1892                 this.ItemView = itemView;
1893             }
1894
1895             /// <summary>
1896             /// Returns the view.
1897             /// </summary>
1898             /// <since_tizen> 6 </since_tizen>
1899             /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
1900             [EditorBrowsable(EditorBrowsableState.Never)]
1901             public View ItemView { get; }
1902
1903             /// <summary>
1904             /// Returns the left edge includes the view left margin.
1905             /// </summary>
1906             /// <since_tizen> 6 </since_tizen>
1907             /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
1908             [EditorBrowsable(EditorBrowsableState.Never)]
1909             public float Left
1910             {
1911                 get
1912                 {
1913                     return ItemView.PositionX - ItemView.Margin.Start;
1914                 }
1915             }
1916
1917             /// <summary>
1918             /// Returns the right edge includes the view right margin.
1919             /// </summary>
1920             /// <since_tizen> 6 </since_tizen>
1921             /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
1922             [EditorBrowsable(EditorBrowsableState.Never)]
1923             public float Right
1924             {
1925                 get
1926                 {
1927                     return ItemView.PositionX + ItemView.SizeWidth + ItemView.Margin.End;
1928                 }
1929             }
1930
1931             /// <summary>
1932             /// Returns the top edge includes the view top margin.
1933             /// </summary>
1934             /// <since_tizen> 6 </since_tizen>
1935             /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
1936             [EditorBrowsable(EditorBrowsableState.Never)]
1937             public float Top
1938             {
1939                 get
1940                 {
1941                     return ItemView.PositionY - ItemView.Margin.Top;
1942                 }
1943             }
1944
1945             /// <summary>
1946             /// Returns the bottom edge includes the view bottom margin.
1947             /// </summary>
1948             /// <since_tizen> 6 </since_tizen>
1949             /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
1950             [EditorBrowsable(EditorBrowsableState.Never)]
1951             public float Bottom
1952             {
1953                 get
1954                 {
1955                     return ItemView.PositionY + ItemView.SizeHeight + ItemView.Margin.Bottom;
1956                 }
1957             }
1958
1959             /// <summary>
1960             /// Returns the position of the ViewHolder in terms of the latest layout pass.
1961             /// </summary>
1962             /// <since_tizen> 6 </since_tizen>
1963             /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
1964             [EditorBrowsable(EditorBrowsableState.Never)]
1965             public int LayoutPosition
1966             {
1967                 get
1968                 {
1969                     return mPreLayoutPosition == NO_POSITION ? AdapterPosition : mPreLayoutPosition;
1970                 }
1971             }
1972
1973             /// <summary>
1974             /// Returns the Adapter position of the item represented by this ViewHolder.
1975             /// </summary>
1976             /// <since_tizen> 6 </since_tizen>
1977             /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
1978             [EditorBrowsable(EditorBrowsableState.Never)]
1979             public int AdapterPosition { get; internal set; } = NO_POSITION;
1980
1981             /// <summary>
1982             /// Get old position of item view.
1983             /// </summary>
1984             /// <since_tizen> 6 </since_tizen>
1985             /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
1986             [EditorBrowsable(EditorBrowsableState.Never)]
1987             public int OldPosition { get; private set; } = NO_POSITION;
1988
1989             /// <summary>
1990             /// Gets or sets item view type.
1991             /// </summary>
1992             /// <since_tizen> 6 </since_tizen>
1993             /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
1994             [EditorBrowsable(EditorBrowsableState.Never)]
1995             public int ItemViewType { get; set; } = INVALID_TYPE;
1996
1997             internal bool IsBound
1998             {
1999                 get;
2000                 set;
2001             }
2002
2003             internal Recycler ScrapContainer { get; set; }
2004
2005             internal bool PendingRecycle
2006             {
2007                 get;
2008                 set;
2009             } = false;
2010
2011
2012             internal bool IsScrap()
2013             {
2014                 return ScrapContainer != null;
2015             }
2016
2017             internal void Unscrap()
2018             {
2019                 ScrapContainer.UnscrapView(this);
2020             }
2021
2022
2023             internal void FlagRemovedAndOffsetPosition(int mNewPosition, int offset, bool applyToPreLayout)
2024             {
2025                 //AddFlags(ViewHolder.FLAG_REMOVED);
2026                 OffsetPosition(offset, applyToPreLayout);
2027                 AdapterPosition = mNewPosition;
2028             }
2029
2030             internal void OffsetPosition(int offset, bool applyToPreLayout)
2031             {
2032                 if (OldPosition == NO_POSITION)
2033                 {
2034                     OldPosition = AdapterPosition;
2035                 }
2036                 if (mPreLayoutPosition == NO_POSITION)
2037                 {
2038                     mPreLayoutPosition = AdapterPosition;
2039                 }
2040                 if (applyToPreLayout)
2041                 {
2042                     mPreLayoutPosition += offset;
2043                 }
2044                 AdapterPosition += offset;
2045             }
2046
2047             internal void ClearOldPosition()
2048             {
2049                 OldPosition = NO_POSITION;
2050                 mPreLayoutPosition = NO_POSITION;
2051             }
2052
2053             internal void SaveOldPosition()
2054             {
2055                 if (OldPosition == NO_POSITION)
2056                 {
2057                     OldPosition = AdapterPosition;
2058                 }
2059             }
2060
2061             private void SetFlags(int flags, int mask)
2062             {
2063                 mFlags = (mFlags & ~mask) | (flags & mask);
2064             }
2065
2066             private void AddFlags(int flags)
2067             {
2068                 mFlags |= flags;
2069             }
2070
2071         }
2072
2073         /// <summary>
2074         /// A Recycler is responsible for managing scrapped or detached item views for reuse.
2075         /// A "scrapped" view is a view that is still attached to its parent FlexibleView but that has been marked for removal or reuse.
2076         /// </summary>
2077         /// <since_tizen> 6 </since_tizen>
2078         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
2079         [EditorBrowsable(EditorBrowsableState.Never)]
2080         public class Recycler
2081         {
2082             private FlexibleView mFlexibleView;
2083             private RecycledViewPool mRecyclerPool;
2084
2085             private List<ViewHolder> mAttachedScrap = new List<ViewHolder>();
2086             private List<ViewHolder> mChangedScrap = null;
2087             //private List<ItemView> mCachedViews = new List<ItemView>();
2088
2089             //private List<ViewHolder> mUnmodifiableAttachedScrap;
2090
2091             private int mCacheSizeMax = 2;
2092
2093             /// <summary>
2094             /// Recycler constructor.
2095             /// </summary>
2096             /// <since_tizen> 6 </since_tizen>
2097             /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
2098             [EditorBrowsable(EditorBrowsableState.Never)]
2099             public Recycler(FlexibleView recyclerView)
2100             {
2101                 mFlexibleView = recyclerView;
2102             }
2103
2104             /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
2105             [EditorBrowsable(EditorBrowsableState.Never)]
2106             public void SetViewCacheSize(int viewCount)
2107             {
2108                 mCacheSizeMax = viewCount;
2109             }
2110
2111             /// <summary>
2112             /// Obtain a view initialized for the given position.
2113             /// </summary>
2114             /// <param name="position">Position to obtain a view for</param>
2115             /// <since_tizen> 6 </since_tizen>
2116             /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
2117             [EditorBrowsable(EditorBrowsableState.Never)]
2118             public ViewHolder GetViewForPosition(int position)
2119             {
2120                 Adapter b = mFlexibleView != null ? mFlexibleView.mAdapter : null;
2121                 if (b == null)
2122                 {
2123                     return null;
2124                 }
2125                 if (position < 0 || position >= b.GetItemCount())
2126                 {
2127                     return null;
2128                 }
2129
2130                 int type = b.GetItemViewType(position);
2131                 ViewHolder itemView = null;
2132                 for (int i = 0; i < mAttachedScrap.Count; i++)
2133                 {
2134                     if (mAttachedScrap[i].LayoutPosition == position && mAttachedScrap[i].ItemViewType == type)
2135                     {
2136                         itemView = mAttachedScrap[i];
2137                         break;
2138                     }
2139                 }
2140                 if (itemView == null)
2141                 {
2142                     itemView = mRecyclerPool.GetRecycledView(type);
2143                     if (itemView == null)
2144                     {
2145                         itemView = b.OnCreateViewHolder(type);
2146                     }
2147
2148                     if (!itemView.IsBound)
2149                     {
2150                         b.OnBindViewHolder(itemView, position);
2151                         itemView.IsBound = true;
2152                     }
2153
2154                     itemView.AdapterPosition = position;
2155                     itemView.ItemViewType = type;
2156                 }
2157
2158                 return itemView;
2159             }
2160
2161             /// <summary>
2162             /// Recycle a detached view.
2163             /// </summary>
2164             /// <param name="itemView">Removed holder for recycling</param>
2165             /// <since_tizen> 6 </since_tizen>
2166             /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
2167             [EditorBrowsable(EditorBrowsableState.Never)]
2168             public void RecycleView(ViewHolder itemView)
2169             {
2170                 itemView.ScrapContainer = null;
2171                 mRecyclerPool.PutRecycledView(itemView);
2172             }
2173
2174             /// <summary>
2175             /// Returns the count in scrap list.
2176             /// </summary>
2177             /// <since_tizen> 6 </since_tizen>
2178             /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
2179             [EditorBrowsable(EditorBrowsableState.Never)]
2180             public int GetScrapCount()
2181             {
2182                 return mAttachedScrap.Count;
2183             }
2184
2185             /// <summary>
2186             /// Gets the scrap view at index.
2187             /// </summary>
2188             /// <param name="index">index</param>
2189             /// <since_tizen> 6 </since_tizen>
2190             /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
2191             [EditorBrowsable(EditorBrowsableState.Never)]
2192             public ViewHolder GetScrapViewAt(int index)
2193             {
2194                 return mAttachedScrap[index];
2195             }
2196
2197             /// <summary>
2198             /// Clear scrap views out of this recycler. Detached views contained within a recycled view pool will remain.
2199             /// </summary>
2200             /// <since_tizen> 6 </since_tizen>
2201             /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
2202             [EditorBrowsable(EditorBrowsableState.Never)]
2203             public void Clear()
2204             {
2205                 mAttachedScrap.Clear();
2206                 if (mChangedScrap != null)
2207                 {
2208                     mChangedScrap.Clear();
2209                 }
2210             }
2211
2212             internal void ScrapView(ViewHolder itemView)
2213             {
2214                 mAttachedScrap.Add(itemView);
2215                 itemView.ScrapContainer = this;
2216             }
2217
2218             internal void UnscrapView(ViewHolder itemView)
2219             {
2220                 mAttachedScrap.Remove(itemView);
2221                 itemView.ScrapContainer = null;
2222             }
2223
2224             internal void SetRecycledViewPool(RecycledViewPool pool)
2225             {
2226                 mRecyclerPool = pool;
2227             }
2228         }
2229
2230         internal class RecycledViewPool
2231         {
2232             private FlexibleView mFlexibleView;
2233
2234             private int mMaxTypeCount = 10;
2235             private List<ViewHolder>[] mScrap;
2236
2237             public RecycledViewPool(FlexibleView flexibleView)
2238             {
2239                 mFlexibleView = flexibleView;
2240                 mScrap = new List<ViewHolder>[mMaxTypeCount];
2241             }
2242
2243             //public void SetViewTypeCount(int typeCount)
2244             //{
2245             //}
2246
2247             public ViewHolder GetRecycledView(int viewType)
2248             {
2249                 if (viewType >= mMaxTypeCount || mScrap[viewType] == null)
2250                 {
2251                     return null;
2252                 }
2253
2254                 int index = mScrap[viewType].Count - 1;
2255                 if (index < 0)
2256                 {
2257                     return null;
2258                 }
2259                 ViewHolder recycledView = mScrap[viewType][index];
2260                 mScrap[viewType].RemoveAt(index);
2261
2262                 return recycledView;
2263             }
2264
2265             public void PutRecycledView(ViewHolder view)
2266             {
2267                 int viewType = view.ItemViewType;
2268                 if (mScrap[viewType] == null)
2269                 {
2270                     mScrap[viewType] = new List<ViewHolder>();
2271                 }
2272                 view.IsBound = false;
2273                 mScrap[viewType].Add(view);
2274             }
2275
2276             public void Clear()
2277             {
2278                 for (int i = 0; i < mMaxTypeCount; i++)
2279                 {
2280                     if (mScrap[i] == null)
2281                     {
2282                         continue;
2283                     }
2284                     for (int j = 0; j < mScrap[i].Count; j++)
2285                     {
2286                         mFlexibleView.DispatchChildDestroyed(mScrap[i][j]);
2287                     }
2288                     mScrap[i].Clear();
2289                 }
2290             }
2291         }
2292
2293         private class ChildHelper
2294         {
2295             private FlexibleView mFlexibleView;
2296             
2297             private List<ViewHolder> mViewList = new List<ViewHolder>();
2298
2299             //private List<ViewHolder> mRemovePendingViews;
2300
2301             private Dictionary<uint, ViewHolder> itemViewTable = new Dictionary<uint, ViewHolder>();
2302             private TapGestureDetector mTapGestureDetector;
2303
2304             public ChildHelper(FlexibleView owner)
2305             {
2306                 mFlexibleView = owner;
2307
2308                 mTapGestureDetector = new TapGestureDetector();
2309                 mTapGestureDetector.Detected += OnTapGestureDetected;
2310             }
2311
2312             public void Clear()
2313             {
2314                 foreach(ViewHolder holder in mViewList)
2315                 {
2316                     mFlexibleView.Remove(holder.ItemView);
2317
2318                     mFlexibleView.DispatchChildDestroyed(holder);
2319                 }
2320                 mViewList.Clear();
2321             }
2322
2323             public void ScrapViews(Recycler recycler)
2324             {
2325                 recycler.Clear();
2326                 foreach (ViewHolder itemView in mViewList)
2327                 {
2328                     recycler.ScrapView(itemView);
2329                 }
2330
2331                 mViewList.Clear();
2332             }
2333
2334             public void AttachView(ViewHolder holder, int index)
2335             {
2336                 if (index == -1)
2337                 {
2338                     index = mViewList.Count;
2339                 }
2340                 mViewList.Insert(index, holder);
2341
2342                 if (!itemViewTable.ContainsKey(holder.ItemView.ID))
2343                 {
2344                     mTapGestureDetector.Attach(holder.ItemView);
2345                     holder.ItemView.TouchEvent += OnTouchEvent; 
2346                 }
2347
2348                 itemViewTable[holder.ItemView.ID] = holder;
2349             }
2350
2351             public void AddView(ViewHolder holder, int index)
2352             {
2353                 mFlexibleView.Add(holder.ItemView);
2354
2355                 mFlexibleView.DispatchChildAttached(holder);
2356
2357                 AttachView(holder, index);
2358             }
2359
2360             public bool RemoveView(ViewHolder holder)
2361             {
2362                 mFlexibleView.Remove(holder.ItemView);
2363
2364                 mFlexibleView.DispatchChildDetached(holder);
2365
2366                 return mViewList.Remove(holder);
2367             }
2368
2369             public bool RemoveViewAt(int index)
2370             {
2371                 ViewHolder itemView = mViewList[index];
2372                 return RemoveView(itemView);
2373             }
2374
2375             public bool RemoveViewsRange(int index, int count)
2376             {
2377                 for (int i = index; i < index + count; i++)
2378                 {
2379                     ViewHolder holder = mViewList[i];
2380                     mFlexibleView.Remove(holder.ItemView);
2381                 }
2382                 mViewList.RemoveRange(index, count);
2383                 return false;
2384             }
2385
2386             public int GetChildCount()
2387             {
2388                 return mViewList.Count;
2389             }
2390
2391             public ViewHolder GetChildAt(int index)
2392             {
2393                 if (index < 0 || index >= mViewList.Count)
2394                 {
2395                     return null;
2396                 }
2397                 return mViewList[index];
2398             }
2399
2400             private void OnTapGestureDetected(object source, TapGestureDetector.DetectedEventArgs e)
2401             {
2402                 View itemView = e.View as View;
2403                 if (itemView == null)
2404                 {
2405                     return;
2406                 }
2407                 if (itemViewTable.ContainsKey(itemView.ID))
2408                 {
2409                     ViewHolder holder = itemViewTable[itemView.ID];
2410                     mFlexibleView.FocusedItemIndex = holder.AdapterPosition;
2411
2412                     mFlexibleView.DispatchItemClicked(holder);
2413                 }
2414             }
2415
2416             private bool OnTouchEvent(object source, TouchEventArgs e)
2417             {
2418                 View itemView = source as View;
2419                 if (itemView != null && itemViewTable.ContainsKey(itemView.ID))
2420                 {
2421                     ViewHolder holder = itemViewTable[itemView.ID];
2422
2423                     mFlexibleView.DispatchItemTouched(holder, e.Touch);
2424                     return true;
2425                 }
2426                 return false;
2427             }
2428         }
2429
2430         private class AdapterHelper
2431         {
2432             private FlexibleView mFlexibleView;
2433
2434             private List<UpdateOp> mPendingUpdates = new List<UpdateOp>();
2435
2436             private int mExistingUpdateTypes = 0;
2437
2438             public AdapterHelper(FlexibleView flexibleView)
2439             {
2440                 mFlexibleView = flexibleView;
2441             }
2442
2443             /**
2444              * @return True if updates should be processed.
2445              */
2446             public bool OnItemRangeInserted(int positionStart, int itemCount)
2447             {
2448                 if (itemCount < 1)
2449                 {
2450                     return false;
2451                 }
2452                 mPendingUpdates.Add(new UpdateOp(UpdateOp.ADD, positionStart, itemCount));
2453                 mExistingUpdateTypes |= UpdateOp.ADD;
2454                 return mPendingUpdates.Count == 1;
2455             }
2456
2457             /**
2458              * @return True if updates should be processed.
2459              */
2460             public bool OnItemRangeRemoved(int positionStart, int itemCount)
2461             {
2462                 if (itemCount < 1)
2463                 {
2464                     return false;
2465                 }
2466                 mPendingUpdates.Add(new UpdateOp(UpdateOp.REMOVE, positionStart, itemCount));
2467                 mExistingUpdateTypes |= UpdateOp.REMOVE;
2468                 return mPendingUpdates.Count == 1;
2469             }
2470
2471             public void PreProcess()
2472             {
2473                 int count = mPendingUpdates.Count;
2474                 for (int i = 0; i < count; i++)
2475                 {
2476                     UpdateOp op = mPendingUpdates[i];
2477                     switch (op.cmd)
2478                     {
2479                         case UpdateOp.ADD:
2480                             mFlexibleView.OffsetPositionRecordsForInsert(op.positionStart, op.itemCount);
2481                             break;
2482                         case UpdateOp.REMOVE:
2483                             mFlexibleView.OffsetPositionRecordsForRemove(op.positionStart, op.itemCount, false);
2484                             break;
2485                         case UpdateOp.UPDATE:
2486                             break;
2487                         case UpdateOp.MOVE:
2488                             break;
2489                     }
2490                 }
2491                 mPendingUpdates.Clear();
2492             }
2493
2494         }
2495
2496         /**
2497          * Queued operation to happen when child views are updated.
2498          */
2499         private class UpdateOp
2500         {
2501
2502             public const int ADD = 1;
2503
2504             public const int REMOVE = 1 << 1;
2505
2506             public const int UPDATE = 1 << 2;
2507
2508             public const int MOVE = 1 << 3;
2509
2510             public const int POOL_SIZE = 30;
2511
2512             public int cmd;
2513
2514             public int positionStart;
2515
2516             // holds the target position if this is a MOVE
2517             public int itemCount;
2518
2519             public UpdateOp(int cmd, int positionStart, int itemCount)
2520             {
2521                 this.cmd = cmd;
2522                 this.positionStart = positionStart;
2523                 this.itemCount = itemCount;
2524             }
2525
2526             public bool Equals(UpdateOp op)
2527             {
2528                 if (cmd != op.cmd)
2529                 {
2530                     return false;
2531                 }
2532                 if (cmd == MOVE && Math.Abs(itemCount - positionStart) == 1)
2533                 {
2534                     // reverse of this is also true
2535                     if (itemCount == op.positionStart && positionStart == op.itemCount)
2536                     {
2537                         return true;
2538                     }
2539                 }
2540                 if (itemCount != op.itemCount)
2541                 {
2542                     return false;
2543                 }
2544                 if (positionStart != op.positionStart)
2545                 {
2546                     return false;
2547                 }
2548
2549                 return true;
2550             }
2551
2552         }
2553
2554         private class ItemViewInfo
2555         {
2556             public float Left
2557             {
2558                 get;
2559                 set;
2560             }
2561             public float Top
2562             {
2563                 get;
2564                 set;
2565             }
2566             public float Right
2567             {
2568                 get;
2569                 set;
2570             }
2571             public float Bottom
2572             {
2573                 get;
2574                 set;
2575             }
2576         }
2577
2578     }
2579 }