diff --git a/CHANGELOG.md b/CHANGELOG.md index 9fd7ec3..040feb2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # 0.16.0 - feat: add `NesIcons.camera` - chore: Removing usage from deprecated members from Flutter 3.18. + - fix!: `NesDialog`s are now aware of the a `NesFixedViewport` scaling value. # 0.15.0 - feat: add `NesIcons.audioMuted` diff --git a/example/lib/advanced/fixed_viewport/page/fixed_viewport_page.dart b/example/lib/advanced/fixed_viewport/page/fixed_viewport_page.dart index b87b554..d833609 100644 --- a/example/lib/advanced/fixed_viewport/page/fixed_viewport_page.dart +++ b/example/lib/advanced/fixed_viewport/page/fixed_viewport_page.dart @@ -78,7 +78,7 @@ class _FixedViewportPageState extends State { const SizedBox(height: 16), Expanded( child: NesFixedViewport( - child: Theme( + builder: (context) => Theme( data: themeData, child: DefaultTextStyle( style: themeData.textTheme.bodyMedium ?? const TextStyle(), @@ -91,8 +91,25 @@ class _FixedViewportPageState extends State { const SizedBox(height: 4), NesButton( type: NesButtonType.primary, - onPressed: () {}, - child: const Text('Button'), + onPressed: () { + NesDialog.show( + context: context, + builder: (_) => Column( + children: [ + const Text('Hello, World!'), + const SizedBox(height: 16), + NesButton( + type: NesButtonType.primary, + onPressed: () { + Navigator.of(context).pop(); + }, + child: const Text('Thanks, bye!'), + ), + ], + ), + ); + }, + child: const Text('Say Hello'), ), ], ), diff --git a/example/lib/main_fixed_viewport_demo.dart b/example/lib/main_fixed_viewport_demo.dart new file mode 100644 index 0000000..75ede10 --- /dev/null +++ b/example/lib/main_fixed_viewport_demo.dart @@ -0,0 +1,119 @@ +import 'package:flutter/material.dart'; +import 'package:nes_ui/nes_ui.dart'; + +void main() { + WidgetsFlutterBinding.ensureInitialized(); + final baseThemeData = flutterNesTheme( + nesTheme: const NesTheme( + pixelSize: 1, + ), + ); + + final themeData = baseThemeData.copyWith( + textTheme: baseThemeData.textTheme.copyWith( + bodyLarge: baseThemeData.textTheme.bodyLarge?.copyWith( + fontSize: 8, + ), + bodyMedium: baseThemeData.textTheme.bodyMedium?.copyWith( + fontSize: 6, + ), + bodySmall: baseThemeData.textTheme.bodySmall?.copyWith( + fontSize: 4, + ), + labelLarge: baseThemeData.textTheme.labelLarge?.copyWith( + fontSize: 8, + ), + labelMedium: baseThemeData.textTheme.labelMedium?.copyWith( + fontSize: 6, + ), + labelSmall: baseThemeData.textTheme.labelSmall?.copyWith( + fontSize: 4, + ), + displayLarge: baseThemeData.textTheme.displayLarge?.copyWith( + fontSize: 8, + ), + displayMedium: baseThemeData.textTheme.displayMedium?.copyWith( + fontSize: 6, + ), + displaySmall: baseThemeData.textTheme.displaySmall?.copyWith( + fontSize: 4, + ), + ), + extensions: [ + ...baseThemeData.extensions.values, + NesContainerTheme( + backgroundColor: const Color(0xFFFFFFFF), + borderColor: const Color(0xFF000000), + padding: const EdgeInsets.all(4), + labelTextStyle: baseThemeData.textTheme.labelSmall ?? const TextStyle(), + ), + ], + ); + runApp( + MaterialApp( + theme: themeData, + home: const FixedViewportPage(), + ), + ); +} + +class FixedViewportPage extends StatefulWidget { + const FixedViewportPage({super.key}); + + @override + State createState() => _FixedViewportPageState(); +} + +class _FixedViewportPageState extends State { + @override + Widget build(BuildContext context) { + return Scaffold( + body: Padding( + padding: const EdgeInsets.all(16), + child: NesFixedViewport( + builder: (context) => DefaultTextStyle( + style: Theme.of(context).textTheme.bodyMedium ?? const TextStyle(), + child: NesContainer( + width: 256, + height: 240, + child: Column( + children: [ + const Text( + 'This content has a fixed viewport of 256x240 (the ' + 'original resolution of the NES). ', + textAlign: TextAlign.center, + ), + const SizedBox(height: 4), + const NesContainer(child: Text('Hello World')), + const SizedBox(height: 4), + NesButton( + type: NesButtonType.primary, + onPressed: () { + NesDialog.show( + context: context, + builder: (_) => Column( + children: [ + const Text('Hello, World!'), + const SizedBox(height: 16), + NesButton( + type: NesButtonType.primary, + onPressed: () { + Navigator.of(context).pop(); + }, + child: const Text('Thanks, bye!'), + ), + ], + ), + ); + }, + child: const Text('Say Hello'), + ), + ], + ), + ), + ), + ), + ), + ); + } +} diff --git a/lib/src/widgets/dialogs/nes_dialog.dart b/lib/src/widgets/dialogs/nes_dialog.dart index 1ae1d2a..e4697a9 100644 --- a/lib/src/widgets/dialogs/nes_dialog.dart +++ b/lib/src/widgets/dialogs/nes_dialog.dart @@ -22,6 +22,9 @@ class NesDialog extends StatelessWidget { required WidgetBuilder builder, }) { final nesTheme = context.nesThemeExtension(); + + final scaling = NesFixedViewportScaling.maybeOf(context); + return showGeneralDialog( context: context, barrierColor: Colors.transparent, @@ -41,9 +44,20 @@ class NesDialog extends StatelessWidget { ), ); }, - pageBuilder: (_, __, ___) => NesDialog( - child: builder(context), - ), + pageBuilder: (_, __, ___) { + final dialog = NesDialog( + child: builder(context), + ); + + if (scaling != null) { + return Transform.scale( + scale: scaling, + child: dialog, + ); + } + + return dialog; + }, ); } diff --git a/lib/src/widgets/nes_fixed_viewport.dart b/lib/src/widgets/nes_fixed_viewport.dart index 810432a..91cdd92 100644 --- a/lib/src/widgets/nes_fixed_viewport.dart +++ b/lib/src/widgets/nes_fixed_viewport.dart @@ -1,5 +1,32 @@ import 'package:flutter/material.dart'; +/// {@template nes_fixed_viewport_scaling} +/// An InheritedWidget that provides the current scale imposed by a +/// [NesFixedViewport] down the widget tree. +/// {@endtemplate} +class NesFixedViewportScaling extends InheritedWidget { + /// {@macro nes_fixed_viewport_scaling} + const NesFixedViewportScaling({ + required this.scale, + required super.child, + super.key, + }); + + /// The viewport scale factor. + final double scale; + + /// Returns the current scale imposed by a [NesFixedViewport], if any. + static double? maybeOf(BuildContext context) { + return context + .dependOnInheritedWidgetOfExactType() + ?.scale; + } + + @override + bool updateShouldNotify(NesFixedViewportScaling oldWidget) => + scale != oldWidget.scale; +} + /// {@template nes_fixed_viewport} /// A widget that imposes a fixed resolution on its child. /// @@ -8,19 +35,20 @@ import 'package:flutter/material.dart'; class NesFixedViewport extends StatelessWidget { /// {@macro nes_fixed_viewport} const NesFixedViewport({ - required this.child, + required this.builder, this.resolution = const Size(256, 240), this.alignment = Alignment.center, super.key, }); - /// The resolution to impose on [child]. + /// The resolution to impose on [builder] returned child. final Size resolution; /// The widget below this widget in the tree. - final Widget child; + final WidgetBuilder builder; - /// The Alignment of [child] within the viewport. + /// The Alignment of the widgets returned by the [builder] within the + /// viewport. final Alignment alignment; @override @@ -49,7 +77,12 @@ class NesFixedViewport extends StatelessWidget { child: SizedBox( width: resolution.width, height: resolution.height, - child: child, + child: NesFixedViewportScaling( + scale: scale, + child: Builder( + builder: builder, + ), + ), ), ), ), diff --git a/test/src/widgets/nes_fixed_viewport_test.dart b/test/src/widgets/nes_fixed_viewport_test.dart index e644f3a..8539b90 100644 --- a/test/src/widgets/nes_fixed_viewport_test.dart +++ b/test/src/widgets/nes_fixed_viewport_test.dart @@ -8,9 +8,9 @@ void main() { await tester.pumpWidget( MaterialApp( theme: flutterNesTheme(), - home: const Scaffold( + home: Scaffold( body: NesFixedViewport( - child: Text('Hello'), + builder: (_) => const Text('Hello'), ), ), ),