Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes #401 - game rooms are misaligned #405

Merged
merged 1 commit into from
Dec 5, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions ClientCore/Extensions/EnumerableExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
using System.Collections.Generic;
using System.Linq;

namespace ClientCore.Extensions;

public static class EnumerableExtensions
{
/// <summary>
/// Converts an enumerable to a matrix of items with a max number of items per column.
/// The matrix is built column by column, left to right.
/// </summary>
/// <param name="enumerable">the enumerable to convert</param>
/// <param name="maxPerColumn">the max number of items per column</param>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public static List<List<T>> ToMatrix<T>(this IEnumerable<T> enumerable, int maxPerColumn)
{
var list = enumerable.ToList();
return list.Aggregate(new List<List<T>>(), (matrix, item) =>
{
int index = list.IndexOf(item);
int column = (index / maxPerColumn);
List<T> columnList = matrix.Count <= column ? new List<T>() : matrix[column];
if (columnList.Count == 0)
matrix.Add(columnList);

columnList.Add(item);
return matrix;
});
}
}
94 changes: 59 additions & 35 deletions DTAConfig/OptionPanels/CnCNetOptionsPanel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@
using Rampastring.XNAUI.XNAControls;
using System;
using System.Collections.Generic;
using System.Linq;
using ClientCore.Enums;
using ClientCore.Extensions;

namespace DTAConfig.OptionPanels
{
Expand Down Expand Up @@ -216,44 +218,66 @@ private void InitGameListPanel()

gameListPanel.AddChild(lblFollowedGames);

int chkCount = 0;
int chkCountPerColumn = 4;
int nextColumnXOffset = 0;
int columnXOffset = 0;
foreach (CnCNetGame game in gameCollection.GameList)
// Max number of games per column
const int maxGamesPerColumn = 4;
// Spacing buffer between columns
const int columnBuffer = 20;
// Spacing buffer between rows
const int rowBuffer = 22;
// Render width of a game icon
const int gameIconWidth = 16;
// Spacing buffer between game icon and game check box
const int gameIconBuffer = 6;

// List of supported games
IEnumerable<CnCNetGame> supportedGames = gameCollection.GameList
.Where(game => game.Supported && !string.IsNullOrEmpty(game.GameBroadcastChannel));

// Convert to a matrix of XNAPanels that contain the game icons and check boxes
List<List<XNAPanel>> gamePanelMatrix = supportedGames
.Select(game =>
{
var gameIconPanel = new XNAPanel(WindowManager);
gameIconPanel.Name = "panel" + game.InternalName;
gameIconPanel.ClientRectangle = new Rectangle(0, 0, gameIconWidth, gameIconWidth);
gameIconPanel.DrawBorders = false;
gameIconPanel.BackgroundTexture = game.Texture;

var gameChkBox = new XNAClientCheckBox(WindowManager);
gameChkBox.Name = game.InternalName.ToUpper();
gameChkBox.ClientRectangle = new Rectangle(gameIconPanel.Right + gameIconBuffer, 0, 0, 0);
gameChkBox.Text = game.UIName;

var gamePanel = new XNAPanel(WindowManager);
gamePanel.DrawBorders = false;
gamePanel.ClientRectangle = new Rectangle(lblFollowedGames.X, 0, gameIconPanel.Width + gameChkBox.Width + gameIconBuffer, gameIconPanel.Height);
gamePanel.AddChild(gameIconPanel);
gamePanel.AddChild(gameChkBox);
followedGameChks.Add(gameChkBox);
return gamePanel;
})
.ToMatrix(maxGamesPerColumn);


// Calculate max widths for each column
List<int> columnWidths = gamePanelMatrix
.Select(columnList => columnList.Max(gamePanel => gamePanel.Children.Last().Right + columnBuffer))
.ToList();

// Reposition each game panel and then add them to the overall list panel
int startY = lblFollowedGames.Bottom + 12;
for (int col = 0; col < gamePanelMatrix.Count; col++)
{
if (!game.Supported || string.IsNullOrEmpty(game.GameBroadcastChannel))
continue;

if (chkCount == chkCountPerColumn)
List<XNAPanel> gamePanelColumn = gamePanelMatrix[col];
for (int row = 0; row < gamePanelColumn.Count; row++)
{
chkCount = 0;
columnXOffset += nextColumnXOffset + 6;
nextColumnXOffset = 0;

int columnOffset = columnWidths.Take(col).Sum();
int rowOffset = startY + row * rowBuffer;
XNAPanel gamePanel = gamePanelColumn[row];
gamePanel.ClientRectangle = new Rectangle(gamePanel.X + columnOffset, rowOffset, gamePanel.Width, gamePanel.Height);
gameListPanel.AddChild(gamePanel);
}

var panel = new XNAPanel(WindowManager);
panel.Name = "panel" + game.InternalName;
panel.ClientRectangle = new Rectangle(lblFollowedGames.X + columnXOffset,
lblFollowedGames.Bottom + 12 + chkCount * 22, 16, 16);
panel.DrawBorders = false;
panel.BackgroundTexture = game.Texture;

var chkBox = new XNAClientCheckBox(WindowManager);
chkBox.Name = game.InternalName.ToUpper();
chkBox.ClientRectangle = new Rectangle(
panel.Right + 6,
panel.Y, 0, 0);
chkBox.Text = game.UIName;

chkCount++;

gameListPanel.AddChild(panel);
gameListPanel.AddChild(chkBox);
followedGameChks.Add(chkBox);

if (chkBox.Right > nextColumnXOffset)
nextColumnXOffset = chkBox.Right;
}
}

Expand Down