OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 import '../fn2.dart'; | 5 import '../fn2.dart'; |
6 import '../layout2.dart'; | 6 import '../layout2.dart'; |
7 import 'drawer.dart'; | |
8 import 'floating_action_button.dart'; | |
9 import '../theme/typography.dart' as typography; | 7 import '../theme/typography.dart' as typography; |
10 | 8 |
11 class Scaffold extends Component { | 9 // RenderNode |
12 static final Style _style = new Style(''' | 10 class RenderScaffold extends RenderDecoratedBox { |
13 ${typography.typeface}; | 11 |
14 ${typography.black.body1};'''); | 12 RenderScaffold({ |
15 | 13 BoxDecoration decoration, |
16 static final Style _mainStyle = new Style(''' | 14 RenderBox toolbar, |
17 height: -webkit-fill-available;'''); | 15 RenderBox body, |
18 | 16 RenderBox statusbar, |
19 static final FlexBoxParentData _contentParentData = new FlexBoxParentData()..f
lex = 1; | 17 RenderBox drawer, |
20 | 18 RenderBox floatingActionButton |
21 static final Style _fabStyle = new Style(''' | 19 }) : super(decoration) { |
22 position: absolute; | 20 this.toolbar = toolbar; |
23 bottom: 16px; | 21 this.body = body; |
24 right: 16px;'''); | 22 this.statusbar = statusbar; |
25 | 23 this.drawer = drawer; |
26 static final Style _drawerStyle = new Style(''' | 24 this.floatingActionButton = floatingActionButton; |
27 position: absolute; | 25 } |
28 top: 0; | 26 |
29 left: 0; | 27 RenderBox _toolbar; |
30 bottom: 0; | 28 RenderBox get toolbar => _toolbar; |
31 right: 0;'''); | 29 void set toolbar (RenderBox value) { |
32 | 30 if (_toolbar != null) |
33 UINode header; | 31 dropChild(_toolbar); |
34 UINode content; | 32 _toolbar = value; |
35 FloatingActionButton fab; | 33 if (_toolbar != null) |
36 Drawer drawer; | 34 adoptChild(_toolbar); |
37 List<UINode> overlays; | 35 markNeedsLayout(); |
| 36 } |
| 37 |
| 38 RenderBox _body; |
| 39 RenderBox get body => _body; |
| 40 void set body (RenderBox value) { |
| 41 if (_body != null) |
| 42 dropChild(_body); |
| 43 _body = value; |
| 44 if (_body != null) |
| 45 adoptChild(_body); |
| 46 markNeedsLayout(); |
| 47 } |
| 48 |
| 49 RenderBox _statusbar; |
| 50 RenderBox get statusbar => _statusbar; |
| 51 void set statusbar (RenderBox value) { |
| 52 if (_statusbar != null) |
| 53 dropChild(_statusbar); |
| 54 _statusbar = value; |
| 55 if (_statusbar != null) |
| 56 adoptChild(_statusbar); |
| 57 markNeedsLayout(); |
| 58 } |
| 59 |
| 60 RenderBox _drawer; |
| 61 RenderBox get drawer => _drawer; |
| 62 void set drawer (RenderBox value) { |
| 63 if (_drawer != null) |
| 64 dropChild(_drawer); |
| 65 _drawer = value; |
| 66 if (_drawer != null) |
| 67 adoptChild(_drawer); |
| 68 markNeedsLayout(); |
| 69 } |
| 70 |
| 71 RenderBox _floatingActionButton; |
| 72 RenderBox get floatingActionButton => _floatingActionButton; |
| 73 void set floatingActionButton (RenderBox value) { |
| 74 if (_floatingActionButton != null) |
| 75 dropChild(_floatingActionButton); |
| 76 _floatingActionButton = value; |
| 77 if (_floatingActionButton != null) |
| 78 adoptChild(_floatingActionButton); |
| 79 markNeedsLayout(); |
| 80 } |
| 81 |
| 82 void layout(BoxConstraints constraints, { RenderNode relayoutSubtreeRoot }) { |
| 83 width = constraints.constrainWidth(double.INFINITY); |
| 84 assert(width < double.INFINITY); |
| 85 height = constraints.constrainHeight(double.INFINITY); |
| 86 assert(height < double.INFINITY); |
| 87 relayout(); |
| 88 } |
| 89 |
| 90 static const kToolbarHeight = 100.0; |
| 91 static const kStatusbarHeight = 50.0; |
| 92 static const kButtonX = -16.0; // from right edge of body |
| 93 static const kButtonY = -16.0; // from bottom edge of body |
| 94 |
| 95 void relayout() { |
| 96 double bodyHeight = height; |
| 97 double bodyPosition = 0.0; |
| 98 if (toolbar != null) { |
| 99 print("laying out toolbar..."); |
| 100 toolbar.layout(new BoxConstraints.tight(width: width, height: kToolbarHeig
ht)); |
| 101 assert(toolbar.parentData is BoxParentData); |
| 102 toolbar.parentData.x = 0.0; |
| 103 toolbar.parentData.y = 0.0; |
| 104 print("...at ${toolbar.parentData.x},${toolbar.parentData.y} dim ${toolbar.w
idth}x${toolbar.height}"); |
| 105 bodyPosition = kToolbarHeight; |
| 106 bodyHeight -= kToolbarHeight; |
| 107 } |
| 108 if (statusbar != null) { |
| 109 statusbar.layout(new BoxConstraints.tight(width: width, height: kStatusbar
Height)); |
| 110 assert(statusbar.parentData is BoxParentData); |
| 111 statusbar.parentData.x = 0.0; |
| 112 statusbar.parentData.y = height - kStatusbarHeight; |
| 113 bodyHeight -= kStatusbarHeight; |
| 114 } |
| 115 if (body != null) { |
| 116 body.layout(new BoxConstraints.tight(width: width, height: bodyHeight)); |
| 117 assert(body.parentData is BoxParentData); |
| 118 body.parentData.x = 0.0; |
| 119 body.parentData.y = bodyPosition; |
| 120 } |
| 121 if (drawer != null) { |
| 122 drawer.layout(new BoxConstraints(minWidth: 0.0, maxWidth: width, minHeight
: height, maxHeight: height)); |
| 123 assert(drawer.parentData is BoxParentData); |
| 124 drawer.parentData.x = 0.0; |
| 125 drawer.parentData.y = 0.0; |
| 126 } |
| 127 if (floatingActionButton != null) { |
| 128 floatingActionButton.layout(new BoxConstraints(minWidth: 0.0, maxWidth: wi
dth, minHeight: height, maxHeight: height)); |
| 129 assert(floatingActionButton.parentData is BoxParentData); |
| 130 floatingActionButton.parentData.x = width - xButtonX; |
| 131 floatingActionButton.parentData.y = bodyPosition + bodyHeight - kButtonY; |
| 132 } |
| 133 layoutDone(); |
| 134 } |
| 135 |
| 136 void paint(RenderNodeDisplayList canvas) { |
| 137 if (body != null) |
| 138 canvas.paintChild(body, (body.parentData as BoxParentData).x, (body.parent
Data as BoxParentData).y); |
| 139 if (statusbar != null) |
| 140 canvas.paintChild(statusbar, (statusbar.parentData as BoxParentData).x, (s
tatusbar.parentData as BoxParentData).y); |
| 141 if (toolbar != null) |
| 142 canvas.paintChild(toolbar, (toolbar.parentData as BoxParentData).x, (toolb
ar.parentData as BoxParentData).y); |
| 143 if (floatingActionButton != null) |
| 144 canvas.paintChild(floatingActionButton, (floatingActionButton.parentData a
s BoxParentData).x, (floatingActionButton.parentData as BoxParentData).y); |
| 145 if (drawer != null) |
| 146 canvas.paintChild(drawer, (drawer.parentData as BoxParentData).x, (drawer.
parentData as BoxParentData).y); |
| 147 } |
| 148 |
| 149 void hitTestChildren(HitTestResult result, { double x, double y }) { |
| 150 assert(floatingActionButton == null || floatingActionButton.parentData is Bo
xParentData); |
| 151 assert(statusBar == null || statusBar.parentData is BoxParentData); |
| 152 if ((drawer != null) && (x < drawer.width)) { |
| 153 drawer.hitTest(result, x: x, y: y); |
| 154 } else if ((floatingActionButton != null) && (x >= floatingActionButton.pare
ntData.x) && (x < floatingActionButton.parentData.x + floatingActionButton.width
) |
| 155 && (y >= floatingActionButton.pare
ntData.y) && (y < floatingActionButton.parentData.y + floatingActionButton.heigh
t)) { |
| 156 floatingActionButton.hitTest(result, x: x-floatingActionButton.parentData.
x, y: y-floatingActionButton.parentData.y); |
| 157 } else if ((toolbar != null) && (y < toolbar.height)) { |
| 158 toolbar.hitTest(result, x: x, y: y); |
| 159 } else if ((statusbar != null) && (y > statusbar.parentData.y)) { |
| 160 statusbar.hitTest(result, x: x, y: y-statusbar.parentData.y); |
| 161 } else { |
| 162 body.hitTest(result, x: x, y: y-body.parentData.y); |
| 163 } |
| 164 } |
| 165 |
| 166 } |
| 167 |
| 168 class Scaffold extends RenderNodeWrapper { |
| 169 |
| 170 // static final Style _style = new Style(''' |
| 171 // ${typography.typeface}; |
| 172 // ${typography.black.body1};'''); |
38 | 173 |
39 Scaffold({ | 174 Scaffold({ |
40 Object key, | 175 Object key, |
41 this.header, | 176 this.toolbar, |
42 this.content, | 177 this.body, |
43 this.fab, | 178 this.statusbar, |
44 this.drawer, | 179 this.drawer, |
45 this.overlays | 180 this.floatingActionButton |
46 }) : super(key: key); | 181 }) : super( |
47 | 182 key: key |
48 UINode build() { | 183 ); |
49 List<UINode> children = [ | 184 |
50 new FlexContainer( | 185 final UINode toolbar; |
51 key: 'Main', | 186 final UINode body; |
52 direction: FlexDirection.Column, | 187 final UINode statusbar; |
53 style: _mainStyle, | 188 final UINode drawer; |
54 children: [header, new ParentDataNode(content, _contentParentData)]) | 189 final UINode floatingActionButton; |
55 ]; | 190 |
56 | 191 RenderScaffold root; |
57 if (fab != null) | 192 RenderScaffold createNode() => new RenderScaffold(); |
58 children.add(new StyleNode(fab, _fabStyle)); | 193 |
59 | 194 static final Scaffold _emptyScaffold = new Scaffold(); |
60 if (drawer != null) | 195 RenderNodeWrapper get emptyNode => _emptyScaffold; |
61 children.add(new StyleNode(drawer, _drawerStyle)); | 196 |
62 | 197 void insert(RenderNodeWrapper child, dynamic slot) { |
63 if (overlays != null) | 198 switch (slot) { |
64 children.addAll(overlays); | 199 case #toolbar: root.toolbar = toolbar == null ? null : toolbar.root; break
; |
65 | 200 case #body: root.body = body == null ? null : body.root; break; |
66 return new Container(style: _style, children: children); | 201 case #statusbar: root.statusbar = statusbar == null ? null : statusbar.roo
t; break; |
67 } | 202 case #drawer: root.drawer = drawer == null ? null : drawer.root; break; |
| 203 case #floatingActionButton: root.floatingActionButton = floatingActionButt
on == null ? null : floatingActionButton.root; break; |
| 204 default: assert(false); |
| 205 } |
| 206 } |
| 207 |
| 208 void removeChild(UINode node) { |
| 209 if (node == root.toolbar) |
| 210 root.toolbar = null; |
| 211 if (node == root.body) |
| 212 root.body = null; |
| 213 if (node == root.statusbar) |
| 214 root.statusbar = null; |
| 215 if (node == root.drawer) |
| 216 root.drawer = null; |
| 217 if (node == root.floatingActionButton) |
| 218 root.floatingActionButton = null; |
| 219 super.removeChild(node); |
| 220 } |
| 221 |
| 222 void syncRenderNode(UINode old) { |
| 223 super.syncRenderNode(old); |
| 224 syncChild(toolbar, old is Scaffold ? old.toolbar : null, #toolbar); |
| 225 syncChild(body, old is Scaffold ? old.body : null, #body); |
| 226 syncChild(statusbar, old is Scaffold ? old.statusbar : null, #statusbar); |
| 227 syncChild(drawer, old is Scaffold ? old.drawer : null, #drawer); |
| 228 syncChild(floatingActionButton, old is Scaffold ? old.floatingActionButton :
null, #floatingActionButton); |
| 229 } |
| 230 |
68 } | 231 } |
OLD | NEW |