blob: 8b21778e1e77bec8fcc4d4f0cece294a667c135f [file] [log] [blame]
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:flutter/widgets.dart';
import 'material.dart';
/// Asserts that the given context has a [Material] ancestor.
///
/// Used by many material design widgets to make sure that they are
/// only used in contexts where they can print ink onto some material.
///
/// To call this function, use the following pattern, typically in the
/// relevant Widget's build method:
///
/// ```dart
/// assert(debugCheckHasMaterial(context));
/// ```
///
/// Does nothing if asserts are disabled. Always returns true.
bool debugCheckHasMaterial(BuildContext context) {
assert(() {
if (context.widget is! Material && context.ancestorWidgetOfExactType(Material) == null) {
final StringBuffer message = new StringBuffer();
message.writeln('No Material widget found.');
message.writeln(
'${context.widget.runtimeType} widgets require a Material '
'widget ancestor.'
);
message.writeln(
'In material design, most widgets are conceptually "printed" on '
'a sheet of material. In Flutter\'s material library, that '
'material is represented by the Material widget. It is the '
'Material widget that renders ink splashes, for instance. '
'Because of this, many material library widgets require that '
'there be a Material widget in the tree above them.'
);
message.writeln(
'To introduce a Material widget, you can either directly '
'include one, or use a widget that contains Material itself, '
'such as a Card, Dialog, Drawer, or Scaffold.'
);
message.writeln(
'The specific widget that could not find a Material ancestor was:'
);
message.writeln(' ${context.widget}');
final List<Widget> ancestors = <Widget>[];
context.visitAncestorElements((Element element) {
ancestors.add(element.widget);
return true;
});
if (ancestors.isNotEmpty) {
message.write('The ancestors of this widget were:');
for (Widget ancestor in ancestors)
message.write('\n $ancestor');
} else {
message.writeln(
'This widget is the root of the tree, so it has no '
'ancestors, let alone a "Material" ancestor.'
);
}
throw new FlutterError(message.toString());
}
return true;
}());
return true;
}