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,195 @@ +/* + * Function that arranges a list of "boxed-like" GUI objects with centered 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 screen size from when init() method is called + * + * To add advanced, more detailed, objects inside each box redefine + * the function "defineChildren" after the your GridBrowser is instantiated. + * + * For example look at mapbrowser.js implementation. + */ + +// initializer, list is each childen data +function GridBrowser(containerName, pageCounterName, list, selectedChild, 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; + + //order matters + this._setChildDimensions(childWidth, childHeight); + this._updateGrid(); + this._updateMaxNumBoxesInScreen(); + this._generateGrid(); + + this._setList(list); + this._updateNumPages(); + this._setSelectedChild(selectedChild) + this._updatePageCounter(); + + this._generatePage(); +} + +GridBrowser.prototype._setSelectedChild = function(index) +{ + this.selectedChild = index; + this.selectedChild_page = index % this.maxNumBoxesInScreen; + let page = Math.floor(index / this.maxNumBoxesInScreen); + this._setCurrentPage(page); +} + +GridBrowser.prototype.setSelectedChild = function(index) +{ + this._setSelectedChild(index); + this._updatePageCounter(); + this._generatePage(); +} + +GridBrowser.prototype.defineChildren = function(value, subIndex, subArray, childObject, index, array) +{ + //empty onpurpose, add modifications only at the object instances +} + +GridBrowser.prototype._setList = function(list) +{ + this.list = list; +} + +GridBrowser.prototype.setList = function(list) +{ + this._setList(list); + this._updateNumPages(); + this._setSelectedChild(0); + this._updatePageCounter(); + this._generatePage(); + +} + +GridBrowser.prototype._setChildDimensions = function(width, height) +{ + this.child = { + "width": width, + "height": height + }; +} + +GridBrowser.prototype.setChildDimensions = function(width, height) +{ + this._setChildDimensions(width, height); + this._updateGrid(); + this._updateMaxNumBoxesInScreen(); + this._generateGrid(); + this._updateNumPages(); + this._setSelectedChild(this.selectedChild); + this._updatePageCounter(); + this._generatePage(); +} + +GridBrowser.prototype._updateMaxNumBoxesInScreen = function() +{ + this.maxNumBoxesInScreen = Math.min(this.nColumns * this.nRows, this.numBoxesCreated); +} + +GridBrowser.prototype._updateGrid = function() +{ + let rect = this.container.getComputedSize(); + rect.width = Math.max(rect.right - rect.left, 0); + rect.height = Math.max(rect.bottom - rect.top, 0); + + const nColumns = Math.max(1, Math.floor(rect.width / this.child.width)); + const nRows = Math.max(1, Math.floor(rect.height / this.child.height)); + + this.xCenter = this.child.width * nColumns / 2; + + if (nColumns == this.nColumns && nRows == this.nRows) + return false; // same grid as before, no need to update + + this.nColumns = nColumns; + this.nRows = nRows; + + return true; +} + +GridBrowser.prototype.updateGrid = function() +{ + + if (!this._updateGrid()) + return; + this._updateMaxNumBoxesInScreen(); + this._generateGrid(); + this._updateNumPages(); + this._setSelectedChild(this.selectedChild); + this._updatePageCounter(); + this._generatePage(); +} + +GridBrowser.prototype._generateGrid = function() +{ + for (let i = 0; i < this.maxNumBoxesInScreen; ++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); + xmin = "50%" + "-" + this.xCenter + "+" + xmin; + xmax = "50%" + "-" + this.xCenter + "+" + xmax; + + this.children[i].size = [xmin, ymin, xmax, ymax].join(" "); + } +} + +GridBrowser.prototype._generatePage = function() +{ + let nubOfBoxesToShow = (this.currentPage == this.numPages - 1) ? (this.list.length - 1) % this.maxNumBoxesInScreen + 1 : this.maxNumBoxesInScreen; + const startIndex = this.currentPage * this.maxNumBoxesInScreen; + 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, this.children[i], startIndex + i , this.list) + } + + for (let i = nubOfBoxesToShow; i < this.numBoxesCreated; ++i) + this.children[i].hidden = true; +} + +GridBrowser.prototype._updateNumPages = function() +{ + let numPages = Math.ceil(this.list.length / this.maxNumBoxesInScreen); + this.numPages = Math.max(numPages,1); // always at least 1 page +} + +GridBrowser.prototype._updatePageCounter = function() +{ + this.pageCounter.caption = (this.currentPage + 1)+"/"+this.numPages; +} + +GridBrowser.prototype._setCurrentPage = function(page) +{ + this.currentPage = page % this.numPages; +} + +GridBrowser.prototype.displacePage = function(displacement) +{ + this._setCurrentPage(this.currentPage + displacement); + this._updatePageCounter(); + this._generatePage(); +} + +GridBrowser.prototype.nextPage = function() +{ + this.displacePage(1); +} + +GridBrowser.prototype.previousPage = function() +{ + this.displacePage(this.numPages - 1); +} \ No newline at end of file