Title: [143901] trunk/Source/WebCore
Revision
143901
Author
[email protected]
Date
2013-02-25 03:31:09 -0800 (Mon, 25 Feb 2013)

Log Message

Add list view for new calendar picker
https://bugs.webkit.org/show_bug.cgi?id=110140

Reviewed by Kent Tamura.

Adding list view class to be used in the new calendar picker (Bug 109439).

No new tests. Code is not yet used.

* Resources/pagepopups/calendarPicker.js:
(ListCell): One row inside the list view. We reuse
list cells to avoid animation hiccups caused by memory allocation.
(ListCell.prototype._recycleBin): Returns array to
store thrown away list cells so we can reuse them.
(ListCell.prototype.throwAway): Hides the cell and puts it in the recycle bin.
(ListCell.prototype.show):
(ListCell.prototype.hide): Hide the cell when we don't need the cell any more.
(ListCell.prototype.width):
(ListCell.prototype.setWidth):
(ListCell.prototype.position):
(ListCell.prototype.setPosition): Sets the CSS transform to position the cell.
(ListCell.prototype.setSelected): Adds selected CSS class.
(ListView): Shows a scrolling list.
(ListView.prototype.onAnimationFrameWillFinish): Calls updateCells if the cells need to be updated.
(ListView.prototype.setNeedsUpdateCells): Mark the cells as need to be updated.
(ListView.prototype.cellAtRow): Returns the cell at a given row. If the cell is not visible and doesn't exist, returns undefined.
(ListView.prototype.rowAtScrollOffset): The row that is displayed at the given scroll offset.
(ListView.prototype.scrollOffsetForRow): The scroll offset for the top of a given row.
(ListView.prototype.addCellIfNecessary): Adds the cell for a given row.
(ListView.prototype.prepareNewCell): Prepares a new or recycled cell for a given row.
(ListView.prototype.throwAwayCell): Throws a way a cell.
(ListView.prototype.firstVisibleRow): The first visible row at the top of the view.
(ListView.prototype.lastVisibleRow): The last visible row at the bottom of the view.
(ListView.prototype.scrollViewDidChangeContentOffset):
(ListView.prototype.scrollViewDidChangeHeight):
(ListView.prototype.scrollViewDidChangePartition):
(ListView.prototype.updateCells): Updates all the cells that are visible.
(ListView.prototype.width):
(ListView.prototype.setWidth):
(ListView.prototype.height):
(ListView.prototype.setHeight):
(ListView.prototype.onClick): Clicking on a row selects it.
(ListView.prototype.select):
(ListView.prototype.deselect):
(ListView.prototype.scrollToRow): Scrolls to a given row.

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (143900 => 143901)


