Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
michael@0 | 1 | <?xml version="1.0"?> |
michael@0 | 2 | <!-- This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 3 | - License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 4 | - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> |
michael@0 | 5 | |
michael@0 | 6 | |
michael@0 | 7 | <!DOCTYPE bindings [ |
michael@0 | 8 | <!ENTITY % treeDTD SYSTEM "chrome://global/locale/tree.dtd"> |
michael@0 | 9 | %treeDTD; |
michael@0 | 10 | ]> |
michael@0 | 11 | |
michael@0 | 12 | <bindings id="treeBindings" |
michael@0 | 13 | xmlns="http://www.mozilla.org/xbl" |
michael@0 | 14 | xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" |
michael@0 | 15 | xmlns:xbl="http://www.mozilla.org/xbl"> |
michael@0 | 16 | |
michael@0 | 17 | <binding id="tree-base" extends="chrome://global/content/bindings/general.xml#basecontrol"> |
michael@0 | 18 | <resources> |
michael@0 | 19 | <stylesheet src="chrome://global/skin/tree.css"/> |
michael@0 | 20 | </resources> |
michael@0 | 21 | <implementation> |
michael@0 | 22 | <method name="_isAccelPressed"> |
michael@0 | 23 | <parameter name="aEvent"/> |
michael@0 | 24 | <body><![CDATA[ |
michael@0 | 25 | # Workaround until bug 302174 is fixed |
michael@0 | 26 | #ifdef XP_MACOSX |
michael@0 | 27 | return aEvent.metaKey; |
michael@0 | 28 | #else |
michael@0 | 29 | return aEvent.ctrlKey; |
michael@0 | 30 | #endif |
michael@0 | 31 | ]]></body> |
michael@0 | 32 | </method> |
michael@0 | 33 | </implementation> |
michael@0 | 34 | </binding> |
michael@0 | 35 | |
michael@0 | 36 | <binding id="tree" extends="chrome://global/content/bindings/tree.xml#tree-base" role="xul:tree"> |
michael@0 | 37 | <content hidevscroll="true" hidehscroll="true" clickthrough="never"> |
michael@0 | 38 | <children includes="treecols"/> |
michael@0 | 39 | <xul:stack class="tree-stack" flex="1"> |
michael@0 | 40 | <xul:treerows class="tree-rows" flex="1" xbl:inherits="hidevscroll"> |
michael@0 | 41 | <children/> |
michael@0 | 42 | </xul:treerows> |
michael@0 | 43 | <xul:textbox anonid="input" class="tree-input" left="0" top="0" hidden="true"/> |
michael@0 | 44 | </xul:stack> |
michael@0 | 45 | <xul:hbox xbl:inherits="collapsed=hidehscroll"> |
michael@0 | 46 | <xul:scrollbar orient="horizontal" flex="1" increment="16" style="position:relative; z-index:2147483647;"/> |
michael@0 | 47 | <xul:scrollcorner xbl:inherits="collapsed=hidevscroll"/> |
michael@0 | 48 | </xul:hbox> |
michael@0 | 49 | </content> |
michael@0 | 50 | |
michael@0 | 51 | <implementation implements="nsIDOMXULTreeElement, nsIDOMXULMultiSelectControlElement"> |
michael@0 | 52 | |
michael@0 | 53 | <!-- ///////////////// nsIDOMXULTreeElement ///////////////// --> |
michael@0 | 54 | |
michael@0 | 55 | <property name="columns" |
michael@0 | 56 | onget="return this.treeBoxObject.columns;"/> |
michael@0 | 57 | |
michael@0 | 58 | <property name="view" |
michael@0 | 59 | onget="return this.treeBoxObject.view;" |
michael@0 | 60 | onset="return this.treeBoxObject.view = val;"/> |
michael@0 | 61 | |
michael@0 | 62 | <property name="body" |
michael@0 | 63 | onget="return this.treeBoxObject.treeBody;"/> |
michael@0 | 64 | |
michael@0 | 65 | <property name="editable" |
michael@0 | 66 | onget="return this.getAttribute('editable') == 'true';" |
michael@0 | 67 | onset="if (val) this.setAttribute('editable', 'true'); |
michael@0 | 68 | else this.removeAttribute('editable'); return val;"/> |
michael@0 | 69 | |
michael@0 | 70 | <!-- ///////////////// nsIDOMXULSelectControlElement ///////////////// --> |
michael@0 | 71 | |
michael@0 | 72 | <!-- ///////////////// nsIDOMXULMultiSelectControlElement ///////////////// --> |
michael@0 | 73 | |
michael@0 | 74 | <property name="selType" |
michael@0 | 75 | onget="return this.getAttribute('seltype')" |
michael@0 | 76 | onset="this.setAttribute('seltype', val); return val;"/> |
michael@0 | 77 | |
michael@0 | 78 | <property name="currentIndex" |
michael@0 | 79 | onget="return this.view ? this.view.selection.currentIndex: - 1;" |
michael@0 | 80 | onset="if (this.view) return this.view.selection.currentIndex = val; return val;"/> |
michael@0 | 81 | |
michael@0 | 82 | <property name="treeBoxObject" |
michael@0 | 83 | onget="return this.boxObject.QueryInterface(Components.interfaces.nsITreeBoxObject);" |
michael@0 | 84 | readonly="true"/> |
michael@0 | 85 | # contentView is obsolete (see bug 202391) |
michael@0 | 86 | <property name="contentView" |
michael@0 | 87 | onget="return this.view; /*.QueryInterface(Components.interfaces.nsITreeContentView)*/" |
michael@0 | 88 | readonly="true"/> |
michael@0 | 89 | # builderView is obsolete (see bug 202393) |
michael@0 | 90 | <property name="builderView" |
michael@0 | 91 | onget="return this.view; /*.QueryInterface(Components.interfaces.nsIXULTreeBuilder)*/" |
michael@0 | 92 | readonly="true"/> |
michael@0 | 93 | <field name="pageUpOrDownMovesSelection"> |
michael@0 | 94 | #ifdef XP_MACOSX |
michael@0 | 95 | false |
michael@0 | 96 | #else |
michael@0 | 97 | true |
michael@0 | 98 | #endif |
michael@0 | 99 | </field> |
michael@0 | 100 | <property name="keepCurrentInView" |
michael@0 | 101 | onget="return (this.getAttribute('keepcurrentinview') == 'true');" |
michael@0 | 102 | onset="if (val) this.setAttribute('keepcurrentinview', 'true'); |
michael@0 | 103 | else this.removeAttribute('keepcurrentinview'); return val;"/> |
michael@0 | 104 | |
michael@0 | 105 | <property name="enableColumnDrag" |
michael@0 | 106 | onget="return this.hasAttribute('enableColumnDrag');" |
michael@0 | 107 | onset="if (val) this.setAttribute('enableColumnDrag', 'true'); |
michael@0 | 108 | else this.removeAttribute('enableColumnDrag'); return val;"/> |
michael@0 | 109 | |
michael@0 | 110 | <field name="_inputField">null</field> |
michael@0 | 111 | |
michael@0 | 112 | <property name="inputField" readonly="true"> |
michael@0 | 113 | <getter><![CDATA[ |
michael@0 | 114 | if (!this._inputField) |
michael@0 | 115 | this._inputField = document.getAnonymousElementByAttribute(this, "anonid", "input"); |
michael@0 | 116 | return this._inputField; |
michael@0 | 117 | ]]></getter> |
michael@0 | 118 | </property> |
michael@0 | 119 | |
michael@0 | 120 | <property name="disableKeyNavigation" |
michael@0 | 121 | onget="return this.hasAttribute('disableKeyNavigation');" |
michael@0 | 122 | onset="if (val) this.setAttribute('disableKeyNavigation', 'true'); |
michael@0 | 123 | else this.removeAttribute('disableKeyNavigation'); return val;"/> |
michael@0 | 124 | |
michael@0 | 125 | <field name="_editingRow">-1</field> |
michael@0 | 126 | <field name="_editingColumn">null</field> |
michael@0 | 127 | |
michael@0 | 128 | <property name="editingRow" readonly="true" |
michael@0 | 129 | onget="return this._editingRow;"/> |
michael@0 | 130 | <property name="editingColumn" readonly="true" |
michael@0 | 131 | onget="return this._editingColumn;"/> |
michael@0 | 132 | |
michael@0 | 133 | <property name="_selectDelay" |
michael@0 | 134 | onset="this.setAttribute('_selectDelay', val);" |
michael@0 | 135 | onget="return this.getAttribute('_selectDelay') || 50;"/> |
michael@0 | 136 | <field name="_columnsDirty">true</field> |
michael@0 | 137 | <field name="_lastKeyTime">0</field> |
michael@0 | 138 | <field name="_incrementalString">""</field> |
michael@0 | 139 | |
michael@0 | 140 | <method name="_ensureColumnOrder"> |
michael@0 | 141 | <body><![CDATA[ |
michael@0 | 142 | if (!this._columnsDirty) |
michael@0 | 143 | return; |
michael@0 | 144 | |
michael@0 | 145 | if (this.columns) { |
michael@0 | 146 | // update the ordinal position of each column to assure that it is |
michael@0 | 147 | // an odd number and 2 positions above its next sibling |
michael@0 | 148 | var cols = []; |
michael@0 | 149 | var i; |
michael@0 | 150 | for (var col = this.columns.getFirstColumn(); col; col = col.getNext()) |
michael@0 | 151 | cols.push(col.element); |
michael@0 | 152 | for (i = 0; i < cols.length; ++i) |
michael@0 | 153 | cols[i].setAttribute("ordinal", (i*2)+1); |
michael@0 | 154 | |
michael@0 | 155 | // update the ordinal positions of splitters to even numbers, so that |
michael@0 | 156 | // they are in between columns |
michael@0 | 157 | var splitters = this.getElementsByTagName("splitter"); |
michael@0 | 158 | for (i = 0; i < splitters.length; ++i) |
michael@0 | 159 | splitters[i].setAttribute("ordinal", (i+1)*2); |
michael@0 | 160 | } |
michael@0 | 161 | this._columnsDirty = false; |
michael@0 | 162 | ]]></body> |
michael@0 | 163 | </method> |
michael@0 | 164 | |
michael@0 | 165 | <method name="_reorderColumn"> |
michael@0 | 166 | <parameter name="aColMove"/> |
michael@0 | 167 | <parameter name="aColBefore"/> |
michael@0 | 168 | <parameter name="aBefore"/> |
michael@0 | 169 | <body><![CDATA[ |
michael@0 | 170 | this._ensureColumnOrder(); |
michael@0 | 171 | |
michael@0 | 172 | var i; |
michael@0 | 173 | var cols = []; |
michael@0 | 174 | var col = this.columns.getColumnFor(aColBefore); |
michael@0 | 175 | if (parseInt(aColBefore.ordinal) < parseInt(aColMove.ordinal)) { |
michael@0 | 176 | if (aBefore) |
michael@0 | 177 | cols.push(aColBefore); |
michael@0 | 178 | for (col = col.getNext(); col.element != aColMove; |
michael@0 | 179 | col = col.getNext()) |
michael@0 | 180 | cols.push(col.element); |
michael@0 | 181 | |
michael@0 | 182 | aColMove.ordinal = cols[0].ordinal; |
michael@0 | 183 | for (i = 0; i < cols.length; ++i) |
michael@0 | 184 | cols[i].ordinal = parseInt(cols[i].ordinal) + 2; |
michael@0 | 185 | } else if (aColBefore.ordinal != aColMove.ordinal) { |
michael@0 | 186 | if (!aBefore) |
michael@0 | 187 | cols.push(aColBefore); |
michael@0 | 188 | for (col = col.getPrevious(); col.element != aColMove; |
michael@0 | 189 | col = col.getPrevious()) |
michael@0 | 190 | cols.push(col.element); |
michael@0 | 191 | |
michael@0 | 192 | aColMove.ordinal = cols[0].ordinal; |
michael@0 | 193 | for (i = 0; i < cols.length; ++i) |
michael@0 | 194 | cols[i].ordinal = parseInt(cols[i].ordinal) - 2; |
michael@0 | 195 | } |
michael@0 | 196 | ]]></body> |
michael@0 | 197 | </method> |
michael@0 | 198 | |
michael@0 | 199 | <method name="_getColumnAtX"> |
michael@0 | 200 | <parameter name="aX"/> |
michael@0 | 201 | <parameter name="aThresh"/> |
michael@0 | 202 | <parameter name="aPos"/> |
michael@0 | 203 | <body><![CDATA[ |
michael@0 | 204 | var isRTL = document.defaultView.getComputedStyle(this, "") |
michael@0 | 205 | .direction == "rtl"; |
michael@0 | 206 | |
michael@0 | 207 | if (aPos) |
michael@0 | 208 | aPos.value = isRTL ? "after" : "before"; |
michael@0 | 209 | |
michael@0 | 210 | var columns = []; |
michael@0 | 211 | var col = this.columns.getFirstColumn(); |
michael@0 | 212 | while (col) { |
michael@0 | 213 | columns.push(col); |
michael@0 | 214 | col = col.getNext(); |
michael@0 | 215 | } |
michael@0 | 216 | if (isRTL) |
michael@0 | 217 | columns.reverse(); |
michael@0 | 218 | var currentX = this.boxObject.x; |
michael@0 | 219 | var adjustedX = aX + this.treeBoxObject.horizontalPosition; |
michael@0 | 220 | for (var i = 0; i < columns.length; ++i) { |
michael@0 | 221 | col = columns[i]; |
michael@0 | 222 | var cw = col.element.boxObject.width; |
michael@0 | 223 | if (cw > 0) { |
michael@0 | 224 | currentX += cw; |
michael@0 | 225 | if (currentX - (cw * aThresh) > adjustedX) |
michael@0 | 226 | return col.element; |
michael@0 | 227 | } |
michael@0 | 228 | } |
michael@0 | 229 | |
michael@0 | 230 | if (aPos) |
michael@0 | 231 | aPos.value = isRTL ? "before" : "after"; |
michael@0 | 232 | return columns.pop().element; |
michael@0 | 233 | ]]></body> |
michael@0 | 234 | </method> |
michael@0 | 235 | |
michael@0 | 236 | <method name="changeOpenState"> |
michael@0 | 237 | <parameter name="row"/> |
michael@0 | 238 | <!-- Optional parameter openState == true or false to set. |
michael@0 | 239 | No openState param == toggle --> |
michael@0 | 240 | <parameter name="openState"/> |
michael@0 | 241 | <body><![CDATA[ |
michael@0 | 242 | if (row < 0 || !this.view.isContainer(row)) { |
michael@0 | 243 | return false; |
michael@0 | 244 | } |
michael@0 | 245 | if (this.view.isContainerOpen(row) != openState) { |
michael@0 | 246 | this.view.toggleOpenState(row); |
michael@0 | 247 | if (row == this.currentIndex) { |
michael@0 | 248 | // Only fire event when current row is expanded or collapsed |
michael@0 | 249 | // because that's all the assistive technology really cares about. |
michael@0 | 250 | var event = document.createEvent('Events'); |
michael@0 | 251 | event.initEvent('OpenStateChange', true, true); |
michael@0 | 252 | this.dispatchEvent(event); |
michael@0 | 253 | } |
michael@0 | 254 | return true; |
michael@0 | 255 | } |
michael@0 | 256 | return false; |
michael@0 | 257 | ]]></body> |
michael@0 | 258 | </method> |
michael@0 | 259 | |
michael@0 | 260 | <property name="_cellSelType"> |
michael@0 | 261 | <getter> |
michael@0 | 262 | <![CDATA[ |
michael@0 | 263 | var seltype = this.selType; |
michael@0 | 264 | if (seltype == "cell" || seltype == "text") |
michael@0 | 265 | return seltype; |
michael@0 | 266 | return null; |
michael@0 | 267 | ]]> |
michael@0 | 268 | </getter> |
michael@0 | 269 | </property> |
michael@0 | 270 | |
michael@0 | 271 | <method name="_getNextColumn"> |
michael@0 | 272 | <parameter name="row"/> |
michael@0 | 273 | <parameter name="left"/> |
michael@0 | 274 | <body><![CDATA[ |
michael@0 | 275 | var col = this.view.selection.currentColumn; |
michael@0 | 276 | if (col) { |
michael@0 | 277 | col = left ? col.getPrevious() : col.getNext(); |
michael@0 | 278 | } |
michael@0 | 279 | else { |
michael@0 | 280 | col = this.columns.getKeyColumn(); |
michael@0 | 281 | } |
michael@0 | 282 | while (col && (col.width == 0 || !col.selectable || |
michael@0 | 283 | !this.view.isSelectable(row, col))) |
michael@0 | 284 | col = left ? col.getPrevious() : col.getNext(); |
michael@0 | 285 | return col; |
michael@0 | 286 | ]]></body> |
michael@0 | 287 | </method> |
michael@0 | 288 | |
michael@0 | 289 | <method name="_keyNavigate"> |
michael@0 | 290 | <parameter name="event"/> |
michael@0 | 291 | <body><![CDATA[ |
michael@0 | 292 | var key = String.fromCharCode(event.charCode).toLowerCase(); |
michael@0 | 293 | if (event.timeStamp - this._lastKeyTime > 1000) |
michael@0 | 294 | this._incrementalString = key; |
michael@0 | 295 | else |
michael@0 | 296 | this._incrementalString += key; |
michael@0 | 297 | this._lastKeyTime = event.timeStamp; |
michael@0 | 298 | |
michael@0 | 299 | var length = this._incrementalString.length; |
michael@0 | 300 | var incrementalString = this._incrementalString; |
michael@0 | 301 | var charIndex = 1; |
michael@0 | 302 | while (charIndex < length && incrementalString[charIndex] == incrementalString[charIndex - 1]) |
michael@0 | 303 | charIndex++; |
michael@0 | 304 | // If all letters in incremental string are same, just try to match the first one |
michael@0 | 305 | if (charIndex == length) { |
michael@0 | 306 | length = 1; |
michael@0 | 307 | incrementalString = incrementalString.substring(0, length); |
michael@0 | 308 | } |
michael@0 | 309 | |
michael@0 | 310 | var keyCol = this.columns.getKeyColumn(); |
michael@0 | 311 | var rowCount = this.view.rowCount; |
michael@0 | 312 | var start = 1; |
michael@0 | 313 | |
michael@0 | 314 | var c = this.currentIndex; |
michael@0 | 315 | if (length > 1) { |
michael@0 | 316 | start = 0; |
michael@0 | 317 | if (c < 0) |
michael@0 | 318 | c = 0; |
michael@0 | 319 | } |
michael@0 | 320 | |
michael@0 | 321 | for (var i = 0; i < rowCount; i++) { |
michael@0 | 322 | var l = (i + start + c) % rowCount; |
michael@0 | 323 | var cellText = this.view.getCellText(l, keyCol); |
michael@0 | 324 | cellText = cellText.substring(0, length).toLowerCase(); |
michael@0 | 325 | if (cellText == incrementalString) |
michael@0 | 326 | return l; |
michael@0 | 327 | } |
michael@0 | 328 | return -1; |
michael@0 | 329 | ]]></body> |
michael@0 | 330 | </method> |
michael@0 | 331 | |
michael@0 | 332 | <method name="startEditing"> |
michael@0 | 333 | <parameter name="row"/> |
michael@0 | 334 | <parameter name="column"/> |
michael@0 | 335 | <body> |
michael@0 | 336 | <![CDATA[ |
michael@0 | 337 | if (!this.editable) |
michael@0 | 338 | return false; |
michael@0 | 339 | if (row < 0 || row >= this.view.rowCount || !column) |
michael@0 | 340 | return false; |
michael@0 | 341 | if (column.type != Components.interfaces.nsITreeColumn.TYPE_TEXT || |
michael@0 | 342 | column.cycler || !this.view.isEditable(row, column)) |
michael@0 | 343 | return false; |
michael@0 | 344 | |
michael@0 | 345 | // Beyond this point, we are going to edit the cell. |
michael@0 | 346 | if (this._editingColumn) |
michael@0 | 347 | this.stopEditing(); |
michael@0 | 348 | |
michael@0 | 349 | var input = this.inputField; |
michael@0 | 350 | |
michael@0 | 351 | var box = this.treeBoxObject; |
michael@0 | 352 | box.ensureCellIsVisible(row, column); |
michael@0 | 353 | |
michael@0 | 354 | // Get the coordinates of the text inside the cell. |
michael@0 | 355 | var textx = {}, texty = {}, textwidth = {}, textheight = {}; |
michael@0 | 356 | var coords = box.getCoordsForCellItem(row, column, "text", |
michael@0 | 357 | textx, texty, textwidth, textheight); |
michael@0 | 358 | |
michael@0 | 359 | // Get the coordinates of the cell itself. |
michael@0 | 360 | var cellx = {}, cellwidth = {}; |
michael@0 | 361 | coords = box.getCoordsForCellItem(row, column, "cell", |
michael@0 | 362 | cellx, {}, cellwidth, {}); |
michael@0 | 363 | |
michael@0 | 364 | // Calculate the top offset of the textbox. |
michael@0 | 365 | var style = window.getComputedStyle(input, ""); |
michael@0 | 366 | var topadj = parseInt(style.borderTopWidth) + parseInt(style.paddingTop); |
michael@0 | 367 | input.top = texty.value - topadj; |
michael@0 | 368 | |
michael@0 | 369 | // The leftside of the textbox is aligned to the left side of the text |
michael@0 | 370 | // in LTR mode, and left side of the cell in RTL mode. |
michael@0 | 371 | var left, widthdiff; |
michael@0 | 372 | if (style.direction == "rtl") { |
michael@0 | 373 | left = cellx.value; |
michael@0 | 374 | widthdiff = cellx.value + cellwidth.value - textx.value - textwidth.value; |
michael@0 | 375 | } else { |
michael@0 | 376 | left = textx.value; |
michael@0 | 377 | widthdiff = textx.value - cellx.value; |
michael@0 | 378 | } |
michael@0 | 379 | |
michael@0 | 380 | input.left = left; |
michael@0 | 381 | input.height = textheight.value + topadj + |
michael@0 | 382 | parseInt(style.borderBottomWidth) + |
michael@0 | 383 | parseInt(style.paddingBottom); |
michael@0 | 384 | input.width = cellwidth.value - widthdiff; |
michael@0 | 385 | input.hidden = false; |
michael@0 | 386 | |
michael@0 | 387 | input.value = this.view.getCellText(row, column); |
michael@0 | 388 | var selectText = function selectText() { |
michael@0 | 389 | input.select(); |
michael@0 | 390 | input.inputField.focus(); |
michael@0 | 391 | } |
michael@0 | 392 | setTimeout(selectText, 0); |
michael@0 | 393 | |
michael@0 | 394 | this._editingRow = row; |
michael@0 | 395 | this._editingColumn = column; |
michael@0 | 396 | |
michael@0 | 397 | this.setAttribute("editing", "true"); |
michael@0 | 398 | return true; |
michael@0 | 399 | ]]> |
michael@0 | 400 | </body> |
michael@0 | 401 | </method> |
michael@0 | 402 | |
michael@0 | 403 | <method name="stopEditing"> |
michael@0 | 404 | <parameter name="accept"/> |
michael@0 | 405 | <body> |
michael@0 | 406 | <![CDATA[ |
michael@0 | 407 | if (!this._editingColumn) |
michael@0 | 408 | return; |
michael@0 | 409 | |
michael@0 | 410 | var input = this.inputField; |
michael@0 | 411 | var editingRow = this._editingRow; |
michael@0 | 412 | var editingColumn = this._editingColumn; |
michael@0 | 413 | this._editingRow = -1; |
michael@0 | 414 | this._editingColumn = null; |
michael@0 | 415 | if (accept) { |
michael@0 | 416 | var value = input.value; |
michael@0 | 417 | this.view.setCellText(editingRow, editingColumn, value); |
michael@0 | 418 | } |
michael@0 | 419 | |
michael@0 | 420 | input.hidden = true; |
michael@0 | 421 | input.value = ""; |
michael@0 | 422 | this.removeAttribute("editing"); |
michael@0 | 423 | ]]> |
michael@0 | 424 | </body> |
michael@0 | 425 | </method> |
michael@0 | 426 | |
michael@0 | 427 | <method name="_moveByOffset"> |
michael@0 | 428 | <parameter name="offset"/> |
michael@0 | 429 | <parameter name="edge"/> |
michael@0 | 430 | <parameter name="event"/> |
michael@0 | 431 | <body> |
michael@0 | 432 | <![CDATA[ |
michael@0 | 433 | if (this._editingColumn || this.view.rowCount == 0) |
michael@0 | 434 | return; |
michael@0 | 435 | |
michael@0 | 436 | if (this._isAccelPressed(event) && this.view.selection.single) { |
michael@0 | 437 | this.treeBoxObject.scrollByLines(offset); |
michael@0 | 438 | return; |
michael@0 | 439 | } |
michael@0 | 440 | |
michael@0 | 441 | var c = this.currentIndex + offset; |
michael@0 | 442 | if (offset > 0 ? c > edge : c < edge) { |
michael@0 | 443 | if (this.view.selection.isSelected(edge) && this.view.selection.count <= 1) |
michael@0 | 444 | return; |
michael@0 | 445 | c = edge; |
michael@0 | 446 | } |
michael@0 | 447 | |
michael@0 | 448 | var cellSelType = this._cellSelType; |
michael@0 | 449 | if (cellSelType) { |
michael@0 | 450 | var column = this.view.selection.currentColumn; |
michael@0 | 451 | if (!column) |
michael@0 | 452 | return; |
michael@0 | 453 | |
michael@0 | 454 | while ((offset > 0 ? c <= edge : c >= edge) && !this.view.isSelectable(c, column)) |
michael@0 | 455 | c += offset; |
michael@0 | 456 | if (offset > 0 ? c > edge : c < edge) |
michael@0 | 457 | return; |
michael@0 | 458 | } |
michael@0 | 459 | |
michael@0 | 460 | if (!this._isAccelPressed(event)) |
michael@0 | 461 | this.view.selection.timedSelect(c, this._selectDelay); |
michael@0 | 462 | else // Ctrl+Up/Down moves the anchor without selecting |
michael@0 | 463 | this.currentIndex = c; |
michael@0 | 464 | this.treeBoxObject.ensureRowIsVisible(c); |
michael@0 | 465 | ]]> |
michael@0 | 466 | </body> |
michael@0 | 467 | </method> |
michael@0 | 468 | |
michael@0 | 469 | <method name="_moveByOffsetShift"> |
michael@0 | 470 | <parameter name="offset"/> |
michael@0 | 471 | <parameter name="edge"/> |
michael@0 | 472 | <parameter name="event"/> |
michael@0 | 473 | <body> |
michael@0 | 474 | <![CDATA[ |
michael@0 | 475 | if (this._editingColumn || this.view.rowCount == 0) |
michael@0 | 476 | return; |
michael@0 | 477 | |
michael@0 | 478 | if (this.view.selection.single) { |
michael@0 | 479 | this.treeBoxObject.scrollByLines(offset); |
michael@0 | 480 | return; |
michael@0 | 481 | } |
michael@0 | 482 | |
michael@0 | 483 | if (this.view.rowCount == 1 && !this.view.selection.isSelected(0)) { |
michael@0 | 484 | this.view.selection.timedSelect(0, this._selectDelay); |
michael@0 | 485 | return; |
michael@0 | 486 | } |
michael@0 | 487 | |
michael@0 | 488 | var c = this.currentIndex; |
michael@0 | 489 | if (c == -1) |
michael@0 | 490 | c = 0; |
michael@0 | 491 | |
michael@0 | 492 | if (c == edge) { |
michael@0 | 493 | if (this.view.selection.isSelected(c)) |
michael@0 | 494 | return; |
michael@0 | 495 | } |
michael@0 | 496 | |
michael@0 | 497 | // Extend the selection from the existing pivot, if any |
michael@0 | 498 | this.view.selection.rangedSelect(-1, c + offset, |
michael@0 | 499 | this._isAccelPressed(event)); |
michael@0 | 500 | this.treeBoxObject.ensureRowIsVisible(c + offset); |
michael@0 | 501 | |
michael@0 | 502 | ]]> |
michael@0 | 503 | </body> |
michael@0 | 504 | </method> |
michael@0 | 505 | |
michael@0 | 506 | <method name="_moveByPage"> |
michael@0 | 507 | <parameter name="offset"/> |
michael@0 | 508 | <parameter name="edge"/> |
michael@0 | 509 | <parameter name="event"/> |
michael@0 | 510 | <body> |
michael@0 | 511 | <![CDATA[ |
michael@0 | 512 | if (this._editingColumn || this.view.rowCount == 0) |
michael@0 | 513 | return; |
michael@0 | 514 | |
michael@0 | 515 | if (this.pageUpOrDownMovesSelection == this._isAccelPressed(event)) { |
michael@0 | 516 | this.treeBoxObject.scrollByPages(offset); |
michael@0 | 517 | return; |
michael@0 | 518 | } |
michael@0 | 519 | |
michael@0 | 520 | if (this.view.rowCount == 1 && !this.view.selection.isSelected(0)) { |
michael@0 | 521 | this.view.selection.timedSelect(0, this._selectDelay); |
michael@0 | 522 | return; |
michael@0 | 523 | } |
michael@0 | 524 | |
michael@0 | 525 | var c = this.currentIndex; |
michael@0 | 526 | if (c == -1) |
michael@0 | 527 | return; |
michael@0 | 528 | |
michael@0 | 529 | if (c == edge && this.view.selection.isSelected(c)) { |
michael@0 | 530 | this.treeBoxObject.ensureRowIsVisible(c); |
michael@0 | 531 | return; |
michael@0 | 532 | } |
michael@0 | 533 | var i = this.treeBoxObject.getFirstVisibleRow(); |
michael@0 | 534 | var p = this.treeBoxObject.getPageLength(); |
michael@0 | 535 | |
michael@0 | 536 | if (offset > 0) { |
michael@0 | 537 | i += p - 1; |
michael@0 | 538 | if (c >= i) { |
michael@0 | 539 | i = c + p; |
michael@0 | 540 | this.treeBoxObject.ensureRowIsVisible(i > edge ? edge : i); |
michael@0 | 541 | } |
michael@0 | 542 | i = i > edge ? edge : i; |
michael@0 | 543 | |
michael@0 | 544 | } else { |
michael@0 | 545 | if (c <= i) { |
michael@0 | 546 | i = c <= p ? 0 : c - p; |
michael@0 | 547 | this.treeBoxObject.ensureRowIsVisible(i); |
michael@0 | 548 | } |
michael@0 | 549 | } |
michael@0 | 550 | this.view.selection.timedSelect(i, this._selectDelay); |
michael@0 | 551 | ]]> |
michael@0 | 552 | </body> |
michael@0 | 553 | </method> |
michael@0 | 554 | |
michael@0 | 555 | <method name="_moveByPageShift"> |
michael@0 | 556 | <parameter name="offset"/> |
michael@0 | 557 | <parameter name="edge"/> |
michael@0 | 558 | <parameter name="event"/> |
michael@0 | 559 | <body> |
michael@0 | 560 | <![CDATA[ |
michael@0 | 561 | if (this._editingColumn || this.view.rowCount == 0) |
michael@0 | 562 | return; |
michael@0 | 563 | |
michael@0 | 564 | if (this.view.rowCount == 1 && !this.view.selection.isSelected(0) && |
michael@0 | 565 | !(this.pageUpOrDownMovesSelection == this._isAccelPressed(event))) { |
michael@0 | 566 | this.view.selection.timedSelect(0, this._selectDelay); |
michael@0 | 567 | return; |
michael@0 | 568 | } |
michael@0 | 569 | |
michael@0 | 570 | if (this.view.selection.single) |
michael@0 | 571 | return; |
michael@0 | 572 | |
michael@0 | 573 | var c = this.currentIndex; |
michael@0 | 574 | if (c == -1) |
michael@0 | 575 | return; |
michael@0 | 576 | if (c == edge && this.view.selection.isSelected(c)) { |
michael@0 | 577 | this.treeBoxObject.ensureRowIsVisible(edge); |
michael@0 | 578 | return; |
michael@0 | 579 | } |
michael@0 | 580 | var i = this.treeBoxObject.getFirstVisibleRow(); |
michael@0 | 581 | var p = this.treeBoxObject.getPageLength(); |
michael@0 | 582 | |
michael@0 | 583 | if (offset > 0) { |
michael@0 | 584 | i += p - 1; |
michael@0 | 585 | if (c >= i) { |
michael@0 | 586 | i = c + p; |
michael@0 | 587 | this.treeBoxObject.ensureRowIsVisible(i > edge ? edge : i); |
michael@0 | 588 | } |
michael@0 | 589 | // Extend the selection from the existing pivot, if any |
michael@0 | 590 | this.view.selection.rangedSelect(-1, i > edge ? edge : i, this._isAccelPressed(event)); |
michael@0 | 591 | |
michael@0 | 592 | } else { |
michael@0 | 593 | |
michael@0 | 594 | if (c <= i) { |
michael@0 | 595 | i = c <= p ? 0 : c - p; |
michael@0 | 596 | this.treeBoxObject.ensureRowIsVisible(i); |
michael@0 | 597 | } |
michael@0 | 598 | // Extend the selection from the existing pivot, if any |
michael@0 | 599 | this.view.selection.rangedSelect(-1, i, this._isAccelPressed(event)); |
michael@0 | 600 | } |
michael@0 | 601 | |
michael@0 | 602 | ]]> |
michael@0 | 603 | </body> |
michael@0 | 604 | </method> |
michael@0 | 605 | |
michael@0 | 606 | <method name="_moveToEdge"> |
michael@0 | 607 | <parameter name="edge"/> |
michael@0 | 608 | <parameter name="event"/> |
michael@0 | 609 | <body> |
michael@0 | 610 | <![CDATA[ |
michael@0 | 611 | if (this._editingColumn || this.view.rowCount == 0) |
michael@0 | 612 | return; |
michael@0 | 613 | |
michael@0 | 614 | if (this.view.selection.isSelected(edge) && this.view.selection.count == 1) { |
michael@0 | 615 | this.currentIndex = edge; |
michael@0 | 616 | return; |
michael@0 | 617 | } |
michael@0 | 618 | |
michael@0 | 619 | // Normal behaviour is to select the first/last row |
michael@0 | 620 | if (!this._isAccelPressed(event)) |
michael@0 | 621 | this.view.selection.timedSelect(edge, this._selectDelay); |
michael@0 | 622 | |
michael@0 | 623 | // In a multiselect tree Ctrl+Home/End moves the anchor |
michael@0 | 624 | else if (!this.view.selection.single) |
michael@0 | 625 | this.currentIndex = edge; |
michael@0 | 626 | |
michael@0 | 627 | this.treeBoxObject.ensureRowIsVisible(edge); |
michael@0 | 628 | ]]> |
michael@0 | 629 | </body> |
michael@0 | 630 | </method> |
michael@0 | 631 | |
michael@0 | 632 | <method name="_moveToEdgeShift"> |
michael@0 | 633 | <parameter name="edge"/> |
michael@0 | 634 | <parameter name="event"/> |
michael@0 | 635 | <body> |
michael@0 | 636 | <![CDATA[ |
michael@0 | 637 | if (this._editingColumn || this.view.rowCount == 0) |
michael@0 | 638 | return; |
michael@0 | 639 | |
michael@0 | 640 | if (this.view.rowCount == 1 && !this.view.selection.isSelected(0)) { |
michael@0 | 641 | this.view.selection.timedSelect(0, this._selectDelay); |
michael@0 | 642 | return; |
michael@0 | 643 | } |
michael@0 | 644 | |
michael@0 | 645 | if (this.view.selection.single || |
michael@0 | 646 | (this.view.selection.isSelected(edge)) && this.view.selection.isSelected(this.currentIndex)) |
michael@0 | 647 | return; |
michael@0 | 648 | |
michael@0 | 649 | // Extend the selection from the existing pivot, if any. |
michael@0 | 650 | // -1 doesn't work here, so using currentIndex instead |
michael@0 | 651 | this.view.selection.rangedSelect(this.currentIndex, edge, this._isAccelPressed(event)); |
michael@0 | 652 | |
michael@0 | 653 | this.treeBoxObject.ensureRowIsVisible(edge); |
michael@0 | 654 | ]]> |
michael@0 | 655 | </body> |
michael@0 | 656 | </method> |
michael@0 | 657 | <method name="_handleEnter"> |
michael@0 | 658 | <parameter name="event"/> |
michael@0 | 659 | <body><![CDATA[ |
michael@0 | 660 | if (this._editingColumn) { |
michael@0 | 661 | this.stopEditing(true); |
michael@0 | 662 | this.focus(); |
michael@0 | 663 | return true; |
michael@0 | 664 | } |
michael@0 | 665 | |
michael@0 | 666 | #ifdef XP_MACOSX |
michael@0 | 667 | // See if we can edit the cell. |
michael@0 | 668 | var row = this.currentIndex; |
michael@0 | 669 | if (this._cellSelType) { |
michael@0 | 670 | var column = this.view.selection.currentColumn; |
michael@0 | 671 | var startedEditing = this.startEditing(row, column); |
michael@0 | 672 | if (startedEditing) |
michael@0 | 673 | return true; |
michael@0 | 674 | } |
michael@0 | 675 | #endif |
michael@0 | 676 | return this.changeOpenState(this.currentIndex); |
michael@0 | 677 | ]]></body> |
michael@0 | 678 | </method> |
michael@0 | 679 | </implementation> |
michael@0 | 680 | |
michael@0 | 681 | <handlers> |
michael@0 | 682 | <handler event="MozMousePixelScroll" preventdefault="true"/> |
michael@0 | 683 | <handler event="DOMMouseScroll" preventdefault="true"> |
michael@0 | 684 | <![CDATA[ |
michael@0 | 685 | if (this._editingColumn) |
michael@0 | 686 | return; |
michael@0 | 687 | if (event.axis == event.HORIZONTAL_AXIS) |
michael@0 | 688 | return; |
michael@0 | 689 | |
michael@0 | 690 | var rows = event.detail; |
michael@0 | 691 | if (rows == UIEvent.SCROLL_PAGE_UP) |
michael@0 | 692 | this.treeBoxObject.scrollByPages(-1); |
michael@0 | 693 | else if (rows == UIEvent.SCROLL_PAGE_DOWN) |
michael@0 | 694 | this.treeBoxObject.scrollByPages(1); |
michael@0 | 695 | else |
michael@0 | 696 | this.treeBoxObject.scrollByLines(rows); |
michael@0 | 697 | ]]> |
michael@0 | 698 | </handler> |
michael@0 | 699 | <handler event="MozSwipeGesture" preventdefault="true"> |
michael@0 | 700 | <![CDATA[ |
michael@0 | 701 | // Figure out which row to show |
michael@0 | 702 | let targetRow = 0; |
michael@0 | 703 | |
michael@0 | 704 | // Only handle swipe gestures up and down |
michael@0 | 705 | switch (event.direction) { |
michael@0 | 706 | case event.DIRECTION_DOWN: |
michael@0 | 707 | targetRow = this.view.rowCount - 1; |
michael@0 | 708 | // Fall through for actual action |
michael@0 | 709 | case event.DIRECTION_UP: |
michael@0 | 710 | this.treeBoxObject.ensureRowIsVisible(targetRow); |
michael@0 | 711 | break; |
michael@0 | 712 | } |
michael@0 | 713 | ]]> |
michael@0 | 714 | </handler> |
michael@0 | 715 | <handler event="select" phase="target" |
michael@0 | 716 | action="if (event.originalTarget == this) this.stopEditing(true);"/> |
michael@0 | 717 | <handler event="focus"> |
michael@0 | 718 | <![CDATA[ |
michael@0 | 719 | this.treeBoxObject.focused = true; |
michael@0 | 720 | if (this.currentIndex == -1 && this.view.rowCount > 0) { |
michael@0 | 721 | this.currentIndex = this.treeBoxObject.getFirstVisibleRow(); |
michael@0 | 722 | } |
michael@0 | 723 | if (this._cellSelType && !this.view.selection.currentColumn) { |
michael@0 | 724 | var col = this._getNextColumn(this.currentIndex, false); |
michael@0 | 725 | this.view.selection.currentColumn = col; |
michael@0 | 726 | } |
michael@0 | 727 | ]]> |
michael@0 | 728 | </handler> |
michael@0 | 729 | <handler event="blur" action="this.treeBoxObject.focused = false;"/> |
michael@0 | 730 | <handler event="blur" phase="capturing" |
michael@0 | 731 | action="if (event.originalTarget == this.inputField.inputField) this.stopEditing(true);"/> |
michael@0 | 732 | <handler event="keydown" keycode="VK_RETURN"> |
michael@0 | 733 | if (this._handleEnter(event)) { |
michael@0 | 734 | event.stopPropagation(); |
michael@0 | 735 | event.preventDefault(); |
michael@0 | 736 | } |
michael@0 | 737 | </handler> |
michael@0 | 738 | #ifndef XP_MACOSX |
michael@0 | 739 | <!-- Use F2 key to enter text editing. --> |
michael@0 | 740 | <handler event="keydown" keycode="VK_F2"> |
michael@0 | 741 | <![CDATA[ |
michael@0 | 742 | if (!this._cellSelType) |
michael@0 | 743 | return; |
michael@0 | 744 | var row = this.currentIndex; |
michael@0 | 745 | var column = this.view.selection.currentColumn; |
michael@0 | 746 | if (this.startEditing(row, column)) |
michael@0 | 747 | event.preventDefault(); |
michael@0 | 748 | ]]> |
michael@0 | 749 | </handler> |
michael@0 | 750 | #endif // XP_MACOSX |
michael@0 | 751 | |
michael@0 | 752 | <handler event="keydown" keycode="VK_ESCAPE"> |
michael@0 | 753 | <![CDATA[ |
michael@0 | 754 | if (this._editingColumn) { |
michael@0 | 755 | this.stopEditing(false); |
michael@0 | 756 | this.focus(); |
michael@0 | 757 | event.stopPropagation(); |
michael@0 | 758 | event.preventDefault(); |
michael@0 | 759 | } |
michael@0 | 760 | ]]> |
michael@0 | 761 | </handler> |
michael@0 | 762 | <handler event="keydown" keycode="VK_LEFT"> |
michael@0 | 763 | <![CDATA[ |
michael@0 | 764 | if (this._editingColumn) |
michael@0 | 765 | return; |
michael@0 | 766 | |
michael@0 | 767 | var row = this.currentIndex; |
michael@0 | 768 | if (row < 0) |
michael@0 | 769 | return; |
michael@0 | 770 | |
michael@0 | 771 | var cellSelType = this._cellSelType; |
michael@0 | 772 | var checkContainers = true; |
michael@0 | 773 | |
michael@0 | 774 | var currentColumn; |
michael@0 | 775 | if (cellSelType) { |
michael@0 | 776 | currentColumn = this.view.selection.currentColumn; |
michael@0 | 777 | if (currentColumn && !currentColumn.primary) |
michael@0 | 778 | checkContainers = false; |
michael@0 | 779 | } |
michael@0 | 780 | |
michael@0 | 781 | if (checkContainers) { |
michael@0 | 782 | if (this.changeOpenState(this.currentIndex, false)) { |
michael@0 | 783 | event.preventDefault(); |
michael@0 | 784 | return; |
michael@0 | 785 | } |
michael@0 | 786 | else { |
michael@0 | 787 | var parentIndex = this.view.getParentIndex(this.currentIndex); |
michael@0 | 788 | if (parentIndex >= 0) { |
michael@0 | 789 | if (cellSelType && !this.view.isSelectable(parentIndex, currentColumn)) { |
michael@0 | 790 | return; |
michael@0 | 791 | } |
michael@0 | 792 | this.view.selection.select(parentIndex); |
michael@0 | 793 | this.treeBoxObject.ensureRowIsVisible(parentIndex); |
michael@0 | 794 | event.preventDefault(); |
michael@0 | 795 | return; |
michael@0 | 796 | } |
michael@0 | 797 | } |
michael@0 | 798 | } |
michael@0 | 799 | |
michael@0 | 800 | if (cellSelType) { |
michael@0 | 801 | var col = this._getNextColumn(row, true); |
michael@0 | 802 | if (col) { |
michael@0 | 803 | this.view.selection.currentColumn = col; |
michael@0 | 804 | this.treeBoxObject.ensureCellIsVisible(row, col); |
michael@0 | 805 | event.preventDefault(); |
michael@0 | 806 | } |
michael@0 | 807 | } |
michael@0 | 808 | ]]> |
michael@0 | 809 | </handler> |
michael@0 | 810 | <handler event="keydown" keycode="VK_RIGHT"> |
michael@0 | 811 | <![CDATA[ |
michael@0 | 812 | if (this._editingColumn) |
michael@0 | 813 | return; |
michael@0 | 814 | |
michael@0 | 815 | var row = this.currentIndex; |
michael@0 | 816 | if (row < 0) |
michael@0 | 817 | return; |
michael@0 | 818 | |
michael@0 | 819 | var cellSelType = this._cellSelType; |
michael@0 | 820 | var checkContainers = true; |
michael@0 | 821 | |
michael@0 | 822 | var currentColumn; |
michael@0 | 823 | if (cellSelType) { |
michael@0 | 824 | currentColumn = this.view.selection.currentColumn; |
michael@0 | 825 | if (currentColumn && !currentColumn.primary) |
michael@0 | 826 | checkContainers = false; |
michael@0 | 827 | } |
michael@0 | 828 | |
michael@0 | 829 | if (checkContainers) { |
michael@0 | 830 | if (this.changeOpenState(row, true)) { |
michael@0 | 831 | event.preventDefault(); |
michael@0 | 832 | return; |
michael@0 | 833 | } |
michael@0 | 834 | else { |
michael@0 | 835 | var c = row + 1; |
michael@0 | 836 | var view = this.view; |
michael@0 | 837 | if (c < view.rowCount && |
michael@0 | 838 | view.getParentIndex(c) == row) { |
michael@0 | 839 | // If already opened, select the first child. |
michael@0 | 840 | // The getParentIndex test above ensures that the children |
michael@0 | 841 | // are already populated and ready. |
michael@0 | 842 | if (cellSelType && !this.view.isSelectable(c , currentColumn)) { |
michael@0 | 843 | var col = this._getNextColumn(c, false); |
michael@0 | 844 | if (col) { |
michael@0 | 845 | this.view.selection.currentColumn = col; |
michael@0 | 846 | } |
michael@0 | 847 | } |
michael@0 | 848 | this.view.selection.timedSelect(c, this._selectDelay); |
michael@0 | 849 | this.treeBoxObject.ensureRowIsVisible(c); |
michael@0 | 850 | event.preventDefault(); |
michael@0 | 851 | return; |
michael@0 | 852 | } |
michael@0 | 853 | } |
michael@0 | 854 | } |
michael@0 | 855 | |
michael@0 | 856 | if (cellSelType) { |
michael@0 | 857 | var col = this._getNextColumn(row, false); |
michael@0 | 858 | if (col) { |
michael@0 | 859 | this.view.selection.currentColumn = col; |
michael@0 | 860 | this.treeBoxObject.ensureCellIsVisible(row, col); |
michael@0 | 861 | event.preventDefault(); |
michael@0 | 862 | } |
michael@0 | 863 | } |
michael@0 | 864 | ]]> |
michael@0 | 865 | </handler> |
michael@0 | 866 | <handler event="keydown" keycode="VK_UP" preventdefault="true" |
michael@0 | 867 | modifiers="accel any" action="_moveByOffset(-1, 0, event);"/> |
michael@0 | 868 | <handler event="keydown" keycode="VK_DOWN" preventdefault="true" |
michael@0 | 869 | modifiers="accel any" action="_moveByOffset(1, this.view.rowCount - 1, event);"/> |
michael@0 | 870 | <handler event="keydown" keycode="VK_UP" preventdefault="true" |
michael@0 | 871 | modifiers="accel any, shift" action="_moveByOffsetShift(-1, 0, event);"/> |
michael@0 | 872 | <handler event="keydown" keycode="VK_DOWN" preventdefault="true" |
michael@0 | 873 | modifiers="accel any, shift" action="_moveByOffsetShift(1, this.view.rowCount - 1, event);"/> |
michael@0 | 874 | <handler event="keydown" keycode="VK_PAGE_UP" preventdefault="true" |
michael@0 | 875 | modifiers="accel any" action="_moveByPage(-1, 0, event);"/> |
michael@0 | 876 | <handler event="keydown" keycode="VK_PAGE_DOWN" preventdefault="true" |
michael@0 | 877 | modifiers="accel any" action="_moveByPage(1, this.view.rowCount - 1, event);"/> |
michael@0 | 878 | <handler event="keydown" keycode="VK_PAGE_UP" preventdefault="true" |
michael@0 | 879 | modifiers="accel any, shift" action="_moveByPageShift(-1, 0, event);"/> |
michael@0 | 880 | <handler event="keydown" keycode="VK_PAGE_DOWN" preventdefault="true" |
michael@0 | 881 | modifiers="accel any, shift" action="_moveByPageShift(1, this.view.rowCount - 1, event);"/> |
michael@0 | 882 | <handler event="keydown" keycode="VK_HOME" preventdefault="true" |
michael@0 | 883 | modifiers="accel any" action="_moveToEdge(0, event);"/> |
michael@0 | 884 | <handler event="keydown" keycode="VK_END" preventdefault="true" |
michael@0 | 885 | modifiers="accel any" action="_moveToEdge(this.view.rowCount - 1, event);"/> |
michael@0 | 886 | <handler event="keydown" keycode="VK_HOME" preventdefault="true" |
michael@0 | 887 | modifiers="accel any, shift" action="_moveToEdgeShift(0, event);"/> |
michael@0 | 888 | <handler event="keydown" keycode="VK_END" preventdefault="true" |
michael@0 | 889 | modifiers="accel any, shift" action="_moveToEdgeShift(this.view.rowCount - 1, event);"/> |
michael@0 | 890 | <handler event="keypress"> |
michael@0 | 891 | <![CDATA[ |
michael@0 | 892 | if (this._editingColumn) |
michael@0 | 893 | return; |
michael@0 | 894 | |
michael@0 | 895 | if (event.charCode == ' '.charCodeAt(0)) { |
michael@0 | 896 | var c = this.currentIndex; |
michael@0 | 897 | if (!this.view.selection.isSelected(c) || |
michael@0 | 898 | (!this.view.selection.single && this._isAccelPressed(event))) { |
michael@0 | 899 | this.view.selection.toggleSelect(c); |
michael@0 | 900 | event.preventDefault(); |
michael@0 | 901 | } |
michael@0 | 902 | } |
michael@0 | 903 | else if (!this.disableKeyNavigation && event.charCode > 0 && |
michael@0 | 904 | !event.altKey && !this._isAccelPressed(event) && |
michael@0 | 905 | !event.metaKey && !event.ctrlKey) { |
michael@0 | 906 | var l = this._keyNavigate(event); |
michael@0 | 907 | if (l >= 0) { |
michael@0 | 908 | this.view.selection.timedSelect(l, this._selectDelay); |
michael@0 | 909 | this.treeBoxObject.ensureRowIsVisible(l); |
michael@0 | 910 | } |
michael@0 | 911 | event.preventDefault(); |
michael@0 | 912 | } |
michael@0 | 913 | ]]> |
michael@0 | 914 | </handler> |
michael@0 | 915 | </handlers> |
michael@0 | 916 | </binding> |
michael@0 | 917 | |
michael@0 | 918 | <binding id="treecols" role="xul:treecolumns"> |
michael@0 | 919 | <resources> |
michael@0 | 920 | <stylesheet src="chrome://global/skin/tree.css"/> |
michael@0 | 921 | </resources> |
michael@0 | 922 | <content orient="horizontal"> |
michael@0 | 923 | <xul:hbox class="tree-scrollable-columns" flex="1"> |
michael@0 | 924 | <children includes="treecol|splitter"/> |
michael@0 | 925 | </xul:hbox> |
michael@0 | 926 | <xul:treecolpicker class="treecol-image" fixed="true" xbl:inherits="tooltiptext=pickertooltiptext"/> |
michael@0 | 927 | </content> |
michael@0 | 928 | <implementation> |
michael@0 | 929 | <constructor><![CDATA[ |
michael@0 | 930 | // Set resizeafter="farthest" on the splitters if nothing else has been |
michael@0 | 931 | // specified. |
michael@0 | 932 | Array.forEach(this.getElementsByTagName("splitter"), function (splitter) { |
michael@0 | 933 | if (!splitter.hasAttribute("resizeafter")) |
michael@0 | 934 | splitter.setAttribute("resizeafter", "farthest"); |
michael@0 | 935 | }); |
michael@0 | 936 | ]]></constructor> |
michael@0 | 937 | </implementation> |
michael@0 | 938 | </binding> |
michael@0 | 939 | |
michael@0 | 940 | <binding id="treerows" extends="chrome://global/content/bindings/tree.xml#tree-base"> |
michael@0 | 941 | <content> |
michael@0 | 942 | <xul:hbox flex="1" class="tree-bodybox"> |
michael@0 | 943 | <children/> |
michael@0 | 944 | </xul:hbox> |
michael@0 | 945 | <xul:scrollbar height="0" minwidth="0" minheight="0" orient="vertical" xbl:inherits="collapsed=hidevscroll" style="position:relative; z-index:2147483647;"/> |
michael@0 | 946 | </content> |
michael@0 | 947 | <handlers> |
michael@0 | 948 | <handler event="underflow"> |
michael@0 | 949 | <![CDATA[ |
michael@0 | 950 | // Scrollport event orientation |
michael@0 | 951 | // 0: vertical |
michael@0 | 952 | // 1: horizontal |
michael@0 | 953 | // 2: both (not used) |
michael@0 | 954 | var tree = document.getBindingParent(this); |
michael@0 | 955 | if (event.detail == 1) |
michael@0 | 956 | tree.setAttribute("hidehscroll", "true"); |
michael@0 | 957 | else if (event.detail == 0) |
michael@0 | 958 | tree.setAttribute("hidevscroll", "true"); |
michael@0 | 959 | event.stopPropagation(); |
michael@0 | 960 | ]]> |
michael@0 | 961 | </handler> |
michael@0 | 962 | <handler event="overflow"> |
michael@0 | 963 | <![CDATA[ |
michael@0 | 964 | var tree = document.getBindingParent(this); |
michael@0 | 965 | if (event.detail == 1) |
michael@0 | 966 | tree.removeAttribute("hidehscroll"); |
michael@0 | 967 | else if (event.detail == 0) |
michael@0 | 968 | tree.removeAttribute("hidevscroll"); |
michael@0 | 969 | event.stopPropagation(); |
michael@0 | 970 | ]]> |
michael@0 | 971 | </handler> |
michael@0 | 972 | </handlers> |
michael@0 | 973 | </binding> |
michael@0 | 974 | |
michael@0 | 975 | <binding id="treebody" extends="chrome://global/content/bindings/tree.xml#tree-base"> |
michael@0 | 976 | <implementation> |
michael@0 | 977 | <constructor> |
michael@0 | 978 | if ("_ensureColumnOrder" in this.parentNode) |
michael@0 | 979 | this.parentNode._ensureColumnOrder(); |
michael@0 | 980 | </constructor> |
michael@0 | 981 | |
michael@0 | 982 | <field name="_lastSelectedRow"> |
michael@0 | 983 | -1 |
michael@0 | 984 | </field> |
michael@0 | 985 | </implementation> |
michael@0 | 986 | <handlers> |
michael@0 | 987 | <!-- If there is no modifier key, we select on mousedown, not |
michael@0 | 988 | click, so that drags work correctly. --> |
michael@0 | 989 | <handler event="mousedown" clickcount="1"> |
michael@0 | 990 | <![CDATA[ |
michael@0 | 991 | if (this.parentNode.disabled) |
michael@0 | 992 | return; |
michael@0 | 993 | if (((!this._isAccelPressed(event) || |
michael@0 | 994 | !this.parentNode.pageUpOrDownMovesSelection) && |
michael@0 | 995 | !event.shiftKey && !event.metaKey) || |
michael@0 | 996 | this.parentNode.view.selection.single) { |
michael@0 | 997 | var row = {}; |
michael@0 | 998 | var col = {}; |
michael@0 | 999 | var obj = {}; |
michael@0 | 1000 | var b = this.parentNode.treeBoxObject; |
michael@0 | 1001 | b.getCellAt(event.clientX, event.clientY, row, col, obj); |
michael@0 | 1002 | |
michael@0 | 1003 | // save off the last selected row |
michael@0 | 1004 | this._lastSelectedRow = row.value; |
michael@0 | 1005 | |
michael@0 | 1006 | if (row.value == -1) |
michael@0 | 1007 | return; |
michael@0 | 1008 | |
michael@0 | 1009 | if (obj.value == "twisty") |
michael@0 | 1010 | return; |
michael@0 | 1011 | |
michael@0 | 1012 | if (col.value) { |
michael@0 | 1013 | if (col.value.cycler) { |
michael@0 | 1014 | b.view.cycleCell(row.value, col.value); |
michael@0 | 1015 | return; |
michael@0 | 1016 | } else if (col.value.type == Components.interfaces.nsITreeColumn.TYPE_CHECKBOX) { |
michael@0 | 1017 | if (this.parentNode.editable && col.value.editable && |
michael@0 | 1018 | b.view.isEditable(row.value, col.value)) { |
michael@0 | 1019 | var value = b.view.getCellValue(row.value, col.value); |
michael@0 | 1020 | value = value == "true" ? "false" : "true"; |
michael@0 | 1021 | b.view.setCellValue(row.value, col.value, value); |
michael@0 | 1022 | return; |
michael@0 | 1023 | } |
michael@0 | 1024 | } |
michael@0 | 1025 | } |
michael@0 | 1026 | |
michael@0 | 1027 | var cellSelType = this.parentNode._cellSelType; |
michael@0 | 1028 | if (cellSelType == "text" && obj.value != "text" && obj.value != "image") |
michael@0 | 1029 | return; |
michael@0 | 1030 | |
michael@0 | 1031 | if (cellSelType) { |
michael@0 | 1032 | if (!col.value.selectable || |
michael@0 | 1033 | !b.view.isSelectable(row.value, col.value)) { |
michael@0 | 1034 | return; |
michael@0 | 1035 | } |
michael@0 | 1036 | } |
michael@0 | 1037 | |
michael@0 | 1038 | if (!b.view.selection.isSelected(row.value)) { |
michael@0 | 1039 | b.view.selection.select(row.value); |
michael@0 | 1040 | b.ensureRowIsVisible(row.value); |
michael@0 | 1041 | } |
michael@0 | 1042 | |
michael@0 | 1043 | if (cellSelType) { |
michael@0 | 1044 | b.view.selection.currentColumn = col.value; |
michael@0 | 1045 | } |
michael@0 | 1046 | } |
michael@0 | 1047 | ]]> |
michael@0 | 1048 | </handler> |
michael@0 | 1049 | |
michael@0 | 1050 | <!-- On a click (up+down on the same item), deselect everything |
michael@0 | 1051 | except this item. --> |
michael@0 | 1052 | <handler event="click" button="0" clickcount="1"> |
michael@0 | 1053 | <![CDATA[ |
michael@0 | 1054 | if (this.parentNode.disabled) |
michael@0 | 1055 | return; |
michael@0 | 1056 | var row = {}; |
michael@0 | 1057 | var col = {}; |
michael@0 | 1058 | var obj = {}; |
michael@0 | 1059 | var b = this.parentNode.treeBoxObject; |
michael@0 | 1060 | b.getCellAt(event.clientX, event.clientY, row, col, obj); |
michael@0 | 1061 | |
michael@0 | 1062 | if (row.value == -1) |
michael@0 | 1063 | return; |
michael@0 | 1064 | |
michael@0 | 1065 | if (obj.value == "twisty") { |
michael@0 | 1066 | if (b.view.selection.currentIndex >= 0 && |
michael@0 | 1067 | b.view.isContainerOpen(row.value)) { |
michael@0 | 1068 | var parentIndex = b.view.getParentIndex(b.view.selection.currentIndex); |
michael@0 | 1069 | while (parentIndex >= 0 && parentIndex != row.value) |
michael@0 | 1070 | parentIndex = b.view.getParentIndex(parentIndex); |
michael@0 | 1071 | if (parentIndex == row.value) { |
michael@0 | 1072 | var parentSelectable = true; |
michael@0 | 1073 | if (this.parentNode._cellSelType) { |
michael@0 | 1074 | var currentColumn = b.view.selection.currentColumn; |
michael@0 | 1075 | if (!b.view.isSelectable(parentIndex, currentColumn)) |
michael@0 | 1076 | parentSelectable = false; |
michael@0 | 1077 | } |
michael@0 | 1078 | if (parentSelectable) |
michael@0 | 1079 | b.view.selection.select(parentIndex); |
michael@0 | 1080 | } |
michael@0 | 1081 | } |
michael@0 | 1082 | this.parentNode.changeOpenState(row.value); |
michael@0 | 1083 | return; |
michael@0 | 1084 | } |
michael@0 | 1085 | |
michael@0 | 1086 | if (! b.view.selection.single) { |
michael@0 | 1087 | var augment = this._isAccelPressed(event); |
michael@0 | 1088 | if (event.shiftKey) { |
michael@0 | 1089 | b.view.selection.rangedSelect(-1, row.value, augment); |
michael@0 | 1090 | b.ensureRowIsVisible(row.value); |
michael@0 | 1091 | return; |
michael@0 | 1092 | } |
michael@0 | 1093 | if (augment) { |
michael@0 | 1094 | b.view.selection.toggleSelect(row.value); |
michael@0 | 1095 | b.ensureRowIsVisible(row.value); |
michael@0 | 1096 | b.view.selection.currentIndex = row.value; |
michael@0 | 1097 | return; |
michael@0 | 1098 | } |
michael@0 | 1099 | } |
michael@0 | 1100 | |
michael@0 | 1101 | /* We want to deselect all the selected items except what was |
michael@0 | 1102 | clicked, UNLESS it was a right-click. We have to do this |
michael@0 | 1103 | in click rather than mousedown so that you can drag a |
michael@0 | 1104 | selected group of items */ |
michael@0 | 1105 | |
michael@0 | 1106 | if (!col.value) return; |
michael@0 | 1107 | |
michael@0 | 1108 | // if the last row has changed in between the time we |
michael@0 | 1109 | // mousedown and the time we click, don't fire the select handler. |
michael@0 | 1110 | // see bug #92366 |
michael@0 | 1111 | if (!col.value.cycler && this._lastSelectedRow == row.value && |
michael@0 | 1112 | col.value.type != Components.interfaces.nsITreeColumn.TYPE_CHECKBOX) { |
michael@0 | 1113 | |
michael@0 | 1114 | var cellSelType = this.parentNode._cellSelType; |
michael@0 | 1115 | if (cellSelType == "text" && obj.value != "text" && obj.value != "image") |
michael@0 | 1116 | return; |
michael@0 | 1117 | |
michael@0 | 1118 | if (cellSelType) { |
michael@0 | 1119 | if (!col.value.selectable || |
michael@0 | 1120 | !b.view.isSelectable(row.value, col.value)) { |
michael@0 | 1121 | return; |
michael@0 | 1122 | } |
michael@0 | 1123 | } |
michael@0 | 1124 | |
michael@0 | 1125 | b.view.selection.select(row.value); |
michael@0 | 1126 | b.ensureRowIsVisible(row.value); |
michael@0 | 1127 | |
michael@0 | 1128 | if (cellSelType) { |
michael@0 | 1129 | b.view.selection.currentColumn = col.value; |
michael@0 | 1130 | } |
michael@0 | 1131 | } |
michael@0 | 1132 | ]]> |
michael@0 | 1133 | </handler> |
michael@0 | 1134 | |
michael@0 | 1135 | <!-- double-click --> |
michael@0 | 1136 | <handler event="click" clickcount="2"> |
michael@0 | 1137 | <![CDATA[ |
michael@0 | 1138 | if (this.parentNode.disabled) |
michael@0 | 1139 | return; |
michael@0 | 1140 | var tbo = this.parentNode.treeBoxObject; |
michael@0 | 1141 | var row = tbo.view.selection.currentIndex; |
michael@0 | 1142 | if (row == -1) |
michael@0 | 1143 | return; |
michael@0 | 1144 | |
michael@0 | 1145 | var col = {}; |
michael@0 | 1146 | var obj = {}; |
michael@0 | 1147 | tbo.getCellAt(event.clientX, event.clientY, {}, col, obj); |
michael@0 | 1148 | |
michael@0 | 1149 | if (obj.value != "twisty") |
michael@0 | 1150 | this.parentNode.startEditing(row, col.value); |
michael@0 | 1151 | |
michael@0 | 1152 | if (this.parentNode._editingColumn || !tbo.view.isContainer(row)) |
michael@0 | 1153 | return; |
michael@0 | 1154 | |
michael@0 | 1155 | // Cyclers and twisties respond to single clicks, not double clicks |
michael@0 | 1156 | if (col.value != -1 && !col.value.cycler && obj.value != "twisty") |
michael@0 | 1157 | this.parentNode.changeOpenState(row); |
michael@0 | 1158 | ]]> |
michael@0 | 1159 | </handler> |
michael@0 | 1160 | |
michael@0 | 1161 | </handlers> |
michael@0 | 1162 | </binding> |
michael@0 | 1163 | |
michael@0 | 1164 | <binding id="treecol-base" role="xul:treecolumnitem" |
michael@0 | 1165 | extends="chrome://global/content/bindings/tree.xml#tree-base"> |
michael@0 | 1166 | <implementation> |
michael@0 | 1167 | <constructor> |
michael@0 | 1168 | this.parentNode.parentNode._columnsDirty = true; |
michael@0 | 1169 | </constructor> |
michael@0 | 1170 | |
michael@0 | 1171 | <property name="ordinal"> |
michael@0 | 1172 | <getter><![CDATA[ |
michael@0 | 1173 | var val = this.getAttribute("ordinal"); |
michael@0 | 1174 | return "" + (val == "" ? 1 : (val == "0" ? 0 : parseInt(val))); |
michael@0 | 1175 | ]]></getter> |
michael@0 | 1176 | <setter><![CDATA[ |
michael@0 | 1177 | this.setAttribute("ordinal", val); |
michael@0 | 1178 | return val; |
michael@0 | 1179 | ]]></setter> |
michael@0 | 1180 | </property> |
michael@0 | 1181 | |
michael@0 | 1182 | <property name="_previousVisibleColumn"> |
michael@0 | 1183 | <getter><![CDATA[ |
michael@0 | 1184 | var sib = this.boxObject.previousSibling; |
michael@0 | 1185 | while (sib) { |
michael@0 | 1186 | if (sib.localName == "treecol" && sib.boxObject.width > 0 && sib.parentNode == this.parentNode) |
michael@0 | 1187 | return sib; |
michael@0 | 1188 | sib = sib.boxObject.previousSibling; |
michael@0 | 1189 | } |
michael@0 | 1190 | return null; |
michael@0 | 1191 | ]]></getter> |
michael@0 | 1192 | </property> |
michael@0 | 1193 | |
michael@0 | 1194 | <method name="_onDragMouseMove"> |
michael@0 | 1195 | <parameter name="aEvent"/> |
michael@0 | 1196 | <body><![CDATA[ |
michael@0 | 1197 | var col = document.treecolDragging; |
michael@0 | 1198 | if (!col) return; |
michael@0 | 1199 | |
michael@0 | 1200 | // determine if we have moved the mouse far enough |
michael@0 | 1201 | // to initiate a drag |
michael@0 | 1202 | if (col.mDragGesturing) { |
michael@0 | 1203 | if (Math.abs(aEvent.clientX - col.mStartDragX) < 5 && |
michael@0 | 1204 | Math.abs(aEvent.clientY - col.mStartDragY) < 5) { |
michael@0 | 1205 | return; |
michael@0 | 1206 | } else { |
michael@0 | 1207 | col.mDragGesturing = false; |
michael@0 | 1208 | col.setAttribute("dragging", "true"); |
michael@0 | 1209 | window.addEventListener("click", col._onDragMouseClick, true); |
michael@0 | 1210 | } |
michael@0 | 1211 | } |
michael@0 | 1212 | |
michael@0 | 1213 | var pos = {}; |
michael@0 | 1214 | var targetCol = col.parentNode.parentNode._getColumnAtX(aEvent.clientX, 0.5, pos); |
michael@0 | 1215 | |
michael@0 | 1216 | // bail if we haven't mousemoved to a different column |
michael@0 | 1217 | if (col.mTargetCol == targetCol && col.mTargetDir == pos.value) |
michael@0 | 1218 | return; |
michael@0 | 1219 | |
michael@0 | 1220 | var tree = col.parentNode.parentNode; |
michael@0 | 1221 | var sib; |
michael@0 | 1222 | var column; |
michael@0 | 1223 | if (col.mTargetCol) { |
michael@0 | 1224 | // remove previous insertbefore/after attributes |
michael@0 | 1225 | col.mTargetCol.removeAttribute("insertbefore"); |
michael@0 | 1226 | col.mTargetCol.removeAttribute("insertafter"); |
michael@0 | 1227 | column = tree.columns.getColumnFor(col.mTargetCol); |
michael@0 | 1228 | tree.treeBoxObject.invalidateColumn(column); |
michael@0 | 1229 | sib = col.mTargetCol._previousVisibleColumn; |
michael@0 | 1230 | if (sib) { |
michael@0 | 1231 | sib.removeAttribute("insertafter"); |
michael@0 | 1232 | column = tree.columns.getColumnFor(sib); |
michael@0 | 1233 | tree.treeBoxObject.invalidateColumn(column); |
michael@0 | 1234 | } |
michael@0 | 1235 | col.mTargetCol = null; |
michael@0 | 1236 | col.mTargetDir = null; |
michael@0 | 1237 | } |
michael@0 | 1238 | |
michael@0 | 1239 | if (targetCol) { |
michael@0 | 1240 | // set insertbefore/after attributes |
michael@0 | 1241 | if (pos.value == "after") { |
michael@0 | 1242 | targetCol.setAttribute("insertafter", "true"); |
michael@0 | 1243 | } else { |
michael@0 | 1244 | targetCol.setAttribute("insertbefore", "true"); |
michael@0 | 1245 | sib = targetCol._previousVisibleColumn; |
michael@0 | 1246 | if (sib) { |
michael@0 | 1247 | sib.setAttribute("insertafter", "true"); |
michael@0 | 1248 | column = tree.columns.getColumnFor(sib); |
michael@0 | 1249 | tree.treeBoxObject.invalidateColumn(column); |
michael@0 | 1250 | } |
michael@0 | 1251 | } |
michael@0 | 1252 | column = tree.columns.getColumnFor(targetCol); |
michael@0 | 1253 | tree.treeBoxObject.invalidateColumn(column); |
michael@0 | 1254 | col.mTargetCol = targetCol; |
michael@0 | 1255 | col.mTargetDir = pos.value; |
michael@0 | 1256 | } |
michael@0 | 1257 | ]]></body> |
michael@0 | 1258 | </method> |
michael@0 | 1259 | |
michael@0 | 1260 | <method name="_onDragMouseUp"> |
michael@0 | 1261 | <parameter name="aEvent"/> |
michael@0 | 1262 | <body><![CDATA[ |
michael@0 | 1263 | var col = document.treecolDragging; |
michael@0 | 1264 | if (!col) return; |
michael@0 | 1265 | |
michael@0 | 1266 | if (!col.mDragGesturing) { |
michael@0 | 1267 | if (col.mTargetCol) { |
michael@0 | 1268 | // remove insertbefore/after attributes |
michael@0 | 1269 | var before = col.mTargetCol.hasAttribute("insertbefore"); |
michael@0 | 1270 | col.mTargetCol.removeAttribute(before ? "insertbefore" : "insertafter"); |
michael@0 | 1271 | |
michael@0 | 1272 | var sib = col.mTargetCol._previousVisibleColumn; |
michael@0 | 1273 | if (before && sib) { |
michael@0 | 1274 | sib.removeAttribute("insertafter"); |
michael@0 | 1275 | } |
michael@0 | 1276 | |
michael@0 | 1277 | // Move the column only if it will result in a different column |
michael@0 | 1278 | // ordering |
michael@0 | 1279 | var move = true; |
michael@0 | 1280 | |
michael@0 | 1281 | // If this is a before move and the previous visible column is |
michael@0 | 1282 | // the same as the column we're moving, don't move |
michael@0 | 1283 | if (before && col == sib) { |
michael@0 | 1284 | move = false; |
michael@0 | 1285 | } |
michael@0 | 1286 | else if (!before && col == col.mTargetCol) { |
michael@0 | 1287 | // If this is an after move and the column we're moving is |
michael@0 | 1288 | // the same as the target column, don't move. |
michael@0 | 1289 | move = false; |
michael@0 | 1290 | } |
michael@0 | 1291 | |
michael@0 | 1292 | if (move) { |
michael@0 | 1293 | col.parentNode.parentNode._reorderColumn(col, col.mTargetCol, before); |
michael@0 | 1294 | } |
michael@0 | 1295 | |
michael@0 | 1296 | // repaint to remove lines |
michael@0 | 1297 | col.parentNode.parentNode.treeBoxObject.invalidate(); |
michael@0 | 1298 | |
michael@0 | 1299 | col.mTargetCol = null; |
michael@0 | 1300 | } |
michael@0 | 1301 | } else |
michael@0 | 1302 | col.mDragGesturing = false; |
michael@0 | 1303 | |
michael@0 | 1304 | document.treecolDragging = null; |
michael@0 | 1305 | col.removeAttribute("dragging"); |
michael@0 | 1306 | |
michael@0 | 1307 | window.removeEventListener("mousemove", col._onDragMouseMove, true); |
michael@0 | 1308 | window.removeEventListener("mouseup", col._onDragMouseUp, true); |
michael@0 | 1309 | // we have to wait for the click event to fire before removing |
michael@0 | 1310 | // cancelling handler |
michael@0 | 1311 | var clickHandler = function(handler) { |
michael@0 | 1312 | window.removeEventListener("click", handler, true); |
michael@0 | 1313 | }; |
michael@0 | 1314 | window.setTimeout(clickHandler, 0, col._onDragMouseClick); |
michael@0 | 1315 | ]]></body> |
michael@0 | 1316 | </method> |
michael@0 | 1317 | |
michael@0 | 1318 | <method name="_onDragMouseClick"> |
michael@0 | 1319 | <parameter name="aEvent"/> |
michael@0 | 1320 | <body><![CDATA[ |
michael@0 | 1321 | // prevent click event from firing after column drag and drop |
michael@0 | 1322 | aEvent.stopPropagation(); |
michael@0 | 1323 | aEvent.preventDefault(); |
michael@0 | 1324 | ]]></body> |
michael@0 | 1325 | </method> |
michael@0 | 1326 | </implementation> |
michael@0 | 1327 | |
michael@0 | 1328 | <handlers> |
michael@0 | 1329 | <handler event="mousedown" button="0"><![CDATA[ |
michael@0 | 1330 | if (this.parentNode.parentNode.enableColumnDrag) { |
michael@0 | 1331 | var xulns = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"; |
michael@0 | 1332 | var cols = this.parentNode.getElementsByTagNameNS(xulns, "treecol"); |
michael@0 | 1333 | |
michael@0 | 1334 | // only start column drag operation if there are at least 2 visible columns |
michael@0 | 1335 | var visible = 0; |
michael@0 | 1336 | for (var i = 0; i < cols.length; ++i) |
michael@0 | 1337 | if (cols[i].boxObject.width > 0) ++visible; |
michael@0 | 1338 | |
michael@0 | 1339 | if (visible > 1) { |
michael@0 | 1340 | window.addEventListener("mousemove", this._onDragMouseMove, true); |
michael@0 | 1341 | window.addEventListener("mouseup", this._onDragMouseUp, true); |
michael@0 | 1342 | document.treecolDragging = this; |
michael@0 | 1343 | this.mDragGesturing = true; |
michael@0 | 1344 | this.mStartDragX = event.clientX; |
michael@0 | 1345 | this.mStartDragY = event.clientY; |
michael@0 | 1346 | } |
michael@0 | 1347 | } |
michael@0 | 1348 | ]]></handler> |
michael@0 | 1349 | <handler event="click" button="0" phase="target"> |
michael@0 | 1350 | <![CDATA[ |
michael@0 | 1351 | if (event.target != event.originalTarget) |
michael@0 | 1352 | return; |
michael@0 | 1353 | |
michael@0 | 1354 | #ifdef XP_WIN |
michael@0 | 1355 | // On Windows multiple clicking on tree columns only cycles one time |
michael@0 | 1356 | // every 2 clicks. |
michael@0 | 1357 | if (event.detail % 2 == 0) |
michael@0 | 1358 | return; |
michael@0 | 1359 | #endif |
michael@0 | 1360 | |
michael@0 | 1361 | var tree = this.parentNode.parentNode; |
michael@0 | 1362 | var column = tree.columns.getColumnFor(this); |
michael@0 | 1363 | tree.view.cycleHeader(column); |
michael@0 | 1364 | ]]> |
michael@0 | 1365 | </handler> |
michael@0 | 1366 | </handlers> |
michael@0 | 1367 | </binding> |
michael@0 | 1368 | |
michael@0 | 1369 | <binding id="treecol" extends="chrome://global/content/bindings/tree.xml#treecol-base"> |
michael@0 | 1370 | <content> |
michael@0 | 1371 | <xul:label class="treecol-text" xbl:inherits="crop,value=label" flex="1" crop="right"/> |
michael@0 | 1372 | <xul:image class="treecol-sortdirection" xbl:inherits="sortDirection,hidden=hideheader"/> |
michael@0 | 1373 | </content> |
michael@0 | 1374 | </binding> |
michael@0 | 1375 | |
michael@0 | 1376 | <binding id="treecol-image" extends="chrome://global/content/bindings/tree.xml#treecol-base"> |
michael@0 | 1377 | <content> |
michael@0 | 1378 | <xul:image class="treecol-icon" xbl:inherits="src"/> |
michael@0 | 1379 | </content> |
michael@0 | 1380 | </binding> |
michael@0 | 1381 | |
michael@0 | 1382 | <binding id="columnpicker" display="xul:button" role="xul:button" |
michael@0 | 1383 | extends="chrome://global/content/bindings/tree.xml#tree-base"> |
michael@0 | 1384 | <content> |
michael@0 | 1385 | <xul:image class="tree-columnpicker-icon"/> |
michael@0 | 1386 | <xul:menupopup anonid="popup"> |
michael@0 | 1387 | <xul:menuseparator anonid="menuseparator"/> |
michael@0 | 1388 | <xul:menuitem anonid="menuitem" label="&restoreColumnOrder.label;"/> |
michael@0 | 1389 | </xul:menupopup> |
michael@0 | 1390 | </content> |
michael@0 | 1391 | |
michael@0 | 1392 | <implementation> |
michael@0 | 1393 | <method name="buildPopup"> |
michael@0 | 1394 | <parameter name="aPopup"/> |
michael@0 | 1395 | <body> |
michael@0 | 1396 | <![CDATA[ |
michael@0 | 1397 | // We no longer cache the picker content, remove the old content. |
michael@0 | 1398 | while (aPopup.childNodes.length > 2) |
michael@0 | 1399 | aPopup.removeChild(aPopup.firstChild); |
michael@0 | 1400 | |
michael@0 | 1401 | var refChild = aPopup.firstChild; |
michael@0 | 1402 | |
michael@0 | 1403 | var tree = this.parentNode.parentNode; |
michael@0 | 1404 | for (var currCol = tree.columns.getFirstColumn(); currCol; |
michael@0 | 1405 | currCol = currCol.getNext()) { |
michael@0 | 1406 | // Construct an entry for each column in the row, unless |
michael@0 | 1407 | // it is not being shown. |
michael@0 | 1408 | var currElement = currCol.element; |
michael@0 | 1409 | if (!currElement.hasAttribute("ignoreincolumnpicker")) { |
michael@0 | 1410 | var popupChild = document.createElement("menuitem"); |
michael@0 | 1411 | popupChild.setAttribute("type", "checkbox"); |
michael@0 | 1412 | var columnName = currElement.getAttribute("display") || |
michael@0 | 1413 | currElement.getAttribute("label"); |
michael@0 | 1414 | popupChild.setAttribute("label", columnName); |
michael@0 | 1415 | popupChild.setAttribute("colindex", currCol.index); |
michael@0 | 1416 | if (currElement.getAttribute("hidden") != "true") |
michael@0 | 1417 | popupChild.setAttribute("checked", "true"); |
michael@0 | 1418 | if (currCol.primary) |
michael@0 | 1419 | popupChild.setAttribute("disabled", "true"); |
michael@0 | 1420 | aPopup.insertBefore(popupChild, refChild); |
michael@0 | 1421 | } |
michael@0 | 1422 | } |
michael@0 | 1423 | |
michael@0 | 1424 | var hidden = !tree.enableColumnDrag; |
michael@0 | 1425 | const anonids = ["menuseparator", "menuitem"]; |
michael@0 | 1426 | for (var i = 0; i < anonids.length; i++) { |
michael@0 | 1427 | var element = document.getAnonymousElementByAttribute(this, "anonid", anonids[i]); |
michael@0 | 1428 | element.hidden = hidden; |
michael@0 | 1429 | } |
michael@0 | 1430 | ]]> |
michael@0 | 1431 | </body> |
michael@0 | 1432 | </method> |
michael@0 | 1433 | </implementation> |
michael@0 | 1434 | |
michael@0 | 1435 | <handlers> |
michael@0 | 1436 | <handler event="command"> |
michael@0 | 1437 | <![CDATA[ |
michael@0 | 1438 | if (event.originalTarget == this) { |
michael@0 | 1439 | var popup = document.getAnonymousElementByAttribute(this, "anonid", "popup"); |
michael@0 | 1440 | this.buildPopup(popup); |
michael@0 | 1441 | popup.showPopup(this, -1, -1, "popup", "bottomright", "topright"); |
michael@0 | 1442 | } |
michael@0 | 1443 | else { |
michael@0 | 1444 | var tree = this.parentNode.parentNode; |
michael@0 | 1445 | tree.stopEditing(true); |
michael@0 | 1446 | var menuitem = document.getAnonymousElementByAttribute(this, "anonid", "menuitem"); |
michael@0 | 1447 | if (event.originalTarget == menuitem) { |
michael@0 | 1448 | tree.columns.restoreNaturalOrder(); |
michael@0 | 1449 | tree._ensureColumnOrder(); |
michael@0 | 1450 | } |
michael@0 | 1451 | else { |
michael@0 | 1452 | var colindex = event.originalTarget.getAttribute("colindex"); |
michael@0 | 1453 | var column = tree.columns[colindex]; |
michael@0 | 1454 | if (column) { |
michael@0 | 1455 | var element = column.element; |
michael@0 | 1456 | if (element.getAttribute("hidden") == "true") |
michael@0 | 1457 | element.setAttribute("hidden", "false"); |
michael@0 | 1458 | else |
michael@0 | 1459 | element.setAttribute("hidden", "true"); |
michael@0 | 1460 | } |
michael@0 | 1461 | } |
michael@0 | 1462 | } |
michael@0 | 1463 | ]]> |
michael@0 | 1464 | </handler> |
michael@0 | 1465 | </handlers> |
michael@0 | 1466 | </binding> |
michael@0 | 1467 | </bindings> |
michael@0 | 1468 |