From bf47b34b603d57c9ba8092c9c7f7db4614934d20 Mon Sep 17 00:00:00 2001 From: Ian Hickson Date: Wed, 23 Aug 2017 10:34:20 -0700 Subject: [PATCH] Directionality widget (#11739) --- packages/flutter/lib/src/widgets/basic.dart | 50 ++++++++++++++ .../test/widgets/directionality_test.dart | 69 +++++++++++++++++++ 2 files changed, 119 insertions(+) create mode 100644 packages/flutter/test/widgets/directionality_test.dart diff --git a/packages/flutter/lib/src/widgets/basic.dart b/packages/flutter/lib/src/widgets/basic.dart index adfd83f170..27c1866787 100644 --- a/packages/flutter/lib/src/widgets/basic.dart +++ b/packages/flutter/lib/src/widgets/basic.dart @@ -55,6 +55,56 @@ export 'package:flutter/rendering.dart' show WrapAlignment, WrapCrossAlignment; +// BIDIRECTIONAL TEXT SUPPORT + +/// A widget that determines the ambient directionality of text and +/// text-direction-sensitive render objects. +/// +/// For example, [Padding] depends on the [Directionality] to resolve +/// [EdgeInsetsDirectional] objects into absolute [EdgeInsets] objects. +class Directionality extends InheritedWidget { + /// Creates a widget that determines the directionality of text and + /// text-direction-sensitive render objects. + /// + /// The [textDirection] and [child] arguments must not be null. + const Directionality({ + Key key, + @required this.textDirection, + @required Widget child + }) : assert(textDirection != null), + assert(child != null), + super(key: key, child: child); + + /// The text direction for this subtree. + final TextDirection textDirection; + + /// The text direction from the closest instance of this class that encloses + /// the given context. + /// + /// If there is no [Directionality] ancestor widget in the tree at the given + /// context, then this will return null. + /// + /// Typical usage is as follows: + /// + /// ```dart + /// TextDirection textDirection = Directionality.of(context); + /// ``` + static TextDirection of(BuildContext context) { + final Directionality widget = context.inheritFromWidgetOfExactType(Directionality); + return widget?.textDirection; + } + + @override + bool updateShouldNotify(Directionality old) => textDirection != old.textDirection; + + @override + void debugFillProperties(DiagnosticPropertiesBuilder description) { + super.debugFillProperties(description); + description.add(new EnumProperty('textDirection', textDirection)); + } +} + + // PAINTING NODES /// A widget that makes its child partially transparent. diff --git a/packages/flutter/test/widgets/directionality_test.dart b/packages/flutter/test/widgets/directionality_test.dart new file mode 100644 index 0000000000..b326de0c26 --- /dev/null +++ b/packages/flutter/test/widgets/directionality_test.dart @@ -0,0 +1,69 @@ +// 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_test/flutter_test.dart'; +import 'package:flutter/widgets.dart'; + +void main() { + testWidgets('Directionality', (WidgetTester tester) async { + final List log = []; + final Widget inner = new Builder( + builder: (BuildContext context) { + log.add(Directionality.of(context)); + return new Placeholder(); + } + ); + await tester.pumpWidget( + new Directionality( + textDirection: TextDirection.ltr, + child: inner, + ), + ); + expect(log, [TextDirection.ltr]); + await tester.pumpWidget( + new Directionality( + textDirection: TextDirection.ltr, + child: inner, + ), + ); + expect(log, [TextDirection.ltr]); + await tester.pumpWidget( + new Directionality( + textDirection: TextDirection.rtl, + child: inner, + ), + ); + expect(log, [TextDirection.ltr, TextDirection.rtl]); + await tester.pumpWidget( + new Directionality( + textDirection: TextDirection.rtl, + child: inner, + ), + ); + expect(log, [TextDirection.ltr, TextDirection.rtl]); + await tester.pumpWidget( + new Directionality( + textDirection: TextDirection.ltr, + child: inner, + ), + ); + expect(log, [TextDirection.ltr, TextDirection.rtl, TextDirection.ltr]); + }); + + testWidgets('Directionality default', (WidgetTester tester) async { + bool good = false; + await tester.pumpWidget(new Builder( + builder: (BuildContext context) { + expect(Directionality.of(context), isNull); + good = true; + return new Placeholder(); + }, + )); + expect(good, isTrue); + }); + + testWidgets('Directionality can\'t be null', (WidgetTester tester) async { + expect(() { new Directionality(textDirection: null, child: new Placeholder()); }, throwsAssertionError); + }); +}