Index: binaries/data/mods/mod/gui/common/GridBrowser.js =================================================================== --- binaries/data/mods/mod/gui/common/GridBrowser.js +++ binaries/data/mods/mod/gui/common/GridBrowser.js @@ -0,0 +1,177 @@ +/** + * Function that arranges a list of "boxed-like" GUI objects with width-centering + * (currently) and page based way mode. + * + * Needs an object as container and a object to display the page numbering (if not + * make hidden object and assign it to it). + * + * To add advanced, more detailed, objects inside each box add a custom childFunction: + * childFunction(page_list_element, page_list_element_index, page_list, + * global_list_element_index, global_list,child_object). + * + * For example look at mapbrowser.js / mapbrowser.xml implementation. + */ + +// initializer, list is each childen data +function GridBrowser(containerName, pageCounterName, list, selectedIndex, childDimensions, childFunction) +{ + // GUI object container of the children + this.container = Engine.GetGUIObjectByName(containerName); + // GUI object type="text" for the numbering of each page + this.pageCounter = Engine.GetGUIObjectByName(pageCounterName); + // list of GUI objects + this.children = this.container.children; + // hardcoded in the GUI file, maximum children capable of showing at a time + this.numBoxesCreated = this.children.length; + this.childFunction = childFunction; + this.list = list; + this.selectedIndex = selectedIndex; + this.child = childDimensions; + // Array to set flag for each child + this.helperList = new Uint8Array(this.numBoxesCreated); + + this._generateGrid(); + this.goToPage(this.getPageOfSelected()); +}; + +GridBrowser.prototype.setIndexOfSelected = function (index) +{ + this.selectedIndex = Math.max(0, Math.min(index, this.list.length - 1)); +}; + +GridBrowser.prototype.goToPage = function (pageNumber) +{ + // Set current page + this.currentPage = Math.max(0, Math.min(pageNumber, this.getNumOfPages() - 1)); + + // Update page counter + this.pageCounter.caption = (this.getCurrentPage() + 1) + "/" + this.getNumOfPages(); + + // Update childs' content (generate page) + let nubOfBoxesToShow = this.list.length === 0 ? 0 + : this.getCurrentPage() == this.getNumOfPages() - 1 ? (this.list.length - 1) % this.getMaxNumBoxesInPage() + 1 + : this.getMaxNumBoxesInPage(); + + const startIndex = this.getCurrentPage() * this.getMaxNumBoxesInPage(); + let subList = this.list.slice(startIndex, startIndex + nubOfBoxesToShow); + let subListChildren = this.children.slice(0, nubOfBoxesToShow); + for (let i = 0; i < nubOfBoxesToShow; ++i) + { + this.children[i].hidden = false; + this.childFunction(subList[i], i, subList, startIndex + i, this.list, this.helperList, this.children[i], subListChildren, this.children) + } + for (let i = nubOfBoxesToShow; i < this.numBoxesCreated; ++i) + this.children[i].hidden = true; +}; + +GridBrowser.prototype.getCurrentPage = function () +{ + return this.list.length === 0 ? 0 : this.currentPage; +}; + +GridBrowser.prototype.getPageOfIndex = function (index) +{ + return this.list.length === 0 ? 0 + : (index == -1) ? 0 + : Math.floor(index / this.getMaxNumBoxesInPage()); +}; + +GridBrowser.prototype.getPageOfSelected = function () +{ + return this.getPageOfIndex(this.selectedIndex); +}; + +GridBrowser.prototype.getPageIndexOfSelected = function () +{ + return (this.selectedIndex == -1) ? -1 + : this.list.length === 0 ? -1 + : this.selectedIndex % this.getMaxNumBoxesInPage(); +}; + +GridBrowser.prototype.getMaxNumBoxesInPage = function () +{ + return Math.min(this.nColumns * this.nRows, this.numBoxesCreated); +}; + +// Update number of pages. Always at least 1 page. +GridBrowser.prototype.getNumOfPages = function () +{ + return Math.max(1, Math.ceil(this.list.length / this.getMaxNumBoxesInPage())); +}; + +GridBrowser.prototype.setList = function (list) +{ + this.list = list; + this.goToPage(0); +}; + +GridBrowser.prototype.setChildDimensions = function (childDimensions) +{ + const inSelectedPage = this.getPageOfSelected() === this.getCurrentPage(); + const firstChildIndex = this.getCurrentPage() * this.getMaxNumBoxesInPage(); + this.child = childDimensions; + this._generateGrid(); + const page = inSelectedPage ? this.getPageOfSelected() : this.getPageOfIndex(firstChildIndex) + this.goToPage(page); +}; + + +GridBrowser.prototype.generateGrid = function () +{ + this._generateGrid(); + this.goToPage(this.getPageOfSelected()); +}; + +GridBrowser.prototype._generateGrid = function () +{ + // Update number of columns and rows + let rect = this.container.getComputedSize(); + rect.width = rect.right - rect.left; + rect.height = rect.bottom - rect.top; + + this.nColumns = Math.max(1, Math.floor(rect.width / this.child.width)); + this.nRows = Math.max(1, Math.floor(rect.height / this.child.height)); + this.xCenter = this.child.width * this.nColumns / 2; + this.yCenter = this.child.height * this.nRows / 2; + + // Update child position, dimensions + for (let i = 0; i < this.numBoxesCreated; ++i) + { + const x = i % this.nColumns; + const y = Math.floor(i / this.nColumns); + + let xMin = this.child.width * x; + let xMax = this.child.width * (x + 1); + let yMin = this.child.height * y; + let yMax = this.child.height * (y + 1); + let fxMin = "50%" + (xMin - this.xCenter); + let fxMax = "50%" + (xMax - this.xCenter); + let fyMin = "0%" + (yMin); + let fyMax = "0%" + (yMax); + + let sizeString = [fxMin, fyMin, fxMax, fyMax].join(" "); + + if (this._generateGrid__once !== undefined) + { + animate(this.children[i], { + "size": sizeString + }); + } + else + { + this.children[i].size = sizeString; + if (i + 1 === this.numBoxesCreated) + this._generateGrid__once = true; + } + } +}; + +GridBrowser.prototype.nextPage = function () +{ + this.goToPage((this.getCurrentPage() + 1) % this.getNumOfPages()); +}; + +GridBrowser.prototype.previousPage = function () +{ + this.goToPage((this.getCurrentPage() + this.getNumOfPages() - 1) % this.getNumOfPages()); +}; \ No newline at end of file