1 /* ************************************************************************
3 qooxdoo - the new era of web development
8 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
11 LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
14 * Sebastian Werner (wpbasti)
15 * Andreas Ecker (ecker)
17 ************************************************************************ */
19 /* ************************************************************************
23 ************************************************************************ */
25 qx.OO.defineClass("qx.ui.listview.ListViewPane", qx.ui.layout.GridLayout,
26 function(vData, vColumns)
28 qx.ui.layout.GridLayout.call(this);
30 // ************************************************************************
32 // ************************************************************************
33 // Add aliases for data tables
35 this._columns = vColumns;
38 // ************************************************************************
40 // ************************************************************************
41 this._manager = new qx.manager.selection.VirtualSelectionManager(this);
44 // ************************************************************************
45 // MOUSE EVENT LISTENER
46 // ************************************************************************
47 // Add handling for mouse wheel events
48 // Needed because the virtual scroll area does not fire browser
49 // understandable events above this pane.
50 this.addEventListener("mousewheel", this._onmousewheel);
52 this.addEventListener("mouseover", this._onmouseover);
53 this.addEventListener("mousedown", this._onmousedown);
54 this.addEventListener("mouseup", this._onmouseup);
55 this.addEventListener("click", this._onclick);
56 this.addEventListener("dblclick", this._ondblclick);
59 // ************************************************************************
61 // ************************************************************************
62 this.addEventListener("keypress", this._onkeypress);
65 qx.OO.changeProperty({ name : "appearance",
67 defaultValue : "list-view-pane"
70 qx.Proto._rowHeight = 16;
78 ---------------------------------------------------------------------------
80 ---------------------------------------------------------------------------
83 qx.Proto.getView = function() {
84 return this.getParent().getParent();
93 ---------------------------------------------------------------------------
95 ---------------------------------------------------------------------------
98 qx.Proto._lastRowCount = 0;
100 qx.Proto._updateLayout = function(vUpdate)
102 // this.debug("InnerHeight: " + this._computeInnerHeight());
103 // this.debug("BoxHeight: " + this._computeBoxHeight());
106 var vColumns = this._columns;
107 var vRowCount = Math.ceil(this.getInnerHeight() / this._rowHeight);
108 var vData = this._data;
111 // this.debug("Row-Count: " + this._lastRowCount + " => " + vRowCount);
113 // Sync cells: Add new ones and configure them
114 if (vRowCount > this._lastRowCount)
116 for (var i=this._lastRowCount, j=0; i<vRowCount; i++, j=0)
118 for (var vCol in vColumns)
120 vCell = new vColumns[vCol].contentClass;
122 this.add(vCell, j++, i);
124 if (vColumns[vCol].align) {
125 vCell.setStyleProperty("textAlign",
126 vColumns[vCol].align);
132 // Sync cells: Remove existing ones and dispose them
133 else if (this._lastRowCount > vRowCount)
135 var vChildren = this.getChildren();
136 var vChildrenLength = vChildren.length - 1;
138 for (var i=this._lastRowCount; i>vRowCount; i--)
140 for (var vCol in vColumns)
142 vCell = vChildren[vChildrenLength--];
149 // Update row and column count
150 this.setRowCount(vRowCount);
152 this.setColumnCount(qx.lang.Object.getLength(vColumns));
155 // Apply height to all rows
156 for (var i=0; i<vRowCount; i++) {
157 this.setRowHeight(i, this._rowHeight);
162 // Apply width and alignment to all columns
164 for (var vCol in vColumns)
166 this.setColumnHorizontalAlignment(vCount, vColumns[vCol].align);
167 this.setColumnWidth(vCount, vColumns[vCol].width);
173 // Store last row count
174 this._lastRowCount = vRowCount;
177 qx.Proto._currentScrollTop = -1;
179 qx.Proto._updateRendering = function(vForce)
181 if (this._updatingRendering) {
185 var vScrollTop = (this._initialLayoutDone
186 ? this.getView().getScroll().getScrollTop()
189 this._updatingRendering = true;
190 this._currentScrollTop = vScrollTop;
192 for (var i=0; i<this._rowCount; i++) {
196 delete this._updatingRendering;
199 qx.Proto._updateRow = function(vRelativeRow)
201 var vData = this._data;
202 var vRowOffset = Math.floor(this._currentScrollTop / this._rowHeight);
204 var vColumnCount = this.getColumnCount();
205 var vColumns = this._columns;
207 var vChildren = this.getVisibleChildren();
208 var vChild, vEntry, vCol;
212 for (vCol in vColumns)
214 vEntry = vData[vRowOffset+vRelativeRow];
215 vChild = vChildren[vColumnCount*vRelativeRow+(j++)];
219 if (vEntry && vEntry._selected) {
220 vChild.addState("selected");
222 vChild.removeState("selected");
226 : vColumns[vCol].empty || vColumns[vCol].contentClass.empty);
231 qx.Proto._onscroll = function(e) {
232 this._updateRendering();
240 ---------------------------------------------------------------------------
242 ---------------------------------------------------------------------------
245 qx.Proto._changeInnerHeight = function(vNew, vOld)
247 this._updateLayout(true);
248 this._updateRendering(true);
250 return qx.ui.layout.GridLayout.prototype._changeInnerHeight.call(this,
261 ---------------------------------------------------------------------------
263 ---------------------------------------------------------------------------
266 qx.Proto.getManager = function() {
267 return this._manager;
270 qx.Proto.getListViewTarget = function(e)
272 var vEventTop = e.getPageY();
273 var vPaneTop = qx.dom.Location.getPageInnerTop(this.getElement());
274 var vItemNo = Math.floor(this._currentScrollTop / this._rowHeight) +
275 Math.floor((vEventTop - vPaneTop) / this._rowHeight);
277 return this._data[vItemNo];
280 qx.Proto.getSelectedItem = function() {
281 return this.getSelectedItems()[0];
284 qx.Proto.getSelectedItems = function() {
285 return this._manager.getSelectedItems();
288 qx.Proto.getData = function() {
292 // use static row height
293 qx.Proto.getItemHeight = function(vItem) {
294 return this._rowHeight;
297 // use the full inner width of the pane
298 qx.Proto.getItemWidth = function(vItem) {
299 return qx.dom.Dimension.getInnerWidth(this.getElement());
302 qx.Proto.getItemLeft = function(vItem) {
306 qx.Proto.getItemTop = function(vItem) {
307 return this._data.indexOf(vItem) * this._rowHeight;
314 ---------------------------------------------------------------------------
316 ---------------------------------------------------------------------------
319 qx.Proto._onmousewheel = function(e)
321 var vScroll = this.getView().getScroll();
322 vScroll.setScrollTop(vScroll.getScrollTop() - (e.getWheelDelta() * 20));
325 qx.Proto._onmouseover = function(e)
327 var vTarget = this.getListViewTarget(e);
329 this._manager.handleMouseOver(vTarget, e);
333 qx.Proto._onmousedown = function(e)
335 var vTarget = this.getListViewTarget(e);
337 this._manager.handleMouseDown(vTarget, e);
341 qx.Proto._onmouseup = function(e)
343 var vTarget = this.getListViewTarget(e);
345 this._manager.handleMouseUp(vTarget, e);
349 qx.Proto._onclick = function(e)
351 var vTarget = this.getListViewTarget(e);
353 this._manager.handleClick(vTarget, e);
357 qx.Proto._ondblclick = function(e)
359 var vTarget = this.getListViewTarget(e);
361 this._manager.handleDblClick(vTarget, e);
371 ---------------------------------------------------------------------------
373 ---------------------------------------------------------------------------
376 qx.Proto._onkeypress = function(e)
378 this._manager.handleKeyPress(e);
388 ---------------------------------------------------------------------------
390 ---------------------------------------------------------------------------
393 qx.Proto._updateSelectionState = function(vItem, vIsSelected)
395 vItem._selected = vIsSelected;
396 this._updateItem(vItem);
399 qx.Proto._updateAnchorState = function(vItem, vIsAnchor)
401 vItem._anchor = vIsAnchor;
402 this._updateItem(vItem);
405 qx.Proto._updateLeadState = function(vItem, vIsLead)
407 vItem._lead = vIsLead;
408 this._updateItem(vItem);
411 qx.Proto.scrollItemIntoView = function(vItem, vAlignLeftTop)
413 this.scrollItemIntoViewX(vItem, vAlignLeftTop);
414 this.scrollItemIntoViewY(vItem, vAlignLeftTop);
417 qx.Proto.scrollItemIntoViewX = function(vItem, vAlignLeft) {
418 // this.error("Not implemented in qx.ui.listview.ListViewPane!");
421 qx.Proto.scrollItemIntoViewY = function(vItem, vAlignTop)
423 var vItems = this._data;
424 var vOffset = vItems.indexOf(vItem) * this._rowHeight;
425 var vHeight = this._rowHeight;
427 // normalize client height (we want that the item is fully visible)
428 var vParentHeight = (Math.floor(this.getClientHeight() / this._rowHeight) *
430 var vParentScrollTop = this._currentScrollTop;
432 var vNewScrollTop = null;
436 vNewScrollTop = vOffset;
438 else if (vAlignTop == false)
440 vNewScrollTop = vOffset + vHeight - vParentHeight;
442 else if (vHeight > vParentHeight || vOffset < vParentScrollTop)
444 vNewScrollTop = vOffset;
446 else if ((vOffset + vHeight) > (vParentScrollTop + vParentHeight))
448 vNewScrollTop = vOffset + vHeight - vParentHeight;
451 if (vNewScrollTop != null) {
452 this.getView().getScroll().setScrollTop(vNewScrollTop);
456 qx.Proto.setScrollTop = function(vScrollTop)
458 this.getView().getScroll().setScrollTop(vScrollTop);
459 this._updateRendering();
462 qx.Proto.getScrollTop = function() {
463 return this._currentScrollTop;
466 qx.Proto.setScrollLeft = function() {
467 this.error("Not implemented in qx.ui.listview.ListViewPane!");
470 qx.Proto.getScrollLeft = function() {
474 qx.Proto.isItemVisible = function(vItem)
476 var vIndex = this._data.indexOf(vItem);
477 var vRowStart = Math.floor(this._currentScrollTop / this._rowHeight);
478 var vRowLength = Math.ceil(this.getClientHeight() / this._rowHeight);
480 return vIndex >= vRowStart && vIndex <= (vRowStart + vRowLength);
483 qx.Proto.getRelativeItemPosition = function(vItem)
485 var vIndex = this._data.indexOf(vItem);
486 var vRowStart = Math.floor(this._currentScrollTop / this._rowHeight);
488 return vIndex - vRowStart;
491 qx.Proto._updateItem = function(vItem)
493 var vIndex = this._data.indexOf(vItem);
494 var vRowStart = Math.floor(this._currentScrollTop / this._rowHeight);
495 var vRowLength = Math.ceil(this.getClientHeight() / this._rowHeight);
497 if (vIndex < vRowStart || vIndex > (vRowStart + vRowLength)) {
501 this._updateRow(vIndex - vRowStart);
510 ---------------------------------------------------------------------------
512 ---------------------------------------------------------------------------
515 qx.Proto.dispose = function()
517 if (this.getDisposed()) {
522 // ************************************************************************
523 // MOUSE EVENT LISTENER
524 // ************************************************************************
525 this.removeEventListener("mousewheel", this._onmousewheel);
526 this.removeEventListener("mouseover", this._onmouseover);
527 this.removeEventListener("mousedown", this._onmousedown);
528 this.removeEventListener("mouseup", this._onmouseup);
529 this.removeEventListener("click", this._onclick);
530 this.removeEventListener("dblclick", this._ondblclick);
533 // ************************************************************************
534 // KEY EVENT LISTENER
535 // ************************************************************************
536 this.removeEventListener("keypress", this._onkeypress);
539 // ************************************************************************
541 // ************************************************************************
543 delete this._columns;
546 // ************************************************************************
548 // ************************************************************************
551 this._manager.dispose();
552 this._manager = null;
555 return qx.ui.layout.GridLayout.prototype.dispose.call(this);