diff --git a/client/lib/controls/create_control.dart b/client/lib/controls/create_control.dart
index 16adf9a3d..f9556aa2f 100644
--- a/client/lib/controls/create_control.dart
+++ b/client/lib/controls/create_control.dart
@@ -12,6 +12,7 @@ import 'circle_avatar.dart';
import 'clipboard.dart';
import 'column.dart';
import 'container.dart';
+import 'divider.dart';
import 'dropdown.dart';
import 'elevated_button.dart';
import 'floating_action_button.dart';
@@ -35,6 +36,7 @@ import 'tabs.dart';
import 'text.dart';
import 'text_button.dart';
import 'textfield.dart';
+import 'vertical_divider.dart';
// abstract class ControlWidget extends Widget {
// const ControlWidget(
@@ -75,6 +77,10 @@ Widget createControl(Control? parent, String id, bool parentDisabled) {
return ClipboardControl(control: controlView.control);
case ControlType.image:
return ImageControl(parent: parent, control: controlView.control);
+ case ControlType.divider:
+ return DividerControl(control: controlView.control);
+ case ControlType.verticalDivider:
+ return VerticalDividerControl(control: controlView.control);
case ControlType.circleAvatar:
return CircleAvatarControl(
parent: parent,
diff --git a/client/lib/controls/divider.dart b/client/lib/controls/divider.dart
new file mode 100644
index 000000000..30a4767b9
--- /dev/null
+++ b/client/lib/controls/divider.dart
@@ -0,0 +1,31 @@
+import 'package:flutter/material.dart';
+
+import '../models/control.dart';
+import '../utils/colors.dart';
+import 'create_control.dart';
+
+class DividerControl extends StatelessWidget {
+ final Control? parent;
+ final Control control;
+
+ const DividerControl({Key? key, this.parent, required this.control})
+ : super(key: key);
+
+ @override
+ Widget build(BuildContext context) {
+ debugPrint("Divider build: ${control.id}");
+
+ var height = control.attrDouble("height");
+ var thickness = control.attrDouble("thickness");
+ var color = HexColor.fromString(context, control.attrString("color", "")!);
+
+ return baseControl(
+ Divider(
+ height: height,
+ thickness: thickness,
+ color: color,
+ ),
+ parent,
+ control);
+ }
+}
diff --git a/client/lib/controls/elevated_button.dart b/client/lib/controls/elevated_button.dart
index 2f62b5dbd..0a64f539f 100644
--- a/client/lib/controls/elevated_button.dart
+++ b/client/lib/controls/elevated_button.dart
@@ -28,10 +28,13 @@ class ElevatedButtonControl extends StatelessWidget {
IconData? icon = getMaterialIcon(control.attrString("icon", "")!);
Color? iconColor =
HexColor.fromString(context, control.attrString("iconColor", "")!);
+ Color? color =
+ HexColor.fromString(context, control.attrString("color", "")!);
+ Color? bgcolor =
+ HexColor.fromString(context, control.attrString("bgcolor", "")!);
+ var elevation = control.attrDouble("elevation");
var contentCtrls = children.where((c) => c.name == "content");
bool autofocus = control.attrBool("autofocus", false)!;
- bool filled = control.attrBool("filled", false)!;
- bool filledTonal = control.attrBool("filledTonal", false)!;
bool disabled = control.isDisabled || parentDisabled;
Function()? onPressed = disabled
@@ -47,20 +50,13 @@ class ElevatedButtonControl extends StatelessWidget {
ElevatedButton? button;
ButtonStyle? style;
- if (filled) {
+ if (color != null || bgcolor != null || elevation != null) {
style = ElevatedButton.styleFrom(
// Foreground color
- onPrimary: Theme.of(context).colorScheme.onPrimary,
+ onPrimary: color,
// Background color
- primary: Theme.of(context).colorScheme.primary,
- ).copyWith(elevation: ButtonStyleButton.allOrNull(0.0));
- } else if (filledTonal) {
- style = ElevatedButton.styleFrom(
- // Foreground color
- onPrimary: Theme.of(context).colorScheme.onSecondaryContainer,
- // Background color
- primary: Theme.of(context).colorScheme.secondaryContainer,
- ).copyWith(elevation: ButtonStyleButton.allOrNull(0.0));
+ primary: bgcolor,
+ ).copyWith(elevation: ButtonStyleButton.allOrNull(elevation));
}
if (icon != null) {
diff --git a/client/lib/controls/vertical_divider.dart b/client/lib/controls/vertical_divider.dart
new file mode 100644
index 000000000..95b8533ed
--- /dev/null
+++ b/client/lib/controls/vertical_divider.dart
@@ -0,0 +1,31 @@
+import 'package:flutter/material.dart';
+
+import '../models/control.dart';
+import '../utils/colors.dart';
+import 'create_control.dart';
+
+class VerticalDividerControl extends StatelessWidget {
+ final Control? parent;
+ final Control control;
+
+ const VerticalDividerControl({Key? key, this.parent, required this.control})
+ : super(key: key);
+
+ @override
+ Widget build(BuildContext context) {
+ debugPrint("VerticalDivider build: ${control.id}");
+
+ var width = control.attrDouble("width");
+ var thickness = control.attrDouble("thickness");
+ var color = HexColor.fromString(context, control.attrString("color", "")!);
+
+ return baseControl(
+ VerticalDivider(
+ width: width,
+ thickness: thickness,
+ color: color,
+ ),
+ parent,
+ control);
+ }
+}
diff --git a/client/lib/models/control_type.dart b/client/lib/models/control_type.dart
index 0fa0afe46..1e7fee5f2 100644
--- a/client/lib/models/control_type.dart
+++ b/client/lib/models/control_type.dart
@@ -6,6 +6,7 @@ enum ControlType {
clipboard,
column,
container,
+ divider,
dropdown,
dropdownOption,
elevatedButton,
@@ -32,5 +33,6 @@ enum ControlType {
tab,
text,
textButton,
- textField
+ textField,
+ verticalDivider
}
diff --git a/docs/roadmap.md b/docs/roadmap.md
index db845ad27..10ef169c9 100644
--- a/docs/roadmap.md
+++ b/docs/roadmap.md
@@ -13,8 +13,13 @@
* [x] Stack
* [x] ListView
* [x] GridView
+ * [ ] Divider
+ * [ ] VerticalDivider
* App structure and navigation
* [x] Tabs
+ * [ ] AppBar
+ * [ ] NavigationRail
+ * [ ] NavigationBar
* Basic controls
* [x] Text
* [x] Icon
@@ -24,10 +29,13 @@
* [x] ProgressRing
* Buttons
* [x] ElevatedButton
+ * [x] FilledButton
+ * [x] FilledTonalButton
* [x] OutlinedButton
* [x] TextButton
* [x] IconButton
* [x] FloatingActionButton
+ * [ ] PopupMenuButton
* Input and selections
* [x] TextField
* [x] Dropdown
@@ -59,12 +67,14 @@
## Sprint 2
+* Authentication
* Controls
+ * Navigation
+ * NavigationDrawer
* Layout
* Row (responsive)
* Column (responsive)
* Behavior
- * Complex embeddable values for `padding`, `marging`, etc, e.g. `.padding = { 'left': 10, 'right': 20 }`
* Visual Density ([more](https://api.flutter.dev/flutter/material/VisualDensity-class.html))
* Early detection of layout issues (like enabling scrolling in unbounded controls) with [Layout Builder](https://api.flutter.dev/flutter/widgets/LayoutBuilder-class.html).
* Scroll speed on Windows Desktop [The issue](https://github.com/flutter/flutter/issues/67985)
@@ -75,6 +85,17 @@
* [ ] Windows ("host" mode with hot reload)
* [ ] macOS ("host" mode with hot reload)
+## Year 2022
+
+* Grids
+* Charts
+* Navigation controls and Routing
+* Responsive layout
+* Adaptive controls
+* Animations
+* PubSub
+* DB
+
## Controls
diff --git a/sdk/python/flet/__init__.py b/sdk/python/flet/__init__.py
index 75189e28e..d875aaa24 100644
--- a/sdk/python/flet/__init__.py
+++ b/sdk/python/flet/__init__.py
@@ -5,8 +5,11 @@
from flet.column import Column
from flet.container import Container
from flet.control import Control
+from flet.divider import Divider
from flet.dropdown import Dropdown
from flet.elevated_button import ElevatedButton
+from flet.filled_button import FilledButton
+from flet.filled_tonal_button import FilledTonalButton
from flet.flet import *
from flet.floating_action_button import FloatingActionButton
from flet.grid_view import GridView
@@ -31,3 +34,4 @@
from flet.text_button import TextButton
from flet.textfield import TextField
from flet.theme import Theme
+from flet.vertical_divider import VerticalDivider
diff --git a/sdk/python/flet/divider.py b/sdk/python/flet/divider.py
new file mode 100644
index 000000000..072b07f22
--- /dev/null
+++ b/sdk/python/flet/divider.py
@@ -0,0 +1,66 @@
+from typing import Union
+
+import beartype
+
+from flet.control import Control, OptionalNumber
+from flet.ref import Ref
+
+
+class Divider(Control):
+ def __init__(
+ self,
+ ref: Ref = None,
+ opacity: OptionalNumber = None,
+ visible: bool = None,
+ data: any = None,
+ #
+ # Specific
+ #
+ height: OptionalNumber = None,
+ thickness: OptionalNumber = None,
+ color: str = None,
+ ):
+
+ Control.__init__(
+ self,
+ ref=ref,
+ opacity=opacity,
+ visible=visible,
+ data=data,
+ )
+
+ self.height = height
+ self.thickness = thickness
+ self.color = color
+
+ def _get_control_name(self):
+ return "divider"
+
+ # height
+ @property
+ def height(self):
+ return self._get_attr("height")
+
+ @height.setter
+ @beartype
+ def height(self, value: OptionalNumber):
+ self._set_attr("height", value)
+
+ # thickness
+ @property
+ def thickness(self):
+ return self._get_attr("thickness")
+
+ @thickness.setter
+ @beartype
+ def thickness(self, value: OptionalNumber):
+ self._set_attr("thickness", value)
+
+ # color
+ @property
+ def color(self):
+ return self._get_attr("color")
+
+ @color.setter
+ def color(self, value):
+ self._set_attr("color", value)
diff --git a/sdk/python/flet/elevated_button.py b/sdk/python/flet/elevated_button.py
index c48c03e18..9df7ec0e3 100644
--- a/sdk/python/flet/elevated_button.py
+++ b/sdk/python/flet/elevated_button.py
@@ -23,8 +23,9 @@ def __init__(
#
# Specific
#
- filled: bool = None,
- filled_tonal: bool = None,
+ color: str = None,
+ bgcolor: str = None,
+ elevation: OptionalNumber = None,
icon: str = None,
icon_color: str = None,
content: Control = None,
@@ -45,8 +46,9 @@ def __init__(
)
self.text = text
- self.filled = filled
- self.filled_tonal = filled_tonal
+ self.color = color
+ self.bgcolor = bgcolor
+ self.elevation = elevation
self.icon = icon
self.icon_color = icon_color
self.content = content
@@ -71,25 +73,33 @@ def text(self):
def text(self, value):
self._set_attr("text", value)
- # filled
+ # color
@property
- def filled(self):
- return self._get_attr("filled", data_type="bool", def_value=False)
+ def color(self):
+ return self._get_attr("color")
- @filled.setter
- @beartype
- def filled(self, value: Optional[bool]):
- self._set_attr("filled", value)
+ @color.setter
+ def color(self, value):
+ self._set_attr("color", value)
+
+ # bgcolor
+ @property
+ def bgcolor(self):
+ return self._get_attr("bgcolor")
+
+ @bgcolor.setter
+ def bgcolor(self, value):
+ self._set_attr("bgcolor", value)
- # filled_tonal
+ # elevation
@property
- def filled_tonal(self):
- return self._get_attr("filledTonal", data_type="bool", def_value=False)
+ def elevation(self) -> OptionalNumber:
+ return self._get_attr("elevation")
- @filled_tonal.setter
+ @elevation.setter
@beartype
- def filled_tonal(self, value: Optional[bool]):
- self._set_attr("filledTonal", value)
+ def elevation(self, value: OptionalNumber):
+ self._set_attr("elevation", value)
# icon
@property
diff --git a/sdk/python/flet/filled_button.py b/sdk/python/flet/filled_button.py
new file mode 100644
index 000000000..f55b76a10
--- /dev/null
+++ b/sdk/python/flet/filled_button.py
@@ -0,0 +1,53 @@
+from typing import Union
+
+from flet.control import Control, OptionalNumber
+from flet.elevated_button import ElevatedButton
+from flet.ref import Ref
+
+
+class FilledButton(ElevatedButton):
+ def __init__(
+ self,
+ text: str = None,
+ ref: Ref = None,
+ width: OptionalNumber = None,
+ height: OptionalNumber = None,
+ expand: Union[bool, int] = None,
+ opacity: OptionalNumber = None,
+ tooltip: str = None,
+ visible: bool = None,
+ disabled: bool = None,
+ data: any = None,
+ #
+ # Specific
+ #
+ icon: str = None,
+ icon_color: str = None,
+ content: Control = None,
+ autofocus: bool = None,
+ on_click=None,
+ ):
+ ElevatedButton.__init__(
+ self,
+ ref=ref,
+ width=width,
+ height=height,
+ expand=expand,
+ opacity=opacity,
+ tooltip=tooltip,
+ visible=visible,
+ disabled=disabled,
+ data=data,
+ #
+ # Specific
+ #
+ color="onPrimary",
+ bgcolor="primary",
+ elevation=0,
+ text=text,
+ icon=icon,
+ icon_color=icon_color,
+ content=content,
+ autofocus=autofocus,
+ on_click=on_click,
+ )
diff --git a/sdk/python/flet/filled_tonal_button.py b/sdk/python/flet/filled_tonal_button.py
new file mode 100644
index 000000000..33c242321
--- /dev/null
+++ b/sdk/python/flet/filled_tonal_button.py
@@ -0,0 +1,53 @@
+from typing import Union
+
+from flet.control import Control, OptionalNumber
+from flet.elevated_button import ElevatedButton
+from flet.ref import Ref
+
+
+class FilledTonalButton(ElevatedButton):
+ def __init__(
+ self,
+ text: str = None,
+ ref: Ref = None,
+ width: OptionalNumber = None,
+ height: OptionalNumber = None,
+ expand: Union[bool, int] = None,
+ opacity: OptionalNumber = None,
+ tooltip: str = None,
+ visible: bool = None,
+ disabled: bool = None,
+ data: any = None,
+ #
+ # Specific
+ #
+ icon: str = None,
+ icon_color: str = None,
+ content: Control = None,
+ autofocus: bool = None,
+ on_click=None,
+ ):
+ ElevatedButton.__init__(
+ self,
+ ref=ref,
+ width=width,
+ height=height,
+ expand=expand,
+ opacity=opacity,
+ tooltip=tooltip,
+ visible=visible,
+ disabled=disabled,
+ data=data,
+ #
+ # Specific
+ #
+ color="onSecondaryContainer",
+ bgcolor="secondaryContainer",
+ elevation=0,
+ text=text,
+ icon=icon,
+ icon_color=icon_color,
+ content=content,
+ autofocus=autofocus,
+ on_click=on_click,
+ )
diff --git a/sdk/python/flet/icon.py b/sdk/python/flet/icon.py
index a687d97de..f04e92f3e 100644
--- a/sdk/python/flet/icon.py
+++ b/sdk/python/flet/icon.py
@@ -1,5 +1,7 @@
from typing import Union
+from beartype import beartype
+
from flet.control import Control, OptionalNumber
from flet.ref import Ref
@@ -19,7 +21,7 @@ def __init__(
# Specific
#
color: str = None,
- size: float = None,
+ size: OptionalNumber = None,
):
Control.__init__(
@@ -64,5 +66,6 @@ def size(self):
return self._get_attr("size")
@size.setter
- def size(self, value):
+ @beartype
+ def size(self, value: OptionalNumber):
self._set_attr("size", value)
diff --git a/sdk/python/flet/vertical_divider.py b/sdk/python/flet/vertical_divider.py
new file mode 100644
index 000000000..bb15cf30f
--- /dev/null
+++ b/sdk/python/flet/vertical_divider.py
@@ -0,0 +1,66 @@
+from typing import Union
+
+import beartype
+
+from flet.control import Control, OptionalNumber
+from flet.ref import Ref
+
+
+class VerticalDivider(Control):
+ def __init__(
+ self,
+ ref: Ref = None,
+ opacity: OptionalNumber = None,
+ visible: bool = None,
+ data: any = None,
+ #
+ # Specific
+ #
+ width: OptionalNumber = None,
+ thickness: OptionalNumber = None,
+ color: str = None,
+ ):
+
+ Control.__init__(
+ self,
+ ref=ref,
+ opacity=opacity,
+ visible=visible,
+ data=data,
+ )
+
+ self.width = width
+ self.thickness = thickness
+ self.color = color
+
+ def _get_control_name(self):
+ return "verticaldivider"
+
+ # width
+ @property
+ def width(self):
+ return self._get_attr("width")
+
+ @width.setter
+ @beartype
+ def width(self, value: OptionalNumber):
+ self._set_attr("width", value)
+
+ # thickness
+ @property
+ def thickness(self):
+ return self._get_attr("thickness")
+
+ @thickness.setter
+ @beartype
+ def thickness(self, value: OptionalNumber):
+ self._set_attr("thickness", value)
+
+ # color
+ @property
+ def color(self):
+ return self._get_attr("color")
+
+ @color.setter
+ def color(self, value):
+ self._set_attr("color", value)
diff --git a/sdk/python/playground/buttons.py b/sdk/python/playground/buttons.py
index cd5519370..8bbe34599 100644
--- a/sdk/python/playground/buttons.py
+++ b/sdk/python/playground/buttons.py
@@ -6,6 +6,8 @@
from flet import (
Column,
ElevatedButton,
+ FilledButton,
+ FilledTonalButton,
FloatingActionButton,
Icon,
IconButton,
@@ -14,6 +16,7 @@
Row,
Text,
TextButton,
+ colors,
icons,
theme,
)
@@ -24,6 +27,7 @@
def main(page: Page):
page.title = "Buttons Example"
page.theme_mode = "light"
+ # page.theme = theme.Theme(color_scheme_seed="green", use_material3=True)
page.padding = 50
page.floating_action_button = FloatingActionButton(icon=icons.ADD)
@@ -56,70 +60,46 @@ def main(page: Page):
alignment="spaceAround",
),
),
+ Row(
+ [
+ ElevatedButton(
+ "Red button",
+ color=colors.WHITE,
+ bgcolor=colors.RED,
+ icon=icons.PALETTE,
+ ),
+ ElevatedButton(
+ "Green button",
+ color=colors.WHITE,
+ bgcolor=colors.GREEN,
+ icon=icons.PALETTE,
+ ),
+ ElevatedButton(
+ "Yellow button",
+ color=colors.BLACK,
+ bgcolor=colors.YELLOW,
+ icon=icons.PALETTE,
+ ),
+ ]
+ ),
#
#
#
- Text("Elevated Filled button", style="headlineMedium"),
- ElevatedButton("Filled button", filled=True),
- ElevatedButton("Disabled button", filled=True, disabled=True),
- ElevatedButton(
- "Button with icon and tooltip",
- filled=True,
- icon="chair_outlined",
- tooltip="Hey, click me!",
- ),
- ElevatedButton(
- "Button with colorful icon",
- filled=True,
- icon="park_rounded",
- icon_color="green400",
- ),
- ElevatedButton(
- width=150,
- filled=True,
- content=Row(
- [
- Icon(name="favorite", color="pink"),
- Icon(name="audiotrack", color="green"),
- Icon(name="beach_access", color="blue"),
- ],
- alignment="spaceAround",
- ),
- ),
+ Text("Filled button", style="headlineMedium"),
+ FilledButton("Filled button"),
+ FilledButton("Disabled button", disabled=True),
+ FilledButton("Filled with icon", icon=icons.ADD),
#
#
#
- Text("Elevated Filled Tonal button", style="headlineMedium"),
- ElevatedButton("Tonal button", filled_tonal=True),
- ElevatedButton("Disabled button", filled_tonal=True, disabled=True),
- ElevatedButton(
- "Button with icon and tooltip",
- filled_tonal=True,
- icon="chair_outlined",
- tooltip="Hey, click me!",
- ),
- ElevatedButton(
- "Button with colorful icon",
- filled_tonal=True,
- icon="park_rounded",
- icon_color="green400",
- ),
- ElevatedButton(
- width=150,
- filled_tonal=True,
- content=Row(
- [
- Icon(name="favorite", color="pink"),
- Icon(name="audiotrack", color="green"),
- Icon(name="beach_access", color="blue"),
- ],
- alignment="spaceAround",
- ),
- ),
+ Text("Filled tonal button", style="headlineMedium"),
+ FilledTonalButton("Filled tonal button"),
+ FilledTonalButton("Disabled button", disabled=True),
+ FilledTonalButton("Filled tonal with icon", icon=icons.ADD),
#
#
#
- Text("Outlined buttons", style="headlineMedium"),
+ Text("Outlined button", style="headlineMedium"),
OutlinedButton("Normal button"),
OutlinedButton("Disabled button", disabled=True),
OutlinedButton("Button with icon", icon="chair_outlined"),
@@ -139,7 +119,7 @@ def main(page: Page):
alignment="spaceAround",
),
),
- Text("Text buttons", style="headlineMedium"),
+ Text("Text button", style="headlineMedium"),
TextButton("Normal button"),
TextButton("Disabled button", disabled=True),
TextButton("Button with icon", icon="chair_outlined"),
@@ -159,7 +139,7 @@ def main(page: Page):
alignment="spaceAround",
),
),
- Text("Icon buttons", style="headlineMedium"),
+ Text("Icon button", style="headlineMedium"),
Row(
[
IconButton(