> [!IMPORTANT] > **Developer Note** > THIS IS A BREAKING CHANGE TO THE NEW API GUMP. > Please give us feedback in [discord ](https://muo.gg/discord) if you have issues, need help, or have ideas for a better API change! ### Summary * Adds support for size/style to dynamic/static builder. * Drastically simplifies the dynamic/static builder api for AddHtml. * Cleans up some legacy gump files.
585 lines
15 KiB
C#
585 lines
15 KiB
C#
/*************************************************************************
|
|
* ModernUO *
|
|
* Copyright 2019-2025 - ModernUO Development Team *
|
|
* Email: hi@modernuo.com *
|
|
* File: GumpGrid.cs *
|
|
* *
|
|
* This program is free software: you can redistribute it and/or modify *
|
|
* it under the terms of the GNU General Public License as published by *
|
|
* the Free Software Foundation, either version 3 of the License, or *
|
|
* (at your option) any later version. *
|
|
* *
|
|
* You should have received a copy of the GNU General Public License *
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
|
*************************************************************************/
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using Server.Collections;
|
|
|
|
namespace Server.Gumps;
|
|
|
|
public class GumpGrid : Gump
|
|
{
|
|
private Dictionary<string, Grid> _grids = new();
|
|
|
|
public GumpGrid(int x, int y) : base(x, y)
|
|
{
|
|
}
|
|
|
|
private void AddColumn(string name, int x, int width)
|
|
{
|
|
_grids[name].Columns.Add(new Col { X = x, Width = width, });
|
|
}
|
|
|
|
private void AddRow(string name, int y, int height)
|
|
{
|
|
_grids[name].Rows.Add(new Row { Y = y, Height = height });
|
|
}
|
|
|
|
private void InitColumn(string name, int column, int w, int x)
|
|
{
|
|
var width = w / column;
|
|
for (int i = 0; i < column; i++)
|
|
{
|
|
AddColumn(name, i * width + x, width);
|
|
}
|
|
}
|
|
|
|
private void InitRow(string name, int row, int h, int y)
|
|
{
|
|
var height = h / row;
|
|
for (int i = 0; i < row; i++)
|
|
{
|
|
AddRow(name, i * height + y, height);
|
|
}
|
|
}
|
|
|
|
private static Swap Exist(ref PooledRefList<Swap> list, int index)
|
|
{
|
|
for (int i = 0; i < list.Count; i++)
|
|
{
|
|
var item = list[i];
|
|
if (item.Index == index)
|
|
{
|
|
return item;
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
private static int CalculateCustom(int column, int len, string[] sizes, ref PooledRefList<Swap> list)
|
|
{
|
|
var cropSize = 0;
|
|
|
|
for (int i = 0; i < column; i++)
|
|
{
|
|
if (sizes[i] == "*")
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//percent
|
|
var percent = sizes[i].RemoveOrdinal("*");
|
|
var size = sizes[i] != percent ? len / 100 * int.Parse(percent) : int.Parse(percent);
|
|
|
|
list.Add(new Swap { Index = i, Size = size });
|
|
cropSize += size;
|
|
}
|
|
|
|
return cropSize;
|
|
}
|
|
private void InitCustomSizeRow(string name, int height, int row, string[] sizes, int y)
|
|
{
|
|
var list = PooledRefList<Swap>.Create();
|
|
var cropHeight = CalculateCustom(row, height, sizes, ref list);
|
|
var Height = height - cropHeight;
|
|
var factor = row - list.Count;
|
|
for (int i = 0; i < row; i++)
|
|
{
|
|
var swap = Exist(ref list, i);
|
|
if (swap != null)
|
|
{
|
|
var size = swap.Size;
|
|
if (i == 0)
|
|
{
|
|
AddRow(name, y, size);
|
|
}
|
|
else
|
|
{
|
|
var col = _grids[name].Rows[i - 1];
|
|
AddRow(name, col.Height + col.Y + y, size);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
var size = Height / factor;
|
|
if (i == 0)
|
|
{
|
|
AddRow(name, y, size);
|
|
}
|
|
else
|
|
{
|
|
var col = _grids[name].Rows[i - 1];
|
|
AddRow(name, col.Height + col.Y + y, size);
|
|
}
|
|
}
|
|
}
|
|
|
|
list.Dispose();
|
|
}
|
|
|
|
private void InitCustomSizeColumn(string name, int width, int column, string[] sizes, int x)
|
|
{
|
|
var list = PooledRefList<Swap>.Create();
|
|
var cropWidth = CalculateCustom(column, width, sizes, ref list);
|
|
var Width = width - cropWidth;
|
|
var factor = column - list.Count;
|
|
|
|
for (int i = 0; i < column; i++)
|
|
{
|
|
var swap = Exist(ref list, i);
|
|
if (swap != null)
|
|
{
|
|
var size = swap.Size;
|
|
if (i == 0)
|
|
{
|
|
AddColumn(name, x, size);
|
|
}
|
|
else
|
|
{
|
|
var col = _grids[name].Columns[i - 1];
|
|
AddColumn(name, col.Width + col.X + x, size);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
var size = Width / factor;
|
|
if (i == 0)
|
|
{
|
|
AddColumn(name, x, size);
|
|
}
|
|
else
|
|
{
|
|
var col = _grids[name].Columns[i - 1];
|
|
AddColumn(name, col.Width + col.X + x, size);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public Grid SubGrid(
|
|
string name,
|
|
string destGridName,
|
|
int columnStart,
|
|
int rowStart,
|
|
int createColumnsCount,
|
|
int createRowsCount,
|
|
int columnSpan = 0,
|
|
int rowSpan = 0,
|
|
string createColumnSize = "",
|
|
string createRowSize = "",
|
|
int marginX = 0,
|
|
int marginY = 0
|
|
)
|
|
{
|
|
if (CalculateCord(
|
|
destGridName,
|
|
columnStart,
|
|
rowStart,
|
|
columnSpan,
|
|
rowSpan,
|
|
out var x,
|
|
out var y,
|
|
out var width,
|
|
out var height
|
|
))
|
|
{
|
|
Grid(
|
|
name,
|
|
width,
|
|
height,
|
|
createColumnsCount,
|
|
createRowsCount,
|
|
createColumnSize,
|
|
createRowSize,
|
|
x + marginX,
|
|
y + marginY
|
|
);
|
|
}
|
|
|
|
return CreateGrid(name, 0, 0);
|
|
}
|
|
|
|
public Grid CreateGrid(string name, int width, int height)
|
|
{
|
|
if (!_grids.TryGetValue(name, out var grid))
|
|
{
|
|
grid = new Grid { Name = name, Width = width, Height = height };
|
|
_grids.Add(name, grid);
|
|
}
|
|
|
|
return grid;
|
|
}
|
|
|
|
public Grid Grid(
|
|
string name,
|
|
int width,
|
|
int height,
|
|
int columns,
|
|
int rows,
|
|
string columnSize = "",
|
|
string rowSize = "",
|
|
int x = 0,
|
|
int y = 0
|
|
)
|
|
{
|
|
if (columns < 1)
|
|
{
|
|
throw new Exception(nameof(columns));
|
|
}
|
|
|
|
if (rows < 1)
|
|
{
|
|
throw new Exception(nameof(columns));
|
|
}
|
|
|
|
var Grid = CreateGrid(name, width, height);
|
|
|
|
if (columnSize.Length > 0)
|
|
{
|
|
var buffer = columnSize.Split(' ');
|
|
if (buffer.Length == columns)
|
|
{
|
|
InitCustomSizeColumn(name, width, columns, buffer, x);
|
|
}
|
|
else
|
|
{
|
|
throw new Exception(nameof(columnSize));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
InitColumn(name, columns, width, x);
|
|
}
|
|
|
|
if (rowSize.Length > 0)
|
|
{
|
|
var buffer = rowSize.Split(' ');
|
|
if (buffer.Length == rows)
|
|
{
|
|
InitCustomSizeRow(name, height, rows, buffer, y);
|
|
}
|
|
else
|
|
{
|
|
throw new Exception(nameof(rowSize));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
InitRow(name, rows, height, y);
|
|
}
|
|
|
|
return Grid;
|
|
}
|
|
|
|
public bool CalculateCord(
|
|
string name,
|
|
int column,
|
|
int row,
|
|
int columnSpan,
|
|
int rowSpan,
|
|
out int x,
|
|
out int y,
|
|
out int width,
|
|
out int height
|
|
)
|
|
{
|
|
x = 0; y = 0; width = 0; height = 0;
|
|
if (_grids.TryGetValue(name, out var grid))
|
|
{
|
|
var count = columnSpan == 0 ? column + 1 : row + columnSpan;
|
|
for (int i = column; i < count; i++)
|
|
{
|
|
if (i >= grid.Columns.Count)
|
|
{
|
|
break;
|
|
}
|
|
|
|
var dcol = grid.Columns[i];
|
|
if (i == column)
|
|
{
|
|
x = dcol.X;
|
|
}
|
|
|
|
width += dcol.Width;
|
|
}
|
|
|
|
count = rowSpan == 0 ? row + 1 : row + rowSpan;
|
|
for (int i = row; i < count; i++)
|
|
{
|
|
if (i >= grid.Rows.Count)
|
|
{
|
|
break;
|
|
}
|
|
|
|
var drow = grid.Rows[i];
|
|
if (i == row)
|
|
{
|
|
y = drow.Y;
|
|
}
|
|
|
|
height += drow.Height;
|
|
}
|
|
|
|
if (width == 0)
|
|
{
|
|
width = grid.Width;
|
|
}
|
|
|
|
if (height == 0)
|
|
{
|
|
height = grid.Height;
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
public class ListView
|
|
{
|
|
public int LineCount { get; }
|
|
public int ItemsCount { get; }
|
|
public ListItem[] Items { get; }
|
|
public ListItem Header { get; }
|
|
public int Page { get; }
|
|
public int TotalPages { get; }
|
|
public int ColHeight { get; }
|
|
public bool CanNext { get; }
|
|
public bool CanBack { get; }
|
|
public int ColsCount { get; }
|
|
|
|
public ListView(
|
|
int itemsCount,
|
|
int columns,
|
|
int heightPerItem,
|
|
int page,
|
|
int x,
|
|
int y,
|
|
int height,
|
|
int pageItemCount,
|
|
int[] ColWidth,
|
|
int marginX = 0,
|
|
int marginY = 0,
|
|
int headerHeight = 0
|
|
)
|
|
{
|
|
ItemsCount = itemsCount;
|
|
var itemsPerPageCount = pageItemCount == 0 ? (height - marginY) / heightPerItem : pageItemCount;
|
|
LineCount = itemsPerPageCount;
|
|
|
|
if (itemsCount > 0)
|
|
{
|
|
TotalPages = itemsCount / itemsPerPageCount;
|
|
if (itemsCount % itemsPerPageCount == 0)
|
|
{
|
|
TotalPages--;
|
|
}
|
|
}
|
|
|
|
Page = page > TotalPages ? TotalPages : page;
|
|
ColsCount = columns;
|
|
ColHeight = heightPerItem;
|
|
|
|
var index = Page * itemsPerPageCount > 0 ? Page * itemsPerPageCount : 0;
|
|
var nowPageItems = index + itemsPerPageCount;
|
|
|
|
if (index > 0)
|
|
{
|
|
CanBack = true;
|
|
}
|
|
|
|
if (nowPageItems < itemsCount)
|
|
{
|
|
CanNext = true;
|
|
}
|
|
|
|
if (nowPageItems > itemsCount)
|
|
{
|
|
itemsPerPageCount = Page > 0 ? itemsCount - Page * itemsPerPageCount : itemsCount;
|
|
}
|
|
|
|
//header
|
|
Header = new ListItem
|
|
{
|
|
X = x,
|
|
Y = y + marginY,
|
|
Index = -1,
|
|
Cols = new Col[columns],
|
|
};
|
|
|
|
var length = x + marginX;
|
|
for (int col = 0; col < columns; col++)
|
|
{
|
|
Header.Cols[col] = new Col();
|
|
Header.Cols[col].Width = ColWidth[col];
|
|
Header.Cols[col].X = length;
|
|
length += ColWidth[col];
|
|
}
|
|
|
|
Items = new ListItem[itemsPerPageCount];
|
|
|
|
for (int i = 0; i < itemsPerPageCount; i++)
|
|
{
|
|
Items[i] = new ListItem
|
|
{
|
|
X = x,
|
|
Y = y + i * heightPerItem + marginY + headerHeight,
|
|
Index = index + i,
|
|
Cols = Header.Cols
|
|
};
|
|
}
|
|
}
|
|
}
|
|
|
|
public ListView AddListView(
|
|
string name,
|
|
int column,
|
|
int row,
|
|
int itemsCount,
|
|
int page,
|
|
int heightPerItem,
|
|
int createColumn,
|
|
int columnSpan = 0,
|
|
int rowSpan = 0,
|
|
int width = 0,
|
|
int height = 0,
|
|
int pageItemCount = 0,
|
|
int marginX = 0,
|
|
int marginY = 0,
|
|
int headerHeight = 0,
|
|
string colSize = ""
|
|
)
|
|
{
|
|
if (CalculateCord(name, column, row, columnSpan, rowSpan, out var x, out var y, out var w, out var h))
|
|
{
|
|
w = width > 0 ? width : w;
|
|
h = height > 0 ? height : h;
|
|
|
|
int[] colWidth = new int[createColumn];
|
|
|
|
if (colSize == string.Empty)
|
|
{
|
|
for (int i = 0; i < createColumn; i++)
|
|
{
|
|
colWidth[i] = w / createColumn;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
var buffer = colSize.Split(' ');
|
|
|
|
if (buffer.Length > 0)
|
|
{
|
|
const string listName = "listView";
|
|
_grids.Add(listName, new Grid());
|
|
|
|
if (createColumn < buffer.Length)
|
|
{
|
|
Array.Resize(ref buffer, createColumn);
|
|
}
|
|
|
|
InitCustomSizeColumn(listName, w, createColumn, buffer, x);
|
|
var cols = _grids[listName].Columns;
|
|
for (var i = 0; i < createColumn; i++)
|
|
{
|
|
colWidth[i] = cols[i].Width;
|
|
}
|
|
|
|
_grids.Remove(listName);
|
|
}
|
|
}
|
|
|
|
return new ListView(
|
|
itemsCount,
|
|
createColumn,
|
|
heightPerItem,
|
|
page,
|
|
x,
|
|
y,
|
|
h,
|
|
pageItemCount,
|
|
colWidth,
|
|
marginX,
|
|
marginY,
|
|
headerHeight
|
|
);
|
|
}
|
|
|
|
return null;
|
|
}
|
|
}
|
|
|
|
public enum GridHues
|
|
{
|
|
White = 2049, // Change to 0x480 if you have old hues.mul
|
|
Black = 0,
|
|
}
|
|
|
|
public static class GridColors
|
|
{
|
|
public const string Gold = "#ffc959";
|
|
public const string White = "#ffffff";
|
|
public const string Blue = "#1D63DC";
|
|
public const string LightBlue = "#7799EE";
|
|
public const string Green = "#80E732";
|
|
public const string Orange = "#F28B00";
|
|
public const string Purple = "#F3ACF6";
|
|
public const string Red = "#B52B2D";
|
|
public const string LightGreen = "#E6FFC0";
|
|
public const string Yellow = "#FFFFBB";
|
|
}
|
|
|
|
public class ListItem
|
|
{
|
|
public int X { get; set; }
|
|
public int Y { get; set; }
|
|
public int Index { get; set; }
|
|
public Col[] Cols { get; set; }
|
|
}
|
|
|
|
public class Col
|
|
{
|
|
public int X { get; set; }
|
|
public int Width { get; set; }
|
|
public int HCenter => X + Width / 2;
|
|
public int HEnd => X + Width;
|
|
}
|
|
|
|
public class Row
|
|
{
|
|
public int Y { get; set; }
|
|
public int Height { get; set; }
|
|
public int VCenter => Y + Height / 2;
|
|
public int VEnd => Y + Height;
|
|
}
|
|
|
|
public class Grid
|
|
{
|
|
public string Name { get; set; }
|
|
public int Height { get; set; }
|
|
public int Width { get; set; }
|
|
public List<Col> Columns { get; set; } = new();
|
|
public List<Row> Rows { get; set; } = new();
|
|
}
|
|
|
|
public class Swap
|
|
{
|
|
public int Index { get; set; }
|
|
public int Size { get; set; }
|
|
}
|
|
|