Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(150)

Side by Side Diff: client/view/SliderMenu.dart

Issue 9382027: Move client/{base, observable, layout, touch, util, view} to samples/ui_lib . (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: '' Created 8 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « client/view/PagedViews.dart ('k') | client/view/resources/view.css » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
3 // BSD-style license that can be found in the LICENSE file.
4
5 typedef void SelectHandler(String menuText);
6
7 /**
8 * This implements a horizontal menu bar with a sliding triangle arrow
9 * that points at the currently selected item.
10 */
11 class SliderMenu extends View {
12 static final int TRIANGLE_WIDTH = 24;
13
14 // currently selected menu item
15 Element selectedItem;
16
17 // This holds the element where a touchstart occured. (This is set
18 // in touchstart, and cleared in touchend.) If this is null, then a
19 // touch operation is not in progress.
20 // TODO(mattsh) - move this to a touch mixin
21 Element touchItem;
22
23 /**
24 * Callback function that we call when the user chooses something from
25 * the menu. This is passed the menu item text.
26 */
27 SelectHandler onSelect;
28
29 List<String> _menuItems;
30
31 SliderMenu(this._menuItems, this.onSelect) : super() {}
32
33 Element render() {
34 // Create a div for each menu item.
35 final items = new StringBuffer();
36 for (final item in _menuItems) {
37 items.add('<div class="sm-item">$item</div>');
38 }
39
40 // Create a root node to hold this view.
41 return new Element.html('''
42 <div class="sm-root">
43 <div class="sm-item-box">
44 <div class="sm-item-filler"></div>
45 $items
46 <div class="sm-item-filler"></div>
47 </div>
48 <div class="sm-slider-box">
49 <div class="sm-triangle"></div>
50 </div>
51 </div>
52 ''');
53 }
54
55 void enterDocument() {
56 // select the first item
57 // todo(jacobr): too much actual work is performed in enterDocument.
58 // Ideally, enterDocument should do nothing more than redecorate a view
59 // and perhaps calculating the correct child sizes for edge cases that
60 // cannot be handled by the browser layout engine.
61 selectItem(node.query('.sm-item'), false);
62
63 // TODO(mattsh), abstract this somehow into a touch click mixin
64 if (Device.supportsTouch) {
65 node.on.touchStart.add((event) {
66 touchItem = itemOfTouchEvent(event);
67 if (touchItem != null) {
68 selectItemText(touchItem);
69 }
70 event.preventDefault();
71 });
72 node.on.touchEnd.add((event) {
73 if (touchItem != null) {
74 if (itemOfTouchEvent(event) == touchItem) {
75 selectItem(touchItem, true);
76 } else {
77 // the Touch target is somewhere other where than the touchstart
78 // occured, so revert the selected menu text back to where it was
79 // before the touchstart,
80 selectItemText(selectedItem);
81 }
82 // touch operation has ended
83 touchItem = null;
84 }
85 event.preventDefault();
86 });
87 } else {
88 node.on.click.add((event) => selectItem(event.target, true));
89 }
90
91 window.on.resize.add((Event event) => updateIndicator(false));
92 }
93
94 /**
95 * Walks the parent chain of the first Touch target to find the first ancestor
96 * that has sm-item class.
97 */
98 Element itemOfTouchEvent(event) {
99 Node node = event.changedTouches[0].target;
100 return itemOfNode(node);
101 }
102
103 Element itemOfNode(Node node) {
104 // TODO(jmesserly): workaround for bug 5399957, document.parent == document
105 while (node != null && node != document) {
106 if (node is Element) {
107 Element element = node;
108 if (element.classes.contains('sm-item')) {
109 return element;
110 }
111 }
112 node = node.parent;
113 }
114 return null;
115 }
116
117 void selectItemText(Element item) {
118 // unselect all menu items
119 for (final sliderItem in node.queryAll('.sm-item')) {
120 sliderItem.classes.remove('sel');
121 }
122
123 // select the item the user clicked on
124 item.classes.add('sel');
125 }
126
127 void selectItem(Element item, bool animate) {
128 if (!item.classes.contains('sm-item')) {
129 return;
130 }
131
132 selectedItem = item;
133 selectItemText(item);
134 updateIndicator(animate);
135 onSelect(item.text);
136 }
137
138 void selectNext(bool animate) {
139 final result = node.query('.sm-item.sel').nextElementSibling;
140 if (result != null) {
141 selectItem(result, animate);
142 }
143 }
144
145 void selectPrevious(bool animate) {
146 final result = node.query('.sm-item.sel').previousElementSibling;
147 if (result != null) {
148 selectItem(result, animate);
149 }
150 }
151
152 /**
153 * animate - if true, then animate the movement of the triangle slider
154 */
155 void updateIndicator(bool animate) {
156 if (selectedItem != null) {
157 // calculate where we want to put the triangle
158 selectedItem.rect.then((ElementRect rect) {
159 num x = rect.offset.left +
160 rect.offset.width / 2 - TRIANGLE_WIDTH / 2;
161 _moveIndicator(x, animate);
162 });
163 } else {
164 _moveIndicator(0, animate);
165 }
166 }
167
168 void _moveIndicator(num x, bool animate) {
169 // find the slider filler (the div element to the left of the
170 // triangle) set its width the push the triangle to where we want it.
171 String duration = animate ? '.3s' : '0s';
172 final triangle = node.query('.sm-triangle');
173 triangle.style.transitionDuration = duration;
174 FxUtil.setWebkitTransform(triangle, x, 0);
175 }
176 }
OLDNEW
« no previous file with comments | « client/view/PagedViews.dart ('k') | client/view/resources/view.css » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698