master #81
@ -19,7 +19,4 @@ import 'package:wyatt_ui_components/src/features/features.dart';
|
|||||||
|
|
||||||
extension ThemeComponentBuildContext on BuildContext {
|
extension ThemeComponentBuildContext on BuildContext {
|
||||||
ComponentThemeData get components => ComponentTheme.of(this);
|
ComponentThemeData get components => ComponentTheme.of(this);
|
||||||
TextTheme get textTheme => Theme.of(this).textTheme;
|
|
||||||
ColorScheme get colorScheme => Theme.of(this).colorScheme;
|
|
||||||
ButtonThemeData get buttonTheme => Theme.of(this).buttonTheme;
|
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
// ignore_for_file: public_member_api_docs, sort_constructors_first
|
|
||||||
// Copyright (C) 2023 WYATT GROUP
|
// Copyright (C) 2023 WYATT GROUP
|
||||||
// Please see the AUTHORS file for details.
|
// Please see the AUTHORS file for details.
|
||||||
//
|
//
|
||||||
@ -52,4 +51,7 @@ class MultiColor {
|
|||||||
}
|
}
|
||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() => 'MultiColor(_colors: $_colors, _color: $_color)';
|
||||||
}
|
}
|
||||||
|
@ -62,4 +62,10 @@ abstract class ButtonStyle<T> {
|
|||||||
///
|
///
|
||||||
/// Default to `null`
|
/// Default to `null`
|
||||||
final BoxShadow? shadow;
|
final BoxShadow? shadow;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() =>
|
||||||
|
'ButtonStyle(radius: $radius, padding: $padding, foregroundColors: '
|
||||||
|
'$foregroundColors, backgroundColors: $backgroundColors, borderColors: '
|
||||||
|
'$borderColors, stroke: $stroke, shadow: $shadow)';
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,6 @@ import 'dart:ui';
|
|||||||
|
|
||||||
import 'package:copy_with_extension/copy_with_extension.dart';
|
import 'package:copy_with_extension/copy_with_extension.dart';
|
||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
import 'package:wyatt_ui_components/src/core/extensions/build_context_extensions.dart';
|
|
||||||
import 'package:wyatt_ui_components/src/core/utils/multi_color.dart';
|
import 'package:wyatt_ui_components/src/core/utils/multi_color.dart';
|
||||||
import 'package:wyatt_ui_components/src/domain/entities/buttons/button_style.dart';
|
import 'package:wyatt_ui_components/src/domain/entities/buttons/button_style.dart';
|
||||||
|
|
||||||
@ -38,19 +37,6 @@ class FileSelectionButtonStyle extends ButtonStyle<FileSelectionButtonStyle> {
|
|||||||
super.shadow,
|
super.shadow,
|
||||||
});
|
});
|
||||||
|
|
||||||
/// Used in negociation to build a style from Flutter default values.
|
|
||||||
factory FileSelectionButtonStyle.fromFlutter(BuildContext context) =>
|
|
||||||
FileSelectionButtonStyle(
|
|
||||||
title: context.textTheme.labelLarge,
|
|
||||||
subTitle: context.textTheme.labelSmall,
|
|
||||||
radius: (context.buttonTheme.shape is RoundedRectangleBorder)
|
|
||||||
? (context.buttonTheme.shape as RoundedRectangleBorder).borderRadius
|
|
||||||
: null,
|
|
||||||
padding: context.buttonTheme.padding,
|
|
||||||
foregroundColors: MultiColor.single(context.colorScheme.onPrimary),
|
|
||||||
backgroundColors: MultiColor.single(context.colorScheme.primary),
|
|
||||||
);
|
|
||||||
|
|
||||||
/// Used for interpolation.
|
/// Used for interpolation.
|
||||||
static FileSelectionButtonStyle? lerp(
|
static FileSelectionButtonStyle? lerp(
|
||||||
FileSelectionButtonStyle? a,
|
FileSelectionButtonStyle? a,
|
||||||
|
@ -18,7 +18,6 @@ import 'dart:ui';
|
|||||||
|
|
||||||
import 'package:copy_with_extension/copy_with_extension.dart';
|
import 'package:copy_with_extension/copy_with_extension.dart';
|
||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
import 'package:wyatt_ui_components/src/core/extensions/build_context_extensions.dart';
|
|
||||||
import 'package:wyatt_ui_components/src/core/utils/multi_color.dart';
|
import 'package:wyatt_ui_components/src/core/utils/multi_color.dart';
|
||||||
import 'package:wyatt_ui_components/src/domain/entities/buttons/button_style.dart';
|
import 'package:wyatt_ui_components/src/domain/entities/buttons/button_style.dart';
|
||||||
|
|
||||||
@ -37,17 +36,6 @@ class FlatButtonStyle extends ButtonStyle<FlatButtonStyle> {
|
|||||||
super.shadow,
|
super.shadow,
|
||||||
});
|
});
|
||||||
|
|
||||||
/// Used in negociation to build a style from Flutter default values.
|
|
||||||
factory FlatButtonStyle.fromFlutter(BuildContext context) => FlatButtonStyle(
|
|
||||||
label: context.textTheme.labelLarge,
|
|
||||||
radius: (context.buttonTheme.shape is RoundedRectangleBorder)
|
|
||||||
? (context.buttonTheme.shape as RoundedRectangleBorder).borderRadius
|
|
||||||
: null,
|
|
||||||
padding: context.buttonTheme.padding,
|
|
||||||
foregroundColors: MultiColor.single(context.colorScheme.onPrimary),
|
|
||||||
backgroundColors: MultiColor.single(context.colorScheme.primary),
|
|
||||||
);
|
|
||||||
|
|
||||||
/// Used for interpolation.
|
/// Used for interpolation.
|
||||||
static FlatButtonStyle? lerp(
|
static FlatButtonStyle? lerp(
|
||||||
FlatButtonStyle? a,
|
FlatButtonStyle? a,
|
||||||
@ -86,4 +74,8 @@ class FlatButtonStyle extends ButtonStyle<FlatButtonStyle> {
|
|||||||
///
|
///
|
||||||
/// Default to `TextTheme.labelLarge`
|
/// Default to `TextTheme.labelLarge`
|
||||||
final TextStyle? label;
|
final TextStyle? label;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() =>
|
||||||
|
'FlatButtonStyle(label: $label), inherited: ${super.toString()}';
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,6 @@ import 'dart:ui';
|
|||||||
|
|
||||||
import 'package:copy_with_extension/copy_with_extension.dart';
|
import 'package:copy_with_extension/copy_with_extension.dart';
|
||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
import 'package:wyatt_ui_components/src/core/extensions/build_context_extensions.dart';
|
|
||||||
import 'package:wyatt_ui_components/src/core/utils/multi_color.dart';
|
import 'package:wyatt_ui_components/src/core/utils/multi_color.dart';
|
||||||
import 'package:wyatt_ui_components/src/domain/entities/buttons/button_style.dart';
|
import 'package:wyatt_ui_components/src/domain/entities/buttons/button_style.dart';
|
||||||
|
|
||||||
@ -37,18 +36,6 @@ class SimpleIconButtonStyle extends ButtonStyle<SimpleIconButtonStyle> {
|
|||||||
super.shadow,
|
super.shadow,
|
||||||
});
|
});
|
||||||
|
|
||||||
/// Used in negociation to build a style from Flutter default values.
|
|
||||||
factory SimpleIconButtonStyle.fromFlutter(BuildContext context) =>
|
|
||||||
SimpleIconButtonStyle(
|
|
||||||
dimension: context.buttonTheme.height,
|
|
||||||
radius: (context.buttonTheme.shape is RoundedRectangleBorder)
|
|
||||||
? (context.buttonTheme.shape as RoundedRectangleBorder).borderRadius
|
|
||||||
: null,
|
|
||||||
padding: context.buttonTheme.padding,
|
|
||||||
foregroundColors: MultiColor.single(context.colorScheme.onPrimary),
|
|
||||||
backgroundColors: MultiColor.single(context.colorScheme.primary),
|
|
||||||
);
|
|
||||||
|
|
||||||
/// Used for interpolation.
|
/// Used for interpolation.
|
||||||
static SimpleIconButtonStyle? lerp(
|
static SimpleIconButtonStyle? lerp(
|
||||||
SimpleIconButtonStyle? a,
|
SimpleIconButtonStyle? a,
|
||||||
|
@ -18,7 +18,6 @@ import 'dart:ui';
|
|||||||
|
|
||||||
import 'package:copy_with_extension/copy_with_extension.dart';
|
import 'package:copy_with_extension/copy_with_extension.dart';
|
||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
import 'package:wyatt_ui_components/src/core/extensions/build_context_extensions.dart';
|
|
||||||
import 'package:wyatt_ui_components/src/core/utils/multi_color.dart';
|
import 'package:wyatt_ui_components/src/core/utils/multi_color.dart';
|
||||||
import 'package:wyatt_ui_components/src/domain/entities/buttons/button_style.dart';
|
import 'package:wyatt_ui_components/src/domain/entities/buttons/button_style.dart';
|
||||||
|
|
||||||
@ -38,19 +37,6 @@ class SymbolButtonStyle extends ButtonStyle<SymbolButtonStyle> {
|
|||||||
super.shadow,
|
super.shadow,
|
||||||
});
|
});
|
||||||
|
|
||||||
/// Used in negociation to build a style from Flutter default values.
|
|
||||||
factory SymbolButtonStyle.fromFlutter(BuildContext context) =>
|
|
||||||
SymbolButtonStyle(
|
|
||||||
label: context.textTheme.labelLarge,
|
|
||||||
dimension: context.buttonTheme.height,
|
|
||||||
radius: (context.buttonTheme.shape is RoundedRectangleBorder)
|
|
||||||
? (context.buttonTheme.shape as RoundedRectangleBorder).borderRadius
|
|
||||||
: null,
|
|
||||||
padding: context.buttonTheme.padding,
|
|
||||||
foregroundColors: MultiColor.single(context.colorScheme.onPrimary),
|
|
||||||
backgroundColors: MultiColor.single(context.colorScheme.primary),
|
|
||||||
);
|
|
||||||
|
|
||||||
/// Used for interpolation.
|
/// Used for interpolation.
|
||||||
static SymbolButtonStyle? lerp(
|
static SymbolButtonStyle? lerp(
|
||||||
SymbolButtonStyle? a,
|
SymbolButtonStyle? a,
|
||||||
|
@ -25,7 +25,7 @@
|
|||||||
|
|
||||||
UIKit and Design System used in Wyatt Studio.
|
UIKit and Design System used in Wyatt Studio.
|
||||||
|
|
||||||
## Theme negociation
|
## Theme negotiation
|
||||||
|
|
||||||
When building a component, most of its attributes can be 'null'.
|
When building a component, most of its attributes can be 'null'.
|
||||||
The `build()` method then starts to negotiate the theme in the tree to obtain the most consistent style possible.
|
The `build()` method then starts to negotiate the theme in the tree to obtain the most consistent style possible.
|
||||||
@ -36,7 +36,11 @@ When you build a component `Button({double? radius})`.
|
|||||||
You have several possibilities:
|
You have several possibilities:
|
||||||
1) Pass the "radius" into the constructor, `Button(radius: 12)`.
|
1) Pass the "radius" into the constructor, `Button(radius: 12)`.
|
||||||
2) Set up a theme extension `ButtonThemeExtension(radius: 15)`.
|
2) Set up a theme extension `ButtonThemeExtension(radius: 15)`.
|
||||||
3) Let `wyatt_ui_kit` "negotiate" and try to find a suitable style in the flutter theme. If this negotiation phase fails, then the style is simply not applied.
|
3) Let `wyatt_ui_kit` "negotiate" and try to find a suitable style in the flutter theme.
|
||||||
|
|
||||||
|
If this negotiation phase fails, then:
|
||||||
|
- If the value is mandatory: a hardcoded value in "wyatt_ui_kit" is chosen.
|
||||||
|
- If not, the style is simply not applied.
|
||||||
|
|
||||||
If, for example, you don't use option 1, then the radius will be 15. If you use neither option 1 nor option 2 then the radius will be 4 as this is the [official Material Design value](https://m2.material.io/design/shape/about-shape.html#shape-customization-tool).
|
If, for example, you don't use option 1, then the radius will be 15. If you use neither option 1 nor option 2 then the radius will be 4 as this is the [official Material Design value](https://m2.material.io/design/shape/about-shape.html#shape-customization-tool).
|
||||||
|
|
||||||
|
@ -19,6 +19,7 @@ import 'package:wyatt_component_copy_with_extension/component_copy_with_extensio
|
|||||||
import 'package:wyatt_ui_components/wyatt_wyatt_ui_components.dart';
|
import 'package:wyatt_ui_components/wyatt_wyatt_ui_components.dart';
|
||||||
import 'package:wyatt_ui_kit/src/components/buttons/cubit/invalid_button_cubit.dart';
|
import 'package:wyatt_ui_kit/src/components/buttons/cubit/invalid_button_cubit.dart';
|
||||||
import 'package:wyatt_ui_kit/src/components/buttons/file_selection_button/file_selection_button_screen.dart';
|
import 'package:wyatt_ui_kit/src/components/buttons/file_selection_button/file_selection_button_screen.dart';
|
||||||
|
import 'package:wyatt_ui_kit/src/components/buttons/file_selection_button/file_selection_button_theme_resolver.dart';
|
||||||
import 'package:wyatt_ui_kit/src/core/mixin/export_bloc_mixin.dart';
|
import 'package:wyatt_ui_kit/src/core/mixin/export_bloc_mixin.dart';
|
||||||
|
|
||||||
part 'file_selection_button.g.dart';
|
part 'file_selection_button.g.dart';
|
||||||
@ -39,6 +40,7 @@ class FileSelectionButton extends FileSelectionButtonComponent
|
|||||||
super.invalidStyle,
|
super.invalidStyle,
|
||||||
super.onPressed,
|
super.onPressed,
|
||||||
super.mainAxisSize,
|
super.mainAxisSize,
|
||||||
|
this.themeResolver,
|
||||||
super.key,
|
super.key,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -75,6 +77,8 @@ class FileSelectionButton extends FileSelectionButtonComponent
|
|||||||
FileSelectionButtonStyle? get invalidStyle =>
|
FileSelectionButtonStyle? get invalidStyle =>
|
||||||
super.invalidStyle as FileSelectionButtonStyle?;
|
super.invalidStyle as FileSelectionButtonStyle?;
|
||||||
|
|
||||||
|
final FileSelectionButtonThemeResolver? themeResolver;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) => exportBloc(
|
Widget build(BuildContext context) => exportBloc(
|
||||||
child: FileSelectionButtonScreen(
|
child: FileSelectionButtonScreen(
|
||||||
@ -90,6 +94,7 @@ class FileSelectionButton extends FileSelectionButtonComponent
|
|||||||
invalidStyle: invalidStyle,
|
invalidStyle: invalidStyle,
|
||||||
onPressed: onPressed,
|
onPressed: onPressed,
|
||||||
mainAxisSize: mainAxisSize,
|
mainAxisSize: mainAxisSize,
|
||||||
|
themeResolver: themeResolver,
|
||||||
key: key,
|
key: key,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -75,6 +75,7 @@ class $FileSelectionButtonCWProxyImpl
|
|||||||
invalidStyle: invalidStyle ?? _value.invalidStyle,
|
invalidStyle: invalidStyle ?? _value.invalidStyle,
|
||||||
onPressed: onPressed ?? _value.onPressed,
|
onPressed: onPressed ?? _value.onPressed,
|
||||||
mainAxisSize: mainAxisSize ?? _value.mainAxisSize,
|
mainAxisSize: mainAxisSize ?? _value.mainAxisSize,
|
||||||
|
themeResolver: themeResolver ?? _value.themeResolver,
|
||||||
key: key ?? _value.key,
|
key: key ?? _value.key,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -22,10 +22,9 @@ import 'package:wyatt_bloc_helper/wyatt_bloc_helper.dart';
|
|||||||
import 'package:wyatt_ui_components/wyatt_wyatt_ui_components.dart';
|
import 'package:wyatt_ui_components/wyatt_wyatt_ui_components.dart';
|
||||||
import 'package:wyatt_ui_kit/src/components/buttons/cubit/button_cubit.dart';
|
import 'package:wyatt_ui_kit/src/components/buttons/cubit/button_cubit.dart';
|
||||||
import 'package:wyatt_ui_kit/src/components/buttons/cubit/invalid_button_cubit.dart';
|
import 'package:wyatt_ui_kit/src/components/buttons/cubit/invalid_button_cubit.dart';
|
||||||
|
import 'package:wyatt_ui_kit/src/components/buttons/file_selection_button/file_selection_button_theme_resolver.dart';
|
||||||
import 'package:wyatt_ui_kit/src/components/gradients/gradient_text.dart';
|
import 'package:wyatt_ui_kit/src/components/gradients/gradient_text.dart';
|
||||||
import 'package:wyatt_ui_kit/src/core/extensions/theme_extensions.dart';
|
|
||||||
import 'package:wyatt_ui_kit/src/core/helpers/linear_gradient_helper.dart';
|
import 'package:wyatt_ui_kit/src/core/helpers/linear_gradient_helper.dart';
|
||||||
import 'package:wyatt_ui_kit/src/domain/button_theme_extension/file_selection_button_theme_extension.dart';
|
|
||||||
|
|
||||||
class FileSelectionButtonScreen
|
class FileSelectionButtonScreen
|
||||||
extends CubitScreen<InvalidButtonCubit, ButtonState> {
|
extends CubitScreen<InvalidButtonCubit, ButtonState> {
|
||||||
@ -42,6 +41,7 @@ class FileSelectionButtonScreen
|
|||||||
this.invalidStyle,
|
this.invalidStyle,
|
||||||
this.onPressed,
|
this.onPressed,
|
||||||
this.mainAxisSize,
|
this.mainAxisSize,
|
||||||
|
this.themeResolver,
|
||||||
super.key,
|
super.key,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -59,138 +59,80 @@ class FileSelectionButtonScreen
|
|||||||
final FileSelectionButtonStyle? invalidStyle;
|
final FileSelectionButtonStyle? invalidStyle;
|
||||||
|
|
||||||
final void Function(ControlState state)? onPressed;
|
final void Function(ControlState state)? onPressed;
|
||||||
|
final FileSelectionButtonThemeResolver? themeResolver;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
InvalidButtonCubit create(BuildContext context) => InvalidButtonCubit();
|
InvalidButtonCubit create(BuildContext context) => InvalidButtonCubit();
|
||||||
|
|
||||||
/// Negotiate the theme to get a complete style.
|
/// Negotiate the theme to get a complete style.
|
||||||
FileSelectionButtonStyle negotiate(BuildContext context, ButtonState state) {
|
FileSelectionButtonStyle resolve(BuildContext context, ButtonState state) {
|
||||||
// Define default style from Flutter values.
|
final FileSelectionButtonThemeResolver resolver = themeResolver ??
|
||||||
FileSelectionButtonStyle style =
|
FileSelectionButtonThemeResolver(
|
||||||
FileSelectionButtonStyle.fromFlutter(context);
|
computeExtensionValueFn: (
|
||||||
|
context,
|
||||||
// Try to retrieve custom theme extension
|
defaultValue,
|
||||||
final fileSelectionButtonThemeExtension =
|
themeExtension, {
|
||||||
context.themeExtension<FileSelectionButtonThemeExtension>();
|
extra,
|
||||||
|
}) {
|
||||||
switch (state.state) {
|
FileSelectionButtonStyle? style = defaultValue;
|
||||||
|
switch (extra?.state) {
|
||||||
case ControlState.disabled:
|
case ControlState.disabled:
|
||||||
style = disabledStyle ??
|
style = themeExtension.disabledStyle;
|
||||||
fileSelectionButtonThemeExtension?.disabledStyle ??
|
|
||||||
style.copyWith(
|
|
||||||
foregroundColors:
|
|
||||||
MultiColor.single(context.colorScheme.onSurface),
|
|
||||||
backgroundColors: MultiColor.single(context.colorScheme.surface),
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
case ControlState.hovered:
|
|
||||||
style = hoveredStyle ??
|
|
||||||
fileSelectionButtonThemeExtension?.hoveredStyle ??
|
|
||||||
style;
|
|
||||||
break;
|
|
||||||
case ControlState.tapped:
|
|
||||||
style = tappedStyle ??
|
|
||||||
fileSelectionButtonThemeExtension?.tappedStyle ??
|
|
||||||
style;
|
|
||||||
break;
|
break;
|
||||||
case ControlState.focused:
|
case ControlState.focused:
|
||||||
style = focusedStyle ??
|
style = themeExtension.focusedStyle;
|
||||||
fileSelectionButtonThemeExtension?.focusedStyle ??
|
break;
|
||||||
style;
|
case ControlState.hovered:
|
||||||
|
style = themeExtension.hoveredStyle;
|
||||||
|
break;
|
||||||
|
case ControlState.tapped:
|
||||||
|
style = themeExtension.tappedStyle;
|
||||||
break;
|
break;
|
||||||
case ControlState.normal:
|
case ControlState.normal:
|
||||||
style = normalStyle ??
|
case null:
|
||||||
fileSelectionButtonThemeExtension?.normalStyle ??
|
style = themeExtension.normalStyle;
|
||||||
style;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (extra?.isSelected ?? false) {
|
||||||
// Apply extra theme
|
style = themeExtension.selectedStyle;
|
||||||
if (state.isSelected) {
|
|
||||||
// TODO(hpcl): enhance copyWith to copy only non-null attributes of an object
|
|
||||||
style = style.copyWith(
|
|
||||||
title: (selectedStyle ??
|
|
||||||
fileSelectionButtonThemeExtension?.selectedStyle ??
|
|
||||||
style)
|
|
||||||
.title,
|
|
||||||
subTitle: (selectedStyle ??
|
|
||||||
fileSelectionButtonThemeExtension?.selectedStyle ??
|
|
||||||
style)
|
|
||||||
.subTitle,
|
|
||||||
radius: (selectedStyle ??
|
|
||||||
fileSelectionButtonThemeExtension?.selectedStyle ??
|
|
||||||
style)
|
|
||||||
.radius,
|
|
||||||
padding: (selectedStyle ??
|
|
||||||
fileSelectionButtonThemeExtension?.selectedStyle ??
|
|
||||||
style)
|
|
||||||
.padding,
|
|
||||||
foregroundColors: (selectedStyle ??
|
|
||||||
fileSelectionButtonThemeExtension?.selectedStyle ??
|
|
||||||
style)
|
|
||||||
.foregroundColors,
|
|
||||||
backgroundColors: (selectedStyle ??
|
|
||||||
fileSelectionButtonThemeExtension?.selectedStyle ??
|
|
||||||
style)
|
|
||||||
.backgroundColors,
|
|
||||||
borderColors: (selectedStyle ??
|
|
||||||
fileSelectionButtonThemeExtension?.selectedStyle ??
|
|
||||||
style)
|
|
||||||
.borderColors,
|
|
||||||
stroke: (selectedStyle ??
|
|
||||||
fileSelectionButtonThemeExtension?.selectedStyle ??
|
|
||||||
style)
|
|
||||||
.stroke,
|
|
||||||
shadow: (selectedStyle ??
|
|
||||||
fileSelectionButtonThemeExtension?.selectedStyle ??
|
|
||||||
style)
|
|
||||||
.shadow,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
if (extra?.isInvalid ?? false) {
|
||||||
if (state.isInvalid) {
|
style = themeExtension.invalidStyle;
|
||||||
// TODO(hpcl): enhance copyWith to copy only non-null attributes of an object
|
|
||||||
style = style.copyWith(
|
|
||||||
title: (invalidStyle ??
|
|
||||||
fileSelectionButtonThemeExtension?.invalidStyle ??
|
|
||||||
style)
|
|
||||||
.title,
|
|
||||||
subTitle: (invalidStyle ??
|
|
||||||
fileSelectionButtonThemeExtension?.invalidStyle ??
|
|
||||||
style)
|
|
||||||
.subTitle,
|
|
||||||
radius: (invalidStyle ??
|
|
||||||
fileSelectionButtonThemeExtension?.invalidStyle ??
|
|
||||||
style)
|
|
||||||
.radius,
|
|
||||||
padding: (invalidStyle ??
|
|
||||||
fileSelectionButtonThemeExtension?.invalidStyle ??
|
|
||||||
style)
|
|
||||||
.padding,
|
|
||||||
foregroundColors: (invalidStyle ??
|
|
||||||
fileSelectionButtonThemeExtension?.invalidStyle ??
|
|
||||||
style)
|
|
||||||
.foregroundColors,
|
|
||||||
backgroundColors: (invalidStyle ??
|
|
||||||
fileSelectionButtonThemeExtension?.invalidStyle ??
|
|
||||||
style)
|
|
||||||
.backgroundColors,
|
|
||||||
borderColors: (invalidStyle ??
|
|
||||||
fileSelectionButtonThemeExtension?.invalidStyle ??
|
|
||||||
style)
|
|
||||||
.borderColors,
|
|
||||||
stroke: (invalidStyle ??
|
|
||||||
fileSelectionButtonThemeExtension?.invalidStyle ??
|
|
||||||
style)
|
|
||||||
.stroke,
|
|
||||||
shadow: (invalidStyle ??
|
|
||||||
fileSelectionButtonThemeExtension?.invalidStyle ??
|
|
||||||
style)
|
|
||||||
.shadow,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return style;
|
return style;
|
||||||
|
},
|
||||||
|
customStyleFn: (context, {extra}) {
|
||||||
|
FileSelectionButtonStyle? style;
|
||||||
|
switch (extra?.state) {
|
||||||
|
case ControlState.disabled:
|
||||||
|
style = disabledStyle;
|
||||||
|
break;
|
||||||
|
case ControlState.focused:
|
||||||
|
style = focusedStyle;
|
||||||
|
break;
|
||||||
|
case ControlState.hovered:
|
||||||
|
style = hoveredStyle;
|
||||||
|
break;
|
||||||
|
case ControlState.tapped:
|
||||||
|
style = tappedStyle;
|
||||||
|
break;
|
||||||
|
case ControlState.normal:
|
||||||
|
case null:
|
||||||
|
style = normalStyle;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (extra?.isSelected ?? false) {
|
||||||
|
style = selectedStyle;
|
||||||
|
}
|
||||||
|
if (extra?.isInvalid ?? false) {
|
||||||
|
style = invalidStyle;
|
||||||
|
}
|
||||||
|
|
||||||
|
return style;
|
||||||
|
},
|
||||||
|
);
|
||||||
|
return resolver.negotiate(context, extra: state);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _border(
|
Widget _border(
|
||||||
@ -217,7 +159,7 @@ class FileSelectionButtonScreen
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget onBuild(BuildContext context, ButtonState state) {
|
Widget onBuild(BuildContext context, ButtonState state) {
|
||||||
final style = negotiate(context, state);
|
final style = resolve(context, state);
|
||||||
|
|
||||||
return Focus(
|
return Focus(
|
||||||
onFocusChange: (hasFocus) =>
|
onFocusChange: (hasFocus) =>
|
||||||
|
@ -0,0 +1,59 @@
|
|||||||
|
// Copyright (C) 2023 WYATT GROUP
|
||||||
|
// Please see the AUTHORS file for details.
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:wyatt_ui_components/wyatt_wyatt_ui_components.dart';
|
||||||
|
import 'package:wyatt_ui_kit/src/components/buttons/cubit/button_cubit.dart';
|
||||||
|
import 'package:wyatt_ui_kit/src/core/helpers/theme_resolver.dart';
|
||||||
|
import 'package:wyatt_ui_kit/wyatt_ui_kit.dart';
|
||||||
|
|
||||||
|
class FileSelectionButtonThemeResolver extends ThemeResolver<
|
||||||
|
FileSelectionButtonStyle, FileSelectionButtonThemeExtension, ButtonState> {
|
||||||
|
const FileSelectionButtonThemeResolver({
|
||||||
|
required this.computeExtensionValueFn,
|
||||||
|
required this.customStyleFn,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
FileSelectionButtonStyle computeDefaultValue(
|
||||||
|
BuildContext context, {
|
||||||
|
ButtonState? extra,
|
||||||
|
}) =>
|
||||||
|
FileSelectionButtonStyle(
|
||||||
|
title: context.textTheme.labelLarge,
|
||||||
|
subTitle: context.textTheme.labelSmall,
|
||||||
|
radius: (context.buttonTheme.shape is RoundedRectangleBorder)
|
||||||
|
? (context.buttonTheme.shape as RoundedRectangleBorder).borderRadius
|
||||||
|
: null,
|
||||||
|
padding: context.buttonTheme.padding,
|
||||||
|
foregroundColors: MultiColor.single(context.colorScheme.onPrimary),
|
||||||
|
backgroundColors: MultiColor.single(context.colorScheme.primary),
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
final FileSelectionButtonStyle? Function(
|
||||||
|
BuildContext context,
|
||||||
|
FileSelectionButtonStyle defaultValue,
|
||||||
|
FileSelectionButtonThemeExtension themeExtension, {
|
||||||
|
ButtonState? extra,
|
||||||
|
}) computeExtensionValueFn;
|
||||||
|
|
||||||
|
@override
|
||||||
|
final FileSelectionButtonStyle? Function(
|
||||||
|
BuildContext context, {
|
||||||
|
ButtonState? extra,
|
||||||
|
}) customStyleFn;
|
||||||
|
}
|
@ -19,6 +19,7 @@ import 'package:wyatt_component_copy_with_extension/component_copy_with_extensio
|
|||||||
import 'package:wyatt_ui_components/wyatt_wyatt_ui_components.dart';
|
import 'package:wyatt_ui_components/wyatt_wyatt_ui_components.dart';
|
||||||
import 'package:wyatt_ui_kit/src/components/buttons/cubit/button_cubit.dart';
|
import 'package:wyatt_ui_kit/src/components/buttons/cubit/button_cubit.dart';
|
||||||
import 'package:wyatt_ui_kit/src/components/buttons/flat_button/flat_button_screen.dart';
|
import 'package:wyatt_ui_kit/src/components/buttons/flat_button/flat_button_screen.dart';
|
||||||
|
import 'package:wyatt_ui_kit/src/components/buttons/flat_button/flat_button_theme_resolver.dart';
|
||||||
import 'package:wyatt_ui_kit/src/core/mixin/export_bloc_mixin.dart';
|
import 'package:wyatt_ui_kit/src/core/mixin/export_bloc_mixin.dart';
|
||||||
|
|
||||||
part 'flat_button.g.dart';
|
part 'flat_button.g.dart';
|
||||||
@ -37,6 +38,7 @@ class FlatButton extends FlatButtonComponent
|
|||||||
super.tappedStyle,
|
super.tappedStyle,
|
||||||
super.onPressed,
|
super.onPressed,
|
||||||
super.mainAxisSize,
|
super.mainAxisSize,
|
||||||
|
this.themeResolver,
|
||||||
super.key,
|
super.key,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -60,6 +62,8 @@ class FlatButton extends FlatButtonComponent
|
|||||||
@override
|
@override
|
||||||
FlatButtonStyle? get tappedStyle => super.tappedStyle as FlatButtonStyle?;
|
FlatButtonStyle? get tappedStyle => super.tappedStyle as FlatButtonStyle?;
|
||||||
|
|
||||||
|
final FlatButtonThemeResolver? themeResolver;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) => exportBloc(
|
Widget build(BuildContext context) => exportBloc(
|
||||||
child: FlatButtonScreen(
|
child: FlatButtonScreen(
|
||||||
@ -73,6 +77,7 @@ class FlatButton extends FlatButtonComponent
|
|||||||
tappedStyle: tappedStyle,
|
tappedStyle: tappedStyle,
|
||||||
onPressed: onPressed,
|
onPressed: onPressed,
|
||||||
mainAxisSize: mainAxisSize,
|
mainAxisSize: mainAxisSize,
|
||||||
|
themeResolver: themeResolver,
|
||||||
key: key,
|
key: key,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -63,6 +63,7 @@ class $FlatButtonCWProxyImpl implements $FlatButtonComponentCWProxy {
|
|||||||
tappedStyle: tappedStyle ?? _value.tappedStyle,
|
tappedStyle: tappedStyle ?? _value.tappedStyle,
|
||||||
onPressed: onPressed ?? _value.onPressed,
|
onPressed: onPressed ?? _value.onPressed,
|
||||||
mainAxisSize: mainAxisSize ?? _value.mainAxisSize,
|
mainAxisSize: mainAxisSize ?? _value.mainAxisSize,
|
||||||
|
themeResolver: themeResolver ?? _value.themeResolver,
|
||||||
key: key ?? _value.key,
|
key: key ?? _value.key,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -20,11 +20,10 @@ import 'package:gap/gap.dart';
|
|||||||
import 'package:wyatt_bloc_helper/wyatt_bloc_helper.dart';
|
import 'package:wyatt_bloc_helper/wyatt_bloc_helper.dart';
|
||||||
import 'package:wyatt_ui_components/wyatt_wyatt_ui_components.dart';
|
import 'package:wyatt_ui_components/wyatt_wyatt_ui_components.dart';
|
||||||
import 'package:wyatt_ui_kit/src/components/buttons/cubit/button_cubit.dart';
|
import 'package:wyatt_ui_kit/src/components/buttons/cubit/button_cubit.dart';
|
||||||
|
import 'package:wyatt_ui_kit/src/components/buttons/flat_button/flat_button_theme_resolver.dart';
|
||||||
import 'package:wyatt_ui_kit/src/components/gradients/gradient_box_border.dart';
|
import 'package:wyatt_ui_kit/src/components/gradients/gradient_box_border.dart';
|
||||||
import 'package:wyatt_ui_kit/src/components/gradients/gradient_text.dart';
|
import 'package:wyatt_ui_kit/src/components/gradients/gradient_text.dart';
|
||||||
import 'package:wyatt_ui_kit/src/core/extensions/theme_extensions.dart';
|
|
||||||
import 'package:wyatt_ui_kit/src/core/helpers/linear_gradient_helper.dart';
|
import 'package:wyatt_ui_kit/src/core/helpers/linear_gradient_helper.dart';
|
||||||
import 'package:wyatt_ui_kit/src/domain/button_theme_extension/flat_button_theme_extension.dart';
|
|
||||||
|
|
||||||
class FlatButtonScreen extends CubitScreen<ButtonCubit, ButtonState> {
|
class FlatButtonScreen extends CubitScreen<ButtonCubit, ButtonState> {
|
||||||
const FlatButtonScreen({
|
const FlatButtonScreen({
|
||||||
@ -38,6 +37,7 @@ class FlatButtonScreen extends CubitScreen<ButtonCubit, ButtonState> {
|
|||||||
this.tappedStyle,
|
this.tappedStyle,
|
||||||
this.onPressed,
|
this.onPressed,
|
||||||
this.mainAxisSize,
|
this.mainAxisSize,
|
||||||
|
this.themeResolver,
|
||||||
super.key,
|
super.key,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -53,49 +53,57 @@ class FlatButtonScreen extends CubitScreen<ButtonCubit, ButtonState> {
|
|||||||
final FlatButtonStyle? tappedStyle;
|
final FlatButtonStyle? tappedStyle;
|
||||||
|
|
||||||
final void Function(ControlState state)? onPressed;
|
final void Function(ControlState state)? onPressed;
|
||||||
|
final FlatButtonThemeResolver? themeResolver;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
ButtonCubit create(BuildContext context) => ButtonCubit();
|
ButtonCubit create(BuildContext context) => ButtonCubit();
|
||||||
|
|
||||||
/// Negotiate the theme to get a complete style.
|
/// Negotiate the theme to get a complete style.
|
||||||
FlatButtonStyle negotiate(BuildContext context, ControlState state) {
|
FlatButtonStyle resolve(BuildContext context, ControlState state) {
|
||||||
// Define default style from Flutter values.
|
final FlatButtonThemeResolver resolver = themeResolver ??
|
||||||
FlatButtonStyle style = FlatButtonStyle.fromFlutter(context);
|
FlatButtonThemeResolver(
|
||||||
|
computeExtensionValueFn: (
|
||||||
// Try to retrieve custom theme extension
|
context,
|
||||||
final flatButtonThemeExtension =
|
defaultValue,
|
||||||
context.themeExtension<FlatButtonThemeExtension>();
|
themeExtension, {
|
||||||
|
extra,
|
||||||
switch (state) {
|
}) {
|
||||||
|
switch (extra) {
|
||||||
case ControlState.disabled:
|
case ControlState.disabled:
|
||||||
style = disabledStyle ??
|
return themeExtension.disabledStyle;
|
||||||
flatButtonThemeExtension?.disabledStyle ??
|
|
||||||
style.copyWith(
|
|
||||||
foregroundColors:
|
|
||||||
MultiColor.single(context.colorScheme.onSurface),
|
|
||||||
backgroundColors: MultiColor.single(context.colorScheme.surface),
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
case ControlState.hovered:
|
|
||||||
style = hoveredStyle ?? flatButtonThemeExtension?.hoveredStyle ?? style;
|
|
||||||
break;
|
|
||||||
case ControlState.tapped:
|
|
||||||
style = tappedStyle ?? flatButtonThemeExtension?.tappedStyle ?? style;
|
|
||||||
break;
|
|
||||||
case ControlState.focused:
|
case ControlState.focused:
|
||||||
style = focusedStyle ?? flatButtonThemeExtension?.focusedStyle ?? style;
|
return themeExtension.focusedStyle;
|
||||||
break;
|
case ControlState.hovered:
|
||||||
|
return themeExtension.hoveredStyle;
|
||||||
|
case ControlState.tapped:
|
||||||
|
return themeExtension.tappedStyle;
|
||||||
case ControlState.normal:
|
case ControlState.normal:
|
||||||
style = normalStyle ?? flatButtonThemeExtension?.normalStyle ?? style;
|
case null:
|
||||||
break;
|
return themeExtension.normalStyle;
|
||||||
}
|
}
|
||||||
|
},
|
||||||
return style;
|
customStyleFn: (context, {extra}) {
|
||||||
|
switch (extra) {
|
||||||
|
case ControlState.disabled:
|
||||||
|
return disabledStyle;
|
||||||
|
case ControlState.focused:
|
||||||
|
return focusedStyle;
|
||||||
|
case ControlState.hovered:
|
||||||
|
return hoveredStyle;
|
||||||
|
case ControlState.tapped:
|
||||||
|
return tappedStyle;
|
||||||
|
case ControlState.normal:
|
||||||
|
case null:
|
||||||
|
return normalStyle;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
return resolver.negotiate(context, extra: state);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget onBuild(BuildContext context, ButtonState state) {
|
Widget onBuild(BuildContext context, ButtonState state) {
|
||||||
final style = negotiate(context, state.state);
|
final style = resolve(context, state.state);
|
||||||
|
|
||||||
return Focus(
|
return Focus(
|
||||||
onFocusChange: (hasFocus) =>
|
onFocusChange: (hasFocus) =>
|
||||||
@ -182,7 +190,6 @@ class FlatButtonScreen extends CubitScreen<ButtonCubit, ButtonState> {
|
|||||||
Gap(style.padding?.vertical ?? 10),
|
Gap(style.padding?.vertical ?? 10),
|
||||||
|
|
||||||
/// Choose color
|
/// Choose color
|
||||||
/// label.style.color ??
|
|
||||||
/// buttonStyle.label.style.color ??
|
/// buttonStyle.label.style.color ??
|
||||||
/// context.textTheme.labelLarge.color
|
/// context.textTheme.labelLarge.color
|
||||||
///
|
///
|
||||||
@ -191,7 +198,7 @@ class FlatButtonScreen extends CubitScreen<ButtonCubit, ButtonState> {
|
|||||||
/// buttonStyle.foregroundColor.colors ??
|
/// buttonStyle.foregroundColor.colors ??
|
||||||
/// null
|
/// null
|
||||||
///
|
///
|
||||||
/// More infos in `negociate()` method
|
/// More infos in ThemeResolver class
|
||||||
if (label != null) ...[
|
if (label != null) ...[
|
||||||
Text(
|
Text(
|
||||||
label!.text,
|
label!.text,
|
||||||
|
@ -0,0 +1,84 @@
|
|||||||
|
// Copyright (C) 2023 WYATT GROUP
|
||||||
|
// Please see the AUTHORS file for details.
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:wyatt_ui_components/wyatt_wyatt_ui_components.dart';
|
||||||
|
import 'package:wyatt_ui_kit/src/core/helpers/theme_resolver.dart';
|
||||||
|
import 'package:wyatt_ui_kit/wyatt_ui_kit.dart';
|
||||||
|
|
||||||
|
class FlatButtonThemeResolver extends ThemeResolver<FlatButtonStyle,
|
||||||
|
FlatButtonThemeExtension, ControlState> {
|
||||||
|
const FlatButtonThemeResolver({
|
||||||
|
required this.computeExtensionValueFn,
|
||||||
|
required this.customStyleFn,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
|
||||||
|
/// Values taken from <https://api.flutter.dev/flutter/material/ElevatedButton/defaultStyleOf.html>
|
||||||
|
FlatButtonStyle computeDefaultValue(
|
||||||
|
BuildContext context, {
|
||||||
|
ControlState? extra,
|
||||||
|
}) {
|
||||||
|
MultiColor backgroundColor = MultiColor.single(context.colorScheme.primary);
|
||||||
|
MultiColor foregroundColor =
|
||||||
|
MultiColor.single(context.colorScheme.onPrimary);
|
||||||
|
|
||||||
|
switch (extra) {
|
||||||
|
case ControlState.disabled:
|
||||||
|
backgroundColor =
|
||||||
|
MultiColor.single(context.colorScheme.onSurface.withOpacity(0.12));
|
||||||
|
foregroundColor =
|
||||||
|
MultiColor.single(context.colorScheme.onSurface.withOpacity(0.38));
|
||||||
|
break;
|
||||||
|
case ControlState.hovered:
|
||||||
|
backgroundColor =
|
||||||
|
MultiColor.single(context.colorScheme.primary.withOpacity(0.92));
|
||||||
|
break;
|
||||||
|
case ControlState.tapped:
|
||||||
|
backgroundColor =
|
||||||
|
MultiColor.single(context.colorScheme.primary.withOpacity(0.92));
|
||||||
|
break;
|
||||||
|
case null:
|
||||||
|
case ControlState.normal:
|
||||||
|
case ControlState.focused:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FlatButtonStyle(
|
||||||
|
label:
|
||||||
|
context.textTheme.labelLarge?.copyWith(color: foregroundColor.color),
|
||||||
|
radius: (context.buttonTheme.shape is RoundedRectangleBorder)
|
||||||
|
? (context.buttonTheme.shape as RoundedRectangleBorder).borderRadius
|
||||||
|
: null,
|
||||||
|
padding: context.buttonTheme.padding,
|
||||||
|
foregroundColors: foregroundColor,
|
||||||
|
backgroundColors: backgroundColor,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
final FlatButtonStyle? Function(
|
||||||
|
BuildContext context,
|
||||||
|
FlatButtonStyle defaultValue,
|
||||||
|
FlatButtonThemeExtension themeExtension, {
|
||||||
|
ControlState? extra,
|
||||||
|
}) computeExtensionValueFn;
|
||||||
|
|
||||||
|
@override
|
||||||
|
final FlatButtonStyle? Function(BuildContext context, {ControlState? extra})
|
||||||
|
customStyleFn;
|
||||||
|
}
|
@ -18,6 +18,7 @@ import 'package:flutter/material.dart' hide ButtonStyle;
|
|||||||
import 'package:wyatt_component_copy_with_extension/component_copy_with_extension.dart';
|
import 'package:wyatt_component_copy_with_extension/component_copy_with_extension.dart';
|
||||||
import 'package:wyatt_ui_components/wyatt_wyatt_ui_components.dart';
|
import 'package:wyatt_ui_components/wyatt_wyatt_ui_components.dart';
|
||||||
import 'package:wyatt_ui_kit/src/components/buttons/cubit/button_cubit.dart';
|
import 'package:wyatt_ui_kit/src/components/buttons/cubit/button_cubit.dart';
|
||||||
|
import 'package:wyatt_ui_kit/src/components/buttons/simple_icon_button/simple_icon_button_theme_resolver.dart';
|
||||||
import 'package:wyatt_ui_kit/src/components/buttons/simple_icon_button/simple_icon_screen.dart';
|
import 'package:wyatt_ui_kit/src/components/buttons/simple_icon_button/simple_icon_screen.dart';
|
||||||
import 'package:wyatt_ui_kit/src/core/mixin/export_bloc_mixin.dart';
|
import 'package:wyatt_ui_kit/src/core/mixin/export_bloc_mixin.dart';
|
||||||
|
|
||||||
@ -34,6 +35,7 @@ class SimpleIconButton extends SimpleIconButtonComponent
|
|||||||
super.focusedStyle,
|
super.focusedStyle,
|
||||||
super.tappedStyle,
|
super.tappedStyle,
|
||||||
super.onPressed,
|
super.onPressed,
|
||||||
|
this.themeResolver,
|
||||||
super.key,
|
super.key,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -62,6 +64,7 @@ class SimpleIconButton extends SimpleIconButtonComponent
|
|||||||
SimpleIconButtonStyle? get tappedStyle =>
|
SimpleIconButtonStyle? get tappedStyle =>
|
||||||
super.tappedStyle as SimpleIconButtonStyle?;
|
super.tappedStyle as SimpleIconButtonStyle?;
|
||||||
|
|
||||||
|
final SimpleIconButtonThemeResolver? themeResolver;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) => exportBloc(
|
Widget build(BuildContext context) => exportBloc(
|
||||||
@ -73,6 +76,7 @@ class SimpleIconButton extends SimpleIconButtonComponent
|
|||||||
focusedStyle: focusedStyle,
|
focusedStyle: focusedStyle,
|
||||||
tappedStyle: tappedStyle,
|
tappedStyle: tappedStyle,
|
||||||
onPressed: onPressed,
|
onPressed: onPressed,
|
||||||
|
themeResolver: themeResolver,
|
||||||
key: key,
|
key: key,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -51,6 +51,7 @@ class $SimpleIconButtonCWProxyImpl
|
|||||||
focusedStyle: focusedStyle ?? _value.focusedStyle,
|
focusedStyle: focusedStyle ?? _value.focusedStyle,
|
||||||
tappedStyle: tappedStyle ?? _value.tappedStyle,
|
tappedStyle: tappedStyle ?? _value.tappedStyle,
|
||||||
onPressed: onPressed ?? _value.onPressed,
|
onPressed: onPressed ?? _value.onPressed,
|
||||||
|
themeResolver: themeResolver ?? _value.themeResolver,
|
||||||
key: key ?? _value.key,
|
key: key ?? _value.key,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,57 @@
|
|||||||
|
// Copyright (C) 2023 WYATT GROUP
|
||||||
|
// Please see the AUTHORS file for details.
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:wyatt_ui_components/wyatt_wyatt_ui_components.dart';
|
||||||
|
import 'package:wyatt_ui_kit/src/core/helpers/theme_resolver.dart';
|
||||||
|
import 'package:wyatt_ui_kit/wyatt_ui_kit.dart';
|
||||||
|
|
||||||
|
class SimpleIconButtonThemeResolver extends ThemeResolver<SimpleIconButtonStyle,
|
||||||
|
SimpleIconButtonThemeExtension, ControlState> {
|
||||||
|
const SimpleIconButtonThemeResolver({
|
||||||
|
required this.computeExtensionValueFn,
|
||||||
|
required this.customStyleFn,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
SimpleIconButtonStyle computeDefaultValue(
|
||||||
|
BuildContext context, {
|
||||||
|
ControlState? extra,
|
||||||
|
}) =>
|
||||||
|
SimpleIconButtonStyle(
|
||||||
|
dimension: context.buttonTheme.height,
|
||||||
|
radius: (context.buttonTheme.shape is RoundedRectangleBorder)
|
||||||
|
? (context.buttonTheme.shape as RoundedRectangleBorder).borderRadius
|
||||||
|
: null,
|
||||||
|
padding: context.buttonTheme.padding,
|
||||||
|
foregroundColors: MultiColor.single(context.colorScheme.onPrimary),
|
||||||
|
backgroundColors: MultiColor.single(context.colorScheme.primary),
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
final SimpleIconButtonStyle? Function(
|
||||||
|
BuildContext context,
|
||||||
|
SimpleIconButtonStyle defaultValue,
|
||||||
|
SimpleIconButtonThemeExtension themeExtension, {
|
||||||
|
ControlState? extra,
|
||||||
|
}) computeExtensionValueFn;
|
||||||
|
|
||||||
|
@override
|
||||||
|
final SimpleIconButtonStyle? Function(
|
||||||
|
BuildContext context, {
|
||||||
|
ControlState? extra,
|
||||||
|
}) customStyleFn;
|
||||||
|
}
|
@ -19,11 +19,10 @@ import 'package:flutter/services.dart';
|
|||||||
import 'package:wyatt_bloc_helper/wyatt_bloc_helper.dart';
|
import 'package:wyatt_bloc_helper/wyatt_bloc_helper.dart';
|
||||||
import 'package:wyatt_ui_components/wyatt_wyatt_ui_components.dart';
|
import 'package:wyatt_ui_components/wyatt_wyatt_ui_components.dart';
|
||||||
import 'package:wyatt_ui_kit/src/components/buttons/cubit/button_cubit.dart';
|
import 'package:wyatt_ui_kit/src/components/buttons/cubit/button_cubit.dart';
|
||||||
|
import 'package:wyatt_ui_kit/src/components/buttons/simple_icon_button/simple_icon_button_theme_resolver.dart';
|
||||||
import 'package:wyatt_ui_kit/src/components/gradients/gradient_box_border.dart';
|
import 'package:wyatt_ui_kit/src/components/gradients/gradient_box_border.dart';
|
||||||
import 'package:wyatt_ui_kit/src/components/gradients/gradient_icon.dart';
|
import 'package:wyatt_ui_kit/src/components/gradients/gradient_icon.dart';
|
||||||
import 'package:wyatt_ui_kit/src/core/extensions/theme_extensions.dart';
|
|
||||||
import 'package:wyatt_ui_kit/src/core/helpers/linear_gradient_helper.dart';
|
import 'package:wyatt_ui_kit/src/core/helpers/linear_gradient_helper.dart';
|
||||||
import 'package:wyatt_ui_kit/src/domain/button_theme_extension/simple_icon_button_theme_extension.dart';
|
|
||||||
|
|
||||||
class SimpleIconButtonScreen extends CubitScreen<ButtonCubit, ButtonState> {
|
class SimpleIconButtonScreen extends CubitScreen<ButtonCubit, ButtonState> {
|
||||||
const SimpleIconButtonScreen({
|
const SimpleIconButtonScreen({
|
||||||
@ -34,6 +33,7 @@ class SimpleIconButtonScreen extends CubitScreen<ButtonCubit, ButtonState> {
|
|||||||
this.focusedStyle,
|
this.focusedStyle,
|
||||||
this.tappedStyle,
|
this.tappedStyle,
|
||||||
this.onPressed,
|
this.onPressed,
|
||||||
|
this.themeResolver,
|
||||||
super.key,
|
super.key,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -46,55 +46,57 @@ class SimpleIconButtonScreen extends CubitScreen<ButtonCubit, ButtonState> {
|
|||||||
final SimpleIconButtonStyle? tappedStyle;
|
final SimpleIconButtonStyle? tappedStyle;
|
||||||
|
|
||||||
final void Function(ControlState state)? onPressed;
|
final void Function(ControlState state)? onPressed;
|
||||||
|
final SimpleIconButtonThemeResolver? themeResolver;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
ButtonCubit create(BuildContext context) => ButtonCubit();
|
ButtonCubit create(BuildContext context) => ButtonCubit();
|
||||||
|
|
||||||
/// Negotiate the theme to get a complete style.
|
/// Negotiate the theme to get a complete style.
|
||||||
SimpleIconButtonStyle negotiate(BuildContext context, ControlState state) {
|
SimpleIconButtonStyle resolve(BuildContext context, ControlState state) {
|
||||||
// Define default style from Flutter values.
|
final SimpleIconButtonThemeResolver resolver = themeResolver ??
|
||||||
SimpleIconButtonStyle style = SimpleIconButtonStyle.fromFlutter(context);
|
SimpleIconButtonThemeResolver(
|
||||||
|
computeExtensionValueFn: (
|
||||||
// Try to retrieve custom theme extension
|
context,
|
||||||
final simpleIconButtonThemeExtension =
|
defaultValue,
|
||||||
context.themeExtension<SimpleIconButtonThemeExtension>();
|
themeExtension, {
|
||||||
|
extra,
|
||||||
switch (state) {
|
}) {
|
||||||
|
switch (extra) {
|
||||||
case ControlState.disabled:
|
case ControlState.disabled:
|
||||||
style = disabledStyle ??
|
return themeExtension.disabledStyle;
|
||||||
simpleIconButtonThemeExtension?.disabledStyle ??
|
|
||||||
style.copyWith(
|
|
||||||
foregroundColors:
|
|
||||||
MultiColor.single(context.colorScheme.onSurface),
|
|
||||||
backgroundColors: MultiColor.single(context.colorScheme.surface),
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
case ControlState.hovered:
|
|
||||||
style = hoveredStyle ??
|
|
||||||
simpleIconButtonThemeExtension?.hoveredStyle ??
|
|
||||||
style;
|
|
||||||
break;
|
|
||||||
case ControlState.tapped:
|
|
||||||
style =
|
|
||||||
tappedStyle ?? simpleIconButtonThemeExtension?.tappedStyle ?? style;
|
|
||||||
break;
|
|
||||||
case ControlState.focused:
|
case ControlState.focused:
|
||||||
style = focusedStyle ??
|
return themeExtension.focusedStyle;
|
||||||
simpleIconButtonThemeExtension?.focusedStyle ??
|
case ControlState.hovered:
|
||||||
style;
|
return themeExtension.hoveredStyle;
|
||||||
break;
|
case ControlState.tapped:
|
||||||
|
return themeExtension.tappedStyle;
|
||||||
case ControlState.normal:
|
case ControlState.normal:
|
||||||
style =
|
case null:
|
||||||
normalStyle ?? simpleIconButtonThemeExtension?.normalStyle ?? style;
|
return themeExtension.normalStyle;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
},
|
||||||
return style;
|
customStyleFn: (context, {extra}) {
|
||||||
|
switch (extra) {
|
||||||
|
case ControlState.disabled:
|
||||||
|
return disabledStyle;
|
||||||
|
case ControlState.focused:
|
||||||
|
return focusedStyle;
|
||||||
|
case ControlState.hovered:
|
||||||
|
return hoveredStyle;
|
||||||
|
case ControlState.tapped:
|
||||||
|
return tappedStyle;
|
||||||
|
case ControlState.normal:
|
||||||
|
case null:
|
||||||
|
return normalStyle;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
return resolver.negotiate(context, extra: state);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget onBuild(BuildContext context, ButtonState state) {
|
Widget onBuild(BuildContext context, ButtonState state) {
|
||||||
final style = negotiate(context, state.state);
|
final style = resolve(context, state.state);
|
||||||
|
|
||||||
return Focus(
|
return Focus(
|
||||||
onFocusChange: (hasFocus) =>
|
onFocusChange: (hasFocus) =>
|
||||||
|
@ -19,6 +19,7 @@ import 'package:wyatt_component_copy_with_extension/component_copy_with_extensio
|
|||||||
import 'package:wyatt_ui_components/wyatt_wyatt_ui_components.dart';
|
import 'package:wyatt_ui_components/wyatt_wyatt_ui_components.dart';
|
||||||
import 'package:wyatt_ui_kit/src/components/buttons/cubit/selectable_button_cubit.dart';
|
import 'package:wyatt_ui_kit/src/components/buttons/cubit/selectable_button_cubit.dart';
|
||||||
import 'package:wyatt_ui_kit/src/components/buttons/symbol_button/symbol_button_screen.dart';
|
import 'package:wyatt_ui_kit/src/components/buttons/symbol_button/symbol_button_screen.dart';
|
||||||
|
import 'package:wyatt_ui_kit/src/components/buttons/symbol_button/symbol_button_theme_resolver.dart';
|
||||||
import 'package:wyatt_ui_kit/src/core/mixin/export_bloc_mixin.dart';
|
import 'package:wyatt_ui_kit/src/core/mixin/export_bloc_mixin.dart';
|
||||||
|
|
||||||
part 'symbol_button.g.dart';
|
part 'symbol_button.g.dart';
|
||||||
@ -36,6 +37,7 @@ class SymbolButton extends SymbolButtonComponent
|
|||||||
super.tappedStyle,
|
super.tappedStyle,
|
||||||
super.selectedStyle,
|
super.selectedStyle,
|
||||||
super.mainAxisSize,
|
super.mainAxisSize,
|
||||||
|
this.themeResolver,
|
||||||
super.onPressed,
|
super.onPressed,
|
||||||
super.key,
|
super.key,
|
||||||
});
|
});
|
||||||
@ -67,6 +69,8 @@ class SymbolButton extends SymbolButtonComponent
|
|||||||
SymbolButtonStyle? get selectedStyle =>
|
SymbolButtonStyle? get selectedStyle =>
|
||||||
super.selectedStyle as SymbolButtonStyle?;
|
super.selectedStyle as SymbolButtonStyle?;
|
||||||
|
|
||||||
|
final SymbolButtonThemeResolver? themeResolver;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) => exportBloc(
|
Widget build(BuildContext context) => exportBloc(
|
||||||
child: SymbolButtonScreen(
|
child: SymbolButtonScreen(
|
||||||
@ -80,6 +84,7 @@ class SymbolButton extends SymbolButtonComponent
|
|||||||
selectedStyle: selectedStyle,
|
selectedStyle: selectedStyle,
|
||||||
onPressed: onPressed,
|
onPressed: onPressed,
|
||||||
mainAxisSize: mainAxisSize,
|
mainAxisSize: mainAxisSize,
|
||||||
|
themeResolver: themeResolver,
|
||||||
key: key,
|
key: key,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -63,6 +63,7 @@ class $SymbolButtonCWProxyImpl implements $SymbolButtonComponentCWProxy {
|
|||||||
tappedStyle: tappedStyle ?? _value.tappedStyle,
|
tappedStyle: tappedStyle ?? _value.tappedStyle,
|
||||||
selectedStyle: selectedStyle ?? _value.selectedStyle,
|
selectedStyle: selectedStyle ?? _value.selectedStyle,
|
||||||
mainAxisSize: mainAxisSize ?? _value.mainAxisSize,
|
mainAxisSize: mainAxisSize ?? _value.mainAxisSize,
|
||||||
|
themeResolver: themeResolver ?? _value.themeResolver,
|
||||||
onPressed: onPressed ?? _value.onPressed,
|
onPressed: onPressed ?? _value.onPressed,
|
||||||
key: key ?? _value.key,
|
key: key ?? _value.key,
|
||||||
);
|
);
|
||||||
|
@ -21,11 +21,10 @@ import 'package:wyatt_bloc_helper/wyatt_bloc_helper.dart';
|
|||||||
import 'package:wyatt_ui_components/wyatt_wyatt_ui_components.dart';
|
import 'package:wyatt_ui_components/wyatt_wyatt_ui_components.dart';
|
||||||
import 'package:wyatt_ui_kit/src/components/buttons/cubit/button_cubit.dart';
|
import 'package:wyatt_ui_kit/src/components/buttons/cubit/button_cubit.dart';
|
||||||
import 'package:wyatt_ui_kit/src/components/buttons/cubit/selectable_button_cubit.dart';
|
import 'package:wyatt_ui_kit/src/components/buttons/cubit/selectable_button_cubit.dart';
|
||||||
|
import 'package:wyatt_ui_kit/src/components/buttons/symbol_button/symbol_button_theme_resolver.dart';
|
||||||
import 'package:wyatt_ui_kit/src/components/gradients/gradient_box_border.dart';
|
import 'package:wyatt_ui_kit/src/components/gradients/gradient_box_border.dart';
|
||||||
import 'package:wyatt_ui_kit/src/components/gradients/gradient_text.dart';
|
import 'package:wyatt_ui_kit/src/components/gradients/gradient_text.dart';
|
||||||
import 'package:wyatt_ui_kit/src/core/extensions/theme_extensions.dart';
|
|
||||||
import 'package:wyatt_ui_kit/src/core/helpers/linear_gradient_helper.dart';
|
import 'package:wyatt_ui_kit/src/core/helpers/linear_gradient_helper.dart';
|
||||||
import 'package:wyatt_ui_kit/src/domain/button_theme_extension/symbol_button_theme_extension.dart';
|
|
||||||
|
|
||||||
class SymbolButtonScreen
|
class SymbolButtonScreen
|
||||||
extends CubitScreen<SelectableButtonCubit, ButtonState> {
|
extends CubitScreen<SelectableButtonCubit, ButtonState> {
|
||||||
@ -40,6 +39,7 @@ class SymbolButtonScreen
|
|||||||
this.selectedStyle,
|
this.selectedStyle,
|
||||||
this.onPressed,
|
this.onPressed,
|
||||||
this.mainAxisSize,
|
this.mainAxisSize,
|
||||||
|
this.themeResolver,
|
||||||
super.key,
|
super.key,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -55,94 +55,79 @@ class SymbolButtonScreen
|
|||||||
final SymbolButtonStyle? selectedStyle;
|
final SymbolButtonStyle? selectedStyle;
|
||||||
|
|
||||||
final void Function(ControlState state)? onPressed;
|
final void Function(ControlState state)? onPressed;
|
||||||
|
final SymbolButtonThemeResolver? themeResolver;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
SelectableButtonCubit create(BuildContext context) => SelectableButtonCubit();
|
SelectableButtonCubit create(BuildContext context) => SelectableButtonCubit();
|
||||||
|
|
||||||
/// Negotiate the theme to get a complete style.
|
/// Negotiate the theme to get a complete style.
|
||||||
SymbolButtonStyle negotiate(BuildContext context, ButtonState state) {
|
SymbolButtonStyle resolve(BuildContext context, ButtonState state) {
|
||||||
// Define default style from Flutter values.
|
final SymbolButtonThemeResolver resolver = themeResolver ??
|
||||||
SymbolButtonStyle style = SymbolButtonStyle.fromFlutter(context);
|
SymbolButtonThemeResolver(
|
||||||
|
computeExtensionValueFn: (
|
||||||
// Try to retrieve custom theme extension
|
context,
|
||||||
final symbolButtonThemeExtension =
|
defaultValue,
|
||||||
context.themeExtension<SymbolButtonThemeExtension>();
|
themeExtension, {
|
||||||
|
extra,
|
||||||
switch (state.state) {
|
}) {
|
||||||
|
SymbolButtonStyle? style = defaultValue;
|
||||||
|
switch (extra?.state) {
|
||||||
case ControlState.disabled:
|
case ControlState.disabled:
|
||||||
style = disabledStyle ??
|
style = themeExtension.disabledStyle;
|
||||||
symbolButtonThemeExtension?.disabledStyle ??
|
|
||||||
style.copyWith(
|
|
||||||
foregroundColors:
|
|
||||||
MultiColor.single(context.colorScheme.onSurface),
|
|
||||||
backgroundColors: MultiColor.single(context.colorScheme.surface),
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
case ControlState.hovered:
|
|
||||||
style =
|
|
||||||
hoveredStyle ?? symbolButtonThemeExtension?.hoveredStyle ?? style;
|
|
||||||
break;
|
|
||||||
case ControlState.tapped:
|
|
||||||
style = tappedStyle ?? symbolButtonThemeExtension?.tappedStyle ?? style;
|
|
||||||
break;
|
break;
|
||||||
case ControlState.focused:
|
case ControlState.focused:
|
||||||
style =
|
style = themeExtension.focusedStyle;
|
||||||
focusedStyle ?? symbolButtonThemeExtension?.focusedStyle ?? style;
|
break;
|
||||||
|
case ControlState.hovered:
|
||||||
|
style = themeExtension.hoveredStyle;
|
||||||
|
break;
|
||||||
|
case ControlState.tapped:
|
||||||
|
style = themeExtension.tappedStyle;
|
||||||
break;
|
break;
|
||||||
case ControlState.normal:
|
case ControlState.normal:
|
||||||
style = normalStyle ?? symbolButtonThemeExtension?.normalStyle ?? style;
|
case null:
|
||||||
|
style = themeExtension.normalStyle;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (extra?.isSelected ?? false) {
|
||||||
// Apply extra theme
|
style = themeExtension.selectedStyle;
|
||||||
if (state.isSelected) {
|
|
||||||
// TODO(hpcl): enhance copyWith to copy only non-null attributes of an object
|
|
||||||
style = style.copyWith(
|
|
||||||
label: (selectedStyle ??
|
|
||||||
symbolButtonThemeExtension?.selectedStyle ??
|
|
||||||
style)
|
|
||||||
.label,
|
|
||||||
dimension: (selectedStyle ??
|
|
||||||
symbolButtonThemeExtension?.selectedStyle ??
|
|
||||||
style)
|
|
||||||
.dimension,
|
|
||||||
radius: (selectedStyle ??
|
|
||||||
symbolButtonThemeExtension?.selectedStyle ??
|
|
||||||
style)
|
|
||||||
.radius,
|
|
||||||
padding: (selectedStyle ??
|
|
||||||
symbolButtonThemeExtension?.selectedStyle ??
|
|
||||||
style)
|
|
||||||
.padding,
|
|
||||||
foregroundColors: (selectedStyle ??
|
|
||||||
symbolButtonThemeExtension?.selectedStyle ??
|
|
||||||
style)
|
|
||||||
.foregroundColors,
|
|
||||||
backgroundColors: (selectedStyle ??
|
|
||||||
symbolButtonThemeExtension?.selectedStyle ??
|
|
||||||
style)
|
|
||||||
.backgroundColors,
|
|
||||||
borderColors: (selectedStyle ??
|
|
||||||
symbolButtonThemeExtension?.selectedStyle ??
|
|
||||||
style)
|
|
||||||
.borderColors,
|
|
||||||
stroke: (selectedStyle ??
|
|
||||||
symbolButtonThemeExtension?.selectedStyle ??
|
|
||||||
style)
|
|
||||||
.stroke,
|
|
||||||
shadow: (selectedStyle ??
|
|
||||||
symbolButtonThemeExtension?.selectedStyle ??
|
|
||||||
style)
|
|
||||||
.shadow,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return style;
|
return style;
|
||||||
|
},
|
||||||
|
customStyleFn: (context, {extra}) {
|
||||||
|
SymbolButtonStyle? style;
|
||||||
|
switch (extra?.state) {
|
||||||
|
case ControlState.disabled:
|
||||||
|
style = disabledStyle;
|
||||||
|
break;
|
||||||
|
case ControlState.focused:
|
||||||
|
style = focusedStyle;
|
||||||
|
break;
|
||||||
|
case ControlState.hovered:
|
||||||
|
style = hoveredStyle;
|
||||||
|
break;
|
||||||
|
case ControlState.tapped:
|
||||||
|
style = tappedStyle;
|
||||||
|
break;
|
||||||
|
case ControlState.normal:
|
||||||
|
case null:
|
||||||
|
style = normalStyle;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (extra?.isSelected ?? false) {
|
||||||
|
style = selectedStyle;
|
||||||
|
}
|
||||||
|
|
||||||
|
return style;
|
||||||
|
},
|
||||||
|
);
|
||||||
|
return resolver.negotiate(context, extra: state);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget onBuild(BuildContext context, ButtonState state) {
|
Widget onBuild(BuildContext context, ButtonState state) {
|
||||||
final style = negotiate(context, state);
|
final style = resolve(context, state);
|
||||||
|
|
||||||
return Focus(
|
return Focus(
|
||||||
onFocusChange: (hasFocus) =>
|
onFocusChange: (hasFocus) =>
|
||||||
|
@ -0,0 +1,59 @@
|
|||||||
|
// Copyright (C) 2023 WYATT GROUP
|
||||||
|
// Please see the AUTHORS file for details.
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:wyatt_ui_components/wyatt_wyatt_ui_components.dart';
|
||||||
|
import 'package:wyatt_ui_kit/src/components/buttons/cubit/button_cubit.dart';
|
||||||
|
import 'package:wyatt_ui_kit/src/core/helpers/theme_resolver.dart';
|
||||||
|
import 'package:wyatt_ui_kit/wyatt_ui_kit.dart';
|
||||||
|
|
||||||
|
class SymbolButtonThemeResolver extends ThemeResolver<SymbolButtonStyle,
|
||||||
|
SymbolButtonThemeExtension, ButtonState> {
|
||||||
|
const SymbolButtonThemeResolver({
|
||||||
|
required this.computeExtensionValueFn,
|
||||||
|
required this.customStyleFn,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
SymbolButtonStyle computeDefaultValue(
|
||||||
|
BuildContext context, {
|
||||||
|
ButtonState? extra,
|
||||||
|
}) =>
|
||||||
|
SymbolButtonStyle(
|
||||||
|
label: context.textTheme.labelLarge,
|
||||||
|
dimension: context.buttonTheme.height,
|
||||||
|
radius: (context.buttonTheme.shape is RoundedRectangleBorder)
|
||||||
|
? (context.buttonTheme.shape as RoundedRectangleBorder).borderRadius
|
||||||
|
: null,
|
||||||
|
padding: context.buttonTheme.padding,
|
||||||
|
foregroundColors: MultiColor.single(context.colorScheme.onPrimary),
|
||||||
|
backgroundColors: MultiColor.single(context.colorScheme.primary),
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
final SymbolButtonStyle? Function(
|
||||||
|
BuildContext context,
|
||||||
|
SymbolButtonStyle defaultValue,
|
||||||
|
SymbolButtonThemeExtension themeExtension, {
|
||||||
|
ButtonState? extra,
|
||||||
|
}) computeExtensionValueFn;
|
||||||
|
|
||||||
|
@override
|
||||||
|
final SymbolButtonStyle? Function(
|
||||||
|
BuildContext context, {
|
||||||
|
ButtonState? extra,
|
||||||
|
}) customStyleFn;
|
||||||
|
}
|
@ -18,4 +18,7 @@ import 'package:flutter/material.dart';
|
|||||||
|
|
||||||
extension BuildContextThemeExtension on BuildContext {
|
extension BuildContextThemeExtension on BuildContext {
|
||||||
T? themeExtension<T>() => Theme.of(this).extension<T>();
|
T? themeExtension<T>() => Theme.of(this).extension<T>();
|
||||||
|
TextTheme get textTheme => Theme.of(this).textTheme;
|
||||||
|
ColorScheme get colorScheme => Theme.of(this).colorScheme;
|
||||||
|
ButtonThemeData get buttonTheme => Theme.of(this).buttonTheme;
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,84 @@
|
|||||||
|
// Copyright (C) 2023 WYATT GROUP
|
||||||
|
// Please see the AUTHORS file for details.
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:wyatt_ui_kit/src/core/extensions/theme_extensions.dart';
|
||||||
|
|
||||||
|
/// {@template theme_resolver}
|
||||||
|
/// In charge of theme negotiation and merge.
|
||||||
|
///
|
||||||
|
/// When you build a component `Component({double? radius})`.
|
||||||
|
/// You have several possibilities:
|
||||||
|
/// 1) Pass the "radius" into the constructor, `Component(radius: 12)`.
|
||||||
|
/// 2) Set up a theme extension `ComponentThemeExtension(radius: 15)`.
|
||||||
|
/// 3) Let `wyatt_ui_kit` "negotiate" and try to find a suitable style in the
|
||||||
|
/// flutter theme.
|
||||||
|
///
|
||||||
|
/// If this negotiation phase fails, then:
|
||||||
|
/// - If the value is mandatory: a hardcoded value in "wyatt_ui_kit" is chosen.
|
||||||
|
/// - If not, the style is simply not applied.
|
||||||
|
/// {@endtemplate}
|
||||||
|
abstract class ThemeResolver<S, T, E> {
|
||||||
|
/// {@macro theme_resolver}
|
||||||
|
const ThemeResolver();
|
||||||
|
|
||||||
|
S? Function(
|
||||||
|
BuildContext context,
|
||||||
|
S defaultValue,
|
||||||
|
T themeExtension, {
|
||||||
|
E? extra,
|
||||||
|
}) get computeExtensionValueFn;
|
||||||
|
S? Function(BuildContext context, {E? extra}) get customStyleFn;
|
||||||
|
|
||||||
|
/// Compute default value from Flutter Theme or with hardcoded values.
|
||||||
|
S computeDefaultValue(BuildContext context, {E? extra});
|
||||||
|
|
||||||
|
/// Compute values from the extension if found
|
||||||
|
S? computeExtensionValue(
|
||||||
|
BuildContext context,
|
||||||
|
S defaultValue, {
|
||||||
|
E? extra,
|
||||||
|
}) {
|
||||||
|
final themeExtension = findExtension(context);
|
||||||
|
if (themeExtension != null) {
|
||||||
|
return computeExtensionValueFn(context, defaultValue, themeExtension);
|
||||||
|
}
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Compute custom value
|
||||||
|
S? computeCustomValue(
|
||||||
|
BuildContext context,
|
||||||
|
S previousPhaseValue, {
|
||||||
|
E? extra,
|
||||||
|
}) {
|
||||||
|
final customStyle = customStyleFn(context, extra: extra);
|
||||||
|
if (customStyle != null) {
|
||||||
|
return customStyle;
|
||||||
|
}
|
||||||
|
return previousPhaseValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
T? findExtension(BuildContext context) => context.themeExtension<T>();
|
||||||
|
|
||||||
|
/// Choose most suitable style for a given context.
|
||||||
|
S negotiate(BuildContext context, {E? extra}) {
|
||||||
|
S style = computeDefaultValue(context, extra: extra);
|
||||||
|
style = computeExtensionValue(context, style, extra: extra) ?? style;
|
||||||
|
style = computeCustomValue(context, style, extra: extra) ?? style;
|
||||||
|
return style;
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user