mirror of
https://gitea.wildfiregames.com/0ad/0ad
synced 2026-06-19 06:43:58 -07:00
eslint --no-config-lookup --fix --rule '"prefer-const": 1' \
binaries/data/mods/public/gui/maps
Ref: #7812
Signed-off-by: Ralph Sennhauser <ralph.sennhauser@gmail.com>
145 lines
3.6 KiB
JavaScript
145 lines
3.6 KiB
JavaScript
/**
|
|
* Class that arranges a grid of items using paging.
|
|
*
|
|
* Needs an object as container with items and a object to display the page numbering (if not
|
|
* make hidden object and assign it to that).
|
|
*/
|
|
class GridBrowser
|
|
{
|
|
constructor(container)
|
|
{
|
|
this.container = container;
|
|
|
|
// These properties may be read from publicly.
|
|
this.pageCount = undefined;
|
|
this.currentPage = undefined;
|
|
this.columnCount = undefined;
|
|
this.minColumns = undefined;
|
|
this.maxColumns = undefined;
|
|
this.rowCount = undefined;
|
|
this.itemCount = undefined;
|
|
this.itemsPerPage = undefined;
|
|
this.selected = undefined;
|
|
|
|
this.gridResizeHandlers = new Set();
|
|
this.pageChangeHandlers = new Set();
|
|
this.selectionChangeHandlers = new Set();
|
|
}
|
|
|
|
registerGridResizeHandler(handler)
|
|
{
|
|
this.gridResizeHandlers.add(handler);
|
|
}
|
|
|
|
registerPageChangeHandler(handler)
|
|
{
|
|
this.pageChangeHandlers.add(handler);
|
|
}
|
|
|
|
registerSelectionChangeHandler(handler)
|
|
{
|
|
this.selectionChangeHandlers.add(handler);
|
|
}
|
|
|
|
// Inheriting classes must subscribe to this event.
|
|
onWindowResized()
|
|
{
|
|
this.resizeGrid();
|
|
this.goToPageOfSelected();
|
|
}
|
|
|
|
setSelectedIndex(index)
|
|
{
|
|
this.selected = index;
|
|
|
|
for (const handler of this.selectionChangeHandlers)
|
|
handler();
|
|
}
|
|
|
|
goToPage(pageNumber)
|
|
{
|
|
if (!Number.isInteger(pageNumber))
|
|
throw new Error("Given argument is not a number");
|
|
|
|
this.currentPage = pageNumber;
|
|
|
|
for (const handler of this.pageChangeHandlers)
|
|
handler();
|
|
}
|
|
|
|
nextPage(wrapAround = true)
|
|
{
|
|
const numberPages = Math.max(1, this.pageCount);
|
|
if (!wrapAround)
|
|
this.goToPage(Math.min(this.currentPage + 1, numberPages - 1));
|
|
else
|
|
this.goToPage((this.currentPage + 1) % numberPages);
|
|
}
|
|
|
|
previousPage(wrapAround = true)
|
|
{
|
|
const numberPages = Math.max(1, this.pageCount);
|
|
if (!wrapAround)
|
|
this.goToPage(Math.max(this.currentPage - 1, 0));
|
|
else
|
|
this.goToPage((this.currentPage + numberPages - 1) % numberPages);
|
|
}
|
|
|
|
goToPageOfSelected()
|
|
{
|
|
this.goToPage(
|
|
Math.max(Math.min(
|
|
Math.floor(this.selected / this.itemsPerRow) - Math.floor(this.rowCount / 2),
|
|
this.pageCount-1),
|
|
0)
|
|
);
|
|
}
|
|
|
|
increaseColumnCount(diff)
|
|
{
|
|
const isSelectedInPage =
|
|
this.selected !== undefined &&
|
|
Math.floor(this.selected / this.itemsPerRow) >= this.currentPage &&
|
|
Math.floor(this.selected / this.itemsPerRow) < this.currentPage + this.rowCount;
|
|
|
|
this.columnCount += diff;
|
|
this.resizeGrid();
|
|
|
|
if (isSelectedInPage)
|
|
this.goToPageOfSelected();
|
|
else
|
|
this.goToPage(Math.min(this.currentPage, Math.max(0, this.pageCount - 1)));
|
|
}
|
|
|
|
resizeGrid()
|
|
{
|
|
const size = this.container.getComputedSize();
|
|
const width = size.right - size.left;
|
|
const height = size.bottom - size.top;
|
|
|
|
const maxColumns = Math.floor(width / this.MinItemWidth);
|
|
if (maxColumns <= 0)
|
|
return;
|
|
|
|
if (this.columnCount === undefined)
|
|
this.columnCount = Math.floor(width / this.DefaultItemWidth);
|
|
|
|
this.minColumns = Math.ceil(width / (height * this.ItemRatio));
|
|
this.maxColumns = maxColumns;
|
|
|
|
|
|
this.columnCount = Math.min(this.maxColumns, Math.max(this.minColumns, this.columnCount));
|
|
|
|
this.itemWidth = Math.floor(width / this.columnCount);
|
|
this.itemHeight = Math.floor(this.itemWidth / this.ItemRatio);
|
|
|
|
this.rowCount = Math.floor((size.bottom - size.top) / this.itemHeight);
|
|
this.itemsPerRow = Math.min(this.columnCount, this.items.length);
|
|
this.itemsPerPage = Math.min(this.columnCount * this.rowCount, this.items.length);
|
|
// NB: pages only change by one row, so items are in several pages.
|
|
this.pageCount = Math.ceil(this.itemCount / this.itemsPerRow) - this.rowCount + 1;
|
|
|
|
for (const handler of this.gridResizeHandlers)
|
|
handler();
|
|
}
|
|
}
|