Index: binaries/data/mods/public/gui/common/GridBrowser.js =================================================================== --- binaries/data/mods/public/gui/common/GridBrowser.js +++ binaries/data/mods/public/gui/common/GridBrowser.js @@ -0,0 +1,161 @@ +/** + * 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) + * childWidth,childHeight: dimensions of each grid box + * The grid will ajust in accordance to the containerName object size + * + * To add advanced, more detailed, objects inside each box add pass 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, childWidth, childHeight, childFunction) +{ + this.container = Engine.GetGUIObjectByName(containerName); //GUI object container of the children + this.pageCounter = Engine.GetGUIObjectByName(pageCounterName); //GUI object type="text" for the numbering of each page + this.children = this.container.children; //list of GUI objects + this.numBoxesCreated = this.children.length; //hardcoded in the GUI file, maximum children capable of showing at a time + this.childFunction = childFunction; + this.list = list; + this.selectedIndex = selectedIndex; + + this._setChildDimensions(childWidth, childHeight); + this._generateGrid(); + + this.goToPage(this.getPageOfSelected()); +}; + +GridBrowser.prototype.setIndexOfSelected = function (index) +{ + this.selectedIndex = index; +}; + +GridBrowser.prototype.goToPage = function (pageNumber) +{ + this.currentPage = pageNumber; + this._generatePage(); +}; + +GridBrowser.prototype.getCurrentPage = function () +{ + return this.currentPage; +}; + +GridBrowser.prototype.getPageOfIndex = function (index) +{ + return (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.selectedIndex % this.getMaxNumBoxesInPage(); +}; + +GridBrowser.prototype.setList = function (list) +{ + this.list = list; + this.goToPage(0); +}; + +GridBrowser.prototype._setChildDimensions = function (width, height) +{ + this.child = { "width": width, "height": height }; +}; + +GridBrowser.prototype.setChildDimensions = function (width, height) +{ + const inSelectedPage = this.getPageOfSelected() === this.getCurrentPage(); + const firstChildIndex = this.getCurrentPage() * this.getMaxNumBoxesInPage(); + + this._setChildDimensions(width, height); + this._generateGrid(); + const page = inSelectedPage ? this.getPageOfSelected() : this.getPageOfIndex(firstChildIndex) + this.goToPage(page); +}; + +GridBrowser.prototype.getMaxNumBoxesInPage = function () +{ + return Math.min(this.nColumns * this.nRows, this.numBoxesCreated); +}; + +GridBrowser.prototype.getNumOfPages = function () +{ // Update number of pages. Always at least 1 page. + return Math.max(1, Math.ceil(this.list.length / this.getMaxNumBoxesInPage())); +}; + +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; + + // 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 sizeString = [ fxmin, ymin, fxmax, ymax ].join(" "); + + if (this._generateGrid__once === undefined) + this.children[ i ].size = sizeString; + else + new AnimateGUI(this.children[ i ], { "size": sizeString }); + } + this._generateGrid__once = true; +}; + +GridBrowser.prototype._generatePage = function () +{ + // Update page counter + this.pageCounter.caption = (this.currentPage + 1) + "/" + this.getNumOfPages(); + // Update childs' content + let nubOfBoxesToShow = (this.currentPage == this.getNumOfPages() - 1) ? (this.list.length - 1) % this.getMaxNumBoxesInPage() + 1 : this.getMaxNumBoxesInPage(); + const startIndex = this.currentPage * this.getMaxNumBoxesInPage(); + const endIndex = startIndex + nubOfBoxesToShow; + let subList = this.list.slice(startIndex, endIndex); + + for (let i = 0; i < nubOfBoxesToShow; ++i) + { + this.children[ i ].hidden = false; + this.childFunction(subList[ i ], i, subList, startIndex + i, this.list, this.children[ i ]) + } + for (let i = nubOfBoxesToShow; i < this.numBoxesCreated; ++i) + this.children[ i ].hidden = true; +}; + +GridBrowser.prototype.nextPage = function () +{ + this.goToPage((this.currentPage + 1) % this.getNumOfPages()); +}; + +GridBrowser.prototype.previousPage = function () +{ + this.goToPage((this.currentPage + this.getNumOfPages() - 1) % this.getNumOfPages()); +}; \ No newline at end of file