Skip to content

Commit

Permalink
Fix issues with *Buttons (#3582)
Browse files Browse the repository at this point in the history
* BorderSide: add stroke_align prop

* proper styling in buttons

* deprecate ThemeVisualDensity in favor of VisualDensity

* ButtonStyle: new props

* deprecation: disabled_color is renamed to disabled_bgcolor
  • Loading branch information
ndonkoHenri authored Jul 5, 2024
1 parent 3a7d56d commit aa7148b
Show file tree
Hide file tree
Showing 21 changed files with 274 additions and 163 deletions.
37 changes: 23 additions & 14 deletions packages/flet/lib/src/controls/cupertino_button.dart
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ class _CupertinoButtonControlState extends State<CupertinoButtonControl> {
Widget build(BuildContext context) {
debugPrint("CupertinoButton build: ${widget.control.id}");
bool disabled = widget.control.isDisabled || widget.parentDisabled;
var theme = Theme.of(context);

var contentCtrls =
widget.children.where((c) => c.name == "content" && c.isVisible);
Expand All @@ -59,7 +60,11 @@ class _CupertinoButtonControlState extends State<CupertinoButtonControl> {
if (icon != null) {
children.add(Icon(
selected ? selectedIcon : icon,
color: selected ? selectedIconColor : iconColor,
color: selected
? selectedIconColor
: disabled
? theme.disabledColor
: iconColor,
size: iconSize,
));
}
Expand Down Expand Up @@ -92,8 +97,10 @@ class _CupertinoButtonControlState extends State<CupertinoButtonControl> {
double pressedOpacity = widget.control.attrDouble("opacityOnClick", 0.4)!;
double minSize = widget.control.attrDouble("minSize", 44.0)!;
String url = widget.control.attrString("url", "")!;
Color disabledColor = widget.control.attrColor("disabledColor", context) ??
CupertinoColors.quaternarySystemFill;
Color disabledColor =
widget.control.attrColor("disabledBgcolor", context) ??
widget.control.attrColor("disabledColor", context) ?? // deprecated
CupertinoColors.quaternarySystemFill;
Color? bgColor = widget.control.attrColor("bgColor", context);
Color? color = widget.control.attrColor("color", context);
AlignmentGeometry alignment =
Expand All @@ -103,7 +110,6 @@ class _CupertinoButtonControlState extends State<CupertinoButtonControl> {

EdgeInsets? padding = parseEdgeInsets(widget.control, "padding");

var theme = Theme.of(context);
var style = parseButtonStyle(Theme.of(context), widget.control, "style",
defaultForegroundColor: theme.colorScheme.primary,
defaultBackgroundColor: Colors.transparent,
Expand All @@ -117,18 +123,21 @@ class _CupertinoButtonControlState extends State<CupertinoButtonControl> {
? const StadiumBorder()
: RoundedRectangleBorder(borderRadius: BorderRadius.circular(4)));

if (padding == null && style != null) {
padding = style.padding?.resolve({}) as EdgeInsets?;
}
if (style != null) {
Set<WidgetState> widgetStates = selected ? {WidgetState.selected} : {};

if (bgColor == null && style != null) {
bgColor = style.backgroundColor
?.resolve(selected ? {WidgetState.selected} : {});
}
// Check if the widget is disabled and update the foregroundColor accordingly
// backgroundColor is not updated here, as it is handled by disabledColor
if (disabled) {
style = style.copyWith(
foregroundColor: WidgetStatePropertyAll(theme.disabledColor),
);
}

if (color == null && style != null) {
color = style.foregroundColor
?.resolve(selected ? {WidgetState.selected} : {});
// Resolve color, background color, and padding based on widget states
color = style.foregroundColor?.resolve(widgetStates);
bgColor = style.backgroundColor?.resolve(widgetStates);
padding = style.padding?.resolve({}) as EdgeInsets?;
}

if (color != null) {
Expand Down
1 change: 1 addition & 0 deletions packages/flet/lib/src/utils/borders.dart
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ BorderSide? borderSideFromJSON(ThemeData? theme, dynamic json,
color:
parseColor(theme, json['c'], defaultSideColor ?? Colors.black)!,
width: parseDouble(json['w'], 1)!,
strokeAlign: parseDouble(json['sa'], BorderSide.strokeAlignInside)!,
style: BorderStyle.solid)
: null;
}
Expand Down
64 changes: 39 additions & 25 deletions packages/flet/lib/src/utils/buttons.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,15 @@ import 'package:flet/src/utils/transforms.dart';
import 'package:flutter/material.dart';

import '../models/control.dart';
import 'alignment.dart';
import 'borders.dart';
import 'colors.dart';
import 'edge_insets.dart';
import 'material_state.dart';
import 'mouse.dart';
import 'numbers.dart';
import 'text.dart';
import 'theme.dart';

ButtonStyle? parseButtonStyle(ThemeData theme, Control control, String propName,
{required Color defaultForegroundColor,
Expand Down Expand Up @@ -54,31 +58,41 @@ ButtonStyle? buttonStyleFromJSON(ThemeData theme, Map<String, dynamic>? json,
return null;
}
return ButtonStyle(
foregroundColor: getWidgetStateProperty<Color?>(json["color"],
(jv) => parseColor(theme, jv as String), defaultForegroundColor),
backgroundColor: getWidgetStateProperty<Color?>(json["bgcolor"],
(jv) => parseColor(theme, jv as String), defaultBackgroundColor),
overlayColor: getWidgetStateProperty<Color?>(json["overlay_color"],
(jv) => parseColor(theme, jv as String), defaultOverlayColor),
shadowColor: getWidgetStateProperty<Color?>(json["shadow_color"],
(jv) => parseColor(theme, jv as String), defaultShadowColor),
surfaceTintColor: getWidgetStateProperty<Color?>(
json["surface_tint_color"],
(jv) => parseColor(theme, jv as String),
defaultSurfaceTintColor),
elevation: getWidgetStateProperty(
json["elevation"], (jv) => parseDouble(jv, 0)!, defaultElevation),
animationDuration: json["animation_duration"] != null
? Duration(milliseconds: parseInt(json["animation_duration"], 0)!)
: null,
padding: getWidgetStateProperty<EdgeInsetsGeometry?>(
json["padding"], (jv) => edgeInsetsFromJson(jv), defaultPadding),
side: getWidgetStateProperty<BorderSide?>(
json["side"],
(jv) => borderSideFromJSON(theme, jv, theme.colorScheme.outline),
defaultBorderSide),
shape: getWidgetStateProperty<OutlinedBorder?>(
json["shape"], (jv) => outlinedBorderFromJSON(jv), defaultShape));
foregroundColor: getWidgetStateProperty<Color?>(json["color"],
(jv) => parseColor(theme, jv as String), defaultForegroundColor),
backgroundColor: getWidgetStateProperty<Color?>(json["bgcolor"],
(jv) => parseColor(theme, jv as String), defaultBackgroundColor),
overlayColor: getWidgetStateProperty<Color?>(json["overlay_color"],
(jv) => parseColor(theme, jv as String), defaultOverlayColor),
shadowColor: getWidgetStateProperty<Color?>(json["shadow_color"],
(jv) => parseColor(theme, jv as String), defaultShadowColor),
surfaceTintColor: getWidgetStateProperty<Color?>(json["surface_tint_color"],
(jv) => parseColor(theme, jv as String), defaultSurfaceTintColor),
elevation: getWidgetStateProperty(
json["elevation"], (jv) => parseDouble(jv, 0)!, defaultElevation),
animationDuration: json["animation_duration"] != null
? Duration(milliseconds: parseInt(json["animation_duration"], 0)!)
: null,
padding: getWidgetStateProperty<EdgeInsetsGeometry?>(
json["padding"], (jv) => edgeInsetsFromJson(jv), defaultPadding),
side: getWidgetStateProperty<BorderSide?>(
json["side"],
(jv) => borderSideFromJSON(theme, jv, theme.colorScheme.outline),
defaultBorderSide),
shape: getWidgetStateProperty<OutlinedBorder?>(
json["shape"], (jv) => outlinedBorderFromJSON(jv), defaultShape),
iconColor: getWidgetStateProperty<Color?>(json["icon_color"],
(jv) => parseColor(theme, jv as String), defaultForegroundColor),
alignment: alignmentFromJson(json["alignment"]),
enableFeedback: parseBool(json["enable_feedback"]),
textStyle: getWidgetStateProperty<TextStyle?>(
json["text_style"], (jv) => textStyleFromJson(theme, jv)),
iconSize: getWidgetStateProperty<double?>(
json["icon_size"], (jv) => parseDouble(jv)),
visualDensity: parseVisualDensity(json["visual_density"]),
mouseCursor: getWidgetStateProperty<MouseCursor?>(
json["mouse_cursor"], (jv) => parseMouseCursor(jv)),
);
}

FloatingActionButtonLocation parseFloatingActionButtonLocation(
Expand Down
5 changes: 3 additions & 2 deletions sdk/python/packages/flet-core/src/flet_core/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
from flet_core.badge import Badge
from flet_core.banner import Banner
from flet_core.blur import Blur, BlurTileMode
from flet_core.border import Border, BorderSide
from flet_core.border import Border, BorderSide, BorderSideStrokeAlign
from flet_core.border_radius import BorderRadius
from flet_core.bottom_app_bar import BottomAppBar
from flet_core.bottom_sheet import BottomSheet
Expand Down Expand Up @@ -321,7 +321,6 @@
TabsTheme,
TextTheme,
Theme,
ThemeVisualDensity,
TimePickerTheme,
TooltipTheme,
)
Expand Down Expand Up @@ -361,6 +360,8 @@
TabAlignment,
TextAlign,
ThemeMode,
ThemeVisualDensity,
VisualDensity,
UrlTarget,
VerticalAlignment,
StrokeCap,
Expand Down
28 changes: 19 additions & 9 deletions sdk/python/packages/flet-core/src/flet_core/border.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,29 @@
import dataclasses
from dataclasses import dataclass, field
from enum import Enum
from typing import Optional, Union

from flet_core.types import OptionalNumber

@dataclasses.dataclass

class BorderSideStrokeAlign(Enum):
STROKE_ALIGN_INSIDE = -1.0
STROKE_ALIGN_CENTER = 0.0
STROKE_ALIGN_OUTSIDE = 1.0


@dataclass
class BorderSide:
width: Union[None, float, int]
color: Optional[str] = dataclasses.field(default=None)
width: OptionalNumber
color: Optional[str] = field(default=None)
stroke_align: Union[BorderSideStrokeAlign, OptionalNumber] = field(default=None)


@dataclasses.dataclass
@dataclass
class Border:
top: Optional[BorderSide] = dataclasses.field(default=None)
right: Optional[BorderSide] = dataclasses.field(default=None)
bottom: Optional[BorderSide] = dataclasses.field(default=None)
left: Optional[BorderSide] = dataclasses.field(default=None)
top: Optional[BorderSide] = field(default=None)
right: Optional[BorderSide] = field(default=None)
bottom: Optional[BorderSide] = field(default=None)
left: Optional[BorderSide] = field(default=None)


def all(width: Optional[float] = None, color: Optional[str] = None) -> Border:
Expand Down
39 changes: 35 additions & 4 deletions sdk/python/packages/flet-core/src/flet_core/buttons.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,18 @@
from dataclasses import dataclass, field
from typing import Dict, Optional, Union

from flet_core.alignment import Alignment
from flet_core.border import BorderSide
from flet_core.types import BorderRadiusValue, ControlState, PaddingValue
from flet_core.text_style import TextStyle
from flet_core.types import (
BorderRadiusValue,
ControlState,
PaddingValue,
Number,
ThemeVisualDensity,
VisualDensity,
MouseCursor,
)


@dataclass
Expand Down Expand Up @@ -48,9 +58,7 @@ def __post_init__(self):
@dataclass
class ButtonStyle:
color: Union[None, str, Dict[Union[str, ControlState], str]] = field(default=None)
bgcolor: Union[None, str, Dict[Union[str, ControlState], str]] = field(
default=None
)
bgcolor: Union[None, str, Dict[Union[str, ControlState], str]] = field(default=None)
overlay_color: Union[None, str, Dict[Union[str, ControlState], str]] = field(
default=None
)
Expand All @@ -73,3 +81,26 @@ class ButtonStyle:
shape: Union[
None, OutlinedBorder, Dict[Union[str, ControlState], OutlinedBorder]
] = field(default=None)
alignment: Union[
None, Alignment, Dict[Union[str, ControlState], Alignment]
] = field(default=None)
enable_feedback: Union[None, bool, Dict[Union[str, ControlState], bool]] = field(
default=None
)
text_style: Union[
None, TextStyle, Dict[Union[str, ControlState], TextStyle]
] = field(default=None)
icon_size: Union[None, Number, Dict[Union[str, ControlState], Number]] = field(
default=None
)
icon_color: Union[None, str, Dict[Union[str, ControlState], str]] = field(
default=None
)
visual_density: Union[
None,
Union[VisualDensity, ThemeVisualDensity],
Dict[Union[str, ControlState], Union[VisualDensity, ThemeVisualDensity]],
] = field(default=None)
mouse_cursor: Union[
None, MouseCursor, Dict[Union[str, ControlState], MouseCursor]
] = field(default=None)
11 changes: 6 additions & 5 deletions sdk/python/packages/flet-core/src/flet_core/checkbox.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
from flet_core.control import OptionalNumber
from flet_core.ref import Ref
from flet_core.text_style import TextStyle
from flet_core.theme import ThemeVisualDensity
from flet_core.types import (
AnimationValue,
LabelPosition,
Expand All @@ -18,6 +17,8 @@
RotateValue,
ScaleValue,
OptionalEventCallable,
ThemeVisualDensity,
VisualDensity,
)


Expand Down Expand Up @@ -74,7 +75,7 @@ def __init__(
splash_radius: OptionalNumber = None,
border_side: Union[None, BorderSide, Dict[ControlState, BorderSide]] = None,
is_error: Optional[bool] = None,
visual_density: Optional[ThemeVisualDensity] = None,
visual_density: Union[None, ThemeVisualDensity, VisualDensity] = None,
mouse_cursor: Optional[MouseCursor] = None,
on_change: OptionalEventCallable = None,
on_focus: OptionalEventCallable = None,
Expand Down Expand Up @@ -230,13 +231,13 @@ def mouse_cursor(self, value: Optional[MouseCursor]):

# visual_density
@property
def visual_density(self) -> Optional[ThemeVisualDensity]:
def visual_density(self) -> Union[None, ThemeVisualDensity, VisualDensity]:
return self.__visual_density

@visual_density.setter
def visual_density(self, value: Optional[ThemeVisualDensity]):
def visual_density(self, value: Union[None, ThemeVisualDensity, VisualDensity]):
self.__visual_density = value
self._set_enum_attr("visualDensity", value, ThemeVisualDensity)
self._set_enum_attr("visualDensity", value, ThemeVisualDensity, VisualDensity)

# autofocus
@property
Expand Down
23 changes: 12 additions & 11 deletions sdk/python/packages/flet-core/src/flet_core/chip.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
from flet_core.control import Control, OptionalNumber
from flet_core.ref import Ref
from flet_core.text_style import TextStyle
from flet_core.theme import ThemeVisualDensity
from flet_core.types import (
AnimationValue,
OffsetValue,
Expand All @@ -17,6 +16,8 @@
ClipBehavior,
ControlState,
OptionalEventCallable,
ThemeVisualDensity,
VisualDensity,
)


Expand Down Expand Up @@ -91,13 +92,13 @@ def __init__(
color: Union[None, str, Dict[Union[ControlState, str], str]] = None,
click_elevation: OptionalNumber = None,
clip_behavior: Optional[ClipBehavior] = None,
visual_density: Optional[ThemeVisualDensity] = None,
visual_density: Union[None, ThemeVisualDensity, VisualDensity] = None,
border_side: Optional[BorderSide] = None,
on_click: OptionalEventCallable = None,
on_delete: OptionalEventCallable = None,
on_select: OptionalEventCallable = None,
on_focus: OptionalEventCallable = None,
on_blur: OptionalEventCallable = None,
on_click: OptionalEventCallable = None,
on_delete: OptionalEventCallable = None,
on_select: OptionalEventCallable = None,
on_focus: OptionalEventCallable = None,
on_blur: OptionalEventCallable = None,
#
# ConstrainedControl
#
Expand All @@ -122,7 +123,7 @@ def __init__(
animate_rotation: AnimationValue = None,
animate_scale: AnimationValue = None,
animate_offset: AnimationValue = None,
on_animation_end: OptionalEventCallable = None,
on_animation_end: OptionalEventCallable = None,
tooltip: Optional[str] = None,
visible: Optional[bool] = None,
disabled: Optional[bool] = None,
Expand Down Expand Up @@ -416,13 +417,13 @@ def shape(self, value: Optional[OutlinedBorder]):

# visual_density
@property
def visual_density(self) -> Optional[ThemeVisualDensity]:
def visual_density(self) -> Union[None, ThemeVisualDensity, VisualDensity]:
return self.__visual_density

@visual_density.setter
def visual_density(self, value: Optional[ThemeVisualDensity]):
def visual_density(self, value: Union[None, ThemeVisualDensity, VisualDensity]):
self.__visual_density = value
self._set_enum_attr("visualDensity", value, ThemeVisualDensity)
self._set_enum_attr("visualDensity", value, ThemeVisualDensity, VisualDensity)

# clip_behavior
@property
Expand Down
Loading

0 comments on commit aa7148b

Please sign in to comment.