Changeset View
Standalone View
binaries/data/mods/public/gui/common/GridBrowser.js
/* | |||||
* 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 | |||||
lyv: Why are these not in the constructor? | |||||
Not Done Inline ActionsNot any specific reason. Seems the constructor choice would be better. nani: Not any specific reason. Seems the constructor choice would be better. | |||||
this.numBoxesCreated = this.children.length; //hardcoded in the GUI file, maximum children capable of showing at a time | |||||
this.childFunction = childFunction; | |||||
//order matters | |||||
Done Inline Actions"GUI objects" elexis: "GUI objects" | |||||
Not Done Inline ActionsSo change xml object to gui object ? nani: So change xml object to gui object ? | |||||
this._setChildDimensions(childWidth, childHeight); | |||||
Not Done Inline Actionsindirection making it more complicated than it needs to be elexis: indirection making it more complicated than it needs to be | |||||
Not Done Inline ActionsI think the variable defines better the meaning of the value. nani: I think the variable defines better the meaning of the value. | |||||
this._updateGrid(); | |||||
this._updateMaxNumBoxesInScreen(); | |||||
this._generateGrid(); | |||||
this._setList(list); | |||||
this._updateNumPages(); | |||||
this._setSelectedChild(selectedChild) | |||||
this._updatePageCounter(); | |||||
this._generatePage(); | |||||
} | |||||
GridBrowser.prototype._setSelectedChild = function(index) | |||||
lyvUnsubmitted Not Done Inline ActionsThese makes it harder to follow. Combine them and possibly add an update() method. lyv: These makes it harder to follow. Combine them and possibly add an update() method. | |||||
{ | |||||
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) | |||||
Done Inline ActionsPass the function to be called as an argument to the constructor or other function. elexis: Pass the function to be called as an argument to the constructor or other function. | |||||
Not Done Inline ActionsCorrect. Passing the function as argument seems simpler. nani: Correct. Passing the function as argument seems simpler. | |||||
{ | |||||
this.list = list; | |||||
} | |||||
Not Done Inline Actionsunnecessary indirection elexis: unnecessary indirection | |||||
Not Done Inline ActionsI think is having setter function homogenizes the function naming convention. nani: I think is having setter function homogenizes the function naming convention. | |||||
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, | |||||
Not Done Inline Actionsunnecessary indirection elexis: unnecessary indirection | |||||
Not Done Inline ActionsSame as the _setList function. nani: Same as the _setList function. | |||||
"height": height | |||||
}; | |||||
} | |||||
Done Inline Actions"" elexis: "" | |||||
Not Done Inline Actionscorrect nani: correct | |||||
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() | |||||
Not Done Inline Actionsthese two functions are always called together.. elexis: these two functions are always called together.. | |||||
Not Done Inline ActionsWhat two functions? nani: What two functions? | |||||
{ | |||||
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); | |||||
Not Done Inline Actionssimplify with min/max or modulo? elexis: simplify with min/max or modulo? | |||||
Not Done Inline ActionsCan't see a way to do it. nani: Can't see a way to do it. | |||||
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() | |||||
Done Inline Actionsunneeded parentheses and Math.max(1, numPages) elexis: unneeded parentheses and Math.max(1, numPages) | |||||
{ | |||||
this.pageCounter.caption = (this.currentPage + 1)+"/"+this.numPages; | |||||
} | |||||
GridBrowser.prototype._setCurrentPage = function(page) | |||||
Done Inline ActionsNo need for template strings (never seen them being used in our JS code either) elexis: No need for template strings (never seen them being used in our JS code either) | |||||
Not Done Inline ActionsWhat is the alternative? nani: What is the alternative? | |||||
Not Done Inline Actionssprintf. Or just regular concatenation if possible. lyv: sprintf. Or just regular concatenation if possible. | |||||
Not Done Inline ActionsI changed to concatenation but I still think string templates are the best option given that reduces needless code duplication of sprintf and is much clear than concatenation. Was sprintf was created before spidermonkey had support for string templates? nani: I changed to concatenation but I still think string templates are the best option given that… | |||||
Not Done Inline ActionsString templates came with ES 2015 IIRC. That file was added in 2014 deducing from a quick file history lookup (probably even earlier). Which raises the question of why its still present? lyv: String templates came with ES 2015 IIRC. That file was added in 2014 deducing from a quick file… | |||||
Not Done Inline Actionssprintf are used in 0ad for translation, the rest of the code uses implicit string conversion elexis: sprintf are used in 0ad for translation, the rest of the code uses implicit string conversion | |||||
{ | |||||
this.currentPage = page % this.numPages; | |||||
} | |||||
Not Done Inline Actionsunnecessary indirection elexis: unnecessary indirection | |||||
Not Done Inline ActionsSame as _setList and _setChildDimensions. nani: Same as _setList and _setChildDimensions. | |||||
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 |
Why are these not in the constructor?