From 9088b737bab3d0bf9d1e54e52a6319b9f2ee6075 Mon Sep 17 00:00:00 2001
From: ndonkoHenri <robotcoder4@protonmail.com>
Date: Wed, 20 Dec 2023 17:04:06 +0100
Subject: [PATCH 1/8] create mouse utils

---
 .../lib/src/controls/gesture_detector.dart    | 80 +------------------
 package/lib/src/utils/mouse.dart              | 80 +++++++++++++++++++
 2 files changed, 81 insertions(+), 79 deletions(-)
 create mode 100644 package/lib/src/utils/mouse.dart

diff --git a/package/lib/src/controls/gesture_detector.dart b/package/lib/src/controls/gesture_detector.dart
index 1c642fd2d..0d98a3cf5 100644
--- a/package/lib/src/controls/gesture_detector.dart
+++ b/package/lib/src/controls/gesture_detector.dart
@@ -6,6 +6,7 @@ import 'package:flutter/material.dart';
 
 import '../flet_app_services.dart';
 import '../models/control.dart';
+import '../utils/mouse.dart';
 import 'create_control.dart';
 import 'error.dart';
 
@@ -584,85 +585,6 @@ class _GestureDetectorControlState extends State<GestureDetectorControl> {
 
     return constrainedControl(context, result, widget.parent, widget.control);
   }
