Commit c82c0cf3 authored by Andrew Wilson's avatar Andrew Wilson

Merge pull request #2757 from apwilson/banner

Refactor CheckedModeBanner into something more reusable.
parents 00263581 86142387
...@@ -9,9 +9,9 @@ import 'package:flutter/rendering.dart'; ...@@ -9,9 +9,9 @@ import 'package:flutter/rendering.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'asset_vendor.dart'; import 'asset_vendor.dart';
import 'banner.dart';
import 'basic.dart'; import 'basic.dart';
import 'binding.dart'; import 'binding.dart';
import 'checked_mode_banner.dart';
import 'framework.dart'; import 'framework.dart';
import 'locale_query.dart'; import 'locale_query.dart';
import 'media_query.dart'; import 'media_query.dart';
......
...@@ -7,16 +7,25 @@ import 'dart:math' as math; ...@@ -7,16 +7,25 @@ import 'dart:math' as math;
import 'basic.dart'; import 'basic.dart';
import 'framework.dart'; import 'framework.dart';
class _CheckedModeBannerPainter extends CustomPainter { enum BannerLocation { topRight, topLeft, bottomRight, bottomLeft }
const _CheckedModeBannerPainter();
class BannerPainter extends CustomPainter {
const BannerPainter({
this.message,
this.location
});
final String message;
final BannerLocation location;
static const Color kColor = const Color(0xA0B71C1C); static const Color kColor = const Color(0xA0B71C1C);
static const double kOffset = 40.0; // distance to bottom of banner, at a 45 degree angle inwards from the top right corner static const double kOffset = 40.0; // distance to bottom of banner, at a 45 degree angle inwards
static const double kHeight = 12.0; // height of banner static const double kHeight = 12.0; // height of banner
static const double kBottomOffset = kOffset + 0.707 * kHeight; // offset plus sqrt(2)/2 * banner height
static const Offset kTextAlign = const Offset(0.0, -3.0); // offset to move text up static const Offset kTextAlign = const Offset(0.0, -3.0); // offset to move text up
static const double kFontSize = kHeight * 0.85; static const double kFontSize = kHeight * 0.85;
static const double kShadowBlur = 4.0; // shadow blur sigma static const double kShadowBlur = 4.0; // shadow blur sigma
static final Rect kRect = new Rect.fromLTWH(-kOffset, kOffset-kHeight, kOffset * 2.0, kHeight); static final Rect kRect = new Rect.fromLTWH(-kOffset, kOffset - kHeight, kOffset * 2.0, kHeight);
static const TextStyle kTextStyles = const TextStyle( static const TextStyle kTextStyles = const TextStyle(
color: const Color(0xFFFFFFFF), color: const Color(0xFFFFFFFF),
fontSize: kFontSize, fontSize: kFontSize,
...@@ -24,12 +33,6 @@ class _CheckedModeBannerPainter extends CustomPainter { ...@@ -24,12 +33,6 @@ class _CheckedModeBannerPainter extends CustomPainter {
textAlign: TextAlign.center textAlign: TextAlign.center
); );
static final TextPainter textPainter = new TextPainter()
..text = new TextSpan(style: kTextStyles, text: 'SLOW MODE')
..maxWidth = kOffset * 2.0
..maxHeight = kHeight
..layout();
@override @override
void paint(Canvas canvas, Size size) { void paint(Canvas canvas, Size size) {
final Paint paintShadow = new Paint() final Paint paintShadow = new Paint()
...@@ -38,21 +41,84 @@ class _CheckedModeBannerPainter extends CustomPainter { ...@@ -38,21 +41,84 @@ class _CheckedModeBannerPainter extends CustomPainter {
final Paint paintBanner = new Paint() final Paint paintBanner = new Paint()
..color = kColor; ..color = kColor;
canvas canvas
..translate(size.width, 0.0) ..translate(_translationX(size.width), _translationY(size.height))
..rotate(math.PI/4) ..rotate(_rotation)
..drawRect(kRect, paintShadow) ..drawRect(kRect, paintShadow)
..drawRect(kRect, paintBanner); ..drawRect(kRect, paintBanner);
final TextPainter textPainter = new TextPainter()
..text = new TextSpan(style: kTextStyles, text: message)
..maxWidth = kOffset * 2.0
..maxHeight = kHeight
..layout();
textPainter.paint(canvas, kRect.topLeft.toOffset() + kTextAlign); textPainter.paint(canvas, kRect.topLeft.toOffset() + kTextAlign);
} }
@override @override
bool shouldRepaint(_CheckedModeBannerPainter oldPainter) => false; bool shouldRepaint(BannerPainter oldPainter) => false;
@override @override
bool hitTest(Point position) => false; bool hitTest(Point position) => false;
double _translationX(double width) {
switch (location) {
case BannerLocation.bottomRight:
return width - kBottomOffset;
case BannerLocation.topRight:
return width;
case BannerLocation.bottomLeft:
return kBottomOffset;
case BannerLocation.topLeft:
return 0.0;
}
}
double _translationY(double height) {
switch (location) {
case BannerLocation.bottomRight:
case BannerLocation.bottomLeft:
return height - kBottomOffset;
case BannerLocation.topRight:
case BannerLocation.topLeft:
return 0.0;
}
}
double get _rotation {
switch (location) {
case BannerLocation.bottomLeft:
case BannerLocation.topRight:
return math.PI / 4.0;
case BannerLocation.bottomRight:
case BannerLocation.topLeft:
return -math.PI / 4.0;
}
}
}
class Banner extends StatelessWidget {
Banner({
Key key,
this.child,
this.message,
this.location
}) : super(key: key);
final Widget child;
final String message;
final BannerLocation location;
@override
Widget build(BuildContext context) {
return new CustomPaint(
foregroundPainter: new BannerPainter(message: message, location: location),
child: child
);
}
} }
/// Displays a banner saying "CHECKED" when running in checked mode. /// Displays a banner saying "SLOW MODE" when running in checked mode.
/// Does nothing in release mode. /// Does nothing in release mode.
class CheckedModeBanner extends StatelessWidget { class CheckedModeBanner extends StatelessWidget {
CheckedModeBanner({ CheckedModeBanner({
...@@ -60,17 +126,16 @@ class CheckedModeBanner extends StatelessWidget { ...@@ -60,17 +126,16 @@ class CheckedModeBanner extends StatelessWidget {
this.child this.child
}) : super(key: key); }) : super(key: key);
/// The widget below this widget in the tree.
final Widget child; final Widget child;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
Widget result = child; Widget result = child;
assert(() { assert(() {
result = new CustomPaint( result = new Banner(
foregroundPainter: const _CheckedModeBannerPainter(), child: result,
child: result message: 'SLOW MODE',
); location: BannerLocation.topRight);
return true; return true;
}); });
return result; return result;
......
...@@ -8,9 +8,9 @@ library widgets; ...@@ -8,9 +8,9 @@ library widgets;
export 'src/widgets/app.dart'; export 'src/widgets/app.dart';
export 'src/widgets/asset_vendor.dart'; export 'src/widgets/asset_vendor.dart';
export 'src/widgets/auto_layout.dart'; export 'src/widgets/auto_layout.dart';
export 'src/widgets/banner.dart';
export 'src/widgets/basic.dart'; export 'src/widgets/basic.dart';
export 'src/widgets/binding.dart'; export 'src/widgets/binding.dart';
export 'src/widgets/checked_mode_banner.dart';
export 'src/widgets/child_view.dart'; export 'src/widgets/child_view.dart';
export 'src/widgets/dismissable.dart'; export 'src/widgets/dismissable.dart';
export 'src/widgets/drag_target.dart'; export 'src/widgets/drag_target.dart';
......
// 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 'dart:math' as math;
import 'package:flutter/widgets.dart';
import 'package:test/test.dart';
class TestCanvas implements Canvas {
final List<Invocation> invocations = <Invocation>[];
@override
void noSuchMethod(Invocation invocation) {
invocations.add(invocation);
}
}
void main() {
test('A Banner with a location of topLeft paints in the top left', () {
BannerPainter bannerPainter = new BannerPainter(
message:"foo",
location: BannerLocation.topLeft
);
TestCanvas canvas = new TestCanvas();
bannerPainter.paint(canvas, new Size(1000.0, 1000.0));
Invocation translateCommand = canvas.invocations.firstWhere((Invocation invocation) {
return invocation.memberName == #translate;
});
expect(translateCommand, isNotNull);
expect(translateCommand.positionalArguments[0], lessThan(100.0));
expect(translateCommand.positionalArguments[1], lessThan(100.0));
Invocation rotateCommand = canvas.invocations.firstWhere((Invocation invocation) {
return invocation.memberName == #rotate;
});
expect(rotateCommand, isNotNull);
expect(rotateCommand.positionalArguments[0], equals(-math.PI / 4.0));
});
test('A Banner with a location of topRight paints in the top right', () {
BannerPainter bannerPainter = new BannerPainter(
message:"foo",
location: BannerLocation.topRight
);
TestCanvas canvas = new TestCanvas();
bannerPainter.paint(canvas, new Size(1000.0, 1000.0));
Invocation translateCommand = canvas.invocations.firstWhere((Invocation invocation) {
return invocation.memberName == #translate;
});
expect(translateCommand, isNotNull);
expect(translateCommand.positionalArguments[0], greaterThan(900.0));
expect(translateCommand.positionalArguments[1], lessThan(100.0));
Invocation rotateCommand = canvas.invocations.firstWhere((Invocation invocation) {
return invocation.memberName == #rotate;
});
expect(rotateCommand, isNotNull);
expect(rotateCommand.positionalArguments[0], equals(math.PI / 4.0));
});
test('A Banner with a location of bottomLeft paints in the bottom left', () {
BannerPainter bannerPainter = new BannerPainter(
message:"foo",
location: BannerLocation.bottomLeft
);
TestCanvas canvas = new TestCanvas();
bannerPainter.paint(canvas, new Size(1000.0, 1000.0));
Invocation translateCommand = canvas.invocations.firstWhere((Invocation invocation) {
return invocation.memberName == #translate;
});
expect(translateCommand, isNotNull);
expect(translateCommand.positionalArguments[0], lessThan(100.0));
expect(translateCommand.positionalArguments[1], greaterThan(900.0));
Invocation rotateCommand = canvas.invocations.firstWhere((Invocation invocation) {
return invocation.memberName == #rotate;
});
expect(rotateCommand, isNotNull);
expect(rotateCommand.positionalArguments[0], equals(math.PI / 4.0));
});
test('A Banner with a location of bottomRight paints in the bottom right', () {
BannerPainter bannerPainter = new BannerPainter(
message:"foo",
location: BannerLocation.bottomRight
);
TestCanvas canvas = new TestCanvas();
bannerPainter.paint(canvas, new Size(1000.0, 1000.0));
Invocation translateCommand = canvas.invocations.firstWhere((Invocation invocation) {
return invocation.memberName == #translate;
});
expect(translateCommand, isNotNull);
expect(translateCommand.positionalArguments[0], greaterThan(900.0));
expect(translateCommand.positionalArguments[1], greaterThan(900.0));
Invocation rotateCommand = canvas.invocations.firstWhere((Invocation invocation) {
return invocation.memberName == #rotate;
});
expect(rotateCommand, isNotNull);
expect(rotateCommand.positionalArguments[0], equals(-math.PI / 4.0));
});
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment