Skip to content

Commit

Permalink
Finished widet spec implementations
Browse files Browse the repository at this point in the history
  • Loading branch information
leoafarias committed Apr 4, 2024
1 parent 96e598e commit 48d68a8
Show file tree
Hide file tree
Showing 7 changed files with 216 additions and 89 deletions.
39 changes: 13 additions & 26 deletions lib/src/specs/container/box_widget.dart
Expand Up @@ -73,22 +73,22 @@ class MixedBox extends StatelessWidget {
const MixedBox({required this.spec, super.key, this.child});

final Widget? child;
final BoxSpec spec;
final BoxSpec? spec;

@override
Widget build(BuildContext context) {
return Container(
alignment: spec.alignment,
padding: spec.padding,
decoration: spec.decoration,
foregroundDecoration: spec.foregroundDecoration,
width: spec.width,
height: spec.height,
constraints: spec.constraints,
margin: spec.margin,
transform: spec.transform,
transformAlignment: spec.transformAlignment,
clipBehavior: spec.clipBehavior ?? Clip.none,
alignment: spec?.alignment,
padding: spec?.padding,
decoration: spec?.decoration,
foregroundDecoration: spec?.foregroundDecoration,
width: spec?.width,
height: spec?.height,
constraints: spec?.constraints,
margin: spec?.margin,
transform: spec?.transform,
transformAlignment: spec?.transformAlignment,
clipBehavior: spec?.clipBehavior ?? Clip.none,
child: child,
);
}
Expand Down Expand Up @@ -131,19 +131,6 @@ class _AnimatedBoxSpecWidgetState
Widget build(BuildContext context) {
final spec = _boxSpec?.evaluate(animation);

return Container(
alignment: spec?.alignment,
padding: spec?.padding,
decoration: spec?.decoration,
foregroundDecoration: spec?.foregroundDecoration,
width: spec?.width,
height: spec?.height,
constraints: spec?.constraints,
margin: spec?.margin,
transform: spec?.transform,
transformAlignment: spec?.transformAlignment,
clipBehavior: spec?.clipBehavior ?? Clip.none,
child: widget.child,
);
return MixedBox(spec: spec, child: widget.child);
}
}
10 changes: 10 additions & 0 deletions lib/src/specs/icon/icon_spec.dart
@@ -1,5 +1,7 @@
import 'dart:ui';

import 'package:flutter/material.dart';

import '../../core/attribute.dart';
import '../../factory/mix_provider_data.dart';
import 'icon_attribute.dart';
Expand Down Expand Up @@ -97,3 +99,11 @@ class IconSpec extends Spec<IconSpec> {
fill,
];
}

class IconSpecTween extends Tween<IconSpec> {
IconSpecTween({IconSpec? begin, IconSpec? end})
: super(begin: begin, end: end);

@override
IconSpec lerp(double t) => begin!.lerp(end, t);
}
97 changes: 78 additions & 19 deletions lib/src/specs/icon/icon_widget.dart
@@ -1,8 +1,6 @@
import 'package:flutter/material.dart';

import '../../core/styled_widget.dart';
import '../../factory/mix_provider.dart';
import '../../factory/mix_provider_data.dart';
import 'icon_spec.dart';

