treeview.js (6898B)
1 /* import-globals-from common.js */ 2 /* import-globals-from events.js */ 3 4 /** 5 * Helper method to start a single XUL tree test. 6 */ 7 function loadXULTreeAndDoTest(aDoTestFunc, aTreeID, aTreeView) { 8 var doTestFunc = aDoTestFunc ? aDoTestFunc : gXULTreeLoadContext.doTestFunc; 9 var treeID = aTreeID ? aTreeID : gXULTreeLoadContext.treeID; 10 var treeView = aTreeView ? aTreeView : gXULTreeLoadContext.treeView; 11 12 let treeNode = getNode(treeID); 13 14 gXULTreeLoadContext.queue = new eventQueue(); 15 gXULTreeLoadContext.queue.push({ 16 treeNode, 17 18 eventSeq: [new invokerChecker(EVENT_REORDER, treeNode)], 19 20 invoke() { 21 this.treeNode.view = treeView; 22 }, 23 24 getID() { 25 return "Load XUL tree " + prettyName(treeID); 26 }, 27 }); 28 gXULTreeLoadContext.queue.onFinish = function () { 29 SimpleTest.executeSoon(doTestFunc); 30 return DO_NOT_FINISH_TEST; 31 }; 32 gXULTreeLoadContext.queue.invoke(); 33 } 34 35 /** 36 * Analogy of addA11yLoadEvent, nice helper to load XUL tree and start the test. 37 */ 38 function addA11yXULTreeLoadEvent(aDoTestFunc, aTreeID, aTreeView) { 39 gXULTreeLoadContext.doTestFunc = aDoTestFunc; 40 gXULTreeLoadContext.treeID = aTreeID; 41 gXULTreeLoadContext.treeView = aTreeView; 42 43 addA11yLoadEvent(loadXULTreeAndDoTest); 44 } 45 46 function nsTableTreeView(aRowCount) { 47 this.__proto__ = new nsTreeView(); 48 49 for (var idx = 0; idx < aRowCount; idx++) { 50 this.mData.push(new treeItem("row" + String(idx) + "_")); 51 } 52 } 53 54 function nsTreeTreeView() { 55 this.__proto__ = new nsTreeView(); 56 57 this.mData = [ 58 new treeItem("row1"), 59 new treeItem("row2_", true, [ 60 new treeItem("row2.1_"), 61 new treeItem("row2.2_"), 62 ]), 63 new treeItem("row3_", false, [ 64 new treeItem("row3.1_"), 65 new treeItem("row3.2_"), 66 ]), 67 new treeItem("row4"), 68 ]; 69 } 70 71 function nsTreeView() { 72 this.mTree = null; 73 this.mData = []; 74 } 75 76 nsTreeView.prototype = { 77 // //////////////////////////////////////////////////////////////////////////// 78 // nsITreeView implementation 79 80 get rowCount() { 81 return this.getRowCountIntl(this.mData); 82 }, 83 setTree: function setTree(aTree) { 84 this.mTree = aTree; 85 }, 86 getCellText: function getCellText(aRow, aCol) { 87 var data = this.getDataForIndex(aRow); 88 if (aCol.id in data.colsText) { 89 return data.colsText[aCol.id]; 90 } 91 92 return data.text + aCol.id; 93 }, 94 getCellValue: function getCellValue(aRow) { 95 var data = this.getDataForIndex(aRow); 96 return data.value; 97 }, 98 getRowProperties: function getRowProperties() { 99 return ""; 100 }, 101 getCellProperties: function getCellProperties(aIndex, aCol) { 102 if (!aCol.cycler) { 103 return ""; 104 } 105 106 var data = this.getDataForIndex(aIndex); 107 return this.mCyclerStates[data.cyclerState]; 108 }, 109 getColumnProperties: function getColumnProperties() { 110 return ""; 111 }, 112 getParentIndex: function getParentIndex(aRowIndex) { 113 var info = this.getInfoByIndex(aRowIndex); 114 return info.parentIndex; 115 }, 116 hasNextSibling: function hasNextSibling() {}, 117 getLevel: function getLevel(aIndex) { 118 var info = this.getInfoByIndex(aIndex); 119 return info.level; 120 }, 121 getImageSrc: function getImageSrc() {}, 122 isContainer: function isContainer(aIndex) { 123 var data = this.getDataForIndex(aIndex); 124 return data.open != undefined; 125 }, 126 isContainerOpen: function isContainerOpen(aIndex) { 127 var data = this.getDataForIndex(aIndex); 128 return data.open; 129 }, 130 isContainerEmpty: function isContainerEmpty(aIndex) { 131 var data = this.getDataForIndex(aIndex); 132 return data.open == undefined; 133 }, 134 isSeparator: function isSeparator() {}, 135 isSorted: function isSorted() {}, 136 toggleOpenState: function toggleOpenState(aIndex) { 137 var data = this.getDataForIndex(aIndex); 138 139 data.open = !data.open; 140 var rowCount = this.getRowCountIntl(data.children); 141 142 if (data.open) { 143 this.mTree.rowCountChanged(aIndex + 1, rowCount); 144 } else { 145 this.mTree.rowCountChanged(aIndex + 1, -rowCount); 146 } 147 }, 148 selectionChanged: function selectionChanged() {}, 149 cycleHeader: function cycleHeader() {}, 150 cycleCell: function cycleCell(aRow, aCol) { 151 var data = this.getDataForIndex(aRow); 152 data.cyclerState = (data.cyclerState + 1) % 3; 153 154 this.mTree.invalidateCell(aRow, aCol); 155 }, 156 isEditable: function isEditable() { 157 return true; 158 }, 159 setCellText: function setCellText(aRow, aCol, aValue) { 160 var data = this.getDataForIndex(aRow); 161 data.colsText[aCol.id] = aValue; 162 }, 163 setCellValue: function setCellValue(aRow, aCol, aValue) { 164 var data = this.getDataForIndex(aRow); 165 data.value = aValue; 166 167 this.mTree.invalidateCell(aRow, aCol); 168 }, 169 170 // //////////////////////////////////////////////////////////////////////////// 171 // public implementation 172 173 appendItem: function appendItem(aText) { 174 this.mData.push(new treeItem(aText)); 175 }, 176 177 // //////////////////////////////////////////////////////////////////////////// 178 // private implementation 179 180 getDataForIndex: function getDataForIndex(aRowIndex) { 181 return this.getInfoByIndex(aRowIndex).data; 182 }, 183 184 getInfoByIndex: function getInfoByIndex(aRowIndex) { 185 var info = { 186 data: null, 187 parentIndex: -1, 188 level: 0, 189 index: -1, 190 }; 191 192 this.getInfoByIndexIntl(aRowIndex, info, this.mData, 0); 193 return info; 194 }, 195 196 getRowCountIntl: function getRowCountIntl(aChildren) { 197 var rowCount = 0; 198 for (var childIdx = 0; childIdx < aChildren.length; childIdx++) { 199 rowCount++; 200 201 var data = aChildren[childIdx]; 202 if (data.open) { 203 rowCount += this.getRowCountIntl(data.children); 204 } 205 } 206 207 return rowCount; 208 }, 209 210 getInfoByIndexIntl: function getInfoByIndexIntl( 211 aRowIdx, 212 aInfo, 213 aChildren, 214 aLevel 215 ) { 216 var rowIdx = aRowIdx; 217 for (var childIdx = 0; childIdx < aChildren.length; childIdx++) { 218 var data = aChildren[childIdx]; 219 220 aInfo.index++; 221 222 if (rowIdx == 0) { 223 aInfo.data = data; 224 aInfo.level = aLevel; 225 return -1; 226 } 227 228 if (data.open) { 229 var parentIdx = aInfo.index; 230 rowIdx = this.getInfoByIndexIntl( 231 rowIdx - 1, 232 aInfo, 233 data.children, 234 aLevel + 1 235 ); 236 237 if (rowIdx == -1) { 238 if (aInfo.parentIndex == -1) { 239 aInfo.parentIndex = parentIdx; 240 } 241 return 0; 242 } 243 } else { 244 rowIdx--; 245 } 246 } 247 248 return rowIdx; 249 }, 250 251 mCyclerStates: ["cyclerState1", "cyclerState2", "cyclerState3"], 252 }; 253 254 function treeItem(aText, aOpen, aChildren) { 255 this.text = aText; 256 this.colsText = {}; 257 this.open = aOpen; 258 this.value = "true"; 259 this.cyclerState = 0; 260 if (aChildren) { 261 this.children = aChildren; 262 } 263 } 264 265 /** 266 * Used in conjunction with loadXULTreeAndDoTest and addA11yXULTreeLoadEvent. 267 */ 268 var gXULTreeLoadContext = { 269 doTestFunc: null, 270 treeID: null, 271 treeView: null, 272 queue: null, 273 };