| OLD | NEW |
| 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 // This file contains View framework classes. | 5 // This file contains View framework classes. |
| 6 // As it grows, it may need to be split into multiple files. | 6 // As it grows, it may need to be split into multiple files. |
| 7 | 7 |
| 8 /** A factory that creates a view from a data model. */ | 8 /** A factory that creates a view from a data model. */ |
| 9 interface ViewFactory<D> { | 9 abstract class ViewFactory<D> { |
| 10 View newView(D item); | 10 View newView(D item); |
| 11 | 11 |
| 12 /** The width of the created view or null if the width is not fixed. */ | 12 /** The width of the created view or null if the width is not fixed. */ |
| 13 int get width; | 13 int get width; |
| 14 | 14 |
| 15 /** The height of the created view or null if the height is not fixed. */ | 15 /** The height of the created view or null if the height is not fixed. */ |
| 16 int get height; | 16 int get height; |
| 17 } | 17 } |
| 18 | 18 |
| 19 interface VariableSizeViewFactory<D> { | 19 abstract class VariableSizeViewFactory<D> { |
| 20 View newView(D item); | 20 View newView(D item); |
| 21 | 21 |
| 22 /** The width of the created view for a specific data model. */ | 22 /** The width of the created view for a specific data model. */ |
| 23 int getWidth(D item); | 23 int getWidth(D item); |
| 24 | 24 |
| 25 /** The height of the created view for a specific data model. */ | 25 /** The height of the created view for a specific data model. */ |
| 26 int getHeight(D item); | 26 int getHeight(D item); |
| 27 } | 27 } |
| 28 | 28 |
| 29 /** A collection of event listeners. */ | 29 /** A collection of event listeners. */ |
| (...skipping 21 matching lines...) Expand all Loading... |
| 51 */ | 51 */ |
| 52 class _PlaceholderView extends View { | 52 class _PlaceholderView extends View { |
| 53 _PlaceholderView() : super() {} | 53 _PlaceholderView() : super() {} |
| 54 | 54 |
| 55 Element render() => new Element.tag('div'); | 55 Element render() => new Element.tag('div'); |
| 56 } | 56 } |
| 57 | 57 |
| 58 /** | 58 /** |
| 59 * Class providing all metrics required to layout a data driven list view. | 59 * Class providing all metrics required to layout a data driven list view. |
| 60 */ | 60 */ |
| 61 interface ListViewLayout<D> { | 61 abstract class ListViewLayout<D> { |
| 62 void onDataChange(); | 62 void onDataChange(); |
| 63 | 63 |
| 64 // TODO(jacobr): placing the newView member function on this class seems like | 64 // TODO(jacobr): placing the newView member function on this class seems like |
| 65 // the wrong design. | 65 // the wrong design. |
| 66 View newView(int index); | 66 View newView(int index); |
| 67 /** Get the height of the view. Possibly expensive to compute. */ | 67 /** Get the height of the view. Possibly expensive to compute. */ |
| 68 int getHeight(int viewLength); | 68 int getHeight(int viewLength); |
| 69 /** Get the width of the view. Possibly expensive to compute. */ | 69 /** Get the width of the view. Possibly expensive to compute. */ |
| 70 int getWidth(int viewLength); | 70 int getWidth(int viewLength); |
| 71 /** Get the length of the view. Possible expensive to compute. */ | 71 /** Get the length of the view. Possible expensive to compute. */ |
| (...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 290 void onResize() { | 290 void onResize() { |
| 291 int lastViewLength = _viewLength; | 291 int lastViewLength = _viewLength; |
| 292 node.rect.then((ElementRect rect) { | 292 node.rect.then((ElementRect rect) { |
| 293 _viewLength = _vertical ? rect.offset.height : rect.offset.width; | 293 _viewLength = _vertical ? rect.offset.height : rect.offset.width; |
| 294 if (_viewLength != lastViewLength) { | 294 if (_viewLength != lastViewLength) { |
| 295 if (_scrollbar != null) { | 295 if (_scrollbar != null) { |
| 296 _scrollbar.refresh(); | 296 _scrollbar.refresh(); |
| 297 } | 297 } |
| 298 renderVisibleItems(true); | 298 renderVisibleItems(true); |
| 299 } | 299 } |
| 300 }); | 300 }); |
| 301 } | 301 } |
| 302 | 302 |
| 303 void enterDocument() { | 303 void enterDocument() { |
| 304 if (scroller != null) { | 304 if (scroller != null) { |
| 305 onResize(); | 305 onResize(); |
| 306 | 306 |
| 307 if (_scrollbar != null) { | 307 if (_scrollbar != null) { |
| 308 _scrollbar.initialize(); | 308 _scrollbar.initialize(); |
| 309 } | 309 } |
| 310 } | 310 } |
| (...skipping 12 matching lines...) Expand all Loading... |
| 323 | 323 |
| 324 void _decelStart() { | 324 void _decelStart() { |
| 325 num currentTarget = scroller.verticalEnabled ? | 325 num currentTarget = scroller.verticalEnabled ? |
| 326 scroller.currentTarget.y : scroller.currentTarget.x; | 326 scroller.currentTarget.y : scroller.currentTarget.x; |
| 327 num current = scroller.verticalEnabled ? | 327 num current = scroller.verticalEnabled ? |
| 328 scroller.contentOffset.y : scroller.contentOffset.x; | 328 scroller.contentOffset.y : scroller.contentOffset.x; |
| 329 num targetIndex = _layout.getSnapIndex(currentTarget, _viewLength); | 329 num targetIndex = _layout.getSnapIndex(currentTarget, _viewLength); |
| 330 if (current != currentTarget) { | 330 if (current != currentTarget) { |
| 331 // The user is throwing rather than statically releasing. | 331 // The user is throwing rather than statically releasing. |
| 332 // For this case, we want to move them to the next snap interval | 332 // For this case, we want to move them to the next snap interval |
| 333 // as long as they made at least a minimal throw gesture. | 333 // as long as they made at least a minimal throw gesture. |
| 334 num currentIndex = _layout.getSnapIndex(current, _viewLength); | 334 num currentIndex = _layout.getSnapIndex(current, _viewLength); |
| 335 if (currentIndex == targetIndex && | 335 if (currentIndex == targetIndex && |
| 336 (currentTarget - current).abs() > SNAP_TO_NEXT_THROW_THRESHOLD && | 336 (currentTarget - current).abs() > SNAP_TO_NEXT_THROW_THRESHOLD && |
| 337 -_layout.getOffset(targetIndex) != currentTarget) { | 337 -_layout.getOffset(targetIndex) != currentTarget) { |
| 338 num snappedCurrentPosition = -_layout.getOffset(targetIndex); | 338 num snappedCurrentPosition = -_layout.getOffset(targetIndex); |
| 339 targetIndex = getNextIndex(targetIndex, currentTarget < current); | 339 targetIndex = getNextIndex(targetIndex, currentTarget < current); |
| 340 } | 340 } |
| 341 } | 341 } |
| 342 num targetPosition = -_layout.getOffset(targetIndex); | 342 num targetPosition = -_layout.getOffset(targetIndex); |
| 343 if (currentTarget != targetPosition) { | 343 if (currentTarget != targetPosition) { |
| 344 if (scroller.verticalEnabled) { | 344 if (scroller.verticalEnabled) { |
| 345 scroller.throwTo(scroller.contentOffset.x, targetPosition); | 345 scroller.throwTo(scroller.contentOffset.x, targetPosition); |
| (...skipping 26 matching lines...) Expand all Loading... |
| 372 _throwTo(_layout.getOffset( | 372 _throwTo(_layout.getOffset( |
| 373 _layout.getPageStartIndex(_pages.target.value, _viewLength))); | 373 _layout.getPageStartIndex(_pages.target.value, _viewLength))); |
| 374 } | 374 } |
| 375 } | 375 } |
| 376 | 376 |
| 377 num get _offset { | 377 num get _offset { |
| 378 return scroller.verticalEnabled ? | 378 return scroller.verticalEnabled ? |
| 379 scroller.getVerticalOffset() : scroller.getHorizontalOffset(); | 379 scroller.getVerticalOffset() : scroller.getHorizontalOffset(); |
| 380 } | 380 } |
| 381 | 381 |
| 382 /** | 382 /** |
| 383 * Calculates visible interval, based on the scroller position. | 383 * Calculates visible interval, based on the scroller position. |
| 384 */ | 384 */ |
| 385 Interval getVisibleInterval() { | 385 Interval getVisibleInterval() { |
| 386 return _layout.computeVisibleInterval(_offset, _viewLength, 0); | 386 return _layout.computeVisibleInterval(_offset, _viewLength, 0); |
| 387 } | 387 } |
| 388 | 388 |
| 389 void renderVisibleItems(bool lengthChanged) { | 389 void renderVisibleItems(bool lengthChanged) { |
| 390 Interval targetInterval; | 390 Interval targetInterval; |
| 391 if (scroller != null) { | 391 if (scroller != null) { |
| 392 targetInterval = getVisibleInterval(); | 392 targetInterval = getVisibleInterval(); |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 457 return view; | 457 return view; |
| 458 } | 458 } |
| 459 | 459 |
| 460 View _addView(int index) { | 460 View _addView(int index) { |
| 461 if (_itemViews.containsKey(index)) { | 461 if (_itemViews.containsKey(index)) { |
| 462 final view = _itemViews[index]; | 462 final view = _itemViews[index]; |
| 463 _addViewHelper(view, index); | 463 _addViewHelper(view, index); |
| 464 childViewAdded(view); | 464 childViewAdded(view); |
| 465 return view; | 465 return view; |
| 466 } | 466 } |
| 467 | 467 |
| 468 final view = _newView(index); | 468 final view = _newView(index); |
| 469 _itemViews[index] = view; | 469 _itemViews[index] = view; |
| 470 // TODO(jacobr): its ugly to put this here... but its needed | 470 // TODO(jacobr): its ugly to put this here... but its needed |
| 471 // as typical even-odd css queries won't work as we only display some | 471 // as typical even-odd css queries won't work as we only display some |
| 472 // children at a time. | 472 // children at a time. |
| 473 if (index == 0) { | 473 if (index == 0) { |
| 474 view.addClass('first-child'); | 474 view.addClass('first-child'); |
| 475 } | 475 } |
| 476 _selectHelper(view, _data[index] == _lastSelectedItem); | 476 _selectHelper(view, _data[index] == _lastSelectedItem); |
| 477 // The order of the child elements doesn't matter as we use absolute | 477 // The order of the child elements doesn't matter as we use absolute |
| 478 // positioning. | 478 // positioning. |
| 479 _addViewHelper(view, index); | 479 _addViewHelper(view, index); |
| 480 childViewAdded(view); | 480 childViewAdded(view); |
| 481 return view; | 481 return view; |
| 482 } | 482 } |
| 483 | 483 |
| 484 void _addViewHelper(View view, int index) { | 484 void _addViewHelper(View view, int index) { |
| 485 _positionSubview(view.node, index); | 485 _positionSubview(view.node, index); |
| 486 // The view might already be attached. | 486 // The view might already be attached. |
| 487 if (view.node.parent != _containerElem) { | 487 if (view.node.parent != _containerElem) { |
| 488 _containerElem.nodes.add(view.node); | 488 _containerElem.nodes.add(view.node); |
| 489 } | 489 } |
| 490 } | 490 } |
| 491 | 491 |
| 492 /** | 492 /** |
| 493 * Detach a subview from the view replacing it with an empty placeholder view. | 493 * Detach a subview from the view replacing it with an empty placeholder view. |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 615 void onDataChange() {} | 615 void onDataChange() {} |
| 616 | 616 |
| 617 View newView(int index) { | 617 View newView(int index) { |
| 618 return itemViewFactory.newView(_data[index]); | 618 return itemViewFactory.newView(_data[index]); |
| 619 } | 619 } |
| 620 | 620 |
| 621 int get _itemLength { | 621 int get _itemLength { |
| 622 return _vertical ? itemViewFactory.height : itemViewFactory.width; | 622 return _vertical ? itemViewFactory.height : itemViewFactory.width; |
| 623 } | 623 } |
| 624 | 624 |
| 625 | 625 |
| 626 int getWidth(int viewLength) { | 626 int getWidth(int viewLength) { |
| 627 return _vertical ? itemViewFactory.width : getLength(viewLength); | 627 return _vertical ? itemViewFactory.width : getLength(viewLength); |
| 628 } | 628 } |
| 629 | 629 |
| 630 int getHeight(int viewLength) { | 630 int getHeight(int viewLength) { |
| 631 return _vertical ? getLength(viewLength) : itemViewFactory.height; | 631 return _vertical ? getLength(viewLength) : itemViewFactory.height; |
| 632 } | 632 } |
| 633 | 633 |
| 634 int getEstimatedHeight(int viewLength) { | 634 int getEstimatedHeight(int viewLength) { |
| 635 // Returns the exact height as it is trivial to compute for this layout. | 635 // Returns the exact height as it is trivial to compute for this layout. |
| 636 return getHeight(viewLength); | 636 return getHeight(viewLength); |
| 637 } | 637 } |
| 638 | 638 |
| 639 int getEstimatedWidth(int viewLength) { | 639 int getEstimatedWidth(int viewLength) { |
| (...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 866 int start = _findFirstItemBefore( | 866 int start = _findFirstItemBefore( |
| 867 -offset - bufferLength, | 867 -offset - bufferLength, |
| 868 _lastVisibleInterval != null ? _lastVisibleInterval.start : 0); | 868 _lastVisibleInterval != null ? _lastVisibleInterval.start : 0); |
| 869 int end = _findFirstItemAfter( | 869 int end = _findFirstItemAfter( |
| 870 -offset + viewLength + bufferLength, | 870 -offset + viewLength + bufferLength, |
| 871 _lastVisibleInterval != null ? _lastVisibleInterval.end : 0); | 871 _lastVisibleInterval != null ? _lastVisibleInterval.end : 0); |
| 872 _lastVisibleInterval = new Interval(start, Math.max(start, end)); | 872 _lastVisibleInterval = new Interval(start, Math.max(start, end)); |
| 873 _lastOffset = offset; | 873 _lastOffset = offset; |
| 874 return _lastVisibleInterval; | 874 return _lastVisibleInterval; |
| 875 } | 875 } |
| 876 | 876 |
| 877 int _findFirstItemAfter(num target, int hint) { | 877 int _findFirstItemAfter(num target, int hint) { |
| 878 for (int i = 0; i < _data.length; i++) { | 878 for (int i = 0; i < _data.length; i++) { |
| 879 if (getOffset(i) > target) { | 879 if (getOffset(i) > target) { |
| 880 return i; | 880 return i; |
| 881 } | 881 } |
| 882 } | 882 } |
| 883 return _data.length; | 883 return _data.length; |
| 884 } | 884 } |
| 885 | 885 |
| 886 // TODO(jacobr): use hint. | 886 // TODO(jacobr): use hint. |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 976 | 976 |
| 977 container = node.query('.dialog-body'); | 977 container = node.query('.dialog-body'); |
| 978 container.nodes.add(_content.node); | 978 container.nodes.add(_content.node); |
| 979 | 979 |
| 980 return node; | 980 return node; |
| 981 } | 981 } |
| 982 | 982 |
| 983 /** Override to handle dialog done. */ | 983 /** Override to handle dialog done. */ |
| 984 void onDone() { } | 984 void onDone() { } |
| 985 } | 985 } |
| OLD | NEW |