mirror of https://github.com/flutter/pinball.git
commit
bf199eb758
After Width: | Height: | Size: 2.3 KiB |
@ -0,0 +1,95 @@
|
||||
import 'package:flame/components.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:pinball_components/pinball_components.dart';
|
||||
import 'package:pinball_ui/pinball_ui.dart';
|
||||
|
||||
final _boldLabelTextPaint = TextPaint(
|
||||
style: const TextStyle(
|
||||
fontSize: 1.8,
|
||||
color: PinballColors.white,
|
||||
fontFamily: PinballFonts.pixeloidSans,
|
||||
fontWeight: FontWeight.w700,
|
||||
),
|
||||
);
|
||||
|
||||
final _labelTextPaint = TextPaint(
|
||||
style: const TextStyle(
|
||||
fontSize: 1.8,
|
||||
color: PinballColors.white,
|
||||
fontFamily: PinballFonts.pixeloidSans,
|
||||
fontWeight: FontWeight.w400,
|
||||
),
|
||||
);
|
||||
|
||||
/// {@template error_component}
|
||||
/// A plain visual component used to show errors for the user.
|
||||
/// {@endtemplate}
|
||||
class ErrorComponent extends SpriteComponent with HasGameRef {
|
||||
/// {@macro error_component}
|
||||
ErrorComponent({required this.label, Vector2? position})
|
||||
: _textPaint = _labelTextPaint,
|
||||
super(
|
||||
position: position,
|
||||
);
|
||||
|
||||
/// {@macro error_component}
|
||||
ErrorComponent.bold({required this.label, Vector2? position})
|
||||
: _textPaint = _boldLabelTextPaint,
|
||||
super(
|
||||
position: position,
|
||||
);
|
||||
|
||||
/// Text shown on the error message.
|
||||
final String label;
|
||||
final TextPaint _textPaint;
|
||||
|
||||
List<String> _splitInLines() {
|
||||
final maxWidth = size.x - 8;
|
||||
final lines = <String>[];
|
||||
var currentLine = '';
|
||||
final words = label.split(' ');
|
||||
while (words.isNotEmpty) {
|
||||
final word = words.removeAt(0);
|
||||
|
||||
if (_textPaint.measureTextWidth('$currentLine $word') <= maxWidth) {
|
||||
currentLine = '$currentLine $word'.trim();
|
||||
} else {
|
||||
lines.add(currentLine);
|
||||
currentLine = word;
|
||||
}
|
||||
}
|
||||
|
||||
lines.add(currentLine);
|
||||
return lines;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> onLoad() async {
|
||||
anchor = Anchor.center;
|
||||
final sprite = await gameRef.loadSprite(
|
||||
Assets.images.errorBackground.keyName,
|
||||
);
|
||||
|
||||
size = sprite.originalSize / 20;
|
||||
this.sprite = sprite;
|
||||
|
||||
final lines = _splitInLines();
|
||||
|
||||
// Calculates vertical offset based on the number of lines of text to be
|
||||
// displayed. This offset is used to keep the middle of the multi-line text
|
||||
// at the center of the [ErrorComponent].
|
||||
final yOffset = ((size.y / 2.2) / lines.length) * 1.5;
|
||||
|
||||
for (var i = 0; i < lines.length; i++) {
|
||||
await add(
|
||||
TextComponent(
|
||||
position: Vector2(size.x / 2, yOffset + 2.2 * i),
|
||||
size: Vector2(size.x - 4, 2.2),
|
||||
text: lines[i],
|
||||
textRenderer: _textPaint,
|
||||
anchor: Anchor.center,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
import 'package:flame/components.dart';
|
||||
import 'package:pinball_components/pinball_components.dart';
|
||||
import 'package:sandbox/common/common.dart';
|
||||
|
||||
class ErrorComponentGame extends AssetsGame {
|
||||
ErrorComponentGame({required this.text});
|
||||
|
||||
static const description = 'Shows how ErrorComponents are rendered.';
|
||||
|
||||
final String text;
|
||||
|
||||
@override
|
||||
Future<void> onLoad() async {
|
||||
camera.followVector2(Vector2.zero());
|
||||
|
||||
await add(ErrorComponent(label: text));
|
||||
await add(
|
||||
ErrorComponent.bold(
|
||||
label: text,
|
||||
position: Vector2(0, 10),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
import 'package:dashbook/dashbook.dart';
|
||||
import 'package:sandbox/common/common.dart';
|
||||
import 'package:sandbox/stories/error_component/error_component_game.dart';
|
||||
|
||||
void addErrorComponentStories(Dashbook dashbook) {
|
||||
dashbook.storiesOf('ErrorComponent').addGame(
|
||||
title: 'Basic',
|
||||
description: ErrorComponentGame.description,
|
||||
gameBuilder: (context) => ErrorComponentGame(
|
||||
text: context.textProperty(
|
||||
'label',
|
||||
'Oh no, something went wrong!',
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
// ignore_for_file: cascade_invocations
|
||||
|
||||
import 'package:flame/components.dart';
|
||||
import 'package:flame_test/flame_test.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:pinball_components/pinball_components.dart';
|
||||
|
||||
import '../../helpers/helpers.dart';
|
||||
|
||||
extension _IterableX on Iterable<Component> {
|
||||
int countTexts(String value) {
|
||||
return where(
|
||||
(component) => component is TextComponent && component.text == value,
|
||||
).length;
|
||||
}
|
||||
}
|
||||
|
||||
void main() {
|
||||
group('ErrorComponent', () {
|
||||
TestWidgetsFlutterBinding.ensureInitialized();
|
||||
final assets = [
|
||||
Assets.images.errorBackground.keyName,
|
||||
];
|
||||
final flameTester = FlameTester(() => TestGame(assets));
|
||||
|
||||
flameTester.test('renders correctly', (game) async {
|
||||
await game.ensureAdd(ErrorComponent(label: 'Error Message'));
|
||||
final count = game.descendants().countTexts('Error Message');
|
||||
|
||||
expect(count, equals(1));
|
||||
});
|
||||
|
||||
group('when the text is longer than one line', () {
|
||||
flameTester.test('renders correctly', (game) async {
|
||||
await game.ensureAdd(
|
||||
ErrorComponent(
|
||||
label: 'Error With A Longer Message',
|
||||
),
|
||||
);
|
||||
final count1 = game.descendants().countTexts('Error With A');
|
||||
final count2 = game.descendants().countTexts('Longer Message');
|
||||
|
||||
expect(count1, equals(1));
|
||||
expect(count2, equals(1));
|
||||
});
|
||||
});
|
||||
|
||||
group('when using the bold font', () {
|
||||
flameTester.test('renders correctly', (game) async {
|
||||
await game.ensureAdd(ErrorComponent.bold(label: 'Error Message'));
|
||||
final count = game.descendants().countTexts('Error Message');
|
||||
|
||||
expect(count, equals(1));
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
Loading…
Reference in new issue