class StyledIcon extends StyledWidget {
Expand All @@ -23,45 +21,54 @@ class StyledIcon extends StyledWidget {
@override
Widget build(BuildContext context) {
return withMix(context, (mix) {
return MixedIcon(
icon,
semanticLabel: semanticLabel,
textDirection: textDirection,
);
final spec = IconSpec.of(mix);

return mix.isAnimated
? AnimatedMixedIcon(
icon: icon,
spec: spec,
semanticLabel: semanticLabel,
textDirection: textDirection,
curve: mix.animation!.curve,
duration: mix.animation!.duration,
)
: MixedIcon(
icon,
spec: spec,
semanticLabel: semanticLabel,
textDirection: textDirection,
);
});
}
}

class MixedIcon extends StatelessWidget {
const MixedIcon(
this.icon, {
this.mix,
this.spec,
this.semanticLabel,
super.key,
this.textDirection,
this.decoratorOrder = const [],
});

final IconData? icon;
final MixData? mix;
final IconSpec? spec;
final String? semanticLabel;
final TextDirection? textDirection;
final List<Type> decoratorOrder;

@override
Widget build(BuildContext context) {
final mix = this.mix ?? MixProvider.of(context);
final spec = IconSpec.of(mix);

return Icon(
icon,
size: spec.size,
fill: spec.fill,
weight: spec.weight,
grade: spec.grade,
opticalSize: spec.opticalSize,
color: spec.color,
shadows: spec.shadows,
size: spec?.size,
fill: spec?.fill,
weight: spec?.weight,
grade: spec?.grade,
opticalSize: spec?.opticalSize,
color: spec?.color,
shadows: spec?.shadows,
semanticLabel: semanticLabel,
textDirection: textDirection,
);
Expand Down Expand Up @@ -101,3 +108,55 @@ class AnimatedStyledIcon extends StyledWidget {
});
}
}

class AnimatedMixedIcon extends ImplicitlyAnimatedWidget {
const AnimatedMixedIcon({
required this.icon,
required this.spec,
super.key,
this.semanticLabel,
this.textDirection,
this.decoratorOrder = const [],
Curve curve = Curves.linear,
required Duration duration,
VoidCallback? onEnd,
}) : super(curve: curve, duration: duration, onEnd: onEnd);

final IconData? icon;
final IconSpec spec;
final String? semanticLabel;
final TextDirection? textDirection;
final List<Type> decoratorOrder;

@override
// ignore: library_private_types_in_public_api
_AnimatedMixedIconState createState() => _AnimatedMixedIconState();
}

class _AnimatedMixedIconState
extends AnimatedWidgetBaseState<AnimatedMixedIcon> {
IconSpecTween? _spec;

@override
// ignore: avoid-dynamic
void forEachTween(TweenVisitor<dynamic> visitor) {
_spec = visitor(
_spec,
widget.spec,
// ignore: avoid-dynamic
(dynamic value) => IconSpecTween(begin: value as IconSpec?),
) as IconSpecTween?;
}

@override
Widget build(BuildContext context) {
final spec = _spec?.evaluate(animation);

return MixedIcon(
widget.icon,
spec: spec,
semanticLabel: widget.semanticLabel,
textDirection: widget.textDirection,
);
}
}
8 changes: 8 additions & 0 deletions lib/src/specs/image/image_spec.dart
Expand Up @@ -101,3 +101,11 @@ class ImageSpec extends Spec<ImageSpec> {
colorBlendMode,
];
}

class ImageSpecTween extends Tween<ImageSpec> {
ImageSpecTween({ImageSpec? begin, ImageSpec? end})
: super(begin: begin, end: end);

@override
ImageSpec lerp(double t) => begin!.lerp(end, t);
}
118 changes: 95 additions & 23 deletions lib/src/specs/image/image_widget.dart
@@ -1,7 +1,7 @@
import 'package:flutter/material.dart';

import '../../core/styled_widget.dart';
import '../../factory/mix_provider_data.dart';
import '../../helpers/constants.dart';
import 'image_spec.dart';

