Skip to content

Commit

Permalink
AutoFillGroup Control (#3047)
Browse files Browse the repository at this point in the history
* AutoFillHint: initial commit

* Mouse utils: lowercase before parsing

* AutoFillGroup: initial commit

* rename AutoFill to Autofill, remove opacity+visible+disabled

* content property is required

* rename AutoFillHint to AutofillHint

* Bug-fix: ExpansionPanel.bgcolor regression
  • Loading branch information
ndonkoHenri authored May 9, 2024
1 parent 5c7422c commit fb7ee1a
Show file tree
Hide file tree
Showing 11 changed files with 437 additions and 35 deletions.
41 changes: 41 additions & 0 deletions packages/flet/lib/src/controls/autofill_group.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import 'package:flet/src/utils/autofill.dart';
import 'package:flutter/material.dart';

import '../models/control.dart';
import 'create_control.dart';
import 'error.dart';

class AutofillGroupControl extends StatelessWidget {
final Control? parent;
final Control control;
final List<Control> children;
final bool parentDisabled;
final bool? parentAdaptive;

const AutofillGroupControl(
{super.key,
required this.parent,
required this.control,
required this.children,
required this.parentDisabled,
this.parentAdaptive});

@override
Widget build(BuildContext context) {
debugPrint("AutofillGroup build: ${control.id}");

var contentCtrls =
children.where((c) => c.name == "content" && c.isVisible);
bool disabled = control.isDisabled || parentDisabled;

if (contentCtrls.isEmpty) {
return const ErrorControl("AutofillGroup control has no content.");
}

return AutofillGroup(
onDisposeAction: parseAutofillContextAction(
control.attrString("disposeAction"), AutofillContextAction.commit)!,
child: createControl(control, contentCtrls.first.id, disabled,
parentAdaptive: parentAdaptive));
}
}
9 changes: 9 additions & 0 deletions packages/flet/lib/src/controls/create_control.dart
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import '../utils/transforms.dart';
import 'alert_dialog.dart';
import 'animated_switcher.dart';
import 'auto_complete.dart';
import 'autofill_group.dart';
import 'badge.dart';
import 'banner.dart';
import 'barchart.dart';
Expand Down Expand Up @@ -803,6 +804,14 @@ Widget createWidget(
parentDisabled: parentDisabled,
parentAdaptive: parentAdaptive,
backend: backend);
case "autofillgroup":
return AutofillGroupControl(
key: key,
parent: parent,
control: controlView.control,
children: controlView.children,
parentDisabled: parentDisabled,
parentAdaptive: parentAdaptive);
case "cupertinoradio":
return CupertinoRadioControl(
key: key,
Expand Down
2 changes: 1 addition & 1 deletion packages/flet/lib/src/controls/expansion_panel.dart
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ class _ExpansionPanelListControlState extends State<ExpansionPanelListControl>
var isExpanded = panelView.control.attrBool("expanded", false)!;
var canTapHeader =
panelView.control.attrBool("canTapHeader", false)!;
var bgColor = widget.control.attrColor("bgColor", context);
var bgColor = panelView.control.attrColor("bgColor", context);

return ExpansionPanel(
backgroundColor: bgColor,
Expand Down
3 changes: 1 addition & 2 deletions packages/flet/lib/src/controls/radio_group.dart
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,7 @@ class RadioGroupControl extends StatelessWidget {
bool disabled = control.isDisabled || parentDisabled;

if (contentCtrls.isEmpty) {
return const ErrorControl(
"RadioGroup control does not have any content.");
return const ErrorControl("RadioGroup control has no content.");
}

return createControl(control, contentCtrls.first.id, disabled,
Expand Down
2 changes: 2 additions & 0 deletions packages/flet/lib/src/controls/textfield.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import 'package:flutter/services.dart';

import '../flet_control_backend.dart';
import '../models/control.dart';
import '../utils/autofill.dart';
import '../utils/borders.dart';
import '../utils/form_field.dart';
import '../utils/text.dart';
Expand Down Expand Up @@ -264,6 +265,7 @@ class _TextFieldControlState extends State<TextFieldControl>
obscureText: password && !_revealPassword,
controller: _controller,
focusNode: focusNode,
autofillHints: parseAutofillHints(widget.control, "autofillHints"),
onChanged: (String value) {
//debugPrint(value);
_value = value;
Expand Down
180 changes: 180 additions & 0 deletions packages/flet/lib/src/utils/autofill.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
import 'dart:convert';

import 'package:flutter/material.dart';

import '../models/control.dart';

List<String>? parseAutofillHints(Control control, String propName) {
var v = control.attrString(propName, null);
if (v == null) {
return null;
}

final j1 = json.decode(v);
return autofillHintsFromJson(j1);
}

List<String> autofillHintsFromJson(dynamic json) {
List<String> hints = [];
if (json is List) {
hints = json
.map((e) => autofillHintFromString(e.toString()))
.whereType<String>()
.toList();
} else if (json is String) {
hints = [autofillHintFromString(json)].whereType<String>().toList();
}

return hints;
}

String? autofillHintFromString(String? hint, [String? defaultAutoFillHint]) {
switch (hint?.toLowerCase()) {
case 'addresscity':
return AutofillHints.addressCity;
case 'addresscityandstate':
return AutofillHints.addressCityAndState;
case 'addressstate':
return AutofillHints.addressState;
case 'birthday':
return AutofillHints.birthday;
case 'birthdayday':
return AutofillHints.birthdayDay;
case 'birthdayMonth':
return AutofillHints.birthdayMonth;
case 'birthdayyear':
return AutofillHints.birthdayYear;
case 'countrycode':
return AutofillHints.countryCode;
case 'countryname':
return AutofillHints.countryName;
case 'creditcardexpirationdate':
return AutofillHints.creditCardExpirationDate;
case 'creditcardexpirationday':
return AutofillHints.creditCardExpirationDay;
case 'creditcardexpirationmonth':
return AutofillHints.creditCardExpirationMonth;
case 'creditcardexpirationyear':
return AutofillHints.creditCardExpirationYear;
case 'creditcardfamilyname':
return AutofillHints.creditCardFamilyName;
case 'creditcardgivenname':
return AutofillHints.creditCardGivenName;
case 'creditcardmiddlename':
return AutofillHints.creditCardMiddleName;
case 'creditcardname':
return AutofillHints.creditCardName;
case 'creditcardnumber':
return AutofillHints.creditCardNumber;
case 'creditcardsecuritycode':
return AutofillHints.creditCardSecurityCode;
case 'creditcardtype':
return AutofillHints.creditCardType;
case 'email':
return AutofillHints.email;
case 'familyname':
return AutofillHints.familyName;
case 'fullstreetaddress':
return AutofillHints.fullStreetAddress;
case 'gender':
return AutofillHints.gender;
case 'givenname':
return AutofillHints.givenName;
case 'impp':
return AutofillHints.impp;
case 'jobtitle':
return AutofillHints.jobTitle;
case 'language':
return AutofillHints.language;
case 'location':
return AutofillHints.location;
case 'middleinitial':
return AutofillHints.middleInitial;
case 'middlename':
return AutofillHints.middleName;
case 'name':
return AutofillHints.name;
case 'nameprefix':
return AutofillHints.namePrefix;
case 'namesuffix':
return AutofillHints.nameSuffix;
case 'newpassword':
return AutofillHints.newPassword;
case 'newusername':
return AutofillHints.newUsername;
case 'nickname':
return AutofillHints.nickname;
case 'onetimecode':
return AutofillHints.oneTimeCode;
case 'organizationname':
return AutofillHints.organizationName;
case 'password':
return AutofillHints.password;
case 'photo':
return AutofillHints.photo;
case 'postaladdress':
return AutofillHints.postalAddress;
case 'postaladdressextended':
return AutofillHints.postalAddressExtended;
case 'postaladdressextendedpostalcode':
return AutofillHints.postalAddressExtendedPostalCode;
case 'postalcode':
return AutofillHints.postalCode;
case 'streetaddresslevel1':
return AutofillHints.streetAddressLevel1;
case 'streetaddresslevel2':
return AutofillHints.streetAddressLevel2;
case 'streetaddresslevel3':
return AutofillHints.streetAddressLevel3;
case 'streetaddresslevel4':
return AutofillHints.streetAddressLevel4;
case 'streetaddressline1':
return AutofillHints.streetAddressLine1;
case 'streetaddressline2':
return AutofillHints.streetAddressLine2;
case 'streetaddressline3':
return AutofillHints.streetAddressLine3;
case 'sublocality':
return AutofillHints.sublocality;
case 'telephonenumber':
return AutofillHints.telephoneNumber;
case 'telephonenumberareacode':
return AutofillHints.telephoneNumberAreaCode;
case 'telephonenumbercountrycode':
return AutofillHints.telephoneNumberCountryCode;
case 'telephonenumberdevice':
return AutofillHints.telephoneNumberDevice;
case 'telephonenumberextension':
return AutofillHints.telephoneNumberExtension;
case 'telephonenumberlocal':
return AutofillHints.telephoneNumberLocal;
case 'telephonenumberlocalprefix':
return AutofillHints.telephoneNumberLocalPrefix;
case 'telephonenumberlocalsuffix':
return AutofillHints.telephoneNumberLocalSuffix;
case 'telephonenumbernational':
return AutofillHints.telephoneNumberNational;
case 'transactionamount':
return AutofillHints.transactionAmount;
case 'transactioncurrency':
return AutofillHints.transactionCurrency;
case 'url':
return AutofillHints.url;
case 'username':
return AutofillHints.username;
default:
return defaultAutoFillHint;
}
}

AutofillContextAction? parseAutofillContextAction(String? action,
[AutofillContextAction? defaultAction]) {
switch (action?.toLowerCase()) {
case 'commit':
return AutofillContextAction.commit;
case 'cancel':
return AutofillContextAction.cancel;
default:
return defaultAction;
}
}
42 changes: 21 additions & 21 deletions packages/flet/lib/src/utils/mouse.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,18 @@ import 'package:flutter/material.dart';

MouseCursor? parseMouseCursor(String? cursor,
[MouseCursor? defaultMouseCursor = MouseCursor.defer]) {
switch (cursor) {
switch (cursor?.toLowerCase()) {
case "alias":
return SystemMouseCursors.alias;
case "allScroll":
case "allscroll":
return SystemMouseCursors.allScroll;
case "basic":
return SystemMouseCursors.basic;
case "cell":
return SystemMouseCursors.cell;
case "click":
return SystemMouseCursors.click;
case "contextMenu":
case "contextmenu":
return SystemMouseCursors.contextMenu;
case "copy":
return SystemMouseCursors.copy;
Expand All @@ -29,51 +29,51 @@ MouseCursor? parseMouseCursor(String? cursor,
return SystemMouseCursors.help;
case "move":
return SystemMouseCursors.move;
case "noDrop":
case "nodrop":
return SystemMouseCursors.noDrop;
case "none":
return SystemMouseCursors.none;
case "precise":
return SystemMouseCursors.precise;
case "progress":
return SystemMouseCursors.progress;
case "resizeColumn":
case "resizecolumn":
return SystemMouseCursors.resizeColumn;
case "resizeDown":
case "resizedown":
return SystemMouseCursors.resizeDown;
case "resizeDownLeft":
case "resizedownleft":
return SystemMouseCursors.resizeDownLeft;
case "resizeDownRight":
case "resizedownright":
return SystemMouseCursors.resizeDownRight;
case "resizeLeft":
case "resizeleft":
return SystemMouseCursors.resizeLeft;
case "resizeLeftRight":
case "resizeleftright":
return SystemMouseCursors.resizeLeftRight;
case "resizeRight":
case "resizeright":
return SystemMouseCursors.resizeRight;
case "resizeRow":
case "resizerow":
return SystemMouseCursors.resizeRow;
case "resizeUp":
case "resizeup":
return SystemMouseCursors.resizeUp;
case "resizeUpDown":
case "resizeupdown":
return SystemMouseCursors.resizeUpDown;
case "resizeUpLeft":
case "resizeupleft":
return SystemMouseCursors.resizeUpLeft;
case "resizeUpLeftDownRight":
case "resizeupleftdownright":
return SystemMouseCursors.resizeUpLeftDownRight;
case "resizeUpRight":
case "resizeupright":
return SystemMouseCursors.resizeUpRight;
case "resizeUpRightDownLeft":
case "resizeuprightdownleft":
return SystemMouseCursors.resizeUpRightDownLeft;
case "text":
return SystemMouseCursors.text;
case "verticalText":
case "verticaltext":
return SystemMouseCursors.verticalText;
case "wait":
return SystemMouseCursors.wait;
case "zoomIn":
case "zoomin":
return SystemMouseCursors.zoomIn;
case "zoomOut":
case "zoomout":
return SystemMouseCursors.zoomOut;
default:
return defaultMouseCursor;
Expand Down
Loading

0 comments on commit fb7ee1a

Please sign in to comment.