-
-  MouseCursor parseMouseCursor(String? cursor) {
-    switch (cursor) {
-      case "alias":
-        return SystemMouseCursors.alias;
-      case "allScroll":
-        return SystemMouseCursors.allScroll;
-      case "basic":
-        return SystemMouseCursors.basic;
-      case "cell":
-        return SystemMouseCursors.cell;
-      case "click":
-        return SystemMouseCursors.click;
-      case "contextMenu":
-        return SystemMouseCursors.contextMenu;
-      case "copy":
-        return SystemMouseCursors.copy;
-      case "disappearing":
-        return SystemMouseCursors.disappearing;
-      case "forbidden":
-        return SystemMouseCursors.forbidden;
-      case "grab":
-        return SystemMouseCursors.grab;
-      case "grabbing":
-        return SystemMouseCursors.grabbing;
-      case "help":
-        return SystemMouseCursors.help;
-      case "move":
-        return SystemMouseCursors.move;
-      case "noDrop":
-        return SystemMouseCursors.noDrop;
-      case "none":
-        return SystemMouseCursors.none;
-      case "precise":
-        return SystemMouseCursors.precise;
-      case "progress":
-        return SystemMouseCursors.progress;
-      case "resizeColumn":
-        return SystemMouseCursors.resizeColumn;
-      case "resizeDown":
-        return SystemMouseCursors.resizeDown;
-      case "resizeDownLeft":
-        return SystemMouseCursors.resizeDownLeft;
-      case "resizeDownRight":
-        return SystemMouseCursors.resizeDownRight;
-      case "resizeLeft":
-        return SystemMouseCursors.resizeLeft;
-      case "resizeLeftRight":
-        return SystemMouseCursors.resizeLeftRight;
-      case "resizeRight":
-        return SystemMouseCursors.resizeRight;
-      case "resizeRow":
-        return SystemMouseCursors.resizeRow;
-      case "resizeUp":
-        return SystemMouseCursors.resizeUp;
-      case "resizeUpDown":
-        return SystemMouseCursors.resizeUpDown;
-      case "resizeUpLeft":
-        return SystemMouseCursors.resizeUpLeft;
-      case "resizeUpLeftDownRight":
-        return SystemMouseCursors.resizeUpLeftDownRight;
-      case "resizeUpRight":
-        return SystemMouseCursors.resizeUpRight;
-      case "resizeUpRightDownLeft":
-        return SystemMouseCursors.resizeUpRightDownLeft;
-      case "text":
-        return SystemMouseCursors.text;
-      case "verticalText":
-        return SystemMouseCursors.verticalText;
-      case "wait":
-        return SystemMouseCursors.wait;
-      case "zoomIn":
-        return SystemMouseCursors.zoomIn;
-      case "zoomOut":
-        return SystemMouseCursors.zoomOut;
-      default:
-        return MouseCursor.defer;
-    }
-  }
 }
 
 class MultiTouchGestureRecognizer extends MultiTapGestureRecognizer {
diff --git a/package/lib/src/utils/mouse.dart b/package/lib/src/utils/mouse.dart
new file mode 100644
index 000000000..7b3c8762e
--- /dev/null
+++ b/package/lib/src/utils/mouse.dart
@@ -0,0 +1,80 @@
+import 'package:flutter/material.dart';
+
+MouseCursor parseMouseCursor(String? cursor) {
+    switch (cursor) {
+      case "alias":
+        return SystemMouseCursors.alias;
+      case "allScroll":
+        return SystemMouseCursors.allScroll;
+      case "basic":
+        return SystemMouseCursors.basic;
+      case "cell":
+        return SystemMouseCursors.cell;
+      case "click":
+        return SystemMouseCursors.click;
+      case "contextMenu":
+        return SystemMouseCursors.contextMenu;
+      case "copy":
+        return SystemMouseCursors.copy;
+      case "disappearing":
+        return SystemMouseCursors.disappearing;
+      case "forbidden":
+        return SystemMouseCursors.forbidden;
+      case "grab":
+        return SystemMouseCursors.grab;
+      case "grabbing":
+        return SystemMouseCursors.grabbing;
+      case "help":
+        return SystemMouseCursors.help;
+      case "move":
+        return SystemMouseCursors.move;
+      case "noDrop":
+        return SystemMouseCursors.noDrop;
+      case "none":
+        return SystemMouseCursors.none;
+      case "precise":
+        return SystemMouseCursors.precise;
+      case "progress":
+        return SystemMouseCursors.progress;
+      case "resizeColumn":
+        return SystemMouseCursors.resizeColumn;
+      case "resizeDown":
+        return SystemMouseCursors.resizeDown;
+      case "resizeDownLeft":
+        return SystemMouseCursors.resizeDownLeft;
+      case "resizeDownRight":
+        return SystemMouseCursors.resizeDownRight;
+      case "resizeLeft":
+        return SystemMouseCursors.resizeLeft;
+      case "resizeLeftRight":
+        return SystemMouseCursors.resizeLeftRight;
+      case "resizeRight":
+        return SystemMouseCursors.resizeRight;
+      case "resizeRow":
+        return SystemMouseCursors.resizeRow;
+      case "resizeUp":
+        return SystemMouseCursors.resizeUp;
+      case "resizeUpDown":
+        return SystemMouseCursors.resizeUpDown;
+      case "resizeUpLeft":
+        return SystemMouseCursors.resizeUpLeft;
+      case "resizeUpLeftDownRight":
+        return SystemMouseCursors.resizeUpLeftDownRight;
+      case "resizeUpRight":
+        return SystemMouseCursors.resizeUpRight;
+      case "resizeUpRightDownLeft":
+        return SystemMouseCursors.resizeUpRightDownLeft;
+      case "text":
+        return SystemMouseCursors.text;
+      case "verticalText":
+        return SystemMouseCursors.verticalText;
+      case "wait":
+        return SystemMouseCursors.wait;
+      case "zoomIn":
+        return SystemMouseCursors.zoomIn;
+      case "zoomOut":
+        return SystemMouseCursors.zoomOut;
+      default:
+        return MouseCursor.defer;
+    }
+  }
\ No newline at end of file

From 2b5344a36a65a54096cc7416980fb241547fddc7 Mon Sep 17 00:00:00 2001
From: ndonkoHenri <robotcoder4@protonmail.com>
Date: Wed, 20 Dec 2023 17:04:38 +0100
Subject: [PATCH 2/8] add .py

---
 .../flet-core/src/flet_core/__init__.py       |   3 +
 .../flet-core/src/flet_core/menu_bar.py       | 144 ++++++++++
 .../src/flet_core/menu_item_button.py         | 245 ++++++++++++++++
 .../flet-core/src/flet_core/submenu_button.py | 265 ++++++++++++++++++
 4 files changed, 657 insertions(+)
 create mode 100644 sdk/python/packages/flet-core/src/flet_core/menu_bar.py
 create mode 100644 sdk/python/packages/flet-core/src/flet_core/menu_item_button.py
 create mode 100644 sdk/python/packages/flet-core/src/flet_core/submenu_button.py

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 3e11bedc1..039a8da23 100644
--- a/sdk/python/packages/flet-core/src/flet_core/__init__.py
+++ b/sdk/python/packages/flet-core/src/flet_core/__init__.py
@@ -21,6 +21,9 @@
 from flet_core.audio import Audio
 from flet_core.badge import Badge
 from flet_core.banner import Banner
+from flet_core.menu_bar import MenuBar, MenuStyle
+from flet_core.submenu_button import SubmenuButton
+from flet_core.menu_item_button import MenuItemButton
 from flet_core.blur import Blur, BlurTileMode
 from flet_core.border import Border, BorderSide
 from flet_core.border_radius import BorderRadius
diff --git a/sdk/python/packages/flet-core/src/flet_core/menu_bar.py b/sdk/python/packages/flet-core/src/flet_core/menu_bar.py
new file mode 100644
index 000000000..7d9425429
--- /dev/null
+++ b/sdk/python/packages/flet-core/src/flet_core/menu_bar.py
@@ -0,0 +1,144 @@
+import dataclasses
+from dataclasses import field
+from typing import Any, List, Optional, Union, Dict
+
+from flet_core.alignment import Alignment
+from flet_core.border import BorderSide
+from flet_core.gesture_detector import MouseCursor
+from flet_core.buttons import OutlinedBorder
+from flet_core.control import Control, OptionalNumber
+from flet_core.ref import Ref
+from flet_core.types import (
+    PaddingValue,
+    ResponsiveNumber,
+    ClipBehavior, MaterialState,
+)
+
+
+@dataclasses.dataclass
+class MenuStyle:
+    alignment: Optional[Alignment] = field(default=None)
+    bgcolor: Union[None, str, Dict[Union[str, MaterialState], str]] = field(
+        default=None
+    )
+    shadow_color: Union[None, str, Dict[Union[str, MaterialState], str]] = field(
+        default=None
+    )
+    surface_tint_color: Union[None, str, Dict[Union[str, MaterialState], str]] = field(
+        default=None
+    )
+    elevation: Union[
+        None, float, int, Dict[Union[str, MaterialState], Union[float, int]]
+    ] = field(default=None)
+    # fixed_size: Union[
+    #     None, float, int, Dict[Union[str, MaterialState], Union[float, int]]
+    # ] = field(default=None)
+    # max_size: Union[
+    #     None, float, int, Dict[Union[str, MaterialState], Union[float, int]]
+    # ] = field(default=None)
+    # min_size: Union[
+    #     None, float, int, Dict[Union[str, MaterialState], Union[float, int]]
+    # ] = field(default=None)
+    padding: Union[PaddingValue, Dict[Union[str, MaterialState], PaddingValue]] = field(
+        default=None
+    )
+    side: Union[None, BorderSide, Dict[Union[str, MaterialState], BorderSide]] = field(
+        default=None
+    )
+    shape: Union[
+        None, OutlinedBorder, Dict[Union[str, MaterialState], OutlinedBorder]
+    ] = field(default=None)
+    mouse_cursor: Union[
+        None, MouseCursor, Dict[Union[str, MaterialState], MouseCursor]
+    ] = field(default=None)
+
+
+class MenuBar(Control):
+    """
+
+
+    ```
+
+    ```
+
+    -----
+
+    Online docs: https://flet.dev/docs/controls/menubar
+    """
+
+    def __init__(
+            self,
+            controls: Optional[List[Control]] = None,
+            ref: Optional[Ref] = None,
+            expand: Union[None, bool, int] = None,
+            col: Optional[ResponsiveNumber] = None,
+            opacity: OptionalNumber = None,
+            visible: Optional[bool] = None,
+            disabled: Optional[bool] = None,
+            data: Any = None,
+            #
+            # Specific
+            #
+            clip_behavior: Optional[ClipBehavior] = None,
+            style: Optional[MenuStyle] = None,
+    ):
+        Control.__init__(
+            self,
+            ref=ref,
+            expand=expand,
+            col=col,
+            opacity=opacity,
+            visible=visible,
+            disabled=disabled,
+            data=data,
+        )
+
+        self.__controls: List[Control] = []
+        self.controls = controls
+        self.clip_behavior = clip_behavior
+        self.style = style
+
+    def _get_control_name(self):
+        return "menubar"
+
+    def _before_build_command(self):
+        super()._before_build_command()
+        if self.__style is not None:
+            self.__style.side = self._wrap_attr_dict(self.__style.side)
+            self.__style.shape = self._wrap_attr_dict(self.__style.shape)
+            self.__style.mouse_cursor = self._wrap_attr_dict(self.__style.mouse_cursor)
+            if self.__style.mouse_cursor:
+                for k, v in self.__style.mouse_cursor.items():
+                    self.__style.mouse_cursor[k] = v.value if isinstance(v, MouseCursor) else str(v)
+        self._set_attr_json("style", self.__style)
+
+    def _get_children(self):
+        return self.__controls
+
+    # controls
+    @property
+    def controls(self):
+        return self.__controls
+
+    @controls.setter
+    def controls(self, value):
+        self.__controls = value if value is not None else []
+
+    # clip_behavior
+    @property
+    def clip_behavior(self) -> Optional[ClipBehavior]:
+        return self.__clip_behavior
+
+    @clip_behavior.setter
+    def clip_behavior(self, value: Optional[ClipBehavior]):
+        self.__clip_behavior = value
+        self._set_attr("clipBehavior", value.value if isinstance(value, ClipBehavior) else value)
+
+    # style
+    @property
+    def style(self) -> Optional[MenuStyle]:
+        return self.__style
+
+    @style.setter
+    def style(self, value: Optional[MenuStyle]):
+        self.__style = value
diff --git a/sdk/python/packages/flet-core/src/flet_core/menu_item_button.py b/sdk/python/packages/flet-core/src/flet_core/menu_item_button.py
new file mode 100644
index 000000000..50b07a261
--- /dev/null
+++ b/sdk/python/packages/flet-core/src/flet_core/menu_item_button.py
@@ -0,0 +1,245 @@
+import time
+from typing import Any, Optional, Union, List
+
+from flet_core.constrained_control import ConstrainedControl
+from flet_core.control import Control, OptionalNumber
+from flet_core.menu_bar import MenuStyle
+from flet_core.buttons import ButtonStyle
+from flet_core.ref import Ref
+from flet_core.types import (
+    AnimationValue,
+    OffsetValue,
+    ResponsiveNumber,
+    RotateValue,
+    ScaleValue,
+    ClipBehavior,
+)
+
+
+class MenuItemButton(ConstrainedControl):
+    """
+
+    -----
+
+    Online docs: https://flet.dev/docs/controls/menuitembutton
+    """
+
+    def __init__(
+            self,
+            content: Optional[Control] = None,
+            ref: Optional[Ref] = None,
+            key: Optional[str] = None,
+            width: OptionalNumber = None,
+            height: OptionalNumber = None,
+            left: OptionalNumber = None,
+            top: OptionalNumber = None,
+            right: OptionalNumber = None,
+            bottom: OptionalNumber = None,
+            expand: Union[None, bool, int] = None,
+            col: Optional[ResponsiveNumber] = None,
+            opacity: OptionalNumber = None,
+            rotate: RotateValue = None,
+            scale: ScaleValue = None,
+            offset: OffsetValue = None,
+            aspect_ratio: OptionalNumber = None,
+            animate_opacity: AnimationValue = None,
+            animate_size: AnimationValue = None,
+            animate_position: AnimationValue = None,
+            animate_rotation: AnimationValue = None,
+            animate_scale: AnimationValue = None,
+            animate_offset: AnimationValue = None,
+            on_animation_end=None,
+            tooltip: Optional[str] = None,
+            visible: Optional[bool] = None,
+            disabled: Optional[bool] = None,
+            data: Any = None,
+            #
+            # Specific
+            #
+            close_on_click: Optional[bool] = None,
+            focus_on_hover: Optional[bool] = None,
+            leading: Optional[Control] = None,
+            trailing: Optional[Control] = None,
+            clip_behavior: Optional[ClipBehavior] = None,
+            style: Optional[ButtonStyle] = None,
+            on_click=None,
+            on_hover=None,
+            on_focus=None,
+            on_blur=None,
+    ):
+        ConstrainedControl.__init__(
+            self,
+            ref=ref,
+            key=key,
+            width=width,
+            height=height,
+            left=left,
+            top=top,
+            right=right,
+            bottom=bottom,
+            expand=expand,
+            col=col,
+            opacity=opacity,
+            rotate=rotate,
+            scale=scale,
+            offset=offset,
+            aspect_ratio=aspect_ratio,
+            animate_opacity=animate_opacity,
+            animate_size=animate_size,
+            animate_position=animate_position,
+            animate_rotation=animate_rotation,
+            animate_scale=animate_scale,
+            animate_offset=animate_offset,
+            on_animation_end=on_animation_end,
+            tooltip=tooltip,
+            visible=visible,
+            disabled=disabled,
+            data=data,
+        )
+
+        self.content = content
+        self.leading = leading
+        self.trailing = trailing
+        self.clip_behavior = clip_behavior
+        self.style = style
+        self.close_on_click = close_on_click
+        self.focus_on_hover = focus_on_hover
+        self.on_click = on_click
+        self.on_hover = on_hover
+        self.on_focus = on_focus
+        self.on_blur = on_blur
+
+    def _get_control_name(self):
+        return "menuitembutton"
+
+    def _before_build_command(self):
+        super()._before_build_command()
+        if self.__style is not None:
+            self.__style.side = self._wrap_attr_dict(self.__style.side)
+            self.__style.shape = self._wrap_attr_dict(self.__style.shape)
+        self._set_attr_json("style", self.__style)
+
+    def _get_children(self):
+        children = []
+        if self.__leading:
+            self.__leading._set_attr_internal("n", "leading")
+            children.append(self.__leading)
+        if self.__trailing:
+            self.__trailing._set_attr_internal("n", "trailing")
+            children.append(self.__trailing)
+        if self.__content:
+            self.__content._set_attr_internal("n", "content")
+            children.append(self.__content)
+        return children
+
+    def focus(self):
+        self._set_attr_json("focus", str(time.time()))
+        self.update()
+
+    async def focus_async(self):
+        self._set_attr_json("focus", str(time.time()))
+        await self.update_async()
+
+    # focus_on_hover
+    @property
+    def focus_on_hover(self) -> Optional[bool]:
+        return self._get_attr("focusOnHover", data_type="bool", def_value=True)
+
+    @focus_on_hover.setter
+    def focus_on_hover(self, value: Optional[bool]):
+        self._set_attr("focusOnHover", value)
+
+    # close_on_click
+    @property
+    def close_on_click(self) -> Optional[bool]:
+        return self._get_attr("closeOnClick", data_type="bool", def_value=True)
+
+    @close_on_click.setter
+    def close_on_click(self, value: Optional[bool]):
+        self._set_attr("closeOnClick", value)
+
+    # leading
+    @property
+    def leading(self) -> Optional[Control]:
+        return self.__leading
+
+    @leading.setter
+    def leading(self, value: Optional[Control]):
+        self.__leading = value
+
+    # trailing
+    @property
+    def trailing(self) -> Optional[Control]:
+        return self.__trailing
+
+    @trailing.setter
+    def trailing(self, value: Optional[Control]):
+        self.__trailing = value
+
+    # content
+    @property
+    def content(self) -> Optional[Control]:
+        return self.__content
+
+    @content.setter
+    def content(self, value: Optional[Control]):
+        self.__content = value
+
+    # style
+    @property
+    def style(self) -> Optional[ButtonStyle]:
+        return self.__style
+
+    @style.setter
+    def style(self, value: Optional[ButtonStyle]):
+        self.__style = value
+
+    # clip_behavior
+    @property
+    def clip_behavior(self) -> Optional[ClipBehavior]:
+        return self.__clip_behavior
+
+    @clip_behavior.setter
+    def clip_behavior(self, value: Optional[ClipBehavior]):
+        self.__clip_behavior = value
+        self._set_attr(
+            "clipBehavior", value.value if isinstance(value, ClipBehavior) else value
+        )
+
+    # on_click
+    @property
+    def on_click(self):
+        return self._get_event_handler("click")
+
+    @on_click.setter
+    def on_click(self, handler):
+        self._add_event_handler("click", handler)
+        self._set_attr("onClick", True if handler is not None else None)
+
+    # on_hover
+    @property
+    def on_hover(self):
+        return self._get_event_handler("hover")
+
+    @on_hover.setter
+    def on_hover(self, handler):
+        self._add_event_handler("hover", handler)
+        self._set_attr("onHover", True if handler is not None else None)
+
+    # on_focus
+    @property
+    def on_focus(self):
+        return self._get_event_handler("focus")
+
+    @on_focus.setter
+    def on_focus(self, handler):
+        self._add_event_handler("focus", handler)
+
+    # on_blur
+    @property
+    def on_blur(self):
+        return self._get_event_handler("blur")
+
+    @on_blur.setter
+    def on_blur(self, handler):
+        self._add_event_handler("blur", handler)
\ No newline at end of file
diff --git a/sdk/python/packages/flet-core/src/flet_core/submenu_button.py b/sdk/python/packages/flet-core/src/flet_core/submenu_button.py
new file mode 100644
index 000000000..b2c974622
--- /dev/null
+++ b/sdk/python/packages/flet-core/src/flet_core/submenu_button.py
@@ -0,0 +1,265 @@
+import time
+from typing import Any, Optional, Union, List
+
+from flet_core.constrained_control import ConstrainedControl
+from flet_core.control import Control, OptionalNumber
+from flet_core.menu_bar import MenuStyle
+from flet_core.buttons import ButtonStyle
+from flet_core.ref import Ref
+from flet_core.types import (
+    AnimationValue,
+    OffsetValue,
+    ResponsiveNumber,
+    RotateValue,
+    ScaleValue,
+    ClipBehavior,
+)
+
+
+class SubmenuButton(ConstrainedControl):
+    """
+
+    -----
+
+    Online docs: https://flet.dev/docs/controls/submenubutton
+    """
+
+    def __init__(
+            self,
+            content: Optional[Control] = None,
+            controls: Optional[List[Control]] = None,
+            ref: Optional[Ref] = None,
+            key: Optional[str] = None,
+            width: OptionalNumber = None,
+            height: OptionalNumber = None,
+            left: OptionalNumber = None,
+            top: OptionalNumber = None,
+            right: OptionalNumber = None,
+            bottom: OptionalNumber = None,
+            expand: Union[None, bool, int] = None,
+            col: Optional[ResponsiveNumber] = None,
+            opacity: OptionalNumber = None,
+            rotate: RotateValue = None,
+            scale: ScaleValue = None,
+            offset: OffsetValue = None,
+            aspect_ratio: OptionalNumber = None,
+            animate_opacity: AnimationValue = None,
+            animate_size: AnimationValue = None,
+            animate_position: AnimationValue = None,
+            animate_rotation: AnimationValue = None,
+            animate_scale: AnimationValue = None,
+            animate_offset: AnimationValue = None,
+            on_animation_end=None,
+            tooltip: Optional[str] = None,
+            visible: Optional[bool] = None,
+            disabled: Optional[bool] = None,
+            data: Any = None,
+            #
+            # Specific
+            #
+            leading: Optional[Control] = None,
+            trailing: Optional[Control] = None,
+            clip_behavior: Optional[ClipBehavior] = None,
+            menu_style: Optional[MenuStyle] = None,
+            style: Optional[ButtonStyle] = None,
+            on_open=None,
+            on_close=None,
+            on_hover=None,
+            on_focus=None,
+            on_blur=None,
+    ):
+        ConstrainedControl.__init__(
+            self,
+            ref=ref,
+            key=key,
+            width=width,
+            height=height,
+            left=left,
+            top=top,
+            right=right,
+            bottom=bottom,
+            expand=expand,
+            col=col,
+            opacity=opacity,
+            rotate=rotate,
+            scale=scale,
+            offset=offset,
+            aspect_ratio=aspect_ratio,
+            animate_opacity=animate_opacity,
+            animate_size=animate_size,
+            animate_position=animate_position,
+            animate_rotation=animate_rotation,
+            animate_scale=animate_scale,
+            animate_offset=animate_offset,
+            on_animation_end=on_animation_end,
+            tooltip=tooltip,
+            visible=visible,
+            disabled=disabled,
+            data=data,
+        )
+
+        self.content = content
+        self.controls = controls
+        self.leading = leading
+        self.trailing = trailing
+        self.clip_behavior = clip_behavior
+        self.style = style
+        self.menu_style = menu_style
+        self.on_open = on_open
+        self.on_close = on_close
+        self.on_hover = on_hover
+        self.on_focus = on_focus
+        self.on_blur = on_blur
+
+    def _get_control_name(self):
+        return "submenubutton"
+
+    def _before_build_command(self):
+        super()._before_build_command()
+        if self.__style is not None:
+            self.__style.side = self._wrap_attr_dict(self.__style.side)
+            self.__style.shape = self._wrap_attr_dict(self.__style.shape)
+        if self.__menu_style is not None:
+            self.__menu_style.side = self._wrap_attr_dict(self.__menu_style.side)
+            self.__menu_style.shape = self._wrap_attr_dict(self.__menu_style.shape)
+        self._set_attr_json("style", self.__style)
+        self._set_attr_json("menuStyle", self.__menu_style)
+
+    def _get_children(self):
+        children = []
+        if self.__controls:
+            for c in self.__controls:
+                c._set_attr_internal("n", "controls")
+                children.append(c)
+        if self.__leading:
+            self.__leading._set_attr_internal("n", "leading")
+            children.append(self.__leading)
+        if self.__trailing:
+            self.__trailing._set_attr_internal("n", "trailing")
+            children.append(self.__trailing)
+        if self.__content:
+            self.__content._set_attr_internal("n", "content")
+            children.append(self.__content)
+        return children
+
+    def focus(self):
+        self._set_attr_json("focus", str(time.time()))
+        self.update()
+
+    async def focus_async(self):
+        self._set_attr_json("focus", str(time.time()))
+        await self.update_async()
+
+    # controls
+    @property
+    def controls(self):
+        return self.__controls
+
+    @controls.setter
+    def controls(self, value: Optional[List[Control]]):
+        self.__controls = value if value is not None else []
+
+    # leading
+    @property
+    def leading(self) -> Optional[Control]:
+        return self.__leading
+
+    @leading.setter
+    def leading(self, value: Optional[Control]):
+        self.__leading = value
+
+    # trailing
+    @property
+    def trailing(self) -> Optional[Control]:
+        return self.__trailing
+
+    @trailing.setter
+    def trailing(self, value: Optional[Control]):
+        self.__trailing = value
+
+    # content
+    @property
+    def content(self) -> Optional[Control]:
+        return self.__content
+
+    @content.setter
+    def content(self, value: Optional[Control]):
+        self.__content = value
+
+    # style
+    @property
+    def style(self) -> Optional[ButtonStyle]:
+        return self.__style
+
+    @style.setter
+    def style(self, value: Optional[ButtonStyle]):
+        self.__style = value
+
+    # menu_style
+    @property
+    def menu_style(self) -> Optional[MenuStyle]:
+        return self.__menu_style
+
+    @menu_style.setter
+    def menu_style(self, value: Optional[MenuStyle]):
+        self.__menu_style = value
+
+    # clip_behavior
+    @property
+    def clip_behavior(self) -> Optional[ClipBehavior]:
+        return self.__clip_behavior
+
+    @clip_behavior.setter
+    def clip_behavior(self, value: Optional[ClipBehavior]):
+        self.__clip_behavior = value
+        self._set_attr(
+            "clipBehavior", value.value if isinstance(value, ClipBehavior) else value
+        )
+
+    # on_open
+    @property
+    def on_open(self):
+        return self._get_event_handler("open")
+
+    @on_open.setter
+    def on_open(self, handler):
+        self._add_event_handler("open", handler)
+        self._set_attr("onOpen", True if handler is not None else None)
+
+    # on_close
+    @property
+    def on_close(self):
+        return self._get_event_handler("close")
+
+    @on_close.setter
+    def on_close(self, handler):
+        self._add_event_handler("close", handler)
+        self._set_attr("onClose", True if handler is not None else None)
+
+    # on_hover
+    @property
+    def on_hover(self):
+        return self._get_event_handler("hover")
+
+    @on_hover.setter
+    def on_hover(self, handler):
+        self._add_event_handler("hover", handler)
+        self._set_attr("onHover", True if handler is not None else None)
+
+    # on_focus
+    @property
+    def on_focus(self):
+        return self._get_event_handler("focus")
+
+    @on_focus.setter
+    def on_focus(self, handler):
+        self._add_event_handler("focus", handler)
+
+    # on_blur
+    @property
+    def on_blur(self):
+        return self._get_event_handler("blur")
+
+    @on_blur.setter
+    def on_blur(self, handler):
+        self._add_event_handler("blur", handler)
\ No newline at end of file

From e8519832aa0cd141121f62cccee71401b5616986 Mon Sep 17 00:00:00 2001
From: ndonkoHenri <robotcoder4@protonmail.com>
Date: Wed, 20 Dec 2023 17:04:46 +0100
Subject: [PATCH 3/8] add .dart

---
 package/lib/src/controls/menu_bar.dart        |  56 +++++++
 .../lib/src/controls/menu_item_button.dart    | 134 +++++++++++++++
 package/lib/src/controls/submenu_button.dart  | 156 ++++++++++++++++++
 package/lib/src/utils/menu.dart               | 110 ++++++++++++
 4 files changed, 456 insertions(+)
 create mode 100644 package/lib/src/controls/menu_bar.dart
 create mode 100644 package/lib/src/controls/menu_item_button.dart
 create mode 100644 package/lib/src/controls/submenu_button.dart
 create mode 100644 package/lib/src/utils/menu.dart

diff --git a/package/lib/src/controls/menu_bar.dart b/package/lib/src/controls/menu_bar.dart
new file mode 100644
index 000000000..942dd0a9d
--- /dev/null
+++ b/package/lib/src/controls/menu_bar.dart
@@ -0,0 +1,56 @@
+import 'package:flutter/material.dart';
+
+import '../models/control.dart';
+import '../utils/menu.dart';
+import 'create_control.dart';
+import 'error.dart';
+
+class MenuBarControl extends StatefulWidget {
+  final Control? parent;
+  final Control control;
+  final List<Control> children;
+  final bool parentDisabled;
+
+  const MenuBarControl(
+      {super.key,
+      this.parent,
+      required this.control,
+      required this.children,
+      required this.parentDisabled});
+
+  @override
+  State<MenuBarControl> createState() => _MenuBarControlState();
+}
+
+class _MenuBarControlState extends State<MenuBarControl> {
+  @override
+  Widget build(BuildContext context) {
+    debugPrint("MenuBar build: ${widget.control.id}");
+
+    var ctrls = widget.children.where((c) => c.isVisible).toList();
+    if (ctrls.isEmpty) {
+      return const ErrorControl(
+        "MenuBar must have at least one child control",
+      );
+    }
+    bool disabled = widget.control.isDisabled || widget.parentDisabled;
+
+    var clipBehavior = Clip.values.firstWhere(
+        (e) =>
+            e.name.toLowerCase() ==
+            widget.control.attrString("clipBehavior", "")!.toLowerCase(),
+        orElse: () => Clip.none);
+
+    var theme = Theme.of(context);
+
+    var style = parseMenuStyle(Theme.of(context), widget.control, "style");
+
+    MenuBar? menuBar = MenuBar(
+      style: style,
+      clipBehavior: clipBehavior,
+      children: ctrls.map((c) => createControl(widget.control, c.id, disabled)).toList(),
+    );
+
+    return constrainedControl(context, menuBar, widget.parent, widget.control);
+  }
+}
diff --git a/package/lib/src/controls/menu_item_button.dart b/package/lib/src/controls/menu_item_button.dart
new file mode 100644
index 000000000..9796c8994
--- /dev/null
+++ b/package/lib/src/controls/menu_item_button.dart
@@ -0,0 +1,134 @@
+import 'package:flutter/material.dart';
+
+import '../flet_app_services.dart';
+import '../models/control.dart';
+import '../utils/buttons.dart';
+import 'create_control.dart';
+
+class MenuItemButtonControl extends StatefulWidget {
+  final Control? parent;
+  final Control control;
+  final List<Control> children;
+  final bool parentDisabled;
+
+  const MenuItemButtonControl(
+      {super.key,
+      this.parent,
+      required this.control,
+      required this.children,
+      required this.parentDisabled});
+
+  @override
+  State<MenuItemButtonControl> createState() => _MenuItemButtonControlState();
+}
+
+class _MenuItemButtonControlState extends State<MenuItemButtonControl> {
+  late final FocusNode _focusNode;
+  String? _lastFocusValue;
+
+  @override
+  void initState() {
+    super.initState();
+    _focusNode = FocusNode();
+    _focusNode.addListener(_onFocusChange);
+  }
+
+  @override
+  void dispose() {
+    _focusNode.removeListener(_onFocusChange);
+    _focusNode.dispose();
+    super.dispose();
+  }
+
+  void _onFocusChange() {
+    FletAppServices.of(context).server.sendPageEvent(
+        eventTarget: widget.control.id,
+        eventName: _focusNode.hasFocus ? "focus" : "blur",
+        eventData: "");
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    debugPrint("MenuItemButton build: ${widget.control.id}");
+    bool disabled = widget.control.isDisabled || widget.parentDisabled;
+
+    var content =
+        widget.children.where((c) => c.name == "content" && c.isVisible);
+    var leading =
+        widget.children.where((c) => c.name == "leading" && c.isVisible);
+    var trailing =
+        widget.children.where((c) => c.name == "trailing" && c.isVisible);
+
+    var clipBehavior = Clip.values.firstWhere(
+        (e) =>
+            e.name.toLowerCase() ==
+            widget.control.attrString("clipBehavior", "")!.toLowerCase(),
+        orElse: () => Clip.none);
+
+    var theme = Theme.of(context);
+    var style = parseButtonStyle(Theme.of(context), widget.control, "style",
+        defaultForegroundColor: theme.colorScheme.primary,
+        defaultBackgroundColor: Colors.transparent,
+        defaultOverlayColor: Colors.transparent,
+        defaultShadowColor: Colors.transparent,
+        defaultSurfaceTintColor: Colors.transparent,
+        defaultElevation: 0,
+        defaultPadding: const EdgeInsets.all(8),
+        defaultBorderSide: BorderSide.none,
+        defaultShape: theme.useMaterial3
+            ? const StadiumBorder()
+            : RoundedRectangleBorder(borderRadius: BorderRadius.circular(4)));
+
+    bool onClick = widget.control.attrBool("onClick", false)!;
+    bool onHover = widget.control.attrBool("onHover", false)!;
+
+    var server = FletAppServices.of(context).server;
+
+    var menuItem = MenuItemButton(
+      focusNode: _focusNode,
+      clipBehavior: clipBehavior,
+      style: style,
+      closeOnActivate: widget.control.attrBool("closeOnClick", true)!,
+      requestFocusOnHover: widget.control.attrBool("focusOnHover", true)!,
+      onHover: onHover && !disabled
+          ? (bool value) {
+              server.sendPageEvent(
+                  eventTarget: widget.control.id,
+                  eventName: "hover",
+                  eventData: "$value");
+            }
+          : null,
+      onPressed: onClick && !disabled
+          ? () {
+              server.sendPageEvent(
+                  eventTarget: widget.control.id,
+                  eventName: "click",
+                  eventData: "");
+            }
+          : null,
+      leadingIcon: leading.isNotEmpty
+          ? leading
+              .map((c) => createControl(widget.control, c.id, disabled))
+              .first
+          : null,
+      trailingIcon: trailing.isNotEmpty
+          ? trailing
+              .map((c) => createControl(widget.control, c.id, disabled))
+              .first
+          : null,
+      child: content.isNotEmpty
+          ? content
+              .map((c) => createControl(widget.control, c.id, disabled))
+              .first
+          : null,
+    );
+
+    var focusValue = widget.control.attrString("focus");
+    if (focusValue != null && focusValue != _lastFocusValue) {
+      _lastFocusValue = focusValue;
+      _focusNode.requestFocus();
+    }
+
+    return constrainedControl(context, menuItem, widget.parent, widget.control);
+  }
+}
diff --git a/package/lib/src/controls/submenu_button.dart b/package/lib/src/controls/submenu_button.dart
new file mode 100644
index 000000000..ff2c086bd
--- /dev/null
+++ b/package/lib/src/controls/submenu_button.dart
@@ -0,0 +1,156 @@
+import 'package:flutter/material.dart';
+
+import '../flet_app_services.dart';
+import '../models/control.dart';
+import '../utils/buttons.dart';
+import '../utils/menu.dart';
+import 'create_control.dart';
+
+class SubMenuButtonControl extends StatefulWidget {
+  final Control? parent;
+  final Control control;
+  final List<Control> children;
+  final bool parentDisabled;
+
+  const SubMenuButtonControl(
+      {super.key,
+      this.parent,
+      required this.control,
+      required this.children,
+      required this.parentDisabled});
+
+  @override
+  State<SubMenuButtonControl> createState() => _SubMenuButtonControlState();
+}
+
+class _SubMenuButtonControlState extends State<SubMenuButtonControl> {
+  late final FocusNode _focusNode;
+  String? _lastFocusValue;
+
+  @override
+  void initState() {
+    super.initState();
+    _focusNode = FocusNode();
+    _focusNode.addListener(_onFocusChange);
+  }
+
+  @override
+  void dispose() {
+    _focusNode.removeListener(_onFocusChange);
+    _focusNode.dispose();
+    super.dispose();
+  }
+
+  void _onFocusChange() {
+    FletAppServices.of(context).server.sendPageEvent(
+        eventTarget: widget.control.id,
+        eventName: _focusNode.hasFocus ? "focus" : "blur",
+        eventData: "");
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    debugPrint("SubMenuButton build: ${widget.control.id}");
+    bool disabled = widget.control.isDisabled || widget.parentDisabled;
+
+    var content =
+        widget.children.where((c) => c.name == "content" && c.isVisible);
+    var ctrls =
+        widget.children.where((c) => c.name == "controls" && c.isVisible);
+    var leading =
+        widget.children.where((c) => c.name == "leading" && c.isVisible);
+    var trailing =
+        widget.children.where((c) => c.name == "trailing" && c.isVisible);
+
+    var clipBehavior = Clip.values.firstWhere(
+        (e) =>
+            e.name.toLowerCase() ==
+            widget.control.attrString("clipBehavior", "")!.toLowerCase(),
+        orElse: () => Clip.hardEdge);
+
+    var theme = Theme.of(context);
+    var style = parseButtonStyle(Theme.of(context), widget.control, "style",
+        defaultForegroundColor: theme.colorScheme.primary,
+        defaultBackgroundColor: Colors.transparent,
+        defaultOverlayColor: Colors.transparent,
+        defaultShadowColor: Colors.transparent,
+        defaultSurfaceTintColor: Colors.transparent,
+        defaultElevation: 0,
+        defaultPadding: const EdgeInsets.all(8),
+        defaultBorderSide: BorderSide.none,
+        defaultShape: theme.useMaterial3
+            ? const StadiumBorder()
+            : RoundedRectangleBorder(borderRadius: BorderRadius.circular(4)));
+
+    var menuStyle =
+        parseMenuStyle(Theme.of(context), widget.control, "menuStyle");
+
+    bool onOpen = widget.control.attrBool("onOpen", false)!;
+    bool onClose = widget.control.attrBool("onClose", false)!;
+    bool onHover = widget.control.attrBool("onHover", false)!;
+
+    var server = FletAppServices.of(context).server;
+
+    var subMenu = SubmenuButton(
+      focusNode: _focusNode,
+      clipBehavior: clipBehavior,
+      style: style,
+      menuStyle: menuStyle,
+      onClose: onClose && !disabled
+          ? () {
+              server.sendPageEvent(
+                  eventTarget: widget.control.id,
+                  eventName: "close",
+                  eventData: "");
+            }
+          : null,
+      onHover: onHover && !disabled
+          ? (bool value) {
+              server.sendPageEvent(
+                  eventTarget: widget.control.id,
+                  eventName: "hover",
+                  eventData: "$value");
+            }
+          : null,
+      onOpen: onOpen && !disabled
+          ? () {
+              server.sendPageEvent(
+                  eventTarget: widget.control.id,
+                  eventName: "open",
+                  eventData: "");
+            }
+          : null,
+      leadingIcon: leading.isNotEmpty
+          ? leading
+              .map((c) => createControl(widget.control, c.id, disabled))
+              .toList()
+              .first
+          : null,
+      trailingIcon: trailing.isNotEmpty
+          ? trailing
+              .map((c) => createControl(widget.control, c.id, disabled))
+              .toList()
+              .first
+          : null,
+      menuChildren: ctrls.isNotEmpty
+          ? ctrls.map((c) {
+              return createControl(widget.control, c.id, disabled);
+            }).toList()
+          : [],
+      child: content.isNotEmpty
+          ? content
+              .map((c) => createControl(widget.control, c.id, disabled))
+              .toList()
+              .first
+          : null,
+    );
+
+    var focusValue = widget.control.attrString("focus");
+    if (focusValue != null && focusValue != _lastFocusValue) {
+      _lastFocusValue = focusValue;
+      _focusNode.requestFocus();
+    }
+
+    return constrainedControl(context, subMenu, widget.parent, widget.control);
+  }
+}
diff --git a/package/lib/src/utils/menu.dart b/package/lib/src/utils/menu.dart
new file mode 100644
index 000000000..5beb7666d
--- /dev/null
+++ b/package/lib/src/utils/menu.dart
@@ -0,0 +1,110 @@
+import 'dart:convert';
+
+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';
+
+MenuStyle? parseMenuStyle(ThemeData theme, Control control, String propName,
+    {Color? defaultBackgroundColor,
+    Color? defaultShadowColor,
+    Color? defaultSurfaceTintColor,
+    double? defaultElevation,
+    Alignment? defaultAlignment,
+    MouseCursor? defaultMouseCursor,
+    // required double? defaultFixedSize,
+    // required double? defaultMaxSize,
+    // required double? defaultMinSize,
+    EdgeInsets? defaultPadding,
+    BorderSide? defaultBorderSide,
+    OutlinedBorder? defaultShape}) {
+  var v = control.attrString(propName, null);
+  if (v == null) {
+    return null;
+  }
+
+  final j1 = json.decode(v);
+  return menuStyleFromJSON(
+      theme,
+      j1,
+      defaultBackgroundColor,
+      defaultShadowColor,
+      defaultSurfaceTintColor,
+      defaultElevation,
+      defaultAlignment,
+      defaultMouseCursor,
+      // defaultFixedSize,
+      // defaultMaxSize,
+      // defaultMinSize,
+      defaultPadding,
+      defaultBorderSide,
+      defaultShape);
+}
+
+MaterialStateProperty<Color?>? parseMaterialStateColor(
+    ThemeData theme, Control control, String propName) {
+  var v = control.attrString(propName, null);
+  if (v == null) {
+    return null;
+  }
+
+  final j1 = json.decode(v);
+  return getMaterialStateProperty<Color?>(
+      j1, (jv) => HexColor.fromString(theme, jv as String), null);
+}
+
+MenuStyle? menuStyleFromJSON(
+    ThemeData theme,
+    Map<String, dynamic> json,
+    Color? defaultBackgroundColor,
+    Color? defaultShadowColor,
+    Color? defaultSurfaceTintColor,
+    double? defaultElevation,
+    Alignment? defaultAlignment,
+    MouseCursor? defaultMouseCursor,
+    // double? defaultFixedSize,
+    // double? defaultMaxSize,
+    // double? defaultMinSize,
+    EdgeInsets? defaultPadding,
+    BorderSide? defaultBorderSide,
+    OutlinedBorder? defaultShape) {
+  return MenuStyle(
+    alignment: json["alignment"] != null
+        ? alignmentFromJson(json["alignment"])
+        : defaultAlignment,
+    backgroundColor: getMaterialStateProperty<Color?>(
+        json["bgcolor"],
+        (jv) => HexColor.fromString(theme, jv as String),
+        defaultBackgroundColor),
+    shadowColor: getMaterialStateProperty<Color?>(json["shadow_color"],
+        (jv) => HexColor.fromString(theme, jv as String), defaultShadowColor),
+    surfaceTintColor: getMaterialStateProperty<Color?>(
+        json["surface_tint_color"],
+        (jv) => HexColor.fromString(theme, jv as String),
+        defaultSurfaceTintColor),
+    elevation: getMaterialStateProperty<double?>(
+        json["elevation"], (jv) => parseDouble(jv), defaultElevation),
+    // fixedSize: getMaterialStateProperty<double?>(
+    //     json["fixed_size"], (jv) => parseDouble(jv), defaultFixedSize),
+    // minimumSize: getMaterialStateProperty<double?>(
+    //     json["min_size"], (jv) => parseDouble(jv), defaultMinimumSize),
+    // maximumSize: getMaterialStateProperty<double?>(
+    //     json["max_size"], (jv) => parseDouble(jv), defaultMaximumSize),
+    padding: getMaterialStateProperty<EdgeInsetsGeometry?>(
+        json["padding"], (jv) => edgeInsetsFromJson(jv), defaultPadding),
+    side: getMaterialStateProperty<BorderSide?>(
+        json["side"],
+        (jv) => borderSideFromJSON(theme, jv, theme.colorScheme.outline),
+        defaultBorderSide),
+    shape: getMaterialStateProperty<OutlinedBorder?>(
+        json["shape"], (jv) => outlinedBorderFromJSON(jv), defaultShape),
+    mouseCursor: getMaterialStateProperty<MouseCursor?>(json["mouse_cursor"],
+        (jv) => parseMouseCursor(jv as String), defaultMouseCursor),
+  );
+}

From 12868167a98423c11a97f3235fbd45883c51ef12 Mon Sep 17 00:00:00 2001
From: ndonkoHenri <robotcoder4@protonmail.com>
Date: Wed, 20 Dec 2023 17:05:29 +0100
Subject: [PATCH 4/8] 'create' new controls

---
 package/lib/src/controls/create_control.dart | 24 ++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/package/lib/src/controls/create_control.dart b/package/lib/src/controls/create_control.dart
index f2994244f..10ae79463 100644
--- a/package/lib/src/controls/create_control.dart
+++ b/package/lib/src/controls/create_control.dart
@@ -1,8 +1,11 @@
 import 'dart:math';
 
 import 'package:collection/collection.dart';
+import 'package:flet/src/controls/menu_bar.dart';
 import 'package:flet/src/controls/search_anchor.dart';
+import 'package:flet/src/controls/menu_item_button.dart';
 import 'package:flet/src/controls/segmented_button.dart';
+import 'package:flet/src/controls/submenu_button.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_redux/flutter_redux.dart';
 
@@ -324,6 +327,27 @@ Widget createWidget(Key? key, ControlViewModel controlView, Control? parent,
           control: controlView.control,
           children: controlView.children,
           parentDisabled: parentDisabled);
+    case "menubar":
+      return MenuBarControl(
+          key: key,
+          parent: parent,
+          control: controlView.control,
+          children: controlView.children,
+          parentDisabled: parentDisabled);
+    case "submenubutton":
+      return SubMenuButtonControl(
+          key: key,
+          parent: parent,
+          control: controlView.control,
+          children: controlView.children,
+          parentDisabled: parentDisabled);
+    case "menuitembutton":
+      return MenuItemButtonControl(
+          key: key,
+          parent: parent,
+          control: controlView.control,
+          children: controlView.children,
+          parentDisabled: parentDisabled);
     case "segmentedbutton":
       return SegmentedButtonControl(
           key: key,

From be11c30517307fb8aeff3a7c165b768a842bdbdb Mon Sep 17 00:00:00 2001
From: ndonkoHenri <robotcoder4@protonmail.com>
Date: Thu, 21 Dec 2023 10:24:38 +0100
Subject: [PATCH 5/8] move fab_location to types.py

---
 .../flet-core/src/flet_core/__init__.py       |  6 ++---
 .../src/flet_core/floating_action_button.py   | 23 -------------------
 .../packages/flet-core/src/flet_core/types.py | 22 ++++++++++++++++++
 3 files changed, 24 insertions(+), 27 deletions(-)

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 039a8da23..7dab0c885 100644
--- a/sdk/python/packages/flet-core/src/flet_core/__init__.py
+++ b/sdk/python/packages/flet-core/src/flet_core/__init__.py
@@ -96,10 +96,7 @@
 from flet_core.filled_button import FilledButton
 from flet_core.filled_tonal_button import FilledTonalButton
 from flet_core.flet_app import FletApp
-from flet_core.floating_action_button import (
-    FloatingActionButton,
-    FloatingActionButtonLocation,
-)
+from flet_core.floating_action_button import FloatingActionButton
 from flet_core.form_field_control import InputBorder
 from flet_core.gesture_detector import (
     DragEndEvent,
@@ -217,6 +214,7 @@
     BoxShape,
     ClipBehavior,
     CrossAxisAlignment,
+    FloatingActionButtonLocation,
     FontWeight,
     ImageFit,
     ImageRepeat,
diff --git a/sdk/python/packages/flet-core/src/flet_core/floating_action_button.py b/sdk/python/packages/flet-core/src/flet_core/floating_action_button.py
index 2c66dc632..40afbd3ea 100644
--- a/sdk/python/packages/flet-core/src/flet_core/floating_action_button.py
+++ b/sdk/python/packages/flet-core/src/flet_core/floating_action_button.py
@@ -1,4 +1,3 @@
-from enum import Enum
 from typing import Any, Optional, Union
 
 from flet_core.buttons import OutlinedBorder
@@ -14,28 +13,6 @@
 )
 
 
-class FloatingActionButtonLocation(Enum):
-    CENTER_DOCKED = "centerDocked"
-    CENTER_FLOAT = "centerFloat"
-    CENTER_TOP = "centerTop"
-    END_CONTAINED = "endContained"
-    END_DOCKED = "endDocked"
-    END_FLOAT = "endFloat"
-    END_TOP = "endTop"
-    MINI_CENTER_DOCKED = "miniCenterDocked"
-    MINI_CENTER_FLOAT = "miniCenterFloat"
-    MINI_CENTER_TOP = "miniCenterTop"
-    MINI_END_DOCKED = "miniEndDocked"
-    MINI_END_FLOAT = "miniEndFloat"
-    MINI_END_TOP = "miniEndTop"
-    MINI_START_DOCKED = "miniStartDocked"
-    MINI_START_FLOAT = "miniStartFloat"
-    MINI_START_TOP = "miniStartTop"
-    START_DOCKED = "startDocked"
-    START_FLOAT = "startFloat"
-    START_TOP = "startTop"
-
-
 class FloatingActionButton(ConstrainedControl):
     """
     A floating action button is a circular icon button that hovers over content to promote a primary action in the application. Floating action button is usually set to `page.floating_action_button`, but can also be added as a regular control at any place on a page.
diff --git a/sdk/python/packages/flet-core/src/flet_core/types.py b/sdk/python/packages/flet-core/src/flet_core/types.py
index 6364a0761..c07f9b4e9 100644
--- a/sdk/python/packages/flet-core/src/flet_core/types.py
+++ b/sdk/python/packages/flet-core/src/flet_core/types.py
@@ -304,3 +304,25 @@ class ThemeMode(Enum):
     SYSTEM = "system"
     LIGHT = "light"
     DARK = "dark"
+
+
+class FloatingActionButtonLocation(Enum):
+    CENTER_DOCKED = "centerDocked"
+    CENTER_FLOAT = "centerFloat"
+    CENTER_TOP = "centerTop"
+    END_CONTAINED = "endContained"
+    END_DOCKED = "endDocked"
+    END_FLOAT = "endFloat"
+    END_TOP = "endTop"
+    MINI_CENTER_DOCKED = "miniCenterDocked"
+    MINI_CENTER_FLOAT = "miniCenterFloat"
+    MINI_CENTER_TOP = "miniCenterTop"
+    MINI_END_DOCKED = "miniEndDocked"
+    MINI_END_FLOAT = "miniEndFloat"
+    MINI_END_TOP = "miniEndTop"
+    MINI_START_DOCKED = "miniStartDocked"
+    MINI_START_FLOAT = "miniStartFloat"
+    MINI_START_TOP = "miniStartTop"
+    START_DOCKED = "startDocked"
+    START_FLOAT = "startFloat"
+    START_TOP = "startTop"

From 4b67970b8da2ec528d03019e2a6e4451f49c09b2 Mon Sep 17 00:00:00 2001
From: ndonkoHenri <robotcoder4@protonmail.com>
Date: Thu, 21 Dec 2023 10:25:15 +0100
Subject: [PATCH 6/8] alignment_offset

---
 package/lib/src/controls/submenu_button.dart          |  6 ++++++
 .../flet-core/src/flet_core/submenu_button.py         | 11 +++++++++++
 2 files changed, 17 insertions(+)

diff --git a/package/lib/src/controls/submenu_button.dart b/package/lib/src/controls/submenu_button.dart
index ff2c086bd..20b5e897b 100644
--- a/package/lib/src/controls/submenu_button.dart
+++ b/package/lib/src/controls/submenu_button.dart
@@ -4,6 +4,7 @@ import '../flet_app_services.dart';
 import '../models/control.dart';
 import '../utils/buttons.dart';
 import '../utils/menu.dart';
+import '../utils/transforms.dart';
 import 'create_control.dart';
 
 class SubMenuButtonControl extends StatefulWidget {
@@ -68,6 +69,8 @@ class _SubMenuButtonControlState extends State<SubMenuButtonControl> {
             widget.control.attrString("clipBehavior", "")!.toLowerCase(),
         orElse: () => Clip.hardEdge);
 
+    var offsetDetails = parseOffset(widget.control, "alignmentOffset");
+
     var theme = Theme.of(context);
     var style = parseButtonStyle(Theme.of(context), widget.control, "style",
         defaultForegroundColor: theme.colorScheme.primary,
@@ -96,6 +99,9 @@ class _SubMenuButtonControlState extends State<SubMenuButtonControl> {
       clipBehavior: clipBehavior,
       style: style,
       menuStyle: menuStyle,
+      alignmentOffset: offsetDetails != null
+          ? Offset(offsetDetails.x, offsetDetails.y)
+          : null,
       onClose: onClose && !disabled
           ? () {
               server.sendPageEvent(
diff --git a/sdk/python/packages/flet-core/src/flet_core/submenu_button.py b/sdk/python/packages/flet-core/src/flet_core/submenu_button.py
index b2c974622..b9ff571de 100644
--- a/sdk/python/packages/flet-core/src/flet_core/submenu_button.py
+++ b/sdk/python/packages/flet-core/src/flet_core/submenu_button.py
@@ -62,6 +62,7 @@ def __init__(
             clip_behavior: Optional[ClipBehavior] = None,
             menu_style: Optional[MenuStyle] = None,
             style: Optional[ButtonStyle] = None,
+            alignment_offset: OffsetValue = None,
             on_open=None,
             on_close=None,
             on_hover=None,
@@ -105,6 +106,7 @@ def __init__(
         self.clip_behavior = clip_behavior
         self.style = style
         self.menu_style = menu_style
+        self.alignment_offset = alignment_offset
         self.on_open = on_open
         self.on_close = on_close
         self.on_hover = on_hover
@@ -216,6 +218,15 @@ def clip_behavior(self, value: Optional[ClipBehavior]):
             "clipBehavior", value.value if isinstance(value, ClipBehavior) else value
         )
 
+    # alignment_offset
+    @property
+    def alignment_offset(self) -> OffsetValue:
+        return self.__alignment_offset
+
+    @alignment_offset.setter
+    def alignment_offset(self, value: OffsetValue):
+        self.__alignment_offset = value
+
     # on_open
     @property
     def on_open(self):

From fc6aab9679bc6860371a2ffc92b4cf8c9a75f8a3 Mon Sep 17 00:00:00 2001
From: ndonkoHenri <robotcoder4@protonmail.com>
Date: Thu, 21 Dec 2023 11:07:23 +0100
Subject: [PATCH 7/8] refactor

---
 .../controls/cupertino_navigation_bar.dart    |  6 +-
 package/lib/src/controls/menu_bar.dart        |  2 +-
 package/lib/src/utils/menu.dart               | 15 ----
 .../flet-core/src/flet_core/menu_bar.py       | 55 ++++++------
 .../src/flet_core/menu_item_button.py         | 90 +++++++++----------
 .../packages/flet-core/src/flet_core/page.py  |  6 +-
 .../flet-core/src/flet_core/submenu_button.py | 89 +++++++++---------
 .../packages/flet-core/src/flet_core/view.py  |  6 +-
 8 files changed, 122 insertions(+), 147 deletions(-)

diff --git a/package/lib/src/controls/cupertino_navigation_bar.dart b/package/lib/src/controls/cupertino_navigation_bar.dart
index b7d2d4205..75ac5721a 100644
--- a/package/lib/src/controls/cupertino_navigation_bar.dart
+++ b/package/lib/src/controls/cupertino_navigation_bar.dart
@@ -1,4 +1,3 @@
-import 'package:collection/collection.dart';
 import 'package:flutter/cupertino.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_redux/flutter_redux.dart';
@@ -22,13 +21,12 @@ class CupertinoNavigationBarControl extends StatefulWidget {
   final dynamic dispatch;
 
   const CupertinoNavigationBarControl(
-      {Key? key,
+      {super.key,
       this.parent,
       required this.control,
       required this.children,
       required this.parentDisabled,
-      required this.dispatch})
-      : super(key: key);
+      required this.dispatch});
 
   @override
   State<CupertinoNavigationBarControl> createState() =>
diff --git a/package/lib/src/controls/menu_bar.dart b/package/lib/src/controls/menu_bar.dart
index 942dd0a9d..7c8328b8a 100644
--- a/package/lib/src/controls/menu_bar.dart
+++ b/package/lib/src/controls/menu_bar.dart
@@ -41,7 +41,7 @@ class _MenuBarControlState extends State<MenuBarControl> {
             widget.control.attrString("clipBehavior", "")!.toLowerCase(),
         orElse: () => Clip.none);
 
-    var theme = Theme.of(context);
+    // var theme = Theme.of(context);
 
     var style = parseMenuStyle(Theme.of(context), widget.control, "style");
 
diff --git a/package/lib/src/utils/menu.dart b/package/lib/src/utils/menu.dart
index 5beb7666d..8d9478bf3 100644
--- a/package/lib/src/utils/menu.dart
+++ b/package/lib/src/utils/menu.dart
@@ -18,9 +18,6 @@ MenuStyle? parseMenuStyle(ThemeData theme, Control control, String propName,
     double? defaultElevation,
     Alignment? defaultAlignment,
     MouseCursor? defaultMouseCursor,
-    // required double? defaultFixedSize,
-    // required double? defaultMaxSize,
-    // required double? defaultMinSize,
     EdgeInsets? defaultPadding,
     BorderSide? defaultBorderSide,
     OutlinedBorder? defaultShape}) {
@@ -39,9 +36,6 @@ MenuStyle? parseMenuStyle(ThemeData theme, Control control, String propName,
       defaultElevation,
       defaultAlignment,
       defaultMouseCursor,
-      // defaultFixedSize,
-      // defaultMaxSize,
-      // defaultMinSize,
       defaultPadding,
       defaultBorderSide,
       defaultShape);
@@ -68,9 +62,6 @@ MenuStyle? menuStyleFromJSON(
     double? defaultElevation,
     Alignment? defaultAlignment,
     MouseCursor? defaultMouseCursor,
-    // double? defaultFixedSize,
-    // double? defaultMaxSize,
-    // double? defaultMinSize,
     EdgeInsets? defaultPadding,
     BorderSide? defaultBorderSide,
     OutlinedBorder? defaultShape) {
@@ -90,12 +81,6 @@ MenuStyle? menuStyleFromJSON(
         defaultSurfaceTintColor),
     elevation: getMaterialStateProperty<double?>(
         json["elevation"], (jv) => parseDouble(jv), defaultElevation),
-    // fixedSize: getMaterialStateProperty<double?>(
-    //     json["fixed_size"], (jv) => parseDouble(jv), defaultFixedSize),
-    // minimumSize: getMaterialStateProperty<double?>(
-    //     json["min_size"], (jv) => parseDouble(jv), defaultMinimumSize),
-    // maximumSize: getMaterialStateProperty<double?>(
-    //     json["max_size"], (jv) => parseDouble(jv), defaultMaximumSize),
     padding: getMaterialStateProperty<EdgeInsetsGeometry?>(
         json["padding"], (jv) => edgeInsetsFromJson(jv), defaultPadding),
     side: getMaterialStateProperty<BorderSide?>(
diff --git a/sdk/python/packages/flet-core/src/flet_core/menu_bar.py b/sdk/python/packages/flet-core/src/flet_core/menu_bar.py
index 7d9425429..ad181d9a8 100644
--- a/sdk/python/packages/flet-core/src/flet_core/menu_bar.py
+++ b/sdk/python/packages/flet-core/src/flet_core/menu_bar.py
@@ -11,7 +11,8 @@
 from flet_core.types import (
     PaddingValue,
     ResponsiveNumber,
-    ClipBehavior, MaterialState,
+    ClipBehavior,
+    MaterialState,
 )
 
 
@@ -30,15 +31,6 @@ class MenuStyle:
     elevation: Union[
         None, float, int, Dict[Union[str, MaterialState], Union[float, int]]
     ] = field(default=None)
-    # fixed_size: Union[
-    #     None, float, int, Dict[Union[str, MaterialState], Union[float, int]]
-    # ] = field(default=None)
-    # max_size: Union[
-    #     None, float, int, Dict[Union[str, MaterialState], Union[float, int]]
-    # ] = field(default=None)
-    # min_size: Union[
-    #     None, float, int, Dict[Union[str, MaterialState], Union[float, int]]
-    # ] = field(default=None)
     padding: Union[PaddingValue, Dict[Union[str, MaterialState], PaddingValue]] = field(
         default=None
     )
@@ -55,11 +47,10 @@ class MenuStyle:
 
 class MenuBar(Control):
     """
+    A menu bar that manages cascading child menus.
 
-
-    ```
-
-    ```
+    It could be placed anywhere but typically resides above the main body of the application 
+    and defines a menu system for invoking callbacks in response to user selection of a menu item.
 
     -----
 
@@ -67,20 +58,20 @@ class MenuBar(Control):
     """
 
     def __init__(
-            self,
-            controls: Optional[List[Control]] = None,
-            ref: Optional[Ref] = None,
-            expand: Union[None, bool, int] = None,
-            col: Optional[ResponsiveNumber] = None,
-            opacity: OptionalNumber = None,
-            visible: Optional[bool] = None,
-            disabled: Optional[bool] = None,
-            data: Any = None,
-            #
-            # Specific
-            #
-            clip_behavior: Optional[ClipBehavior] = None,
-            style: Optional[MenuStyle] = None,
+        self,
+        controls: Optional[List[Control]] = None,
+        ref: Optional[Ref] = None,
+        expand: Union[None, bool, int] = None,
+        col: Optional[ResponsiveNumber] = None,
+        opacity: OptionalNumber = None,
+        visible: Optional[bool] = None,
+        disabled: Optional[bool] = None,
+        data: Any = None,
+        #
+        # Specific
+        #
+        clip_behavior: Optional[ClipBehavior] = None,
+        style: Optional[MenuStyle] = None,
     ):
         Control.__init__(
             self,
@@ -109,7 +100,9 @@ def _before_build_command(self):
             self.__style.mouse_cursor = self._wrap_attr_dict(self.__style.mouse_cursor)
             if self.__style.mouse_cursor:
                 for k, v in self.__style.mouse_cursor.items():
-                    self.__style.mouse_cursor[k] = v.value if isinstance(v, MouseCursor) else str(v)
+                    self.__style.mouse_cursor[k] = (
+                        v.value if isinstance(v, MouseCursor) else str(v)
+                    )
         self._set_attr_json("style", self.__style)
 
     def _get_children(self):
@@ -132,7 +125,9 @@ def clip_behavior(self) -> Optional[ClipBehavior]:
     @clip_behavior.setter
     def clip_behavior(self, value: Optional[ClipBehavior]):
         self.__clip_behavior = value
-        self._set_attr("clipBehavior", value.value if isinstance(value, ClipBehavior) else value)
+        self._set_attr(
+            "clipBehavior", value.value if isinstance(value, ClipBehavior) else value
+        )
 
     # style
     @property
diff --git a/sdk/python/packages/flet-core/src/flet_core/menu_item_button.py b/sdk/python/packages/flet-core/src/flet_core/menu_item_button.py
index 50b07a261..3399c1a95 100644
--- a/sdk/python/packages/flet-core/src/flet_core/menu_item_button.py
+++ b/sdk/python/packages/flet-core/src/flet_core/menu_item_button.py
@@ -1,10 +1,9 @@
 import time
-from typing import Any, Optional, Union, List
+from typing import Any, Optional, Union
 
+from flet_core.buttons import ButtonStyle
 from flet_core.constrained_control import ConstrainedControl
 from flet_core.control import Control, OptionalNumber
-from flet_core.menu_bar import MenuStyle
-from flet_core.buttons import ButtonStyle
 from flet_core.ref import Ref
 from flet_core.types import (
     AnimationValue,
@@ -18,6 +17,7 @@
 
 class MenuItemButton(ConstrainedControl):
     """
+    A button for use in a MenuBar or on its own, that can be activated by click or keyboard navigation.
 
     -----
 
@@ -25,47 +25,47 @@ class MenuItemButton(ConstrainedControl):
     """
 
     def __init__(
-            self,
-            content: Optional[Control] = None,
-            ref: Optional[Ref] = None,
-            key: Optional[str] = None,
-            width: OptionalNumber = None,
-            height: OptionalNumber = None,
-            left: OptionalNumber = None,
-            top: OptionalNumber = None,
-            right: OptionalNumber = None,
-            bottom: OptionalNumber = None,
-            expand: Union[None, bool, int] = None,
-            col: Optional[ResponsiveNumber] = None,
-            opacity: OptionalNumber = None,
-            rotate: RotateValue = None,
-            scale: ScaleValue = None,
-            offset: OffsetValue = None,
-            aspect_ratio: OptionalNumber = None,
-            animate_opacity: AnimationValue = None,
-            animate_size: AnimationValue = None,
-            animate_position: AnimationValue = None,
-            animate_rotation: AnimationValue = None,
-            animate_scale: AnimationValue = None,
-            animate_offset: AnimationValue = None,
-            on_animation_end=None,
-            tooltip: Optional[str] = None,
-            visible: Optional[bool] = None,
-            disabled: Optional[bool] = None,
-            data: Any = None,
-            #
-            # Specific
-            #
-            close_on_click: Optional[bool] = None,
-            focus_on_hover: Optional[bool] = None,
-            leading: Optional[Control] = None,
-            trailing: Optional[Control] = None,
-            clip_behavior: Optional[ClipBehavior] = None,
-            style: Optional[ButtonStyle] = None,
-            on_click=None,
-            on_hover=None,
-            on_focus=None,
-            on_blur=None,
+        self,
+        content: Optional[Control] = None,
+        ref: Optional[Ref] = None,
+        key: Optional[str] = None,
+        width: OptionalNumber = None,
+        height: OptionalNumber = None,
+        left: OptionalNumber = None,
+        top: OptionalNumber = None,
+        right: OptionalNumber = None,
+        bottom: OptionalNumber = None,
+        expand: Union[None, bool, int] = None,
+        col: Optional[ResponsiveNumber] = None,
+        opacity: OptionalNumber = None,
+        rotate: RotateValue = None,
+        scale: ScaleValue = None,
+        offset: OffsetValue = None,
+        aspect_ratio: OptionalNumber = None,
+        animate_opacity: AnimationValue = None,
+        animate_size: AnimationValue = None,
+        animate_position: AnimationValue = None,
+        animate_rotation: AnimationValue = None,
+        animate_scale: AnimationValue = None,
+        animate_offset: AnimationValue = None,
+        on_animation_end=None,
+        tooltip: Optional[str] = None,
+        visible: Optional[bool] = None,
+        disabled: Optional[bool] = None,
+        data: Any = None,
+        #
+        # Specific
+        #
+        close_on_click: Optional[bool] = None,
+        focus_on_hover: Optional[bool] = None,
+        leading: Optional[Control] = None,
+        trailing: Optional[Control] = None,
+        clip_behavior: Optional[ClipBehavior] = None,
+        style: Optional[ButtonStyle] = None,
+        on_click=None,
+        on_hover=None,
+        on_focus=None,
+        on_blur=None,
     ):
         ConstrainedControl.__init__(
             self,
@@ -242,4 +242,4 @@ def on_blur(self):
 
     @on_blur.setter
     def on_blur(self, handler):
-        self._add_event_handler("blur", handler)
\ No newline at end of file
+        self._add_event_handler("blur", handler)
diff --git a/sdk/python/packages/flet-core/src/flet_core/page.py b/sdk/python/packages/flet-core/src/flet_core/page.py
index 9813bb995..26b35184e 100644
--- a/sdk/python/packages/flet-core/src/flet_core/page.py
+++ b/sdk/python/packages/flet-core/src/flet_core/page.py
@@ -23,10 +23,7 @@
 from flet_core.control_event import ControlEvent
 from flet_core.event import Event
 from flet_core.event_handler import EventHandler
-from flet_core.floating_action_button import (
-    FloatingActionButton,
-    FloatingActionButtonLocation,
-)
+from flet_core.floating_action_button import FloatingActionButton
 from flet_core.locks import AsyncNopeLock, NopeLock
 from flet_core.navigation_bar import NavigationBar
 from flet_core.cupertino_navigation_bar import CupertinoNavigationBar
@@ -38,6 +35,7 @@
 from flet_core.theme import Theme
 from flet_core.types import (
     CrossAxisAlignment,
+    FloatingActionButtonLocation,
     MainAxisAlignment,
     PaddingValue,
     PageDesignLanguage,
diff --git a/sdk/python/packages/flet-core/src/flet_core/submenu_button.py b/sdk/python/packages/flet-core/src/flet_core/submenu_button.py
index b9ff571de..0275ebdc7 100644
--- a/sdk/python/packages/flet-core/src/flet_core/submenu_button.py
+++ b/sdk/python/packages/flet-core/src/flet_core/submenu_button.py
@@ -18,6 +18,7 @@
 
 class SubmenuButton(ConstrainedControl):
     """
+    A menu button that displays a cascading menu. It can be used as part of a MenuBar, or as a standalone control.
 
     -----
 
@@ -25,49 +26,49 @@ class SubmenuButton(ConstrainedControl):
     """
 
     def __init__(
-            self,
-            content: Optional[Control] = None,
-            controls: Optional[List[Control]] = None,
-            ref: Optional[Ref] = None,
-            key: Optional[str] = None,
-            width: OptionalNumber = None,
-            height: OptionalNumber = None,
-            left: OptionalNumber = None,
-            top: OptionalNumber = None,
-            right: OptionalNumber = None,
-            bottom: OptionalNumber = None,
-            expand: Union[None, bool, int] = None,
-            col: Optional[ResponsiveNumber] = None,
-            opacity: OptionalNumber = None,
-            rotate: RotateValue = None,
-            scale: ScaleValue = None,
-            offset: OffsetValue = None,
-            aspect_ratio: OptionalNumber = None,
-            animate_opacity: AnimationValue = None,
-            animate_size: AnimationValue = None,
-            animate_position: AnimationValue = None,
-            animate_rotation: AnimationValue = None,
-            animate_scale: AnimationValue = None,
-            animate_offset: AnimationValue = None,
-            on_animation_end=None,
-            tooltip: Optional[str] = None,
-            visible: Optional[bool] = None,
-            disabled: Optional[bool] = None,
-            data: Any = None,
-            #
-            # Specific
-            #
-            leading: Optional[Control] = None,
-            trailing: Optional[Control] = None,
-            clip_behavior: Optional[ClipBehavior] = None,
-            menu_style: Optional[MenuStyle] = None,
-            style: Optional[ButtonStyle] = None,
-            alignment_offset: OffsetValue = None,
-            on_open=None,
-            on_close=None,
-            on_hover=None,
-            on_focus=None,
-            on_blur=None,
+        self,
+        content: Optional[Control] = None,
+        controls: Optional[List[Control]] = None,
+        ref: Optional[Ref] = None,
+        key: Optional[str] = None,
+        width: OptionalNumber = None,
+        height: OptionalNumber = None,
+        left: OptionalNumber = None,
+        top: OptionalNumber = None,
+        right: OptionalNumber = None,
+        bottom: OptionalNumber = None,
+        expand: Union[None, bool, int] = None,
+        col: Optional[ResponsiveNumber] = None,
+        opacity: OptionalNumber = None,
+        rotate: RotateValue = None,
+        scale: ScaleValue = None,
+        offset: OffsetValue = None,
+        aspect_ratio: OptionalNumber = None,
+        animate_opacity: AnimationValue = None,
+        animate_size: AnimationValue = None,
+        animate_position: AnimationValue = None,
+        animate_rotation: AnimationValue = None,
+        animate_scale: AnimationValue = None,
+        animate_offset: AnimationValue = None,
+        on_animation_end=None,
+        tooltip: Optional[str] = None,
+        visible: Optional[bool] = None,
+        disabled: Optional[bool] = None,
+        data: Any = None,
+        #
+        # Specific
+        #
+        leading: Optional[Control] = None,
+        trailing: Optional[Control] = None,
+        clip_behavior: Optional[ClipBehavior] = None,
+        menu_style: Optional[MenuStyle] = None,
+        style: Optional[ButtonStyle] = None,
+        alignment_offset: OffsetValue = None,
+        on_open=None,
+        on_close=None,
+        on_hover=None,
+        on_focus=None,
+        on_blur=None,
     ):
         ConstrainedControl.__init__(
             self,
@@ -273,4 +274,4 @@ def on_blur(self):
 
     @on_blur.setter
     def on_blur(self, handler):
-        self._add_event_handler("blur", handler)
\ No newline at end of file
+        self._add_event_handler("blur", handler)
diff --git a/sdk/python/packages/flet-core/src/flet_core/view.py b/sdk/python/packages/flet-core/src/flet_core/view.py
index 4ec987e0a..46ff93972 100644
--- a/sdk/python/packages/flet-core/src/flet_core/view.py
+++ b/sdk/python/packages/flet-core/src/flet_core/view.py
@@ -4,10 +4,7 @@
 from flet_core.app_bar import AppBar
 from flet_core.bottom_app_bar import BottomAppBar
 from flet_core.control import OptionalNumber
-from flet_core.floating_action_button import (
-    FloatingActionButton,
-    FloatingActionButtonLocation,
-)
+from flet_core.floating_action_button import FloatingActionButton
 from flet_core.navigation_bar import NavigationBar
 from flet_core.cupertino_navigation_bar import CupertinoNavigationBar
 from flet_core.navigation_drawer import NavigationDrawer
@@ -15,6 +12,7 @@
 from flet_core.types import (
     CrossAxisAlignment,
     CrossAxisAlignmentString,
+    FloatingActionButtonLocation,
     MainAxisAlignment,
     MainAxisAlignmentString,
     PaddingValue,

From 340121abf3fa514fb913e8a485218a52c6f50fd3 Mon Sep 17 00:00:00 2001
From: ndonkoHenri <robotcoder4@protonmail.com>
Date: Fri, 22 Dec 2023 13:25:14 +0100
Subject: [PATCH 8/8] sort imports

---
 package/lib/src/controls/create_control.dart       | 14 ++++++++------
 package/lib/src/controls/submenu_button.dart       |  2 ++
 .../packages/flet-core/src/flet_core/menu_bar.py   | 13 ++++---------
 .../flet-core/src/flet_core/menu_item_button.py    |  2 +-
 .../flet-core/src/flet_core/submenu_button.py      |  6 +++---
 5 files changed, 18 insertions(+), 19 deletions(-)

diff --git a/package/lib/src/controls/create_control.dart b/package/lib/src/controls/create_control.dart
index 10ae79463..19be5e404 100644
--- a/package/lib/src/controls/create_control.dart
+++ b/package/lib/src/controls/create_control.dart
@@ -1,12 +1,8 @@
 import 'dart:math';
 
-import 'package:collection/collection.dart';
-import 'package:flet/src/controls/menu_bar.dart';
-import 'package:flet/src/controls/search_anchor.dart';
-import 'package:flet/src/controls/menu_item_button.dart';
-import 'package:flet/src/controls/segmented_button.dart';
-import 'package:flet/src/controls/submenu_button.dart';
 import 'package:flutter/material.dart';
+
+import 'package:collection/collection.dart';
 import 'package:flutter_redux/flutter_redux.dart';
 
 import '../flet_app_services.dart';
@@ -17,6 +13,7 @@ import '../models/page_media_view_model.dart';
 import '../utils/animations.dart';
 import '../utils/theme.dart';
 import '../utils/transforms.dart';
+
 import 'alert_dialog.dart';
 import 'animated_switcher.dart';
 import 'audio.dart';
@@ -62,6 +59,8 @@ import 'linechart.dart';
 import 'list_tile.dart';
 import 'list_view.dart';
 import 'markdown.dart';
+import 'menu_bar.dart';
+import 'menu_item_button.dart';
 import 'navigation_bar.dart';
 import 'navigation_rail.dart';
 import 'outlined_button.dart';
@@ -76,6 +75,8 @@ import 'range_slider.dart';
 import 'responsive_row.dart';
 import 'row.dart';
 import 'safe_area.dart';
+import 'search_anchor.dart';
+import 'segmented_button.dart';
 import 'selection_area.dart';
 import 'semantics.dart';
 import 'shader_mask.dart';
@@ -83,6 +84,7 @@ import 'shake_detector.dart';
 import 'slider.dart';
 import 'snack_bar.dart';
 import 'stack.dart';
+import 'submenu_button.dart';
 import 'switch.dart';
 import 'tabs.dart';
 import 'text.dart';
diff --git a/package/lib/src/controls/submenu_button.dart b/package/lib/src/controls/submenu_button.dart
index 20b5e897b..ff2048667 100644
--- a/package/lib/src/controls/submenu_button.dart
+++ b/package/lib/src/controls/submenu_button.dart
@@ -5,8 +5,10 @@ import '../models/control.dart';
 import '../utils/buttons.dart';
 import '../utils/menu.dart';
 import '../utils/transforms.dart';
+
 import 'create_control.dart';
 
+
 class SubMenuButtonControl extends StatefulWidget {
   final Control? parent;
   final Control control;
diff --git a/sdk/python/packages/flet-core/src/flet_core/menu_bar.py b/sdk/python/packages/flet-core/src/flet_core/menu_bar.py
index ad181d9a8..c09dd5d05 100644
--- a/sdk/python/packages/flet-core/src/flet_core/menu_bar.py
+++ b/sdk/python/packages/flet-core/src/flet_core/menu_bar.py
@@ -1,19 +1,14 @@
 import dataclasses
 from dataclasses import field
-from typing import Any, List, Optional, Union, Dict
+from typing import Any, Dict, List, Optional, Union
 
 from flet_core.alignment import Alignment
 from flet_core.border import BorderSide
-from flet_core.gesture_detector import MouseCursor
 from flet_core.buttons import OutlinedBorder
 from flet_core.control import Control, OptionalNumber
+from flet_core.gesture_detector import MouseCursor
 from flet_core.ref import Ref
-from flet_core.types import (
-    PaddingValue,
-    ResponsiveNumber,
-    ClipBehavior,
-    MaterialState,
-)
+from flet_core.types import ClipBehavior, MaterialState, PaddingValue, ResponsiveNumber
 
 
 @dataclasses.dataclass
@@ -49,7 +44,7 @@ class MenuBar(Control):
     """
     A menu bar that manages cascading child menus.
 
-    It could be placed anywhere but typically resides above the main body of the application 
+    It could be placed anywhere but typically resides above the main body of the application
     and defines a menu system for invoking callbacks in response to user selection of a menu item.
 
     -----
diff --git a/sdk/python/packages/flet-core/src/flet_core/menu_item_button.py b/sdk/python/packages/flet-core/src/flet_core/menu_item_button.py
index 3399c1a95..33c72af3b 100644
--- a/sdk/python/packages/flet-core/src/flet_core/menu_item_button.py
+++ b/sdk/python/packages/flet-core/src/flet_core/menu_item_button.py
@@ -7,11 +7,11 @@
 from flet_core.ref import Ref
 from flet_core.types import (
     AnimationValue,
+    ClipBehavior,
     OffsetValue,
     ResponsiveNumber,
     RotateValue,
     ScaleValue,
-    ClipBehavior,
 )
 
 
diff --git a/sdk/python/packages/flet-core/src/flet_core/submenu_button.py b/sdk/python/packages/flet-core/src/flet_core/submenu_button.py
index 0275ebdc7..2a9cdfa6b 100644
--- a/sdk/python/packages/flet-core/src/flet_core/submenu_button.py
+++ b/sdk/python/packages/flet-core/src/flet_core/submenu_button.py
@@ -1,18 +1,18 @@
 import time
-from typing import Any, Optional, Union, List
+from typing import Any, List, Optional, Union
 
+from flet_core.buttons import ButtonStyle
 from flet_core.constrained_control import ConstrainedControl
 from flet_core.control import Control, OptionalNumber
 from flet_core.menu_bar import MenuStyle
-from flet_core.buttons import ButtonStyle
 from flet_core.ref import Ref
 from flet_core.types import (
     AnimationValue,
+    ClipBehavior,
     OffsetValue,
     ResponsiveNumber,
     RotateValue,
     ScaleValue,
-    ClipBehavior,
 )