class StyledImage extends StyledWidget {
Expand All @@ -28,15 +28,29 @@ class StyledImage extends StyledWidget {
@override
Widget build(BuildContext context) {
return withMix(context, (mix) {
return MixedImage(
mix: mix,
image: image,
frameBuilder: frameBuilder,
loadingBuilder: loadingBuilder,
errorBuilder: errorBuilder,
semanticLabel: semanticLabel,
excludeFromSemantics: excludeFromSemantics,
);
final spec = ImageSpec.of(mix);

return mix.isAnimated
? AnimatedMixedImage(
spec: spec,
image: image,
frameBuilder: frameBuilder,
loadingBuilder: loadingBuilder,
errorBuilder: errorBuilder,
semanticLabel: semanticLabel,
excludeFromSemantics: excludeFromSemantics,
duration: mix.animation!.duration,
curve: mix.animation!.curve,
)
: MixedImage(
spec: spec,
image: image,
frameBuilder: frameBuilder,
loadingBuilder: loadingBuilder,
errorBuilder: errorBuilder,
semanticLabel: semanticLabel,
excludeFromSemantics: excludeFromSemantics,
);
});
}
}
Expand All @@ -45,7 +59,7 @@ class MixedImage extends StatelessWidget {
const MixedImage({
super.key,
this.decoratorOrder = const [],
required this.mix,
this.spec,
required this.image,
this.frameBuilder,
this.loadingBuilder,
Expand All @@ -54,7 +68,7 @@ class MixedImage extends StatelessWidget {
this.excludeFromSemantics = false,
});

final MixData mix;
final ImageSpec? spec;
final ImageProvider<Object> image;
final ImageFrameBuilder? frameBuilder;
final ImageLoadingBuilder? loadingBuilder;
Expand All @@ -65,24 +79,82 @@ class MixedImage extends StatelessWidget {

@override
Widget build(BuildContext context) {
final spec = ImageSpec.of(mix);

return Image(
image: image,
frameBuilder: frameBuilder,
loadingBuilder: loadingBuilder,
errorBuilder: errorBuilder,
semanticLabel: semanticLabel,
excludeFromSemantics: excludeFromSemantics,
width: spec.width,
height: spec.height,
color: spec.color,
colorBlendMode: spec.colorBlendMode ?? BlendMode.clear,
fit: spec.fit,
alignment: spec.alignment ?? Alignment.center,
repeat: spec.repeat ?? ImageRepeat.noRepeat,
centerSlice: spec.centerSlice,
filterQuality: spec.filterQuality ?? FilterQuality.low,
width: spec?.width,
height: spec?.height,
color: spec?.color,
colorBlendMode: spec?.colorBlendMode ?? BlendMode.clear,
fit: spec?.fit,
alignment: spec?.alignment ?? Alignment.center,
repeat: spec?.repeat ?? ImageRepeat.noRepeat,
centerSlice: spec?.centerSlice,
filterQuality: spec?.filterQuality ?? FilterQuality.low,
);
}
}

class AnimatedMixedImage extends ImplicitlyAnimatedWidget {
const AnimatedMixedImage({
this.spec,
required this.image,
this.frameBuilder,
this.loadingBuilder,
this.errorBuilder,
this.semanticLabel,
this.excludeFromSemantics = false,
super.key,
super.duration = kDefaultAnimationDuration,
super.curve = Curves.linear,
super.onEnd,
});

final ImageSpec? spec;
final ImageProvider<Object> image;
final ImageFrameBuilder? frameBuilder;
final ImageLoadingBuilder? loadingBuilder;
final ImageErrorWidgetBuilder? errorBuilder;
final String? semanticLabel;
final bool excludeFromSemantics;

@override
AnimatedWidgetBaseState<AnimatedMixedImage> createState() =>
_AnimatedMixedImageState();
}

class _AnimatedMixedImageState
extends AnimatedWidgetBaseState<AnimatedMixedImage> {
ImageSpecTween? _spec;

// forEachTween
@override
// ignore: avoid-dynamic
void forEachTween(TweenVisitor<dynamic> visitor) {
_spec = visitor(
_spec,
widget.spec,
// ignore: avoid-dynamic
(dynamic value) => ImageSpecTween(begin: value as ImageSpec?),
) as ImageSpecTween?;
}

@override
Widget build(BuildContext context) {
final spec = _spec?.evaluate(animation);

return MixedImage(
spec: spec,
image: widget.image,
frameBuilder: widget.frameBuilder,
loadingBuilder: widget.loadingBuilder,
errorBuilder: widget.errorBuilder,
semanticLabel: widget.semanticLabel,
excludeFromSemantics: widget.excludeFromSemantics,
);
}
}

0 comments on commit 48d68a8

Please sign in to comment.