< Summary

Class:GridContainerComponentView
Assembly:UIComponents
File(s):/tmp/workspace/unity-renderer/unity-renderer/Assets/UIComponents/Scripts/Components/GridContainer/GridContainerComponentView.cs
Covered lines:161
Uncovered lines:25
Coverable lines:186
Total lines:476
Line coverage:86.5% (161 of 186)
Covered branches:0
Total branches:0

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
GridContainerComponentView()0%110100%
Awake()0%110100%
Configure(...)0%110100%
RefreshControl()0%3.013088.89%
OnScreenSizeChanged()0%110100%
Dispose()0%110100%
SetConstraint(...)0%2.032080%
SetConstraintCount(...)0%2.032080%
SetItemSizeToContainerAdaptation(...)0%110100%
SetItemSize(...)0%11.0711091.67%
CalculateAutoSize(...)0%8.348082.61%
CalculateHorizontalSizeForFixedColumnConstraint(...)0%220100%
CalculateHorizontalSizeForFixedRowConstraint(...)0%110100%
CalculateHorizontalSizeForFlexibleConstraint(...)0%10.935038.1%
SetSpaceBetweenItems(...)0%2.032080%
SetMinWidthForFlexibleItems(...)0%110100%
SetItems(...)0%220100%
SetItems(...)0%220100%
AddItem(...)0%110100%
RemoveItem(...)0%220100%
GetItems()0%2100%
ExtractItems()0%330100%
RemoveItems()0%330100%
CreateItem(...)0%2.012087.5%
ResizeGridContainer()0%660100%
RegisterCurrentInstantiatedItems()0%4.014090.91%

File(s)

/tmp/workspace/unity-renderer/unity-renderer/Assets/UIComponents/Scripts/Components/GridContainer/GridContainerComponentView.cs

