/* * 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); } } } } }