From 7524cc5e1820962a999ec3b4833cae6d9ef1c5d3 Mon Sep 17 00:00:00 2001 From: InesaFitsner Date: Tue, 21 Nov 2023 12:28:17 -0800 Subject: [PATCH 01/10] time_picker.dart initial version --- client/pubspec.lock | 20 +-- package/lib/src/controls/create_control.dart | 9 ++ package/lib/src/controls/time_picker.dart | 150 +++++++++++++++++++ 3 files changed, 169 insertions(+), 10 deletions(-) create mode 100644 package/lib/src/controls/time_picker.dart diff --git a/client/pubspec.lock b/client/pubspec.lock index 266b530e1..60ec9c1d5 100644 --- a/client/pubspec.lock +++ b/client/pubspec.lock @@ -434,10 +434,10 @@ packages: dependency: transitive description: name: plugin_platform_interface - sha256: da3fdfeccc4d4ff2da8f8c556704c08f912542c5fb3cf2233ed75372384a034d + sha256: f4f88d4a900933e7267e2b353594774fc0d07fb072b47eedcd5b54e1ea3269f8 url: "https://pub.dev" source: hosted - version: "2.1.6" + version: "2.1.7" pointycastle: dependency: transitive description: @@ -546,10 +546,10 @@ packages: dependency: transitive description: name: shared_preferences_web - sha256: d762709c2bbe80626ecc819143013cc820fa49ca5e363620ee20a8b15a3e3daf + sha256: "7b15ffb9387ea3e237bb7a66b8a23d2147663d391cafc5c8f37b2e7b4bde5d21" url: "https://pub.dev" source: hosted - version: "2.2.1" + version: "2.2.2" shared_preferences_windows: dependency: transitive description: @@ -663,10 +663,10 @@ packages: dependency: transitive description: name: url_launcher_ios - sha256: "4ac97281cf60e2e8c5cc703b2b28528f9b50c8f7cebc71df6bdf0845f647268a" + sha256: bba3373219b7abb6b5e0d071b0fe66dfbe005d07517a68e38d4fc3638f35c6d3 url: "https://pub.dev" source: hosted - version: "6.2.0" + version: "6.2.1" url_launcher_linux: dependency: transitive description: @@ -807,10 +807,10 @@ packages: dependency: transitive description: name: webview_flutter_platform_interface - sha256: "6d9213c65f1060116757a7c473247c60f3f7f332cac33dc417c9e362a9a13e4f" + sha256: adb8c03c2be231bea5a8ed0e9039e9d18dbb049603376beaefa15393ede468a5 url: "https://pub.dev" source: hosted - version: "2.6.0" + version: "2.7.0" webview_flutter_wkwebview: dependency: transitive description: @@ -868,5 +868,5 @@ packages: source: hosted version: "3.1.2" sdks: - dart: ">=3.2.0-194.0.dev <4.0.0" - flutter: ">=3.13.0" + dart: ">=3.2.0 <4.0.0" + flutter: ">=3.16.0" diff --git a/package/lib/src/controls/create_control.dart b/package/lib/src/controls/create_control.dart index f8a52bcf5..974dbee40 100644 --- a/package/lib/src/controls/create_control.dart +++ b/package/lib/src/controls/create_control.dart @@ -29,6 +29,7 @@ import 'column.dart'; import 'container.dart'; import 'datatable.dart'; import 'date_picker.dart'; +import 'time_picker.dart'; import 'divider.dart'; import 'drag_target.dart'; import 'draggable.dart'; @@ -326,6 +327,14 @@ Widget createWidget(Key? key, ControlViewModel controlView, Control? parent, parentDisabled: parentDisabled, dispatch: controlView.dispatch, ); + case "timepicker": + return TimePickerControl( + parent: parent, + control: controlView.control, + children: controlView.children, + parentDisabled: parentDisabled, + dispatch: controlView.dispatch, + ); case "draggable": return DraggableControl( key: key, diff --git a/package/lib/src/controls/time_picker.dart b/package/lib/src/controls/time_picker.dart new file mode 100644 index 000000000..a4636e8be --- /dev/null +++ b/package/lib/src/controls/time_picker.dart @@ -0,0 +1,150 @@ +import 'package:flutter/material.dart'; + +import '../actions.dart'; +import '../flet_app_services.dart'; +import '../models/control.dart'; +import '../protocol/update_control_props_payload.dart'; +import '../utils/icons.dart'; +import 'form_field.dart'; + +class TimePickerControl extends StatefulWidget { + final Control? parent; + final Control control; + final List children; + final bool parentDisabled; + final dynamic dispatch; + + const TimePickerControl({ + Key? key, + this.parent, + required this.control, + required this.children, + required this.parentDisabled, + required this.dispatch, + }) : super(key: key); + + @override + State createState() => _TimePickerControlState(); +} + +class _TimePickerControlState extends State { + @override + Widget build(BuildContext context) { + debugPrint("TimePicker build: ${widget.control.id}"); + + bool lastOpen = widget.control.state["open"] ?? false; + + var open = widget.control.attrBool("open", false)!; + DateTime? value = widget.control.attrDateTime("value"); + DateTime? firstDate = widget.control.attrDateTime("firstDate"); + DateTime? lastDate = widget.control.attrDateTime("lastDate"); + DateTime? currentDate = widget.control.attrDateTime("currentDate"); + //String? localeString = widget.control.attrString("locale"); + String? helpText = widget.control.attrString("helpText"); + String? cancelText = widget.control.attrString("cancelText"); + String? confirmText = widget.control.attrString("confirmText"); + String? errorFormatText = widget.control.attrString("errorFormatText"); + String? errorInvalidText = widget.control.attrString("errorInvalidText"); + TextInputType keyboardType = + parseTextInputType(widget.control.attrString("keyboardType", "")!); + DatePickerMode datePickerMode = DatePickerMode.values.firstWhere( + (a) => + a.name.toLowerCase() == + widget.control.attrString("datePickerMode", "")!.toLowerCase(), + orElse: () => DatePickerMode.day); + DatePickerEntryMode datePickerEntryMode = DatePickerEntryMode.values + .firstWhere( + (a) => + a.name.toLowerCase() == + widget.control + .attrString("datePickerEntryMode", "")! + .toLowerCase(), + orElse: () => DatePickerEntryMode.calendar); + String? fieldHintText = widget.control.attrString("fieldHintText"); + String? fieldLabelText = widget.control.attrString("fieldLabelText"); + IconData? switchToCalendarEntryModeIcon = getMaterialIcon( + widget.control.attrString("switchToCalendarEntryModeIcon", "")!); + IconData? switchToInputEntryModeIcon = getMaterialIcon( + widget.control.attrString("switchToInputEntryModeIcon", "")!); + + //Locale locale; + // if (localeString == null) { + // locale = Localizations.localeOf(context); + // } else { + // //locale = Locale(localeString); + // } + + void onClosed(DateTime? dateValue) { + String stringValue; + String eventName; + if (dateValue == null) { + stringValue = + value?.toIso8601String() ?? currentDate?.toIso8601String() ?? ""; + eventName = "dismiss"; + } else { + stringValue = dateValue.toIso8601String(); + eventName = "change"; + } + widget.control.state["open"] = false; + List> props = [ + {"i": widget.control.id, "value": stringValue, "open": "false"} + ]; + widget.dispatch( + UpdateControlPropsAction(UpdateControlPropsPayload(props: props))); + FletAppServices.of(context).server.updateControlProps(props: props); + + FletAppServices.of(context).server.sendPageEvent( + eventTarget: widget.control.id, + eventName: eventName, + eventData: stringValue); + } + + Widget createSelectDateDialog() { + Widget dialog = TimePickerDialog( + initialTime: TimeOfDay.now(), + //initialDate: value ?? currentDate ?? DateTime.now(), + //firstDate: firstDate ?? DateTime(1900), + //lastDate: lastDate ?? DateTime(2050), + //currentDate: currentDate ?? DateTime.now(), + helpText: helpText, + cancelText: cancelText, + confirmText: confirmText, + //errorFormatText: errorFormatText, + errorInvalidText: errorInvalidText, + //keyboardType: keyboardType, + //initialCalendarMode: datePickerMode, + initialEntryMode: TimePickerEntryMode.dial, + //fieldHintText: fieldHintText, + //fieldLabelText: fieldLabelText, + //switchToCalendarEntryModeIcon: switchToCalendarEntryModeIcon != null + // ? Icon(switchToCalendarEntryModeIcon) + // : null, + //switchToInputEntryModeIcon: switchToInputEntryModeIcon != null + // ? Icon(switchToInputEntryModeIcon) + // : null, + ); + + // dialog = Localizations.override( + // context: context, + // locale: locale, + // child: dialog, + // ); + + return dialog; + } + + if (open && (open != lastOpen)) { + widget.control.state["open"] = open; + + WidgetsBinding.instance.addPostFrameCallback((_) { + showDialog( + context: context, + builder: (context) => createSelectDateDialog()).then((result) { + debugPrint("pickDate() completed"); + onClosed(result); + }); + }); + } + return const SizedBox.shrink(); + } +} From e2dc8d03fb6b53a96a9f1a062155f5538bee7bea Mon Sep 17 00:00:00 2001 From: InesaFitsner Date: Tue, 21 Nov 2023 12:57:02 -0800 Subject: [PATCH 02/10] time_picker.py initial commit --- package/lib/src/controls/time_picker.dart | 2 +- .../flet-core/src/flet_core/__init__.py | 1 + .../flet-core/src/flet_core/time_picker.py | 358 ++++++++++++++++++ 3 files changed, 360 insertions(+), 1 deletion(-) create mode 100644 sdk/python/packages/flet-core/src/flet_core/time_picker.py diff --git a/package/lib/src/controls/time_picker.dart b/package/lib/src/controls/time_picker.dart index a4636e8be..859321e6b 100644 --- a/package/lib/src/controls/time_picker.dart +++ b/package/lib/src/controls/time_picker.dart @@ -113,7 +113,7 @@ class _TimePickerControlState extends State { errorInvalidText: errorInvalidText, //keyboardType: keyboardType, //initialCalendarMode: datePickerMode, - initialEntryMode: TimePickerEntryMode.dial, + initialEntryMode: TimePickerEntryMode.input, //fieldHintText: fieldHintText, //fieldLabelText: fieldLabelText, //switchToCalendarEntryModeIcon: switchToCalendarEntryModeIcon != null diff --git a/sdk/python/packages/flet-core/src/flet_core/__init__.py b/sdk/python/packages/flet-core/src/flet_core/__init__.py index be5790700..d6567133a 100644 --- a/sdk/python/packages/flet-core/src/flet_core/__init__.py +++ b/sdk/python/packages/flet-core/src/flet_core/__init__.py @@ -177,6 +177,7 @@ TextField, TextOnlyInputFilter, ) +from flet_core.time_picker import TimePicker from flet_core.theme import ( ColorScheme, PageTransitionsTheme, diff --git a/sdk/python/packages/flet-core/src/flet_core/time_picker.py b/sdk/python/packages/flet-core/src/flet_core/time_picker.py new file mode 100644 index 000000000..a9a054f6a --- /dev/null +++ b/sdk/python/packages/flet-core/src/flet_core/time_picker.py @@ -0,0 +1,358 @@ +from datetime import date, datetime +from enum import Enum +from typing import Any, Optional, Union + +from flet_core.control import Control, OptionalNumber +from flet_core.ref import Ref +from flet_core.text_style import TextStyle +from flet_core.textfield import KeyboardType, KeyboardTypeString +from flet_core.types import ResponsiveNumber + +try: + from typing import Literal +except ImportError: + from typing_extensions import Literal + + +class DatePickerMode(Enum): + DAY = "day" + YEAR = "year" + + +class DatePickerEntryMode(Enum): + CALENDAR = "calendar" + INPUT = "input" + CALENDAR_ONLY = "calendarOnly" + INPUT_ONLY = "inputOnly" + + +class TimePicker(Control): + """ + A Material-style date picker dialog. + + It is added to [`page.overlay`](page#overlay) and called using its `pick_date()` method. + + Depending on the `date_picker_mode`, it will show either a Calendar or an Input (TextField) for picking a date. + + Example: + ``` + import datetime + import flet as ft + + def main(page: ft.Page): + def change_date(e): + print(f"Date picker changed, value is {date_picker.value}") + + def date_picker_dismissed(e): + print(f"Date picker dismissed, value is {date_picker.value}") + + date_picker = ft.DatePicker( + on_change=change_date, + on_dismiss=date_picker_dismissed, + first_date=datetime.datetime(2023, 10, 1), + last_date=datetime.datetime(2024, 10, 1), + ) + + page.overlay.append(date_picker) + + date_button = ft.ElevatedButton( + "Pick date", + icon=ft.icons.CALENDAR_MONTH, + on_click=lambda _: date_picker.pick_date(), + ) + + page.add(date_button) + + + ft.app(target=main) + ``` + + ----- + + Online docs: https://flet.dev/docs/controls/date_picker + """ + + def __init__( + self, + ref: Optional[Ref] = None, + expand: Optional[Union[bool, int]] = None, + col: Optional[ResponsiveNumber] = None, + opacity: OptionalNumber = None, + tooltip: Optional[str] = None, + visible: Optional[bool] = None, + disabled: Optional[bool] = None, + data: Any = None, + open: bool = False, + value: Optional[datetime] = None, + text_style: Optional[TextStyle] = None, + first_date: Optional[datetime] = None, + last_date: Optional[datetime] = None, + current_date: Optional[datetime] = None, + keyboard_type: Optional[KeyboardType] = None, + date_picker_mode: Optional[DatePickerMode] = None, + date_picker_entry_mode: Optional[DatePickerEntryMode] = None, + # locale: Optional[str] = None, + help_text: Optional[str] = None, + cancel_text: Optional[str] = None, + confirm_text: Optional[str] = None, + error_format_text: Optional[str] = None, + error_invalid_text: Optional[str] = None, + field_hint_text: Optional[str] = None, + field_label_text: Optional[str] = None, + switch_to_calendar_icon: Optional[str] = None, + switch_to_input_icon: Optional[str] = None, + on_change=None, + on_dismiss=None, + ): + Control.__init__( + self, + ref=ref, + expand=expand, + col=col, + opacity=opacity, + tooltip=tooltip, + visible=visible, + disabled=disabled, + data=data, + ) + self.value = value + self.first_date = first_date + self.last_date = last_date + self.current_date = current_date + self.keyboard_type = keyboard_type + # self.locale = locale + self.help_text = help_text + self.cancel_text = cancel_text + self.confirm_text = confirm_text + self.error_format_text = error_format_text + self.error_invalid_text = error_invalid_text + self.date_picker_mode = date_picker_mode + self.date_picker_entry_mode = date_picker_entry_mode + self.text_style = text_style + self.field_hint_text = field_hint_text + self.field_label_text = field_label_text + self.switch_to_calendar_icon = switch_to_calendar_icon + self.switch_to_input_icon = switch_to_input_icon + self.on_change = on_change + self.on_dismiss = on_dismiss + self.open = open + + def _get_control_name(self): + return "timepicker" + + def _before_build_command(self): + super()._before_build_command() + + def pick_date(self): + self.open = True + self.update() + + async def pick_date_async(self): + self.open = True + await self.update_async() + + # open + @property + def open(self) -> Optional[bool]: + return self._get_attr("open", data_type="bool", def_value=False) + + @open.setter + def open(self, value: Optional[bool]): + self._set_attr("open", value) + + # value + @property + def value(self) -> Optional[datetime]: + value_string = self._get_attr("value", def_value=None) + return datetime.fromisoformat(value_string) if value_string else None + + @value.setter + def value(self, value: Optional[Union[datetime, str]]): + if isinstance(value, (date, datetime)): + value = value.isoformat() + self._set_attr("value", value) + + # first_date + @property + def first_date(self) -> Optional[datetime]: + value_string = self._get_attr("firstDate", def_value=None) + if value_string is None: + return None + else: + return datetime.fromisoformat(value_string) + + @first_date.setter + def first_date(self, value: Optional[Union[datetime, str]]): + if isinstance(value, (date, datetime)): + value = value.isoformat() + self._set_attr("firstDate", value) + + # last_date + @property + def last_date(self) -> Optional[datetime]: + value_string = self._get_attr("lastDate", def_value=None) + if value_string is None: + return None + else: + return datetime.fromisoformat(value_string) + + @last_date.setter + def last_date(self, value: Optional[Union[datetime, str]]): + if isinstance(value, (date, datetime)): + value = value.isoformat() + self._set_attr("lastDate", value) + + # current_date + @property + def current_date(self) -> Optional[datetime]: + value_string = self._get_attr("currentDate", def_value=None) + if value_string is None: + return None + else: + return datetime.fromisoformat(value_string) + + @current_date.setter + def current_date(self, value: Optional[Union[datetime, str]]): + if isinstance(value, (date, datetime)): + value = value.isoformat() + self._set_attr("currentDate", value) + + # # locale + # @property + # def locale(self) -> Optional[str]: + # return self._get_attr("locale", def_value=None) + + # @locale.setter + # def locale(self, value: Optional[str]): + # self._set_attr("locale", value) + + # field_hint_text + @property + def field_hint_text(self) -> Optional[str]: + return self._get_attr("fieldHintText", def_value=None) + + @field_hint_text.setter + def field_hint_text(self, value: Optional[str]): + self._set_attr("fieldHintText", value) + + # field_label_text + @property + def field_label_text(self) -> Optional[str]: + return self._get_attr("fieldLabelText", def_value=None) + + @field_label_text.setter + def field_label_text(self, value: Optional[str]): + self._set_attr("fieldLabelText", value) + + # help_text + @property + def help_text(self) -> Optional[str]: + return self._get_attr("helpText", def_value=None) + + @help_text.setter + def help_text(self, value: Optional[str]): + self._set_attr("helpText", value) + + # cancel_text + @property + def cancel_text(self) -> Optional[str]: + return self._get_attr("cancelText", def_value=None) + + @cancel_text.setter + def cancel_text(self, value: Optional[str]): + self._set_attr("cancelText", value) + + # confirm_text + @property + def confirm_text(self) -> Optional[str]: + return self._get_attr("confirmText", def_value=None) + + @confirm_text.setter + def confirm_text(self, value: Optional[str]): + self._set_attr("confirmText", value) + + # error_format_text + @property + def error_format_text(self) -> Optional[str]: + return self._get_attr("errorFormatText", def_value=None) + + @error_format_text.setter + def error_format_text(self, value: Optional[str]): + self._set_attr("errorFormatText", value) + + # error_invalid_text + @property + def error_invalid_text(self) -> Optional[str]: + return self._get_attr("errorInvalidText", def_value=None) + + @error_invalid_text.setter + def error_invalid_text(self, value: Optional[str]): + self._set_attr("errorInvalidText", value) + + # keyboard_type + @property + def keyboard_type(self) -> Optional[KeyboardType]: + return self.__keyboard_type + + @keyboard_type.setter + def keyboard_type(self, value: Optional[KeyboardType]): + self.__keyboard_type = value + self._set_attr("keyboardType", value.value if value is not None else None) + + # date_picker_mode + @property + def date_picker_mode(self) -> Optional[DatePickerMode]: + return self.__date_picker_mode + + @date_picker_mode.setter + def date_picker_mode(self, value: Optional[DatePickerMode]): + self.__date_picker_mode = value + self._set_attr("datePickerMode", value.value if value is not None else None) + + # date_picker_entry_mode + @property + def date_picker_entry_mode(self) -> Optional[DatePickerEntryMode]: + return self.__date_picker_entry_mode + + @date_picker_entry_mode.setter + def date_picker_entry_mode(self, value: Optional[DatePickerEntryMode]): + self.__date_picker_entry_mode = value + self._set_attr( + "datePickerEntryMode", value.value if value is not None else None + ) + + # switch_to_calendar_icon + @property + def switch_to_calendar_icon(self): + return self._get_attr("switchToCalendarEntryModeIcon") + + @switch_to_calendar_icon.setter + def switch_to_calendar_icon(self, value): + self._set_attr("switchToCalendarEntryModeIcon", value) + + # switch_to_input_icon + @property + def switch_to_input_icon(self): + return self._get_attr("switchToInputEntryModeIcon") + + @switch_to_input_icon.setter + def switch_to_input_icon(self, value): + self._set_attr("switchToInputEntryModeIcon", value) + + # on_change + @property + def on_change(self): + return self._get_event_handler("change") + + @on_change.setter + def on_change(self, handler): + self._add_event_handler("change", handler) + + # on_dismiss + @property + def on_dismiss(self): + return self._get_event_handler("dismiss") + + @on_dismiss.setter + def on_dismiss(self, handler): + self._add_event_handler("dismiss", handler) From 2cf705c66f8758af0d07e12fc3fcb8431c191d63 Mon Sep 17 00:00:00 2001 From: InesaFitsner Date: Tue, 21 Nov 2023 13:48:19 -0800 Subject: [PATCH 03/10] time_picker_entry_mode property --- package/lib/src/controls/time_picker.dart | 13 +-- .../flet-core/src/flet_core/__init__.py | 2 +- .../flet-core/src/flet_core/date_picker.py | 2 +- .../flet-core/src/flet_core/time_picker.py | 99 ++++--------------- 4 files changed, 25 insertions(+), 91 deletions(-) diff --git a/package/lib/src/controls/time_picker.dart b/package/lib/src/controls/time_picker.dart index 859321e6b..2422de5bd 100644 --- a/package/lib/src/controls/time_picker.dart +++ b/package/lib/src/controls/time_picker.dart @@ -47,19 +47,14 @@ class _TimePickerControlState extends State { String? errorInvalidText = widget.control.attrString("errorInvalidText"); TextInputType keyboardType = parseTextInputType(widget.control.attrString("keyboardType", "")!); - DatePickerMode datePickerMode = DatePickerMode.values.firstWhere( - (a) => - a.name.toLowerCase() == - widget.control.attrString("datePickerMode", "")!.toLowerCase(), - orElse: () => DatePickerMode.day); - DatePickerEntryMode datePickerEntryMode = DatePickerEntryMode.values + TimePickerEntryMode timePickerEntryMode = TimePickerEntryMode.values .firstWhere( (a) => a.name.toLowerCase() == widget.control - .attrString("datePickerEntryMode", "")! + .attrString("timePickerEntryMode", "")! .toLowerCase(), - orElse: () => DatePickerEntryMode.calendar); + orElse: () => TimePickerEntryMode.dial); String? fieldHintText = widget.control.attrString("fieldHintText"); String? fieldLabelText = widget.control.attrString("fieldLabelText"); IconData? switchToCalendarEntryModeIcon = getMaterialIcon( @@ -113,7 +108,7 @@ class _TimePickerControlState extends State { errorInvalidText: errorInvalidText, //keyboardType: keyboardType, //initialCalendarMode: datePickerMode, - initialEntryMode: TimePickerEntryMode.input, + initialEntryMode: timePickerEntryMode, //fieldHintText: fieldHintText, //fieldLabelText: fieldLabelText, //switchToCalendarEntryModeIcon: switchToCalendarEntryModeIcon != null diff --git a/sdk/python/packages/flet-core/src/flet_core/__init__.py b/sdk/python/packages/flet-core/src/flet_core/__init__.py index d6567133a..81ad3b07a 100644 --- a/sdk/python/packages/flet-core/src/flet_core/__init__.py +++ b/sdk/python/packages/flet-core/src/flet_core/__init__.py @@ -177,7 +177,7 @@ TextField, TextOnlyInputFilter, ) -from flet_core.time_picker import TimePicker +from flet_core.time_picker import TimePicker, TimePickerEntryMode from flet_core.theme import ( ColorScheme, PageTransitionsTheme, diff --git a/sdk/python/packages/flet-core/src/flet_core/date_picker.py b/sdk/python/packages/flet-core/src/flet_core/date_picker.py index 032a433d4..df50cffc9 100644 --- a/sdk/python/packages/flet-core/src/flet_core/date_picker.py +++ b/sdk/python/packages/flet-core/src/flet_core/date_picker.py @@ -32,7 +32,7 @@ class DatePicker(Control): It is added to [`page.overlay`](page#overlay) and called using its `pick_date()` method. - Depending on the `date_picker_mode`, it will show either a Calendar or an Input (TextField) for picking a date. + Depending on the `date_picker_entry_mode`, it will show either a Calendar or an Input (TextField) for picking a date. Example: ``` diff --git a/sdk/python/packages/flet-core/src/flet_core/time_picker.py b/sdk/python/packages/flet-core/src/flet_core/time_picker.py index a9a054f6a..78a57c426 100644 --- a/sdk/python/packages/flet-core/src/flet_core/time_picker.py +++ b/sdk/python/packages/flet-core/src/flet_core/time_picker.py @@ -14,62 +14,33 @@ from typing_extensions import Literal -class DatePickerMode(Enum): - DAY = "day" - YEAR = "year" +# class DatePickerMode(Enum): +# DAY = "day" +# YEAR = "year" -class DatePickerEntryMode(Enum): - CALENDAR = "calendar" +class TimePickerEntryMode(Enum): + DIAL = "dial" INPUT = "input" - CALENDAR_ONLY = "calendarOnly" + DIAL_ONLY = "dialOnly" INPUT_ONLY = "inputOnly" class TimePicker(Control): """ - A Material-style date picker dialog. + A Material-style time picker dialog. - It is added to [`page.overlay`](page#overlay) and called using its `pick_date()` method. + It is added to [`page.overlay`](page#overlay) and called using its `pick_time()` method. - Depending on the `date_picker_mode`, it will show either a Calendar or an Input (TextField) for picking a date. + Depending on the `time_picker_mode`, it will show either a Dial or an Input (TextField) for picking a time. Example: ``` - import datetime - import flet as ft - - def main(page: ft.Page): - def change_date(e): - print(f"Date picker changed, value is {date_picker.value}") - - def date_picker_dismissed(e): - print(f"Date picker dismissed, value is {date_picker.value}") - - date_picker = ft.DatePicker( - on_change=change_date, - on_dismiss=date_picker_dismissed, - first_date=datetime.datetime(2023, 10, 1), - last_date=datetime.datetime(2024, 10, 1), - ) - - page.overlay.append(date_picker) - - date_button = ft.ElevatedButton( - "Pick date", - icon=ft.icons.CALENDAR_MONTH, - on_click=lambda _: date_picker.pick_date(), - ) - - page.add(date_button) - - - ft.app(target=main) ``` ----- - Online docs: https://flet.dev/docs/controls/date_picker + Online docs: https://flet.dev/docs/controls/time_picker """ def __init__( @@ -89,8 +60,7 @@ def __init__( last_date: Optional[datetime] = None, current_date: Optional[datetime] = None, keyboard_type: Optional[KeyboardType] = None, - date_picker_mode: Optional[DatePickerMode] = None, - date_picker_entry_mode: Optional[DatePickerEntryMode] = None, + time_picker_entry_mode: Optional[TimePickerEntryMode] = None, # locale: Optional[str] = None, help_text: Optional[str] = None, cancel_text: Optional[str] = None, @@ -126,8 +96,7 @@ def __init__( self.confirm_text = confirm_text self.error_format_text = error_format_text self.error_invalid_text = error_invalid_text - self.date_picker_mode = date_picker_mode - self.date_picker_entry_mode = date_picker_entry_mode + self.time_picker_entry_mode = time_picker_entry_mode self.text_style = text_style self.field_hint_text = field_hint_text self.field_label_text = field_label_text @@ -217,16 +186,6 @@ def current_date(self, value: Optional[Union[datetime, str]]): value = value.isoformat() self._set_attr("currentDate", value) - # # locale - # @property - # def locale(self) -> Optional[str]: - # return self._get_attr("locale", def_value=None) - - # @locale.setter - # def locale(self, value: Optional[str]): - # self._set_attr("locale", value) - - # field_hint_text @property def field_hint_text(self) -> Optional[str]: return self._get_attr("fieldHintText", def_value=None) @@ -289,36 +248,16 @@ def error_invalid_text(self) -> Optional[str]: def error_invalid_text(self, value: Optional[str]): self._set_attr("errorInvalidText", value) - # keyboard_type - @property - def keyboard_type(self) -> Optional[KeyboardType]: - return self.__keyboard_type - - @keyboard_type.setter - def keyboard_type(self, value: Optional[KeyboardType]): - self.__keyboard_type = value - self._set_attr("keyboardType", value.value if value is not None else None) - - # date_picker_mode - @property - def date_picker_mode(self) -> Optional[DatePickerMode]: - return self.__date_picker_mode - - @date_picker_mode.setter - def date_picker_mode(self, value: Optional[DatePickerMode]): - self.__date_picker_mode = value - self._set_attr("datePickerMode", value.value if value is not None else None) - - # date_picker_entry_mode + # time_picker_entry_mode @property - def date_picker_entry_mode(self) -> Optional[DatePickerEntryMode]: - return self.__date_picker_entry_mode + def time_picker_entry_mode(self) -> Optional[TimePickerEntryMode]: + return self.__time_picker_entry_mode - @date_picker_entry_mode.setter - def date_picker_entry_mode(self, value: Optional[DatePickerEntryMode]): - self.__date_picker_entry_mode = value + @time_picker_entry_mode.setter + def time_picker_entry_mode(self, value: Optional[TimePickerEntryMode]): + self.__time_picker_entry_mode = value self._set_attr( - "datePickerEntryMode", value.value if value is not None else None + "timePickerEntryMode", value.value if value is not None else None ) # switch_to_calendar_icon From 7c8b5a098ab572dcf733409d89dd9ba1467a2d15 Mon Sep 17 00:00:00 2001 From: InesaFitsner Date: Thu, 23 Nov 2023 09:53:06 -0800 Subject: [PATCH 04/10] value error fixed for on_change --- package/lib/src/controls/time_picker.dart | 24 ++++-- package/lib/src/models/control.dart | 12 +++ .../flet-core/src/flet_core/time_picker.py | 86 ++++--------------- 3 files changed, 44 insertions(+), 78 deletions(-) diff --git a/package/lib/src/controls/time_picker.dart b/package/lib/src/controls/time_picker.dart index 2422de5bd..e21c80d72 100644 --- a/package/lib/src/controls/time_picker.dart +++ b/package/lib/src/controls/time_picker.dart @@ -35,7 +35,7 @@ class _TimePickerControlState extends State { bool lastOpen = widget.control.state["open"] ?? false; var open = widget.control.attrBool("open", false)!; - DateTime? value = widget.control.attrDateTime("value"); + TimeOfDay? value = widget.control.attrTime("value"); DateTime? firstDate = widget.control.attrDateTime("firstDate"); DateTime? lastDate = widget.control.attrDateTime("lastDate"); DateTime? currentDate = widget.control.attrDateTime("currentDate"); @@ -69,15 +69,22 @@ class _TimePickerControlState extends State { // //locale = Locale(localeString); // } - void onClosed(DateTime? dateValue) { + void onClosed(TimeOfDay? timeValue) { String stringValue; String eventName; - if (dateValue == null) { - stringValue = - value?.toIso8601String() ?? currentDate?.toIso8601String() ?? ""; + if (timeValue == null) { + // stringValue = + // value?.toIso8601String() ?? currentDate?.toIso8601String() ?? ""; + // stringValue = value?.toString() ?? TimeOfDay.now().toString(); + String? hourString = value?.hour.toString(); + String? minuteString = value?.minute.toString(); + stringValue = '$hourString:$minuteString'; eventName = "dismiss"; } else { - stringValue = dateValue.toIso8601String(); + String? hourString = timeValue.hour.toString(); + String? minuteString = timeValue.minute.toString(); + stringValue = '$hourString:$minuteString'; + //stringValue = timeValue.toString(); eventName = "change"; } widget.control.state["open"] = false; @@ -96,7 +103,7 @@ class _TimePickerControlState extends State { Widget createSelectDateDialog() { Widget dialog = TimePickerDialog( - initialTime: TimeOfDay.now(), + initialTime: value ?? TimeOfDay.now(), //initialDate: value ?? currentDate ?? DateTime.now(), //firstDate: firstDate ?? DateTime(1900), //lastDate: lastDate ?? DateTime(2050), @@ -132,7 +139,8 @@ class _TimePickerControlState extends State { widget.control.state["open"] = open; WidgetsBinding.instance.addPostFrameCallback((_) { - showDialog( + //showDialog( + showDialog( context: context, builder: (context) => createSelectDateDialog()).then((result) { debugPrint("pickDate() completed"); diff --git a/package/lib/src/models/control.dart b/package/lib/src/models/control.dart index 9de0569ec..ca7de59ef 100644 --- a/package/lib/src/models/control.dart +++ b/package/lib/src/models/control.dart @@ -1,4 +1,6 @@ import 'package:equatable/equatable.dart'; +import 'package:flutter/material.dart'; +//import 'package:flutter/src/material/time.dart'; class Control extends Equatable { static const reservedProps = ['i', 'p', 't', 'c', 'n']; @@ -96,6 +98,16 @@ class Control extends Equatable { return DateTime.parse(value); } + TimeOfDay? attrTime(String name, [TimeOfDay? defValue]) { + var value = attrs[name.toLowerCase()]; + if (value == null) { + return defValue; + } + List splitted = value.split(':'); + return TimeOfDay( + hour: int.parse(splitted[0]), minute: int.parse(splitted[1])); + } + Control copyWith( {String? id, String? pid, diff --git a/sdk/python/packages/flet-core/src/flet_core/time_picker.py b/sdk/python/packages/flet-core/src/flet_core/time_picker.py index 78a57c426..6471009c4 100644 --- a/sdk/python/packages/flet-core/src/flet_core/time_picker.py +++ b/sdk/python/packages/flet-core/src/flet_core/time_picker.py @@ -1,4 +1,4 @@ -from datetime import date, datetime +from datetime import time from enum import Enum from typing import Any, Optional, Union @@ -8,16 +8,6 @@ from flet_core.textfield import KeyboardType, KeyboardTypeString from flet_core.types import ResponsiveNumber -try: - from typing import Literal -except ImportError: - from typing_extensions import Literal - - -# class DatePickerMode(Enum): -# DAY = "day" -# YEAR = "year" - class TimePickerEntryMode(Enum): DIAL = "dial" @@ -54,11 +44,8 @@ def __init__( disabled: Optional[bool] = None, data: Any = None, open: bool = False, - value: Optional[datetime] = None, + value: Optional[time] = None, text_style: Optional[TextStyle] = None, - first_date: Optional[datetime] = None, - last_date: Optional[datetime] = None, - current_date: Optional[datetime] = None, keyboard_type: Optional[KeyboardType] = None, time_picker_entry_mode: Optional[TimePickerEntryMode] = None, # locale: Optional[str] = None, @@ -86,9 +73,6 @@ def __init__( data=data, ) self.value = value - self.first_date = first_date - self.last_date = last_date - self.current_date = current_date self.keyboard_type = keyboard_type # self.locale = locale self.help_text = help_text @@ -112,11 +96,11 @@ def _get_control_name(self): def _before_build_command(self): super()._before_build_command() - def pick_date(self): + def pick_time(self): self.open = True self.update() - async def pick_date_async(self): + async def pick_time_async(self): self.open = True await self.update_async() @@ -131,61 +115,23 @@ def open(self, value: Optional[bool]): # value @property - def value(self) -> Optional[datetime]: + def value(self) -> Optional[time]: value_string = self._get_attr("value", def_value=None) - return datetime.fromisoformat(value_string) if value_string else None + splitted = value_string.split(":") + return ( + time(hour=int(splitted[0]), minute=int(splitted[1])) + if value_string + else None + ) + # return time.fromisoformat(value_string) if value_string else None @value.setter - def value(self, value: Optional[Union[datetime, str]]): - if isinstance(value, (date, datetime)): - value = value.isoformat() + def value(self, value: Optional[Union[time, str]]): + if isinstance(value, (time)): + # value = value.isoformat() + value = value.strftime("%H:%M") self._set_attr("value", value) - # first_date - @property - def first_date(self) -> Optional[datetime]: - value_string = self._get_attr("firstDate", def_value=None) - if value_string is None: - return None - else: - return datetime.fromisoformat(value_string) - - @first_date.setter - def first_date(self, value: Optional[Union[datetime, str]]): - if isinstance(value, (date, datetime)): - value = value.isoformat() - self._set_attr("firstDate", value) - - # last_date - @property - def last_date(self) -> Optional[datetime]: - value_string = self._get_attr("lastDate", def_value=None) - if value_string is None: - return None - else: - return datetime.fromisoformat(value_string) - - @last_date.setter - def last_date(self, value: Optional[Union[datetime, str]]): - if isinstance(value, (date, datetime)): - value = value.isoformat() - self._set_attr("lastDate", value) - - # current_date - @property - def current_date(self) -> Optional[datetime]: - value_string = self._get_attr("currentDate", def_value=None) - if value_string is None: - return None - else: - return datetime.fromisoformat(value_string) - - @current_date.setter - def current_date(self, value: Optional[Union[datetime, str]]): - if isinstance(value, (date, datetime)): - value = value.isoformat() - self._set_attr("currentDate", value) - @property def field_hint_text(self) -> Optional[str]: return self._get_attr("fieldHintText", def_value=None) From a964bb121f40c770b15ef7068e011451286995a8 Mon Sep 17 00:00:00 2001 From: InesaFitsner Date: Thu, 23 Nov 2023 09:58:28 -0800 Subject: [PATCH 05/10] fixed value for on_dismiss --- package/lib/src/controls/time_picker.dart | 21 ++------------------- 1 file changed, 2 insertions(+), 19 deletions(-) diff --git a/package/lib/src/controls/time_picker.dart b/package/lib/src/controls/time_picker.dart index e21c80d72..d7f291bb9 100644 --- a/package/lib/src/controls/time_picker.dart +++ b/package/lib/src/controls/time_picker.dart @@ -35,18 +35,12 @@ class _TimePickerControlState extends State { bool lastOpen = widget.control.state["open"] ?? false; var open = widget.control.attrBool("open", false)!; - TimeOfDay? value = widget.control.attrTime("value"); - DateTime? firstDate = widget.control.attrDateTime("firstDate"); - DateTime? lastDate = widget.control.attrDateTime("lastDate"); - DateTime? currentDate = widget.control.attrDateTime("currentDate"); - //String? localeString = widget.control.attrString("locale"); + TimeOfDay value = widget.control.attrTime("value") ?? TimeOfDay.now(); String? helpText = widget.control.attrString("helpText"); String? cancelText = widget.control.attrString("cancelText"); String? confirmText = widget.control.attrString("confirmText"); String? errorFormatText = widget.control.attrString("errorFormatText"); String? errorInvalidText = widget.control.attrString("errorInvalidText"); - TextInputType keyboardType = - parseTextInputType(widget.control.attrString("keyboardType", "")!); TimePickerEntryMode timePickerEntryMode = TimePickerEntryMode.values .firstWhere( (a) => @@ -57,17 +51,6 @@ class _TimePickerControlState extends State { orElse: () => TimePickerEntryMode.dial); String? fieldHintText = widget.control.attrString("fieldHintText"); String? fieldLabelText = widget.control.attrString("fieldLabelText"); - IconData? switchToCalendarEntryModeIcon = getMaterialIcon( - widget.control.attrString("switchToCalendarEntryModeIcon", "")!); - IconData? switchToInputEntryModeIcon = getMaterialIcon( - widget.control.attrString("switchToInputEntryModeIcon", "")!); - - //Locale locale; - // if (localeString == null) { - // locale = Localizations.localeOf(context); - // } else { - // //locale = Locale(localeString); - // } void onClosed(TimeOfDay? timeValue) { String stringValue; @@ -103,7 +86,7 @@ class _TimePickerControlState extends State { Widget createSelectDateDialog() { Widget dialog = TimePickerDialog( - initialTime: value ?? TimeOfDay.now(), + initialTime: value, //initialDate: value ?? currentDate ?? DateTime.now(), //firstDate: firstDate ?? DateTime(1900), //lastDate: lastDate ?? DateTime(2050), From f4ca1e5f182fa6ed205d0b5c88f3626a2efc7d2d Mon Sep 17 00:00:00 2001 From: InesaFitsner Date: Thu, 23 Nov 2023 10:20:40 -0800 Subject: [PATCH 06/10] hour_label_text and minute_label_text --- package/lib/src/controls/time_picker.dart | 7 ++-- .../flet-core/src/flet_core/time_picker.py | 35 ++++++++++--------- 2 files changed, 23 insertions(+), 19 deletions(-) diff --git a/package/lib/src/controls/time_picker.dart b/package/lib/src/controls/time_picker.dart index d7f291bb9..0cd18aef0 100644 --- a/package/lib/src/controls/time_picker.dart +++ b/package/lib/src/controls/time_picker.dart @@ -39,7 +39,8 @@ class _TimePickerControlState extends State { String? helpText = widget.control.attrString("helpText"); String? cancelText = widget.control.attrString("cancelText"); String? confirmText = widget.control.attrString("confirmText"); - String? errorFormatText = widget.control.attrString("errorFormatText"); + String? hourLabelText = widget.control.attrString("hourLabelText"); + String? minuteLabelText = widget.control.attrString("minuteLabelText"); String? errorInvalidText = widget.control.attrString("errorInvalidText"); TimePickerEntryMode timePickerEntryMode = TimePickerEntryMode.values .firstWhere( @@ -49,8 +50,6 @@ class _TimePickerControlState extends State { .attrString("timePickerEntryMode", "")! .toLowerCase(), orElse: () => TimePickerEntryMode.dial); - String? fieldHintText = widget.control.attrString("fieldHintText"); - String? fieldLabelText = widget.control.attrString("fieldLabelText"); void onClosed(TimeOfDay? timeValue) { String stringValue; @@ -94,6 +93,8 @@ class _TimePickerControlState extends State { helpText: helpText, cancelText: cancelText, confirmText: confirmText, + hourLabelText: hourLabelText, + minuteLabelText: minuteLabelText, //errorFormatText: errorFormatText, errorInvalidText: errorInvalidText, //keyboardType: keyboardType, diff --git a/sdk/python/packages/flet-core/src/flet_core/time_picker.py b/sdk/python/packages/flet-core/src/flet_core/time_picker.py index 6471009c4..159062f21 100644 --- a/sdk/python/packages/flet-core/src/flet_core/time_picker.py +++ b/sdk/python/packages/flet-core/src/flet_core/time_picker.py @@ -48,7 +48,8 @@ def __init__( text_style: Optional[TextStyle] = None, keyboard_type: Optional[KeyboardType] = None, time_picker_entry_mode: Optional[TimePickerEntryMode] = None, - # locale: Optional[str] = None, + hour_label_text: Optional[str] = None, + minute_label_text: Optional[str] = None, help_text: Optional[str] = None, cancel_text: Optional[str] = None, confirm_text: Optional[str] = None, @@ -74,12 +75,13 @@ def __init__( ) self.value = value self.keyboard_type = keyboard_type - # self.locale = locale self.help_text = help_text self.cancel_text = cancel_text self.confirm_text = confirm_text self.error_format_text = error_format_text self.error_invalid_text = error_invalid_text + self.hour_label_text = hour_label_text + self.minute_label_text = minute_label_text self.time_picker_entry_mode = time_picker_entry_mode self.text_style = text_style self.field_hint_text = field_hint_text @@ -116,38 +118,39 @@ def open(self, value: Optional[bool]): # value @property def value(self) -> Optional[time]: - value_string = self._get_attr("value", def_value=None) + value_string = self._get_attr( + "value", def_value=None + ) # value_string in comes in format 'HH:MM' splitted = value_string.split(":") return ( time(hour=int(splitted[0]), minute=int(splitted[1])) if value_string else None ) - # return time.fromisoformat(value_string) if value_string else None @value.setter def value(self, value: Optional[Union[time, str]]): if isinstance(value, (time)): - # value = value.isoformat() value = value.strftime("%H:%M") self._set_attr("value", value) + # hour_label_text @property - def field_hint_text(self) -> Optional[str]: - return self._get_attr("fieldHintText", def_value=None) + def hour_label_text(self) -> Optional[str]: + return self._get_attr("hourLabelText", def_value=None) - @field_hint_text.setter - def field_hint_text(self, value: Optional[str]): - self._set_attr("fieldHintText", value) + @hour_label_text.setter + def hour_label_text(self, value: Optional[str]): + self._set_attr("hourLabelText", value) - # field_label_text + # minute_label_text @property - def field_label_text(self) -> Optional[str]: - return self._get_attr("fieldLabelText", def_value=None) + def minute_label_text(self) -> Optional[str]: + return self._get_attr("minuteLabelText", def_value=None) - @field_label_text.setter - def field_label_text(self, value: Optional[str]): - self._set_attr("fieldLabelText", value) + @minute_label_text.setter + def minute_label_text(self, value: Optional[str]): + self._set_attr("minuteLabelText", value) # help_text @property From 8574b4ef546cdb532991d639ee07430a5a27cfda Mon Sep 17 00:00:00 2001 From: InesaFitsner Date: Thu, 23 Nov 2023 10:34:56 -0800 Subject: [PATCH 07/10] remove commented code --- package/lib/src/controls/time_picker.dart | 42 ++++------------------- 1 file changed, 7 insertions(+), 35 deletions(-) diff --git a/package/lib/src/controls/time_picker.dart b/package/lib/src/controls/time_picker.dart index 0cd18aef0..5b0a5c443 100644 --- a/package/lib/src/controls/time_picker.dart +++ b/package/lib/src/controls/time_picker.dart @@ -4,8 +4,6 @@ import '../actions.dart'; import '../flet_app_services.dart'; import '../models/control.dart'; import '../protocol/update_control_props_payload.dart'; -import '../utils/icons.dart'; -import 'form_field.dart'; class TimePickerControl extends StatefulWidget { final Control? parent; @@ -55,18 +53,14 @@ class _TimePickerControlState extends State { String stringValue; String eventName; if (timeValue == null) { - // stringValue = - // value?.toIso8601String() ?? currentDate?.toIso8601String() ?? ""; - // stringValue = value?.toString() ?? TimeOfDay.now().toString(); - String? hourString = value?.hour.toString(); - String? minuteString = value?.minute.toString(); + String hourString = value.hour.toString(); + String minuteString = value.minute.toString(); stringValue = '$hourString:$minuteString'; eventName = "dismiss"; } else { - String? hourString = timeValue.hour.toString(); - String? minuteString = timeValue.minute.toString(); + String hourString = timeValue.hour.toString(); + String minuteString = timeValue.minute.toString(); stringValue = '$hourString:$minuteString'; - //stringValue = timeValue.toString(); eventName = "change"; } widget.control.state["open"] = false; @@ -83,39 +77,18 @@ class _TimePickerControlState extends State { eventData: stringValue); } - Widget createSelectDateDialog() { + Widget createSelectTimeDialog() { Widget dialog = TimePickerDialog( initialTime: value, - //initialDate: value ?? currentDate ?? DateTime.now(), - //firstDate: firstDate ?? DateTime(1900), - //lastDate: lastDate ?? DateTime(2050), - //currentDate: currentDate ?? DateTime.now(), helpText: helpText, cancelText: cancelText, confirmText: confirmText, hourLabelText: hourLabelText, minuteLabelText: minuteLabelText, - //errorFormatText: errorFormatText, errorInvalidText: errorInvalidText, - //keyboardType: keyboardType, - //initialCalendarMode: datePickerMode, initialEntryMode: timePickerEntryMode, - //fieldHintText: fieldHintText, - //fieldLabelText: fieldLabelText, - //switchToCalendarEntryModeIcon: switchToCalendarEntryModeIcon != null - // ? Icon(switchToCalendarEntryModeIcon) - // : null, - //switchToInputEntryModeIcon: switchToInputEntryModeIcon != null - // ? Icon(switchToInputEntryModeIcon) - // : null, ); - // dialog = Localizations.override( - // context: context, - // locale: locale, - // child: dialog, - // ); - return dialog; } @@ -123,11 +96,10 @@ class _TimePickerControlState extends State { widget.control.state["open"] = open; WidgetsBinding.instance.addPostFrameCallback((_) { - //showDialog( showDialog( context: context, - builder: (context) => createSelectDateDialog()).then((result) { - debugPrint("pickDate() completed"); + builder: (context) => createSelectTimeDialog()).then((result) { + debugPrint("pickTime() completed"); onClosed(result); }); }); From 65b4a1ab357749518f5b85dd1f3999fb602a508b Mon Sep 17 00:00:00 2001 From: InesaFitsner Date: Thu, 23 Nov 2023 10:40:20 -0800 Subject: [PATCH 08/10] refactor --- .../flet-core/src/flet_core/time_picker.py | 49 +------------------ 1 file changed, 2 insertions(+), 47 deletions(-) diff --git a/sdk/python/packages/flet-core/src/flet_core/time_picker.py b/sdk/python/packages/flet-core/src/flet_core/time_picker.py index 159062f21..a897b815b 100644 --- a/sdk/python/packages/flet-core/src/flet_core/time_picker.py +++ b/sdk/python/packages/flet-core/src/flet_core/time_picker.py @@ -4,8 +4,7 @@ from flet_core.control import Control, OptionalNumber from flet_core.ref import Ref -from flet_core.text_style import TextStyle -from flet_core.textfield import KeyboardType, KeyboardTypeString + from flet_core.types import ResponsiveNumber @@ -22,7 +21,7 @@ class TimePicker(Control): It is added to [`page.overlay`](page#overlay) and called using its `pick_time()` method. - Depending on the `time_picker_mode`, it will show either a Dial or an Input (TextField) for picking a time. + Depending on the `time_picker_mode`, it will show either a Dial or an Input (hour and minute text fields) for picking a time. Example: ``` @@ -45,20 +44,13 @@ def __init__( data: Any = None, open: bool = False, value: Optional[time] = None, - text_style: Optional[TextStyle] = None, - keyboard_type: Optional[KeyboardType] = None, time_picker_entry_mode: Optional[TimePickerEntryMode] = None, hour_label_text: Optional[str] = None, minute_label_text: Optional[str] = None, help_text: Optional[str] = None, cancel_text: Optional[str] = None, confirm_text: Optional[str] = None, - error_format_text: Optional[str] = None, error_invalid_text: Optional[str] = None, - field_hint_text: Optional[str] = None, - field_label_text: Optional[str] = None, - switch_to_calendar_icon: Optional[str] = None, - switch_to_input_icon: Optional[str] = None, on_change=None, on_dismiss=None, ): @@ -74,20 +66,13 @@ def __init__( data=data, ) self.value = value - self.keyboard_type = keyboard_type self.help_text = help_text self.cancel_text = cancel_text self.confirm_text = confirm_text - self.error_format_text = error_format_text self.error_invalid_text = error_invalid_text self.hour_label_text = hour_label_text self.minute_label_text = minute_label_text self.time_picker_entry_mode = time_picker_entry_mode - self.text_style = text_style - self.field_hint_text = field_hint_text - self.field_label_text = field_label_text - self.switch_to_calendar_icon = switch_to_calendar_icon - self.switch_to_input_icon = switch_to_input_icon self.on_change = on_change self.on_dismiss = on_dismiss self.open = open @@ -95,9 +80,6 @@ def __init__( def _get_control_name(self): return "timepicker" - def _before_build_command(self): - super()._before_build_command() - def pick_time(self): self.open = True self.update() @@ -179,15 +161,6 @@ def confirm_text(self) -> Optional[str]: def confirm_text(self, value: Optional[str]): self._set_attr("confirmText", value) - # error_format_text - @property - def error_format_text(self) -> Optional[str]: - return self._get_attr("errorFormatText", def_value=None) - - @error_format_text.setter - def error_format_text(self, value: Optional[str]): - self._set_attr("errorFormatText", value) - # error_invalid_text @property def error_invalid_text(self) -> Optional[str]: @@ -209,24 +182,6 @@ def time_picker_entry_mode(self, value: Optional[TimePickerEntryMode]): "timePickerEntryMode", value.value if value is not None else None ) - # switch_to_calendar_icon - @property - def switch_to_calendar_icon(self): - return self._get_attr("switchToCalendarEntryModeIcon") - - @switch_to_calendar_icon.setter - def switch_to_calendar_icon(self, value): - self._set_attr("switchToCalendarEntryModeIcon", value) - - # switch_to_input_icon - @property - def switch_to_input_icon(self): - return self._get_attr("switchToInputEntryModeIcon") - - @switch_to_input_icon.setter - def switch_to_input_icon(self, value): - self._set_attr("switchToInputEntryModeIcon", value) - # on_change @property def on_change(self): From 59230241f97a0500c8b7024203b7ce2cb3394821 Mon Sep 17 00:00:00 2001 From: InesaFitsner Date: Thu, 23 Nov 2023 10:43:23 -0800 Subject: [PATCH 09/10] example code added --- .../flet-core/src/flet_core/time_picker.py | 46 +++++++++++++++---- 1 file changed, 38 insertions(+), 8 deletions(-) diff --git a/sdk/python/packages/flet-core/src/flet_core/time_picker.py b/sdk/python/packages/flet-core/src/flet_core/time_picker.py index a897b815b..158f066ea 100644 --- a/sdk/python/packages/flet-core/src/flet_core/time_picker.py +++ b/sdk/python/packages/flet-core/src/flet_core/time_picker.py @@ -17,19 +17,49 @@ class TimePickerEntryMode(Enum): class TimePicker(Control): """ - A Material-style time picker dialog. + A Material-style time picker dialog. - It is added to [`page.overlay`](page#overlay) and called using its `pick_time()` method. + It is added to [`page.overlay`](page#overlay) and called using its `pick_time()` method. - Depending on the `time_picker_mode`, it will show either a Dial or an Input (hour and minute text fields) for picking a time. + Depending on the `time_picker_mode`, it will show either a Dial or an Input (hour and minute text fields) for picking a time. - Example: - ``` - ``` + Example: + ``` + import datetime + import flet as ft - ----- + def main(page: ft.Page): + def change_time(e): + print(f"Time picker changed, value (minute) is {time_picker.value.minute}") - Online docs: https://flet.dev/docs/controls/time_picker + def dismissed(e): + print(f"Time picker dismissed, value is {time_picker.value}") + + time_picker = ft.TimePicker( + confirm_text="Confirm", + error_invalid_text="Time out of range", + help_text="Pick your time slot", + on_change=change_time, + on_dismiss=dismissed, + ) + + page.overlay.append(time_picker) + + date_button = ft.ElevatedButton( + "Pick time", + icon=ft.icons.TIME_TO_LEAVE, + on_click=lambda _: time_picker.pick_time(), + ) + + page.add(date_button) + + + ft.app(target=main) + ``` + + ----- + + Online docs: https://flet.dev/docs/controls/time_picker """ def __init__( From b36f2efeb4d447f7595060205c2f9e4cec8b1207 Mon Sep 17 00:00:00 2001 From: InesaFitsner Date: Thu, 23 Nov 2023 11:23:15 -0800 Subject: [PATCH 10/10] removed commented line --- package/lib/src/models/control.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/package/lib/src/models/control.dart b/package/lib/src/models/control.dart index ca7de59ef..a4f3a15e2 100644 --- a/package/lib/src/models/control.dart +++ b/package/lib/src/models/control.dart @@ -1,6 +1,5 @@ import 'package:equatable/equatable.dart'; import 'package:flutter/material.dart'; -//import 'package:flutter/src/material/time.dart'; class Control extends Equatable { static const reservedProps = ['i', 'p', 't', 'c', 'n'];