#LineLine coverage
 1using System;
 2using System.Collections.Generic;
 3using System.Linq;
 4using UnityEngine;
 5using UnityEngine.UI;
 6using static UnityEngine.UI.GridLayoutGroup;
 7
 8public interface IGridContainerComponentView
 9{
 10    /// <summary>
 11    /// Number of items per row that fit with the current grid configuration.
 12    /// </summary>
 13    int currentItemsPerRow { get; }
 14
 15    /// <summary>
 16    /// Set the type of constraint of the grid.
 17    /// </summary>
 18    /// <param name="newConstraint">Type of constraint.</param>
 19    void SetConstraint(Constraint newConstraint);
 20
 21    /// <summary>
 22    /// Set the number of columns/rows of the grid depending on the type of constraint set.
 23    /// </summary>
 24    /// <param name="newConstraintCount">Number of columns or rows.</param>
 25    void SetConstraintCount(int newConstraintCount);
 26
 27    /// <summary>
 28    /// Set the item size adaptation to the container.
 29    /// </summary>
 30    /// <param name="adaptItemSizeToContainer">True for activate the size adaptation.</param>
 31    void SetItemSizeToContainerAdaptation(bool adaptItemSizeToContainer);
 32
 33    /// <summary>
 34    /// Set the size of each child item.
 35    /// </summary>
 36    /// <param name="newItemSize">Size of each child.</param>
 37    void SetItemSize(Vector2 newItemSize);
 38
 39    /// <summary>
 40    /// Set the space between child items.
 41    /// </summary>
 42    /// <param name="newSpace">Space between children.</param>
 43    void SetSpaceBetweenItems(Vector2 newSpace);
 44
 45    /// <summary>
 46    /// Set the minimum width for the items when constraint is set to flexible.
 47    /// </summary>
 48    /// <param name="minWidthForFlexibleItems">Min item width.</param>
 49    void SetMinWidthForFlexibleItems(float minWidthForFlexibleItems);
 50
 51    /// <summary>
 52    /// Creates the items of the grid from the prefab. All previously existing items will be removed.
 53    /// </summary>
 54    /// <param name="prefab">Prefab to create items</param>
 55    /// <param name="amountOfItems">Amounts of items to be created</param>
 56    void SetItems(BaseComponentView prefab, int amountOfItems);
 57
 58    /// <summary>
 59    /// Set the items of the grid. All previously existing items will be removed.
 60    /// </summary>
 61    /// <param name="items">List of UI components.</param>
 62    void SetItems(List<BaseComponentView> items);
 63
 64    /// <summary>
 65    /// Adds a new item in the grid.
 66    /// </summary>
 67    /// <param name="item">An UI component.</param>
 68    void AddItem(BaseComponentView item);
 69
 70    /// <summary>
 71    /// Remove an item from the grid.
 72    /// </summary>
 73    /// <param name="item">An UI component</param>
 74    void RemoveItem(BaseComponentView item);
 75
 76    /// <summary>
 77    /// Get all the items of the grid.
 78    /// </summary>
 79    /// <returns>List of items.</returns>
 80    List<BaseComponentView> GetItems();
 81
 82    /// <summary>
 83    /// Extract all items out of the grid.
 84    /// </summary>
 85    /// <returns>The list of extracted items.</returns>
 86    List<BaseComponentView> ExtractItems();
 87
 88    /// <summary>
 89    /// Remove all existing items from the grid.
 90    /// </summary>
 91    void RemoveItems();
 92}
 93
 94public class GridContainerComponentView : BaseComponentView, IGridContainerComponentView, IComponentModelConfig
 95{
 96    [Header("Prefab References")]
 97    [SerializeField] internal GridLayoutGroup gridLayoutGroup;
 98    [SerializeField] internal RectTransform externalParentToAdaptSize;
 99
 100    [Header("Configuration")]
 101    [SerializeField] internal GridContainerComponentModel model;
 102
 865103    internal List<BaseComponentView> instantiatedItems = new List<BaseComponentView>();
 104
 0105    public int currentItemsPerRow { get; internal set; }
 106
 107    public override void Awake()
 108    {
 317109        base.Awake();
 110
 317111        RegisterCurrentInstantiatedItems();
 317112    }
 113
 114    public void Configure(BaseComponentModel newModel)
 115    {
 3116        model = (GridContainerComponentModel)newModel;
 3117        RefreshControl();
 3118    }
 119
 120    public override void RefreshControl()
 121    {
 4122        if (model == null)
 0123            return;
 124
 125        //We only do this if we don't have items, this is done because the editor doesn't call awake method
 4126        if (instantiatedItems.Count == 0)
 2127            RegisterCurrentInstantiatedItems();
 128
 4129        SetConstraint(model.constraint);
 4130        SetItemSize(model.itemSize);
 4131        SetConstraintCount(model.constraintCount);
 4132        SetSpaceBetweenItems(model.spaceBetweenItems);
 4133    }
 134
 135    public override void OnScreenSizeChanged()
 136    {
 1137        base.OnScreenSizeChanged();
 138
 1139        SetItemSize(model.itemSize);
 1140        SetConstraintCount(model.constraintCount);
 1141    }
 142
 143    public override void Dispose()
 144    {
 903145        base.Dispose();
 146
 903147        RemoveItems();
 903148    }
 149
 150    public void SetConstraint(Constraint newConstraint)
 151    {
 7152        model.constraint = newConstraint;
 153
 7154        if (gridLayoutGroup == null)
 0155            return;
 156
 7157        gridLayoutGroup.constraint = newConstraint;
 7158    }
 159
 160    public void SetConstraintCount(int newConstraintCount)
 161    {
 325162        model.constraintCount = newConstraintCount;
 163
 325164        if (gridLayoutGroup == null)
 0165            return;
 166
 325167        gridLayoutGroup.constraintCount = newConstraintCount;
 325168    }
 169
 170    public void SetItemSizeToContainerAdaptation(bool adaptItemSizeToContainer)
 171    {
 1172        model.adaptHorizontallyItemSizeToContainer = adaptItemSizeToContainer;
 1173        SetItemSize(model.itemSize);
 1174    }
 175
 176    public void SetItemSize(Vector2 newItemSize)
 177    {
 371178        Vector2 newSizeToApply = newItemSize;
 179
 371180        if (model.adaptVerticallyItemSizeToContainer  && model.adaptHorizontallyItemSizeToContainer)
 181        {
 10182            CalculateAutoSize(out newSizeToApply);
 10183        }
 361184        else if (model.adaptVerticallyItemSizeToContainer)
 185        {
 186            //TODO: We need to implement this functionality. Nobody is using it
 187            //      Please implement it if needed
 0188            throw new Exception("Not implemented yet! Please implement the functionality");
 189        }
 361190        else if (model.adaptHorizontallyItemSizeToContainer)
 191        {
 161192            switch (model.constraint)
 193            {
 194                case Constraint.FixedColumnCount:
 159195                    CalculateHorizontalSizeForFixedColumnConstraint(out newSizeToApply);
 159196                    break;
 197                case Constraint.FixedRowCount:
 1198                    CalculateHorizontalSizeForFixedRowConstraint(out newSizeToApply);
 1199                    break;
 200                case Constraint.Flexible:
 1201                    CalculateHorizontalSizeForFlexibleConstraint(out newSizeToApply, newItemSize);
 1202                    break;
 203            }
 204        }
 205        else
 206        {
 200207            switch (model.constraint)
 208            {
 209                case Constraint.FixedColumnCount:
 210                case Constraint.Flexible:
 33211                    currentItemsPerRow = model.constraintCount;
 33212                    break;
 213                case Constraint.FixedRowCount:
 167214                    currentItemsPerRow = (int)Mathf.Ceil((float)instantiatedItems.Count / model.constraintCount);
 215                    break;
 216            }
 217        }
 218
 371219        model.itemSize = newSizeToApply;
 220
 371221        if (gridLayoutGroup == null)
 0222            return;
 223
 371224        gridLayoutGroup.cellSize = newSizeToApply;
 225
 371226        ResizeGridContainer();
 371227    }
 228
 229    internal void CalculateAutoSize(out Vector2 newSizeToApply)
 230    {
 10231        float height = externalParentToAdaptSize != null ? externalParentToAdaptSize.rect.height : ((RectTransform)trans
 10232        float width = externalParentToAdaptSize != null ? externalParentToAdaptSize.rect.width : ((RectTransform)transfo
 233
 10234        int amountsOfHorizontalItemsPerRow =  instantiatedItems.Count / model.constraintCount;
 10235        int amountsOfVerticalItemsPerColumn =  instantiatedItems.Count / amountsOfHorizontalItemsPerRow;
 236
 10237        float extraSpaceToRemoveX = model.spaceBetweenItems.x * (amountsOfHorizontalItemsPerRow - 1);
 10238        float extraSpaceToRemoveY = model.spaceBetweenItems.y * (amountsOfVerticalItemsPerColumn - 1);
 239
 10240        float itemWidth = model.recommendedWidthForFlexibleItems;
 10241        float itemHeight = model.recommendedHeightForFlexibleItems;
 242
 10243        if (itemWidth * amountsOfHorizontalItemsPerRow + extraSpaceToRemoveX >= width)
 0244            itemWidth = width / amountsOfHorizontalItemsPerRow - extraSpaceToRemoveX;
 245
 10246        if (itemWidth < model.minWidthForFlexibleItems)
 0247            itemWidth = model.minWidthForFlexibleItems;
 248
 10249        if (itemHeight * amountsOfVerticalItemsPerColumn + extraSpaceToRemoveY >= height)
 0250            itemHeight = height / amountsOfVerticalItemsPerColumn - extraSpaceToRemoveY;
 251
 10252        if (itemHeight < model.minHeightForFlexibleItems)
 0253            itemHeight = model.minHeightForFlexibleItems;
 254
 10255        if (model.sameHeightAndWidhtFlexibleItem)
 256        {
 10257            float minValue = Mathf.Min(itemHeight, itemWidth);
 10258            itemHeight = minValue;
 10259            itemWidth = minValue;
 260        }
 261
 10262        newSizeToApply = new Vector2(
 263            itemWidth,
 264            itemHeight);
 265
 10266        currentItemsPerRow = model.constraintCount;
 10267    }
 268
 269    internal void CalculateHorizontalSizeForFixedColumnConstraint(out Vector2 newSizeToApply)
 270    {
 159271        float width = externalParentToAdaptSize != null ? externalParentToAdaptSize.rect.width : ((RectTransform)transfo
 159272        float extraSpaceToRemove = (model.spaceBetweenItems.x * (model.constraintCount - 1)) / model.constraintCount;
 273
 159274        newSizeToApply = new Vector2(
 275            (width / model.constraintCount) - extraSpaceToRemove,
 276            model.itemSize.y);
 277
 159278        currentItemsPerRow = model.constraintCount;
 159279    }
 280
 281    internal void CalculateHorizontalSizeForFixedRowConstraint(out Vector2 newSizeToApply)
 282    {
 1283        float height = ((RectTransform)transform).rect.height;
 1284        float extraSpaceToRemove = (model.spaceBetweenItems.y / (model.constraintCount / 2f));
 285
 1286        newSizeToApply = new Vector2(
 287            model.itemSize.x,
 288            (height / model.constraintCount) - extraSpaceToRemove);
 289
 1290        currentItemsPerRow = (int)Mathf.Ceil((float)instantiatedItems.Count / model.constraintCount);
 1291    }
 292
 293    internal void CalculateHorizontalSizeForFlexibleConstraint(out Vector2 newSizeToApply, Vector2 newItemSize)
 294    {
 1295        newSizeToApply = newItemSize;
 296
 1297        float width = externalParentToAdaptSize != null ? externalParentToAdaptSize.rect.width : ((RectTransform)transfo
 1298        int numberOfPossibleItems = (int)(width / model.minWidthForFlexibleItems);
 299
 1300        SetConstraint(Constraint.FixedColumnCount);
 301
 1302        if (numberOfPossibleItems > 0)
 303        {
 0304            for (int numColumnsToTry = 1; numColumnsToTry <= numberOfPossibleItems; numColumnsToTry++)
 305            {
 0306                SetConstraintCount(numColumnsToTry);
 0307                SetItemSize(model.itemSize);
 0308                currentItemsPerRow = numColumnsToTry;
 309
 0310                if (model.itemSize.x < model.minWidthForFlexibleItems)
 311                {
 0312                    SetConstraintCount(numColumnsToTry - 1);
 0313                    SetItemSize(model.itemSize);
 0314                    currentItemsPerRow = numColumnsToTry - 1;
 0315                    break;
 316                }
 317
 0318                newSizeToApply = model.itemSize;
 319            }
 0320        }
 321        else
 322        {
 1323            newSizeToApply = new Vector2(model.minWidthForFlexibleItems, newSizeToApply.y);
 324        }
 325
 1326        SetConstraint(Constraint.Flexible);
 1327    }
 328
 329    public void SetSpaceBetweenItems(Vector2 newSpace)
 330    {
 163331        model.spaceBetweenItems = newSpace;
 332
 163333        if (gridLayoutGroup == null)
 0334            return;
 335
 163336        gridLayoutGroup.spacing = newSpace;
 163337    }
 338
 339    public void SetMinWidthForFlexibleItems(float minWidthForFlexibleItems)
 340    {
 1341        model.minWidthForFlexibleItems = minWidthForFlexibleItems;
 1342        SetItemSize(model.itemSize);
 1343    }
 344
 345    public void SetItems(BaseComponentView prefab, int amountOfItems)
 346    {
 2347        RemoveItems();
 348
 20349        for (int i = 0; i < amountOfItems; i++)
 350        {
 8351            BaseComponentView instanciatedItem = Instantiate(prefab);
 8352            CreateItem(instanciatedItem, $"Item{i}");
 353        }
 354
 2355        SetItemSize(model.itemSize);
 2356    }
 357
 358    public void SetItems(List<BaseComponentView> items)
 359    {
 12360        RemoveItems();
 361
 74362        for (int i = 0; i < items.Count; i++)
 363        {
 25364            CreateItem(items[i], $"Item{i}");
 365        }
 366
 12367        SetItemSize(model.itemSize);
 12368    }
 369
 370    public void AddItem(BaseComponentView item)
 371    {
 21372        CreateItem(item, $"Item{instantiatedItems.Count}");
 21373        SetItemSize(model.itemSize);
 21374    }
 375
 376    public void RemoveItem(BaseComponentView item)
 377    {
 8378        BaseComponentView itemToRemove = instantiatedItems.FirstOrDefault(x => x == item);
 4379        if (itemToRemove != null)
 380        {
 4381            Destroy(itemToRemove.gameObject);
 4382            instantiatedItems.Remove(item);
 383        }
 384
 4385        SetItemSize(model.itemSize);
 4386    }
 387
 0388    public List<BaseComponentView> GetItems() { return instantiatedItems; }
 389
 390    public List<BaseComponentView> ExtractItems()
 391    {
 1313392        List<BaseComponentView> extractedItems = new List<BaseComponentView>();
 2998393        foreach (BaseComponentView item in instantiatedItems)
 394        {
 186395            if (item != null)
 181396                item.transform.SetParent(null);
 397
 186398            extractedItems.Add(item);
 399        }
 400
 1313401        instantiatedItems.Clear();
 402
 1313403        return extractedItems;
 404    }
 405
 406    public void RemoveItems()
 407    {
 1197408        List<BaseComponentView> itemsToDestroy = ExtractItems();
 2726409        foreach (BaseComponentView itemToDestroy in itemsToDestroy)
 410        {
 166411            if (itemToDestroy != null)
 161412                DestroyImmediate(itemToDestroy.gameObject);
 413        }
 1197414        itemsToDestroy.Clear();
 415
 1197416        instantiatedItems.Clear();
 1197417    }
 418
 419    internal void CreateItem(BaseComponentView newItem, string name)
 420    {
 55421        if (newItem == null)
 0422            return;
 423
 55424        newItem.transform.SetParent(transform);
 55425        newItem.transform.localPosition = Vector3.zero;
 55426        newItem.transform.localScale = Vector3.one;
 55427        newItem.name = name;
 428
 55429        instantiatedItems.Add(newItem);
 55430    }
 431
 432    internal void ResizeGridContainer()
 433    {
 371434        int currentNumberOfItems = transform.childCount;
 435
 371436        if (currentNumberOfItems == 0)
 437        {
 213438            ((RectTransform)transform).sizeDelta = Vector2.zero;
 213439            return;
 440        }
 441
 158442        if (model.constraint == Constraint.FixedColumnCount)
 443        {
 140444            int numRows = (int)Mathf.Ceil((float)currentNumberOfItems / model.constraintCount);
 140445            ((RectTransform)transform).sizeDelta = new Vector2(
 446                model.adaptHorizontallyItemSizeToContainer ? ((RectTransform)transform).sizeDelta.x : (model.constraintC
 447                (numRows * model.itemSize.y) + (model.spaceBetweenItems.y * (numRows - 1)));
 140448        }
 18449        else if (model.constraint == Constraint.FixedRowCount)
 450        {
 18451            int numCols = (int)Mathf.Ceil((float)currentNumberOfItems / model.constraintCount);
 18452            ((RectTransform)transform).sizeDelta = new Vector2(
 453                (numCols * model.itemSize.x) + (model.spaceBetweenItems.x * (numCols - 1)),
 454                model.adaptHorizontallyItemSizeToContainer ? ((RectTransform)transform).sizeDelta.y : (model.constraintC
 455        }
 456
 158457        SetSpaceBetweenItems(model.spaceBetweenItems);
 158458    }
 459
 460    internal void RegisterCurrentInstantiatedItems()
 461    {
 319462        instantiatedItems.Clear();
 463
 908464        foreach (Transform child in transform)
 465        {
 135466            BaseComponentView existingItem = child.GetComponent<BaseComponentView>();
 135467            if (existingItem != null)
 135468                instantiatedItems.Add(existingItem);
 469            else
 0470                DestroyImmediate(child.gameObject);
 471        }
 472
 319473        SetItemSize(model.itemSize);
 319474        SetConstraintCount(model.constraintCount);
 319475    }
 476}