--- trunk/Source/WebCore/ChangeLog	2013-02-25 10:53:00 UTC (rev 143900)
+++ trunk/Source/WebCore/ChangeLog	2013-02-25 11:31:09 UTC (rev 143901)
@@ -1,3 +1,51 @@
+2013-02-25  Keishi Hattori  <[email protected]>
+
+        Add list view for new calendar picker
+        https://bugs.webkit.org/show_bug.cgi?id=110140
+
+        Reviewed by Kent Tamura.
+
+        Adding list view class to be used in the new calendar picker (Bug 109439).
+
+        No new tests. Code is not yet used.
+
+        * Resources/pagepopups/calendarPicker.js:
+        (ListCell): One row inside the list view. We reuse
+        list cells to avoid animation hiccups caused by memory allocation.
+        (ListCell.prototype._recycleBin): Returns array to
+        store thrown away list cells so we can reuse them.
+        (ListCell.prototype.throwAway): Hides the cell and puts it in the recycle bin.
+        (ListCell.prototype.show):
+        (ListCell.prototype.hide): Hide the cell when we don't need the cell any more.
+        (ListCell.prototype.width):
+        (ListCell.prototype.setWidth):
+        (ListCell.prototype.position):
+        (ListCell.prototype.setPosition): Sets the CSS transform to position the cell.
+        (ListCell.prototype.setSelected): Adds selected CSS class.
+        (ListView): Shows a scrolling list.
+        (ListView.prototype.onAnimationFrameWillFinish): Calls updateCells if the cells need to be updated.
+        (ListView.prototype.setNeedsUpdateCells): Mark the cells as need to be updated.
+        (ListView.prototype.cellAtRow): Returns the cell at a given row. If the cell is not visible and doesn't exist, returns undefined.
+        (ListView.prototype.rowAtScrollOffset): The row that is displayed at the given scroll offset.
+        (ListView.prototype.scrollOffsetForRow): The scroll offset for the top of a given row.
+        (ListView.prototype.addCellIfNecessary): Adds the cell for a given row.
+        (ListView.prototype.prepareNewCell): Prepares a new or recycled cell for a given row.
+        (ListView.prototype.throwAwayCell): Throws a way a cell.
+        (ListView.prototype.firstVisibleRow): The first visible row at the top of the view.
+        (ListView.prototype.lastVisibleRow): The last visible row at the bottom of the view.
+        (ListView.prototype.scrollViewDidChangeContentOffset):
+        (ListView.prototype.scrollViewDidChangeHeight):
+        (ListView.prototype.scrollViewDidChangePartition):
+        (ListView.prototype.updateCells): Updates all the cells that are visible.
+        (ListView.prototype.width):
+        (ListView.prototype.setWidth):
+        (ListView.prototype.height):
+        (ListView.prototype.setHeight):
+        (ListView.prototype.onClick): Clicking on a row selects it.
+        (ListView.prototype.select):
+        (ListView.prototype.deselect):
+        (ListView.prototype.scrollToRow): Scrolls to a given row.
+
 2013-02-25  Alexei Filippov  <[email protected]>
 
         Web Inspector: move profile type specific code out of ProfilesPanel (refactor)

Modified: trunk/Source/WebCore/Resources/pagepopups/calendarPicker.js (143900 => 143901)


