[NUI] TCSACR-226 code change (#1032)
[platform/core/csapi/tizenfx.git] / src / Tizen.NUI.Components / Controls / FlexibleView / GridLayoutManager.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.ComponentModel;
18
19 namespace Tizen.NUI.Components
20 {
21     /// <summary>
22     /// Layout collection of views in a grid.
23     /// </summary>
24     /// <since_tizen> 6 </since_tizen>
25     /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
26     [EditorBrowsable(EditorBrowsableState.Never)]
27     public class GridLayoutManager : LinearLayoutManager
28     {
29         private static readonly int DEFAULT_SPAN_COUNT = -1;
30
31         private int mSpanCount = DEFAULT_SPAN_COUNT;
32
33         /// <summary>
34         /// Creates a GridLayoutManager with orientation. 
35         /// </summary>
36         /// <param name="spanCount">The number of columns or rows in the grid</param>
37         /// <param name="orientation">Layout orientation.Should be HORIZONTAL or VERTICAL</param>
38         /// <since_tizen> 6 </since_tizen>
39         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
40         [EditorBrowsable(EditorBrowsableState.Never)]
41         public GridLayoutManager(int spanCount, int orientation) : base(orientation)
42         {
43             mSpanCount = spanCount;
44         }
45
46         internal override void EnsureAnchorReady(FlexibleView.Recycler recycler, AnchorInfo anchorInfo, int itemDirection)
47         {
48             bool layingOutInPrimaryDirection = (itemDirection == LayoutState.ITEM_DIRECTION_TAIL);
49             int span = anchorInfo.Position;
50             if (layingOutInPrimaryDirection)
51             {
52                 // choose span 0
53                 while (span > 0 && anchorInfo.Position > 0)
54                 {
55                     anchorInfo.Position--;
56                     span = anchorInfo.Position;
57                 }
58             }
59             else
60             {
61                 // choose the max span we can get. hopefully last one
62                 int indexLimit = GetChildCount() - 1;
63                 int pos = anchorInfo.Position;
64                 int bestSpan = span;
65                 while (pos < indexLimit)
66                 {
67                     int next = (pos + 1);
68                     if (next > bestSpan)
69                     {
70                         pos += 1;
71                         bestSpan = next;
72                     }
73                     else
74                     {
75                         break;
76                     }
77                 }
78                 anchorInfo.Position = pos;
79             }
80         }
81
82         /// <summary>
83         /// Retrieves a position that neighbor to current position by direction. 
84         /// </summary>
85         /// <param name="position">The anchor adapter position</param>
86         /// <param name="direction">The direction.</param>
87         /// <since_tizen> 6 </since_tizen>
88         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
89         [EditorBrowsable(EditorBrowsableState.Never)]
90         protected override int GetNextPosition(int position, FlexibleView.LayoutManager.Direction direction)
91         {
92             if (mOrientation == HORIZONTAL)
93             {
94                 switch (direction)
95                 {
96                     case FlexibleView.LayoutManager.Direction.Left:
97                         if (position >= mSpanCount)
98                         {
99                             return position - mSpanCount;
100                         }
101                         break;
102                     case FlexibleView.LayoutManager.Direction.Right:
103                         if (position < ItemCount - mSpanCount)
104                         {
105                             return position + mSpanCount;
106                         }
107                         break;
108                     case FlexibleView.LayoutManager.Direction.Up:
109                         if (position % mSpanCount > 0)
110                         {
111                             return position - 1;
112                         }
113                         break;
114                     case FlexibleView.LayoutManager.Direction.Down:
115                         if (position < ItemCount - 1 && (position % mSpanCount < mSpanCount - 1))
116                         {
117                             return position + 1;
118                         }
119                         break;
120                 }
121             }
122             else
123             {
124                 switch (direction)
125                 {
126                     case FlexibleView.LayoutManager.Direction.Left:
127                         if (position % mSpanCount > 0)
128                         {
129                             return position - 1;
130                         }
131                         break;
132                     case FlexibleView.LayoutManager.Direction.Right:
133                         if (position < ItemCount - 1 && (position % mSpanCount < mSpanCount - 1))
134                         {
135                             return position + 1;
136                         }
137                         break;
138                     case FlexibleView.LayoutManager.Direction.Up:
139                         if (position >= mSpanCount)
140                         {
141                             return position - mSpanCount;
142                         }
143                         break;
144                     case FlexibleView.LayoutManager.Direction.Down:
145                         if (position < ItemCount - mSpanCount)
146                         {
147                             return position + mSpanCount;
148                         }
149                         break;
150                 }
151             }
152
153             return NO_POSITION;
154         }
155
156         internal override void LayoutChunk(FlexibleView.Recycler recycler,
157             LayoutState layoutState, LayoutChunkResult result)
158         {
159             bool layingOutInPrimaryDirection =
160                 layoutState.ItemDirection == LayoutState.ITEM_DIRECTION_TAIL;
161
162             int count = mSpanCount;
163             for (int i = 0; i < count; i++)
164             {
165                 FlexibleView.ViewHolder holder = layoutState.Next(recycler);
166                 if (holder == null)
167                 {
168                     result.Finished = true;
169                     return;
170                 }
171
172                 if (layingOutInPrimaryDirection)
173                     AddView(holder);
174                 else
175                     AddView(holder, 0);
176
177                 result.Consumed = mOrientationHelper.GetViewHolderMeasurement(holder);
178
179                 float left, top, width, height;
180                 if (mOrientation == VERTICAL)
181                 {
182                     width = (GetWidth() - GetPaddingLeft() - GetPaddingRight()) / count;
183                     height = result.Consumed;
184                     if (layoutState.LayoutDirection == LayoutState.LAYOUT_END)
185                     {
186                         left = GetPaddingLeft() + width * i;
187                         top = layoutState.Offset;
188                     }
189                     else
190                     {
191                         left = GetPaddingLeft() + width * (count - 1 - i);
192                         top = layoutState.Offset - height;
193                     }
194                     LayoutChild(holder, left, top, width, height);
195                 }
196                 else
197                 {
198                     width = result.Consumed;
199                     height = (GetHeight() - GetPaddingTop() - GetPaddingBottom()) / count;
200                     if (layoutState.LayoutDirection == LayoutState.LAYOUT_END)
201                     {
202                         top = GetPaddingTop() + height * i;
203                         left = layoutState.Offset;
204                     }
205                     else
206                     {
207                         top = GetPaddingTop() + height * (count - 1 - i);
208                         left = layoutState.Offset - width;
209                     }
210                     LayoutChild(holder, left, top, width, height);
211                 }
212             }
213         }
214
215
216     }
217 }