Skip to content

fix:ControlState should be resolved based on user-defined order #4556

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Dec 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 21 additions & 21 deletions packages/flet/lib/src/utils/material_state.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import 'dart:collection';
import 'package:flutter/material.dart';

WidgetStateProperty<T?>? getWidgetStateProperty<T>(
Expand All @@ -8,43 +9,42 @@ WidgetStateProperty<T?>? getWidgetStateProperty<T>(
}
var j = jsonDictValue;
if (j is! Map<String, dynamic>) {
j = {"": j};
j = {"default": j};
}
return WidgetStateFromJSON(j, converterFromJson, defaultValue);
}

class WidgetStateFromJSON<T> extends WidgetStateProperty<T?> {
late final Map<String, T> _states;
late final LinkedHashMap<String, T> _states;
late final T? _defaultValue;

WidgetStateFromJSON(Map<String, dynamic>? jsonDictValue,
T Function(dynamic) converterFromJson, T? defaultValue) {
_defaultValue = defaultValue;
_states = {};
if (jsonDictValue != null) {
jsonDictValue.forEach((stateStr, jv) {
stateStr.split(",").map((s) => s.trim().toLowerCase()).forEach((state) {
_states[state] = converterFromJson(jv);
});
});
}

// preserve user-defined order
_states = LinkedHashMap<String, T>.from(
jsonDictValue?.map((key, value) {
var normalizedKey = key.trim().toLowerCase();
// "" is now deprecated; use "default" instead
if (normalizedKey == "") normalizedKey = "default";
return MapEntry(normalizedKey, converterFromJson(value));
}) ??
{},
);
}

@override
T? resolve(Set<WidgetState> states) {
//debugPrint("WidgetStateFromJSON states: $states, _states: $_states");
// find specific state
for (var state in states) {
if (_states.containsKey(state.name)) {
return _states[state.name]!;
// Resolve using user-defined order in _states
for (var stateName in _states.keys) {
if (stateName == "default") continue; // Skip "default"; handled last
if (states.any((state) => state.name == stateName)) {
return _states[stateName];
}
}

// catch-all value
if (_states.containsKey("")) {
return _states[""];
}

return _defaultValue;
// Default state
return _states["default"] ?? _defaultValue;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,6 @@ def __init__(
self.items = items
self.icon = icon
self.on_cancel = on_cancel
self.on_cancelled = on_cancelled
self.on_open = on_open
self.shape = shape
self.padding = padding
Expand Down
2 changes: 1 addition & 1 deletion sdk/python/packages/flet/src/flet/core/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ class ControlState(Enum):
SCROLLED_UNDER = "scrolledUnder"
DISABLED = "disabled"
ERROR = "error"
DEFAULT = ""
DEFAULT = "default"


class MainAxisAlignment(Enum):
Expand Down
15 changes: 10 additions & 5 deletions sdk/python/packages/flet/tests/test_datatable.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import flet as ft
from flet.core.protocol import Command

import flet as ft


def test_datatable_instance_no_attrs_set():
r = ft.DataTable(columns=[ft.DataColumn(label=ft.Text("Header"))])
Expand Down Expand Up @@ -38,7 +39,7 @@ def test_datarow_color_literal_material_state_as_string():
indent=0,
name=None,
values=["datarow"],
attrs={"color": '{"":"yellow"}'},
attrs={"color": '{"default":"yellow"}'},
commands=[],
),
Command(indent=2, name=None, values=["datacell"], attrs={}, commands=[]),
Expand All @@ -51,15 +52,19 @@ def test_datarow_color_literal_material_state_as_string():
def test_datarow_color_multiple_material_states_as_strings():
r = ft.DataRow(
cells=[ft.DataCell(content=ft.Text("Cell"))],
color={"selected": "red", "hovered": "blue", "": "yellow"},
color={
ft.ControlState.SELECTED: "red",
ft.ControlState.HOVERED: "blue",
ft.ControlState.DEFAULT: "yellow",
},
)
assert isinstance(r, ft.Control)
assert r._build_add_commands() == [
Command(
indent=0,
name=None,
values=["datarow"],
attrs={"color": '{"selected":"red","hovered":"blue","":"yellow"}'},
attrs={"color": '{"selected":"red","hovered":"blue","default":"yellow"}'},
commands=[],
),
Command(indent=2, name=None, values=["datacell"], attrs={}, commands=[]),
Expand All @@ -84,7 +89,7 @@ def test_datarow_color_multiple_material_states():
indent=0,
name=None,
values=["datarow"],
attrs={"color": '{"selected":"red","hovered":"blue","":"yellow"}'},
attrs={"color": '{"selected":"red","hovered":"blue","default":"yellow"}'},
commands=[],
),
Command(indent=2, name=None, values=["datacell"], attrs={}, commands=[]),
Expand Down