--- trunk/Source/WebCore/Resources/pagepopups/calendarPicker.js	2013-02-25 10:53:00 UTC (rev 143900)
+++ trunk/Source/WebCore/Resources/pagepopups/calendarPicker.js	2013-02-25 11:31:09 UTC (rev 143901)
@@ -1365,6 +1365,363 @@
 
 /**
  * @constructor
+ * @extends View
+ */
+function ListCell() {
+    View.call(this, createElement("div", ListCell.ClassNameListCell));
+    
+    /**
+     * @type {!number}
+     */
+    this.row = NaN;
+    /**
+     * @type {!number}
+     */
+    this._width = 0;
+    /**
+     * @type {!number}
+     */
+    this._position = 0;
+}
+
+ListCell.prototype = Object.create(View.prototype);
+
+ListCell.DefaultRecycleBinLimit = 64;
+ListCell.ClassNameListCell = "list-cell";
+ListCell.ClassNameHidden = "hidden";
+
+/**
+ * @return {!Array} An array to keep thrown away cells.
+ */
+ListCell.prototype._recycleBin = function() {
+    console.assert(false, "NOT REACHED: ListCell.prototype._recycleBin needs to be overridden.");
+    return [];
+};
+
+ListCell.prototype.throwAway = function() {
+    this.hide();
+    var limit = typeof this.constructor.RecycleBinLimit === "undefined" ? ListCell.DefaultRecycleBinLimit : this.constructor.RecycleBinLimit;
+    var recycleBin = this._recycleBin();
+    if (recycleBin.length < limit)
+        recycleBin.push(this);
+};
+
+ListCell.prototype.show = function() {
+    this.element.classList.remove(ListCell.ClassNameHidden);
+};
+
+ListCell.prototype.hide = function() {
+    this.element.classList.add(ListCell.ClassNameHidden);
+};
+
+/**
+ * @return {!number} Width in pixels.
+ */
+ListCell.prototype.width = function(){
+    return this._width;
+};
+
+/**
+ * @param {!number} width Width in pixels.
+ */
+ListCell.prototype.setWidth = function(width){
+    if (this._width === width)
+        return;
+    this._width = width;
+    this.element.style.width = this._width + "px";
+};
+
+/**
+ * @return {!number} Position in pixels.
+ */
+ListCell.prototype.position = function(){
+    return this._position;
+};
+
+/**
+ * @param {!number} y Position in pixels.
+ */
+ListCell.prototype.setPosition = function(y) {
+    if (this._position === y)
+        return;
+    this._position = y;
+    this.element.style.webkitTransform = "translate(0, " + this._position + "px)";
+};
+
+/**
+ * @param {!boolean} selected
+ */
+ListCell.prototype.setSelected = function(selected) {
+    if (this._selected === selected)
+        return;
+    this._selected = selected;
+    if (this._selected)
+        this.element.classList.add("selected");
+    else
+        this.element.classList.remove("selected");
+};
+
+/**
+ * @constructor
+ * @extends View
+ */
+function ListView() {
+    View.call(this, createElement("div", ListView.ClassNameListView));
+    this.element.tabIndex = 0;
+
+    /**
+     * @type {!number}
+     * @private
+     */
+    this._width = 0;
+    /**
+     * @type {!Object}
+     * @private
+     */
+    this._cells = {};
+
+    /**
+     * @type {!number}
+     */
+    this.selectedRow = ListView.NoSelection;
+
+    /**
+     * @type {!ScrollView}
+     */
+    this.scrollView = new ScrollView();
+    this.scrollView.delegate = this;
+    this.scrollView.minimumContentOffset = 0;
+    this.scrollView.setWidth(0);
+    this.scrollView.setHeight(0);
+    this.scrollView.attachTo(this);
+
+    this.element.addEventListener("click", this.onClick, false);
+
+    /**
+     * @type {!boolean}
+     * @private
+     */
+    this._needsUpdateCells = false;
+}
+
+ListView.prototype = Object.create(View.prototype);
+
+ListView.NoSelection = -1;
+ListView.ClassNameListView = "list-view";
+
+ListView.prototype._onAnimationFrameWillFinish_ = function() {
+    if (this._needsUpdateCells)
+        this.updateCells();
+};
+
+/**
+ * @param {!boolean} needsUpdateCells
+ */
+ListView.prototype.setNeedsUpdateCells = function(needsUpdateCells) {
+    if (this._needsUpdateCells === needsUpdateCells)
+        return;
+    this._needsUpdateCells = needsUpdateCells;
+    if (this._needsUpdateCells)
+        AnimationManager.shared.on(AnimationManager.EventTypeAnimationFrameWillFinish, this.onAnimationFrameWillFinish);
+    else
+        AnimationManager.shared.removeListener(AnimationManager.EventTypeAnimationFrameWillFinish, this.onAnimationFrameWillFinish);
+};
+
+/**
+ * @param {!number} row
+ * @return {?ListCell}
+ */
+ListView.prototype.cellAtRow = function(row) {
+    return this._cells[row];
+};
+
+/**
+ * @param {!number} offset Scroll offset in pixels.
+ * @return {!number}
+ */
+ListView.prototype.rowAtScrollOffset = function(offset) {
+    console.assert(false, "NOT REACHED: ListView.prototype.rowAtScrollOffset needs to be overridden.");
+    return 0;
+};
+
+/**
+ * @param {!number} row
+ * @return {!number} Scroll offset in pixels.
+ */
+ListView.prototype.scrollOffsetForRow = function(row) {
+    console.assert(false, "NOT REACHED: ListView.prototype.scrollOffsetForRow needs to be overridden.");
+    return 0;
+};
+
+/**
+ * @param {!number} row
+ * @return {!ListCell}
+ */
+ListView.prototype.addCellIfNecessary = function(row) {
+    var cell = this._cells[row];
+    if (cell)
+        return cell;
+    cell = this.prepareNewCell(row);
+    cell.attachTo(this.scrollView.contentElement);
+    cell.setWidth(this._width);
+    cell.setPosition(this.scrollView.contentPositionForContentOffset(this.scrollOffsetForRow(row)));
+    this._cells[row] = cell;
+    return cell;
+};
+
+/**
+ * @param {!number} row
+ * @return {!ListCell}
+ */
+ListView.prototype.prepareNewCell = function(row) {
+    console.assert(false, "NOT REACHED: ListView.prototype.prepareNewCell should be overridden.");
+    return new ListCell();
+};
+
+/**
+ * @param {!ListCell} cell
+ */
+ListView.prototype.throwAwayCell = function(cell) {
+    delete this._cells[cell.row];
+    cell.throwAway();
+};
+
+/**
+ * @return {!number}
+ */
+ListView.prototype.firstVisibleRow = function() {
+    return this.rowAtScrollOffset(this.scrollView.contentOffset());
+};
+
+/**
+ * @return {!number}
+ */
+ListView.prototype.lastVisibleRow = function() {
+    return this.rowAtScrollOffset(this.scrollView.contentOffset() + this.scrollView.height() - 1);
+};
+
+/**
+ * @param {!ScrollView} scrollView
+ */
+ListView.prototype.scrollViewDidChangeContentOffset = function(scrollView) {
+    this.setNeedsUpdateCells(true);
+};
+
+/**
+ * @param {!ScrollView} scrollView
+ */
+ListView.prototype.scrollViewDidChangeHeight = function(scrollView) {
+    this.setNeedsUpdateCells(true);
+};
+
+/**
+ * @param {!ScrollView} scrollView
+ */
+ListView.prototype.scrollViewDidChangePartition = function(scrollView) {
+    this.setNeedsUpdateCells(true);
+};
+
+ListView.prototype.updateCells = function() {
+    var firstVisibleRow = this.firstVisibleRow();
+    var lastVisibleRow = this.lastVisibleRow();
+    console.assert(firstVisibleRow <= lastVisibleRow);
+    for (var c in this._cells) {
+        var cell = this._cells[c];
+        if (cell.row < firstVisibleRow || cell.row > lastVisibleRow)
+            this.throwAwayCell(cell);
+    }
+    for (var i = firstVisibleRow; i <= lastVisibleRow; ++i) {
+        var cell = this._cells[i];
+        if (cell)
+            cell.setPosition(this.scrollView.contentPositionForContentOffset(this.scrollOffsetForRow(cell.row)));
+        else
+            this.addCellIfNecessary(i);
+    }
+    this.setNeedsUpdateCells(false);
+};
+
+/**
+ * @return {!number} Width in pixels.
+ */
+ListView.prototype.width = function() {
+    return this._width;
+};
+
+/**
+ * @param {!number} width Width in pixels.
+ */
+ListView.prototype.setWidth = function(width) {
+    if (this._width === width)
+        return;
+    this._width = width;
+    this.scrollView.setWidth(this._width);
+    for (var c in this._cells) {
+        this._cells[c].setWidth(this._width);
+    }
+    this.element.style.width = this._width + "px";
+    this.setNeedsUpdateCells(true);
+};
+
+/**
+ * @return {!number} Height in pixels.
+ */
+ListView.prototype.height = function() {
+    return this.scrollView.height();
+};
+
+/**
+ * @param {!number} height Height in pixels.
+ */
+ListView.prototype.setHeight = function(height) {
+    this.scrollView.setHeight(height);
+};
+
+/**
+ * @param {?Event} event
+ */
+ListView.prototype._onClick_ = function(event) {
+    var clickedCellElement = enclosingNodeOrSelfWithClass(event.target, ListCell.ClassNameListCell);
+    if (!clickedCellElement)
+        return;
+    var clickedCell = clickedCellElement.$view;
+    if (clickedCell.row !== this.selectedRow)
+        this.select(clickedCell.row);
+};
+
+/**
+ * @param {!number} row
+ */
+ListView.prototype.select = function(row) {
+    if (this.selectedRow === row)
+        return;
+    this.deselect();
+    if (row === ListView.NoSelection)
+        return;
+    this.selectedRow = row;
+    var selectedCell = this._cells[this.selectedRow];
+    if (selectedCell)
+        selectedCell.setSelected(true);
+};
+
+ListView.prototype.deselect = function() {
+    if (this.selectedRow === ListView.NoSelection)
+        return;
+    var selectedCell = this._cells[this.selectedRow];
+    if (selectedCell)
+        selectedCell.setSelected(false);
+    this.selectedRow = ListView.NoSelection;
+};
+
+/**
+ * @param {!number} row
+ * @param {!boolean} animate
+ */
+ListView.prototype.scrollToRow = function(row, animate) {
+    this.scrollView.scrollTo(this.scrollOffsetForRow(row), animate);
+};
+
+/**
+ * @constructor
  * @param {!Element} element
  * @param {!Object} config
  */
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to