// 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; }