/*
* Copyright(c) 2019 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
using System.ComponentModel;
namespace Tizen.NUI.Components
{
///
/// Layout collection of views in a grid.
///
/// 6
/// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
[EditorBrowsable(EditorBrowsableState.Never)]
public class GridLayoutManager : LinearLayoutManager
{
private const int DEFAULT_SPAN_COUNT = -1;
private int mSpanCount = DEFAULT_SPAN_COUNT;
///
/// Creates a GridLayoutManager with orientation.
///
/// The number of columns or rows in the grid
/// Layout orientation.Should be HORIZONTAL or VERTICAL
/// 6
/// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
[EditorBrowsable(EditorBrowsableState.Never)]
public GridLayoutManager(int spanCount, int orientation) : base(orientation)
{
mSpanCount = spanCount;
}
internal override void EnsureAnchorReady(FlexibleViewRecycler recycler, AnchorInfo anchorInfo, int itemDirection)
{
bool layingOutInPrimaryDirection = (itemDirection == LayoutState.ITEM_DIRECTION_TAIL);
int span = anchorInfo.Position % mSpanCount;
if (layingOutInPrimaryDirection)
{
// choose span 0
while (span > 0 && anchorInfo.Position > 0)
{
anchorInfo.Position--;
span = anchorInfo.Position;
}
}
else
{
// choose the max span we can get. hopefully last one
int indexLimit = ChildCount - 1;
int pos = anchorInfo.Position;
int bestSpan = span;
while (pos < indexLimit)
{
int next = (pos + 1) % mSpanCount;
if (next > bestSpan)
{
pos += 1;
bestSpan = next;
}
else
{
break;
}
}
anchorInfo.Position = pos;
}
}
///
/// Retrieves a position that neighbor to current position by direction.
///
/// The anchor adapter position
/// The direction.
/// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
[EditorBrowsable(EditorBrowsableState.Never)]
protected override int GetNextPosition(int position, FlexibleViewLayoutManager.Direction direction)
{
if (mOrientation == HORIZONTAL)
{
switch (direction)
{
case FlexibleViewLayoutManager.Direction.Left:
if (position >= mSpanCount)
{
return position - mSpanCount;
}
break;
case FlexibleViewLayoutManager.Direction.Right:
if (position < ItemCount - mSpanCount)
{
return position + mSpanCount;
}
break;
case FlexibleViewLayoutManager.Direction.Up:
if (position % mSpanCount > 0)
{
return position - 1;
}
break;
case FlexibleViewLayoutManager.Direction.Down:
if (position < ItemCount - 1 && (position % mSpanCount < mSpanCount - 1))
{
return position + 1;
}
break;
}
}
else
{
switch (direction)
{
case FlexibleViewLayoutManager.Direction.Left:
if (position % mSpanCount > 0)
{
return position - 1;
}
break;
case FlexibleViewLayoutManager.Direction.Right:
if (position < ItemCount - 1 && (position % mSpanCount < mSpanCount - 1))
{
return position + 1;
}
break;
case FlexibleViewLayoutManager.Direction.Up:
if (position >= mSpanCount)
{
return position - mSpanCount;
}
break;
case FlexibleViewLayoutManager.Direction.Down:
if (position < ItemCount - mSpanCount)
{
return position + mSpanCount;
}
break;
}
}
return NO_POSITION;
}
internal override void LayoutChunk(FlexibleViewRecycler recycler,
LayoutState layoutState, LayoutChunkResult result)
{
bool layingOutInPrimaryDirection =
layoutState.ItemDirection == LayoutState.ITEM_DIRECTION_TAIL;
int count = mSpanCount;
for (int i = 0; i < count; i++)
{
FlexibleViewViewHolder holder = layoutState.Next(recycler);
if (holder == null)
{
result.Finished = true;
return;
}
if (layingOutInPrimaryDirection)
AddView(holder);
else
AddView(holder, 0);
result.Consumed = mOrientationHelper.GetViewHolderMeasurement(holder);
float left, top, width, height;
if (mOrientation == VERTICAL)
{
width = (Width - PaddingLeft - PaddingRight) / count;
height = result.Consumed;
if (layoutState.LayoutDirection == LayoutState.LAYOUT_END)
{
left = PaddingLeft + width * i;
top = layoutState.Offset;
}
else
{
left = PaddingLeft + width * (count - 1 - i);
top = layoutState.Offset - height;
}
LayoutChild(holder, left, top, width, height);
}
else
{
width = result.Consumed;
height = (Height - PaddingTop - PaddingBottom) / count;
if (layoutState.LayoutDirection == LayoutState.LAYOUT_END)
{
top = PaddingTop + height * i;
left = layoutState.Offset;
}
else
{
top = PaddingTop + height * (count - 1 - i);
left = layoutState.Offset - width;
}
LayoutChild(holder, left, top, width, height);
}
}
}
}
}