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

Side by Side Diff: sky/sdk/lib/widgets/widget.dart

Issue 1222823004: Make the menu items in the drawer change colour when tapped, per Material spec. (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: Created 5 years, 5 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
« no previous file with comments | « sky/sdk/lib/widgets/theme.dart ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 'dart:async'; 5 import 'dart:async';
6 import 'dart:collection'; 6 import 'dart:collection';
7 import 'dart:mirrors'; 7 import 'dart:mirrors';
8 import 'dart:sky' as sky; 8 import 'dart:sky' as sky;
9 9
10 import '../base/hit_test.dart'; 10 import '../base/hit_test.dart';
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after
216 216
217 } 217 }
218 218
219 class ParentDataNode extends TagNode { 219 class ParentDataNode extends TagNode {
220 ParentDataNode(Widget child, this.parentData, { String key }) 220 ParentDataNode(Widget child, this.parentData, { String key })
221 : super(child, key: key); 221 : super(child, key: key);
222 final ParentData parentData; 222 final ParentData parentData;
223 } 223 }
224 224
225 abstract class Inherited extends TagNode { 225 abstract class Inherited extends TagNode {
226
226 Inherited({ String key, Widget child }) : super._withKey(child, key); 227 Inherited({ String key, Widget child }) : super._withKey(child, key);
228
229 void _sync(Widget old, dynamic slot) {
230 if (old != null && syncShouldNotify(old)) {
231 void notifyChildren(Widget child) {
232 if (child is Component &&
233 child._dependencies != null &&
234 child._dependencies.contains(runtimeType))
abarth-chromium 2015/07/06 20:13:43 Do we want to capture runtimeType in a final varia
235 child._dependenciesChanged();
236 if (child.runtimeType != this)
abarth-chromium 2015/07/06 20:13:43 child.runtimeType != runtimeType ?
237 child.walkChildren(notifyChildren);
238 }
239 walkChildren(notifyChildren);
240 }
241 super._sync(old, slot);
242 }
243
244 bool syncShouldNotify(Inherited old);
245
227 } 246 }
228 247
229 typedef void GestureEventListener(sky.GestureEvent e); 248 typedef void GestureEventListener(sky.GestureEvent e);
230 typedef void PointerEventListener(sky.PointerEvent e); 249 typedef void PointerEventListener(sky.PointerEvent e);
231 typedef void EventListener(sky.Event e); 250 typedef void EventListener(sky.Event e);
232 251
233 class Listener extends TagNode { 252 class Listener extends TagNode {
234 253
235 Listener({ 254 Listener({
236 String key, 255 String key,
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
347 _built = null; 366 _built = null;
348 super.remove(); 367 super.remove();
349 } 368 }
350 369
351 void detachRoot() { 370 void detachRoot() {
352 assert(_built != null); 371 assert(_built != null);
353 assert(root != null); 372 assert(root != null);
354 _built.detachRoot(); 373 _built.detachRoot();
355 } 374 }
356 375
376 Set<Type> _dependencies;
357 Inherited inheritedOfType(Type targetType) { 377 Inherited inheritedOfType(Type targetType) {
378 if (_dependencies == null)
379 _dependencies = new Set<Type>();
380 _dependencies.add(targetType);
358 Widget ancestor = parent; 381 Widget ancestor = parent;
359 while (ancestor != null && ancestor.runtimeType != targetType) 382 while (ancestor != null && ancestor.runtimeType != targetType)
360 ancestor = ancestor.parent; 383 ancestor = ancestor.parent;
361 return ancestor; 384 return ancestor;
362 } 385 }
386 void _dependenciesChanged() {
387 // called by Inherited.sync()
388 scheduleBuild();
389 }
363 390
364 bool _retainStatefulNodeIfPossible(Widget old) { 391 bool _retainStatefulNodeIfPossible(Component old) {
365 assert(!_disqualifiedFromEverAppearingAgain); 392 assert(!_disqualifiedFromEverAppearingAgain);
366 393
367 Component oldComponent = old as Component; 394 if (old == null || !old._stateful)
368 if (oldComponent == null || !oldComponent._stateful)
369 return false; 395 return false;
370 396
371 assert(runtimeType == oldComponent.runtimeType); 397 assert(runtimeType == old.runtimeType);
372 assert(key == oldComponent.key); 398 assert(key == old.key);
373 399
374 // Make |this|, the newly-created object, into the "old" Component, and kill it 400 // Make |this|, the newly-created object, into the "old" Component, and kill it
375 _stateful = false; 401 _stateful = false;
376 _built = oldComponent._built; 402 _built = old._built;
377 assert(_built != null); 403 assert(_built != null);
378 _disqualifiedFromEverAppearingAgain = true; 404 _disqualifiedFromEverAppearingAgain = true;
379 405
380 // Make |oldComponent| the "new" component 406 // Make |old| the "new" component
381 oldComponent._built = null; 407 old._built = null;
382 oldComponent._dirty = true; 408 old._dirty = true;
383 oldComponent.syncFields(this); 409 old.syncFields(this);
384 return true; 410 return true;
385 } 411 }
386 412
387 // This is called by _retainStatefulNodeIfPossible(), during 413 // This is called by _retainStatefulNodeIfPossible(), during
388 // syncChild(), just before _sync() is called. 414 // syncChild(), just before _sync() is called.
389 // This must be implemented on any subclass that can become stateful 415 // This must be implemented on any subclass that can become stateful
390 // (but don't call super.syncFields() if you inherit directly from 416 // (but don't call super.syncFields() if you inherit directly from
391 // Component, since that'll fire an assert). 417 // Component, since that'll fire an assert).
392 // If you don't ever become stateful, then don't override this. 418 // If you don't ever become stateful, then don't override this.
393 void syncFields(Component source) { 419 void syncFields(Component source) {
394 assert(false); 420 assert(false);
395 } 421 }
396 422
423 // order corresponds to _build_ order, not depth in the tree.
424 // All the Components built by a particular other Component will have the
425 // same order, regardless of whether one is subsequently inserted
426 // into another. The order is used to not tell a Component to
427 // rebuild if the Component that it built has itself been rebuilt.
397 final int _order; 428 final int _order;
398 static int _currentOrder = 0; 429 static int _currentOrder = 0;
399 430
400 // There are three cases here: 431 // There are three cases here:
401 // 1) Building for the first time: 432 // 1) Building for the first time:
402 // assert(_built == null && old == null) 433 // assert(_built == null && old == null)
403 // 2) Re-building (because a dirty flag got set): 434 // 2) Re-building (because a dirty flag got set):
404 // assert(_built != null && old == null) 435 // assert(_built != null && old == null)
405 // 3) Syncing against an old version 436 // 3) Syncing against an old version
406 // assert(_built == null && old != null) 437 // assert(_built == null && old != null)
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
439 void _buildIfDirty() { 470 void _buildIfDirty() {
440 assert(!_disqualifiedFromEverAppearingAgain); 471 assert(!_disqualifiedFromEverAppearingAgain);
441 if (!_dirty || !_mounted) 472 if (!_dirty || !_mounted)
442 return; 473 return;
443 474
444 assert(root != null); 475 assert(root != null);
445 _sync(null, _slot); 476 _sync(null, _slot);
446 } 477 }
447 478
448 void scheduleBuild() { 479 void scheduleBuild() {
449 setState(() {}); 480 assert(!_disqualifiedFromEverAppearingAgain);
481 if (_isBuilding || _dirty || !_mounted)
482 return;
483 _dirty = true;
484 _scheduleComponentForRender(this);
450 } 485 }
451 486
452 void setState(Function fn()) { 487 void setState(Function fn()) {
453 assert(!_disqualifiedFromEverAppearingAgain);
454 assert(_stateful); 488 assert(_stateful);
455 fn(); 489 fn();
456 if (_isBuilding || _dirty || !_mounted) 490 scheduleBuild();
457 return;
458
459 _dirty = true;
460 _scheduleComponentForRender(this);
461 } 491 }
462 492
463 Widget build(); 493 Widget build();
464 494
465 } 495 }
466 496
467 Set<Component> _dirtyComponents = new Set<Component>(); 497 Set<Component> _dirtyComponents = new Set<Component>();
468 bool _buildScheduled = false; 498 bool _buildScheduled = false;
469 bool _inRenderDirtyComponents = false; 499 bool _inRenderDirtyComponents = false;
470 500
471 List<int> _debugFrameTimes = <int>[]; 501 List<int> _debugFrameTimes = <int>[];
472 502
503 void _absorbDirtyComponents(List<Component> list) {
504 list.addAll(_dirtyComponents);
505 _dirtyComponents.clear();
506 list.sort((Component a, Component b) => a._order - b._order);
507 }
508
473 void _buildDirtyComponents() { 509 void _buildDirtyComponents() {
474 Stopwatch sw; 510 Stopwatch sw;
475 if (_shouldLogRenderDuration) 511 if (_shouldLogRenderDuration)
476 sw = new Stopwatch()..start(); 512 sw = new Stopwatch()..start();
477 513
514 _inRenderDirtyComponents = true;
478 try { 515 try {
479 sky.tracing.begin('Widgets._buildDirtyComponents'); 516 sky.tracing.begin('Widgets._buildDirtyComponents');
480 _inRenderDirtyComponents = true; 517 List<Component> sortedDirtyComponents = new List<Component>();
481 518 _absorbDirtyComponents(sortedDirtyComponents);
482 List<Component> sortedDirtyComponents = _dirtyComponents.toList(); 519 int index = 0;
483 sortedDirtyComponents.sort((Component a, Component b) => a._order - b._order ); 520 while (index < sortedDirtyComponents.length) {
484 for (var comp in sortedDirtyComponents) { 521 Component component = sortedDirtyComponents[index];
485 comp._buildIfDirty(); 522 component._buildIfDirty();
523 if (_dirtyComponents.length > 0) {
524 // the following assert verifies that we're not rebuilding anyone twice in one frame
525 assert(_dirtyComponents.every((Component component) => !sortedDirtyCompo nents.contains(component)));
526 _absorbDirtyComponents(sortedDirtyComponents);
527 index = 0;
528 } else {
529 index += 1;
530 }
486 } 531 }
487 532 } finally {
488 _dirtyComponents.clear();
489 _buildScheduled = false; 533 _buildScheduled = false;
490 } finally {
491 _inRenderDirtyComponents = false; 534 _inRenderDirtyComponents = false;
492 sky.tracing.end('Widgets._buildDirtyComponents'); 535 sky.tracing.end('Widgets._buildDirtyComponents');
493 } 536 }
494 537
495 Widget._notifyMountStatusChanged(); 538 Widget._notifyMountStatusChanged();
496 539
497 if (_shouldLogRenderDuration) { 540 if (_shouldLogRenderDuration) {
498 sw.stop(); 541 sw.stop();
499 _debugFrameTimes.add(sw.elapsedMicroseconds); 542 _debugFrameTimes.add(sw.elapsedMicroseconds);
500 if (_debugFrameTimes.length >= 1000) { 543 if (_debugFrameTimes.length >= 1000) {
501 _debugFrameTimes.sort(); 544 _debugFrameTimes.sort();
502 const int i = 99; 545 const int i = 99;
503 print('_buildDirtyComponents: ${i+1}th fastest frame out of the last ${_de bugFrameTimes.length}: ${_debugFrameTimes[i]} microseconds'); 546 print('_buildDirtyComponents: ${i+1}th fastest frame out of the last ${_de bugFrameTimes.length}: ${_debugFrameTimes[i]} microseconds');
504 _debugFrameTimes.clear(); 547 _debugFrameTimes.clear();
505 } 548 }
506 } 549 }
507 } 550 }
508 551
509 void _scheduleComponentForRender(Component c) { 552 void _scheduleComponentForRender(Component c) {
510 assert(!_inRenderDirtyComponents);
511 _dirtyComponents.add(c); 553 _dirtyComponents.add(c);
512
513 if (!_buildScheduled) { 554 if (!_buildScheduled) {
514 _buildScheduled = true; 555 _buildScheduled = true;
515 new Future.microtask(_buildDirtyComponents); 556 new Future.microtask(_buildDirtyComponents);
516 } 557 }
517 } 558 }
518 559
519 560
520 // RenderObjectWrappers correspond to a desired state of a RenderObject. 561 // RenderObjectWrappers correspond to a desired state of a RenderObject.
521 // They are fully immutable, with one exception: A Widget which is a 562 // They are fully immutable, with one exception: A Widget which is a
522 // Component which lives within an MultiChildRenderObjectWrapper's 563 // Component which lives within an MultiChildRenderObjectWrapper's
(...skipping 446 matching lines...) Expand 10 before | Expand all | Expand 10 after
969 if (root.parent == null) { 1010 if (root.parent == null) {
970 // we haven't attached it yet 1011 // we haven't attached it yet
971 assert(_container.child == null); 1012 assert(_container.child == null);
972 _container.child = root; 1013 _container.child = root;
973 } 1014 }
974 assert(root.parent == _container); 1015 assert(root.parent == _container);
975 } 1016 }
976 1017
977 Widget build() => builder(); 1018 Widget build() => builder();
978 } 1019 }
OLDNEW
« no previous file with comments | « sky/sdk/lib/widgets/theme.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698