Showing preview only (404K chars total). Download the full file or copy to clipboard to get everything.
Repository: ndonkoHenri/Flet-Samples
Branch: master
Commit: a25c6aefa01e
Files: 83
Total size: 379.7 KB
Directory structure:
gitextract_f_v8w953/
├── .gitattributes
├── .gitignore
├── Flet-Utils/
│ ├── Dockerfile
│ ├── README.md
│ ├── assets/
│ │ ├── index.html
│ │ └── manifest.json
│ ├── fly.toml
│ ├── main.py
│ ├── requirements.txt
│ └── utils/
│ ├── alignment_utils.py
│ ├── blur_utils.py
│ ├── border_radius_utils.py
│ ├── border_utils.py
│ ├── circle_avatar_utils.py
│ ├── colors_utils.py
│ ├── divider_utils.py
│ ├── gradient_utils.py
│ ├── icon_utils.py
│ ├── icons_browser_utils.py
│ ├── padding_utils.py
│ ├── progress_bar_utils.py
│ ├── progress_ring_utils.py
│ ├── shadermask_utils.py
│ ├── shadow_utils.py
│ ├── shape_utils.py
│ ├── tooltip_utils.py
│ └── vertical_divider_utils.py
├── Forms/
│ ├── README.md
│ ├── login_utils.py
│ ├── login_with_captcha.py
│ └── requirements.txt
├── IP Revealer/
│ ├── README.md
│ ├── assets/
│ │ └── fonts/
│ │ ├── Plus_Jakarta_Sans/
│ │ │ └── OFL.txt
│ │ └── Stick/
│ │ └── OFL.txt
│ ├── main.py
│ ├── main_with_ipify.py
│ └── requirements.txt
├── LICENSE
├── Markdown Editor/
│ ├── Dockerfile
│ ├── README.md
│ ├── assets/
│ │ ├── index.html
│ │ └── manifest.json
│ ├── fly.toml
│ ├── main.py
│ ├── requirements.txt
│ └── utils.py
├── QR Code Generator/
│ ├── Dockerfile
│ ├── README.md
│ ├── assets/
│ │ ├── index.html
│ │ └── manifest.json
│ ├── fly.toml
│ ├── main.py
│ └── requirements.txt
├── README.md
├── Random Image Viewer/
│ ├── README.md
│ ├── assets/
│ │ ├── fonts/
│ │ │ ├── JetBrains_Mono/
│ │ │ │ └── OFL.txt
│ │ │ ├── Kalam/
│ │ │ │ └── OFL.txt
│ │ │ └── Space_Grotesk/
│ │ │ └── OFL.txt
│ │ ├── index.html
│ │ └── manifest.json
│ ├── main.py
│ ├── requirements.txt
│ └── utils.py
├── Short Jokes/
│ ├── README.md
│ ├── assets/
│ │ ├── fonts/
│ │ │ ├── JetBrains_Mono/
│ │ │ │ └── OFL.txt
│ │ │ ├── Kalam/
│ │ │ │ └── OFL.txt
│ │ │ └── Space_Grotesk/
│ │ │ └── OFL.txt
│ │ ├── index.html
│ │ └── manifest.json
│ ├── joke.py
│ ├── main.py
│ ├── requirements.txt
│ └── utils.py
├── StartUp Name Generator/
│ ├── README.md
│ ├── main.py
│ ├── requirements.txt
│ └── utils.py
└── URL shortener/
├── Dockerfile
├── README.md
├── assets/
│ └── index.html
├── fly.toml
├── main.py
└── requirements.txt
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitattributes
================================================
# Auto detect text files and perform LF normalization
* text=auto
================================================
FILE: .gitignore
================================================
/.idea
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
.pybuilder/
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
# For a library or package, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# .python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# poetry
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
# This is especially recommended for binary packages to ensure reproducibility, and is more
# commonly ignored for libraries.
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
#poetry.lock
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
# pytype static type analyzer
.pytype/
# Cython debug symbols
cython_debug/
# PyCharm
# JetBrains specific template is maintainted in a separate JetBrains.gitignore that can
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/
/main.py
/URL shortener/assets/manifest.json
================================================
FILE: Flet-Utils/Dockerfile
================================================
FROM python:3-alpine
WORKDIR /app
COPY requirements.txt ./
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
EXPOSE 8080
CMD ["python", "./main.py"]
================================================
FILE: Flet-Utils/README.md
================================================
# Flet-Utils (Flutils)
**Link to Online Demo [here](https://flutils.pages.dev/)!**
When developing with Flet([website](https://flet.dev), [gitHub](https://github.com/flet-dev/flet)), It's not that easy to work with classes that take alot of parameters.
Choosing the perfect values for the Padding, Alignment, Border Radius... of our Controls becomes very difficult, time-consuming and/or very annoying.
I then decided to build this tool - Flet Utils - to help out all those using Flet to build applications, to efficiently and rapidly choose parameters when working with Controls.
## Captures (to be added)
See the [website](https://flutils.pages.dev/) itself till I add please.
## Issues and Contribution
If you have any error/issue/problem using this app, please raise one on the [Issues section of this repo](https://github.com/ndonkoHenri/Flet-Samples/issues).
Also, feel free to a drop a pull request in case you wish to contribute.
**Flet-ty MEME by [@Hololeo](https://github.com/hololeo)**:
<img src="https://user-images.githubusercontent.com/98978078/195565736-170f1aea-ed0b-433c-ab2d-3a34d23a6994.jpeg" alt="thats-the-power-of-flet" width=80% align="center">
================================================
FILE: Flet-Utils/assets/index.html
================================================
<html><head>
<base href="/">
<meta charset="UTF-8">
<meta content="IE=Edge" http-equiv="X-UA-Compatible">
<meta name="description" content="A collection of utility tools for Flet developers.">
<!-- iOS meta tags & icons -->
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<meta name="apple-mobile-web-app-title" content="Flet Utilities">
<link rel="apple-touch-icon" href="icons/apple-touch-icon-192.png">
<!-- Favicon -->
<link rel="icon" type="image/png" href="favicon.png">
<!-- Flet specific -->
<meta name="flet-route-url-strategy" content="path">
<title>Flet Utilities</title>
<link rel="manifest" href="manifest.json">
<script>window.flutterWebRenderer="canvaskit";</script>
<script>
// The value below is injected by flutter build, do not touch.
var serviceWorkerVersion = '1463662306';
</script>
<!-- This script adds the flutter initialization JS code -->
<script src="flutter.js" defer=""></script>
<script src="https://unpkg.com/canvaskit-wasm@0.35.0/bin/canvaskit.js"></script></head>
<body>
<div id="loading" class="main_done">
<style>
body {
inset: 0; overflow: hidden;
margin: 0; padding: 0;
position: fixed;
}
#loading {
align-items: center;
display: flex;
height: 100%;
justify-content: center;
width: 100%;
}
#loading img {
animation: 1s ease-in-out 0s infinite alternate breathe;
opacity: .66;
transition: opacity .4s;
}
#loading.main_done img {
opacity: 1;
}
#loading.init_done img {
animation: .33s ease-in-out 0s 1 forwards zooooom;
opacity: .05;
}
@keyframes breathe { from { transform: scale(1) } to { transform: scale(0.95)}}
@keyframes zooooom { from { transform: scale(1) } to { transform: scale(10)}}
</style>
<img src="icons/loading-animation.png" alt="Loading indicator...">
</div>
<script>
window.addEventListener('load', function() {
var loading = document.querySelector('#loading');
_flutter.loader.loadEntrypoint({
serviceWorker: {
serviceWorkerVersion: serviceWorkerVersion,
}
}).then(function(engineInitializer) {
loading.classList.add('main_done');
return engineInitializer.initializeEngine();
}).then(function(appRunner) {
loading.classList.add('init_done');
return appRunner.runApp();
}).then(function(app) {
// Wait a few milliseconds so users can see the "zoooom" animation
// before getting rid of the "loading" div.
window.setTimeout(function() {
loading.remove();
}, 200);
});
});
</script>
<script src="main.dart.js" type="application/javascript"></script></body></html>
================================================
FILE: Flet-Utils/assets/manifest.json
================================================
{
"name": "Flet Utilities",
"short_name": "Flet Utils",
"start_url": ".",
"display": "standalone",
"background_color": "#ffffff",
"theme_color": "#0175C2",
"description": "A collection of utility tools for Flet developers.",
"orientation": "natural",
"prefer_related_applications": false,
"icons": [
{
"src": "icons/icon-192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "icons/icon-512.png",
"sizes": "512x512",
"type": "image/png"
},
{
"src": "icons/icon-maskable-192.png",
"sizes": "192x192",
"type": "image/png",
"purpose": "maskable"
},
{
"src": "icons/icon-maskable-512.png",
"sizes": "512x512",
"type": "image/png",
"purpose": "maskable"
}
]
}
================================================
FILE: Flet-Utils/fly.toml
================================================
app = "flutils"
kill_signal = "SIGINT"
kill_timeout = 5
processes = []
[env]
FLET_SERVER_PORT = "8080"
[experimental]
allowed_public_ports = []
auto_rollback = true
[[services]]
http_checks = []
internal_port = 8080
processes = ["app"]
protocol = "tcp"
script_checks = []
[services.concurrency]
hard_limit = 25
soft_limit = 20
type = "connections"
[[services.ports]]
force_https = true
handlers = ["http"]
port = 80
[[services.ports]]
handlers = ["tls", "http"]
port = 443
[[services.tcp_checks]]
grace_period = "1s"
interval = "15s"
restart_limit = 0
timeout = "2s"
================================================
FILE: Flet-Utils/main.py
================================================
import flet as ft
from utils.padding_utils import TabContentPadding
from utils.alignment_utils import TabContentAlignment
from utils.border_utils import TabContentBorder
from utils.border_radius_utils import TabContentBorderRadius
from utils.colors_utils import TabContentColors1, TabContentColors2
from utils.icons_browser_utils import TabContentIconsBrowser
from utils.gradient_utils import TabContentLinearGradient, TabContentSweepGradient, TabContentRadialGradient
from utils.shadermask_utils import TabContentShaderMask
from utils.shape_utils import TabContentShape
from utils.tooltip_utils import TabContentTooltip
from utils.icon_utils import TabContentIcon
from utils.progress_ring_utils import TabContentProgressRing
from utils.progress_bar_utils import TabContentProgressBar
from utils.divider_utils import TabContentDivider
from utils.vertical_divider_utils import TabContentVerticalDivider
from utils.circle_avatar_utils import TabContentCircleAvatar
from utils.shadow_utils import TabContentShadow
from utils.blur_utils import TabContentBlur
def main(page: ft.Page):
page.title = "Flet Utilities"
page.theme_mode = "light"
# page.window_always_on_top = True
page.vertical_alignment = "start"
# set the width and height of the window.
page.window_width = 640
page.window_height = 750
# page.horizontal_alignment = "center"
def change_theme(e):
"""
Changes the app's theme_mode, from dark to light or light to dark.
:param e: The event that triggered the function
:type e: ControlEvent
"""
page.theme_mode = "light" if page.theme_mode == "dark" else "dark" # changes the page's theme_mode
theme_icon_button.selected = not theme_icon_button.selected # changes the icon
page.update()
theme_icon_button = ft.IconButton(
ft.icons.DARK_MODE,
selected=False,
selected_icon=ft.icons.LIGHT_MODE,
icon_size=35,
tooltip="change theme",
on_click=change_theme,
style=ft.ButtonStyle(color={"": ft.colors.BLACK, "selected": ft.colors.WHITE}, ),
)
page.appbar = ft.AppBar(
title=ft.Text(
"Flet Utilities",
color="white"
),
center_title=True,
bgcolor="blue",
actions=[theme_icon_button],
leading=ft.IconButton(
icon=ft.icons.CODE,
icon_color=ft.colors.YELLOW_ACCENT,
on_click=lambda e: page.launch_url(
"https://github.com/ndonkoHenri/Flet-Samples/tree/master/Flet-Utils"),
tooltip="View Code"
),
)
icon_content = TabContentIcon()
tooltip_content = TabContentTooltip()
progress_ring_content = TabContentProgressRing()
progress_bar_content = TabContentProgressBar()
divider_content = TabContentDivider()
vertical_divider_content = TabContentVerticalDivider()
circle_avatar_content = TabContentCircleAvatar()
border_radius_content = TabContentBorderRadius()
padding_content = TabContentPadding()
icons_browser_content = TabContentIconsBrowser()
colors1_content = TabContentColors1()
colors2_content = TabContentColors2(page)
alignment_content = TabContentAlignment()
shape_content = TabContentShape()
shadow_content = TabContentShadow()
blur_content = TabContentBlur()
border_content = TabContentBorder()
linear_gradient_content = TabContentLinearGradient()
radial_gradient_content = TabContentRadialGradient()
sweep_gradient_content = TabContentSweepGradient()
shader_mask_content = TabContentShaderMask()
page.add(
ft.Tabs(
expand=True,
selected_index=0,
tabs=[
ft.Tab(
text="Icon",
content=icon_content
),
ft.Tab(
text="Tooltip",
content=tooltip_content
),
ft.Tab(
text="ProgressRing",
content=progress_ring_content
),
ft.Tab(
text="ProgressBar",
content=progress_bar_content
),
ft.Tab(
text="Divider",
content=divider_content
),
ft.Tab(
text="VerticalDivider",
content=vertical_divider_content
),
ft.Tab(
text="CircleAvatar",
content=circle_avatar_content
),
ft.Tab(
text="Shadow",
content=shadow_content
),
ft.Tab(
text="Blur",
content=blur_content
),
ft.Tab(
text="BorderRadius",
content=border_radius_content
),
ft.Tab(
text="Padding",
content=padding_content
),
ft.Tab(
text="Icons Browser",
content=icons_browser_content
),
ft.Tab(
text="Colors V1",
content=colors1_content
),
ft.Tab(
text="Colors V2",
content=colors2_content
),
ft.Tab(
text="Alignment",
content=alignment_content
),
ft.Tab(
text="Shape",
content=shape_content
),
ft.Tab(
text="Border",
content=border_content
),
ft.Tab(
text="Linear Gradient",
content=linear_gradient_content
),
ft.Tab(
text="Radial Gradient",
content=radial_gradient_content
),
ft.Tab(
text="Sweep Gradient",
content=sweep_gradient_content
),
ft.Tab(
text="Shader Mask",
content=shader_mask_content
),
]
),
ft.Text(
"Made with ❤ by @ndonkoHenri aka TheEthicalBoy!",
style=ft.TextThemeStyle.LABEL_SMALL,
weight=ft.FontWeight.BOLD,
italic=True,
color=ft.colors.BLUE_900,
)
)
ft.app(
target=main,
route_url_strategy="path",
assets_dir="assets",
view=ft.WEB_BROWSER
)
================================================
FILE: Flet-Utils/requirements.txt
================================================
flet==0.9.0
================================================
FILE: Flet-Utils/utils/alignment_utils.py
================================================
import flet as ft
# the content of the alignment tab
class TabContentAlignment(ft.UserControl):
def __init__(self):
super().__init__()
# slider for x parameter of the Alignment object
self.slider_x = ft.Slider(
label="x",
value=0,
on_change=self.update_alignment,
min=-1,
max=1,
divisions=100,
)
# slider for y parameter of the Alignment object
self.slider_y = ft.Slider(
label="y",
value=0,
on_change=self.update_alignment,
min=-1,
max=1,
divisions=100,
)
self.container_button = ft.Ref[ft.FilledTonalButton]()
self.container_obj = ft.Ref[ft.Container]()
def copy_to_clipboard(self, e: ft.ControlEvent):
"""
It copies the alignment used by the container to the clipboard.
:param e: The event object
"""
# update the text in the clipboard
e.page.set_clipboard(f"{self.container_obj.current.alignment}")
# show a snackbar to account for the changes
e.page.show_snack_bar(ft.SnackBar(ft.Text(f"Copied: {self.container_obj.current.alignment}"), open=True))
def update_alignment(self, e: ft.ControlEvent):
"""
It updates the alignment of the container object.
:param e: The event object
"""
# round the values from the sliders to 2 decimals to avoid long values, and store result in variables
x = round(float(self.slider_x.value), 2)
y = round(float(self.slider_y.value), 2)
# update container's alignment
self.container_obj.current.alignment = ft.Alignment(x, y)
# update the text of the button in the container
self.container_button.current.text = f"Pos: {x},{y}"
self.update()
# show a snackbar to account for the changes
e.page.show_snack_bar(ft.SnackBar(ft.Text("Updated Alignment!"), open=True))
def build(self):
all_sliders = ft.Row(
controls=[
self.slider_x,
self.slider_y
],
wrap=True
)
return ft.Column(
[
ft.Column(
[
ft.Text("Alignment Builder:", weight=ft.FontWeight.BOLD, size=21),
ft.Text(
"CheatSheet:\ntopLeft = (-1,-1) | topCenter = (0,-1) | topRight = (1,-1)\ncenterLeft = ("
"-1,0) | Center = (0,0) | centerRight = (1,0)\nbottomLeft = (-1,1) | bottomCenter = ("
"0,1) | bottomRight = (1,1)", italic=True, ),
all_sliders
],
alignment=ft.MainAxisAlignment.CENTER),
ft.Row(
[
ft.Container(
content=ft.FilledTonalButton(
content=ft.Text(
"Pos: 0.0,0.0",
weight=ft.FontWeight.BOLD
),
ref=self.container_button,
disabled=True
),
expand=True,
ref=self.container_obj,
bgcolor=ft.colors.DEEP_PURPLE_ACCENT_700,
width=160,
height=160,
alignment=ft.Alignment(0, 0), # align its contents in the center
)
],
alignment=ft.MainAxisAlignment.CENTER),
ft.Row(
[
ft.FilledButton(
"Copy Value to Clipboard",
icon=ft.icons.COPY,
on_click=self.copy_to_clipboard
),
ft.FilledTonalButton(
"Go to Docs",
icon=ft.icons.DATASET_LINKED_OUTLINED,
url="https://flet.dev/docs/controls/container/#alignment"
)
],
alignment=ft.MainAxisAlignment.CENTER,
)
],
alignment=ft.MainAxisAlignment.CENTER,
scroll=ft.ScrollMode.HIDDEN
)
if __name__ == "__main__":
def main(page: ft.Page):
page.add(TabContentAlignment())
ft.app(main)
================================================
FILE: Flet-Utils/utils/blur_utils.py
================================================
import random
from flet import *
import flet as ft
# todo: change link to docs
# the content of the blur tab
class TabContentBlur(ft.UserControl):
def __init__(self):
super().__init__()
self.blur_sigma_y = None
self.blur_sigma_x = None
self.blur_tile_mode = None
self.blur_obj = ft.Ref[ft.Container]()
# text field for the sigma x property of the Blur object
self.field_sigma_x = ft.TextField(
label="sigma_x",
helper_text="Union[int, float]",
value="",
on_change=self.update_blur,
keyboard_type=ft.KeyboardType.NUMBER,
expand=1
)
# text field for the sigma_y property of the Blur object
self.field_sigma_y = ft.TextField(
label="sigma_y",
value="",
helper_text="Union[int, float]",
on_change=self.update_blur,
keyboard_type=ft.KeyboardType.NUMBER,
expand=1
)
# radio buttons for the tile_mode parameter
self.tile_mode_radio_group = ft.RadioGroup(
ft.Row(
[
ft.Radio(value="clamp", label="clamp"),
ft.Radio(value="decal", label="decal"),
ft.Radio(value="mirror", label="mirror"),
ft.Radio(value="repeated", label="repeated"),
],
alignment=ft.MainAxisAlignment.CENTER
),
value="clamp",
on_change=self.update_blur,
)
def build(self):
all_fields = ft.Column(
controls=[
ft.Row(
[self.field_sigma_x, self.field_sigma_y]
),
self.tile_mode_radio_group,
],
alignment=ft.MainAxisAlignment.CENTER,
spacing=11,
)
w, h = 300, 300
return ft.Column(
[
ft.Text("Blur Builder:", weight=ft.FontWeight.BOLD, size=21),
all_fields,
ft.Row(
[
ft.Stack(
[
ft.Container(
ref=self.blur_obj,
# bgcolor=ft.colors.AMBER,
image_src=f"https://picsum.photos/300/300?random={random.randint(1, 500)}",
alignment=ft.alignment.center,
tooltip="reload page to get a new image",
width=w,
height=h,
),
ft.Container(
ref=self.blur_obj,
# bgcolor=ft.colors.AMBER,
alignment=ft.alignment.center,
width=w,
height=h,
),
]
)
],
alignment=ft.MainAxisAlignment.CENTER,
),
ft.Row(
[
ft.FilledButton(
"Copy Value to Clipboard",
icon=ft.icons.COPY,
on_click=self.copy_to_clipboard
),
ft.FilledTonalButton(
"Go to Docs",
icon=ft.icons.DATASET_LINKED_OUTLINED,
url="https://flet.dev/docs/controls/verticaldivider/"
)
],
alignment=ft.MainAxisAlignment.CENTER,
)
],
alignment=ft.MainAxisAlignment.CENTER,
scroll=ft.ScrollMode.HIDDEN,
spacing=30,
expand=True
)
def update_blur(self, e: ft.ControlEvent):
"""It updates the blur object."""
self.blur_sigma_x, self.blur_sigma_y = (
int(self.field_sigma_x.value.strip()) if self.field_sigma_x.value.strip().isnumeric() else None,
int(self.field_sigma_y.value.strip()) if self.field_sigma_y.value.strip().isnumeric() else None,
)
self.blur_tile_mode = self.tile_mode_radio_group.value
# sigma_y
try:
if self.field_sigma_y.value:
self.blur_sigma_y = eval(self.field_sigma_y.value)
assert isinstance(self.blur_sigma_y,
(int, float)), "`sigma_y` must be either of type float or int !"
else:
self.blur_sigma_y = None
except Exception as x:
print(f"Sigma Y Error: {x}")
e.page.show_snack_bar(ft.SnackBar(ft.Text(f"ERROR: {x}"), open=True))
return
# sigma_x
try:
if self.field_sigma_x.value:
self.blur_sigma_x = eval(self.field_sigma_x.value)
assert isinstance(self.blur_sigma_x,
(int, float)), "`sigma_x` must be either of type float or int !"
else:
self.blur_sigma_x = None
except Exception as x:
print(f"Sigma X Error: {x}")
e.page.show_snack_bar(ft.SnackBar(ft.Text(f"ERROR: {x}"), open=True))
return
self.blur_obj.current.blur = ft.Blur(self.blur_sigma_x, self.blur_sigma_y, self.blur_tile_mode)
self.update()
e.page.show_snack_bar(ft.SnackBar(ft.Text("Updated Blur!"), open=True))
def copy_to_clipboard(self, e: ft.ControlEvent):
"""It copies the blur object/instance to the clipboard."""
val = self.blur_obj.current.blur
e.page.set_clipboard(val)
e.page.show_snack_bar(ft.SnackBar(ft.Text(f"Copied: {val}"), open=True))
print(val)
if __name__ == "__main__":
def main(page: ft.Page):
page.theme_mode = ft.ThemeMode.LIGHT
page.window_always_on_top = True
page.add(TabContentBlur())
ft.app(main, view=ft.WEB_BROWSER)
================================================
FILE: Flet-Utils/utils/border_radius_utils.py
================================================
import flet as ft
# the content of the border radius tab
class TabContentBorderRadius(ft.UserControl):
def __init__(self):
super().__init__()
# text field for topLeft(tl) property of the BorderRadius object
self.field_tl = ft.TextField(
label="topLeft",
value="",
width=120,
height=50,
on_change=self.update_border_radius,
keyboard_type=ft.KeyboardType.NUMBER
)
# text field for topRight(tr) property of the BorderRadius object
self.field_tr = ft.TextField(
label="topRight",
value="",
width=120,
height=50,
on_change=self.update_border_radius,
keyboard_type=ft.KeyboardType.NUMBER
)
# text field for bottomLeft(bl) property of the BorderRadius object
self.field_bl = ft.TextField(
label="bottomLeft",
value="",
width=120,
height=50,
on_change=self.update_border_radius,
keyboard_type=ft.KeyboardType.NUMBER
)
# text field for bottomRight(br) property of the BorderRadius object
self.field_br = ft.TextField(
label="bottomRight",
value="",
width=120,
height=50,
on_change=self.update_border_radius,
keyboard_type=ft.KeyboardType.NUMBER
)
# text field for the width property of the Container object
self.field_width = ft.TextField(
label="Width",
hint_text=f"default=160",
value="160",
width=120,
height=50,
on_submit=self.update_container_size
)
# text field for the height property of the Container object
self.field_height = ft.TextField(
label="Height",
hint_text=f"default=160",
value="160",
width=120,
height=50,
on_submit=self.update_container_size
)
self.container_obj = ft.Ref[ft.Container]()
self.container_text = ft.Ref[ft.Text]()
def update_border_radius(self, e: ft.ControlEvent):
"""
It updates the border radius of the container object.
:param e: The event object
"""
if e.control.value.strip().isnumeric() or not e.control.value.strip():
# if the value of the text field in focus is numeric or if it is empty...
self.container_obj.current.border_radius = ft.border_radius.BorderRadius(
int(self.field_tl.value.strip()) if self.field_tl.value.strip().isnumeric() else 0,
int(self.field_tr.value.strip()) if self.field_tr.value.strip().isnumeric() else 0,
int(self.field_bl.value.strip()) if self.field_bl.value.strip().isnumeric() else 0,
int(self.field_br.value.strip()) if self.field_br.value.strip().isnumeric() else 0, )
self.container_text.current.value = f"{int(self.field_tl.value.strip()) if self.field_tl.value.strip().isnumeric() else 0}, {int(self.field_tr.value.strip()) if self.field_tr.value.strip().isnumeric() else 0}, {int(self.field_bl.value.strip()) if self.field_bl.value.strip().isnumeric() else 0}, {int(self.field_br.value.strip()) if self.field_br.value.strip().isnumeric() else 0} "
self.update()
e.page.show_snack_bar(ft.SnackBar(ft.Text("Updated BorderRadius!"), open=True))
else:
# Show a snackbar with the error message.
e.page.show_snack_bar(
ft.SnackBar(ft.Text("ERROR: The value(ex: non-integer) entered is not valid!"), open=True))
def update_container_size(self, e: ft.ControlEvent):
"""
The function updates the container size when the width or height values are changed.
:param e: The event object
"""
if e.control.value.strip().isnumeric():
# if the value of the text field in focus is numeric...
self.container_obj.current.height = int(
self.field_height.value.strip()) if self.field_height.value.strip().isnumeric() else 160
self.container_obj.current.width = int(
self.field_width.value.strip()) if self.field_width.value.strip().isnumeric() else 160
self.container_obj.current.update()
e.page.show_snack_bar(ft.SnackBar(ft.Text("Updated Container Size!"), open=True))
else:
# Show a snackbar with the error message.
e.page.show_snack_bar(
ft.SnackBar(ft.Text("ERROR: The value(ex: non-integer) entered is not valid!"), open=True))
def copy_to_clipboard(self, e: ft.ControlEvent):
"""
It copies the border radius of the container to the clipboard.
:param e: The event object
"""
e.page.set_clipboard(f"{self.container_obj.current.border_radius}")
e.page.show_snack_bar(ft.SnackBar(ft.Text(f"Copied: {self.container_obj.current.border_radius}"), open=True))
def build(self):
all_fields = ft.Row(
controls=[
self.field_tl, self.field_tr, self.field_bl, self.field_br
],
alignment=ft.MainAxisAlignment.CENTER,
)
return ft.Column(
[
ft.Column(
[
ft.Text("Container's Size:", weight=ft.FontWeight.BOLD, size=21),
ft.Row(
[self.field_width, self.field_height],
alignment=ft.MainAxisAlignment.CENTER,
),
ft.Divider(height=2, thickness=2),
ft.Text("BorderRadius Builder:", weight=ft.FontWeight.BOLD, size=21),
all_fields
],
alignment=ft.MainAxisAlignment.CENTER
),
ft.Row(
[
ft.Container(
content=ft.Text(
"0, 0, 0, 0",
ref=self.container_text,
weight=ft.FontWeight.BOLD,
size=18,
color="black"),
ref=self.container_obj,
bgcolor=ft.colors.RED_ACCENT_700,
padding=ft.Padding(15, 0, 15, 0),
width=160,
height=160,
alignment=ft.Alignment(0, 0),
border_radius=ft.BorderRadius(0, 0, 0, 0),
)
],
alignment=ft.MainAxisAlignment.CENTER),
ft.Row(
[
ft.FilledButton(
"Copy Value to Clipboard",
icon=ft.icons.COPY,
on_click=self.copy_to_clipboard
),
ft.FilledTonalButton(
"Go to Docs",
icon=ft.icons.DATASET_LINKED_OUTLINED,
url="https://flet.dev/docs/controls/container#border_radius"
),
],
alignment=ft.MainAxisAlignment.CENTER,
)
],
alignment=ft.MainAxisAlignment.CENTER,
scroll=ft.ScrollMode.HIDDEN
)
if __name__ == "__main__":
def main(page: ft.Page):
page.add(TabContentBorderRadius())
ft.app(main)
================================================
FILE: Flet-Utils/utils/border_utils.py
================================================
import flet as ft
# todo: add respective colors to each
# the content of the border tab
class TabContentBorder(ft.UserControl):
# border = border.only(BorderSide(2, "blue"), BorderSide(2, "blue"), BorderSide(2, "blue"), BorderSide(2, "blue"),)
def __init__(self):
super().__init__()
self.container_obj = ft.Ref[ft.Container]()
# text field for left property of the Border object
self.field_left = ft.TextField(
label="left",
value="",
width=120,
height=50,
content_padding=9,
on_change=self.update_border,
keyboard_type=ft.KeyboardType.NUMBER
)
# text field for right property of the Border object
self.field_right = ft.TextField(
label="right",
value="",
width=120,
height=50,
content_padding=9,
on_change=self.update_border,
keyboard_type=ft.KeyboardType.NUMBER
)
# text field for top property of the Border object
self.field_top = ft.TextField(
label="top",
value="",
width=120,
height=50,
content_padding=9,
on_change=self.update_border,
keyboard_type=ft.KeyboardType.NUMBER
)
# text field for bottom property of the Border object
self.field_bottom = ft.TextField(
label="bottom",
value="",
width=120,
height=50,
content_padding=9,
on_change=self.update_border,
keyboard_type=ft.KeyboardType.NUMBER
)
# text field for the width property of the Container object
self.field_width = ft.TextField(
label="Width",
hint_text=f"default=160",
value="160",
width=120,
height=50,
content_padding=9,
on_submit=self.update_container_size
)
# text field for the height property of the Container object
self.field_height = ft.TextField(
label="Height",
hint_text=f"default=160",
value="160",
width=120,
height=50,
content_padding=9,
on_submit=self.update_container_size
)
def update_border(self, e: ft.ControlEvent):
"""
It updates the border radius of the container object.
:param e: The event object
"""
left, right, top, bottom = int(
self.field_left.value.strip()) if self.field_left.value.strip().isnumeric() else 0, int(
self.field_right.value.strip()) if self.field_right.value.strip().isnumeric() else 0, int(
self.field_top.value.strip()) if self.field_top.value.strip().isnumeric() else 0, int(
self.field_bottom.value.strip()) if self.field_bottom.value.strip().isnumeric() else 0
if e.control.value.strip().isnumeric() or not e.control.value.strip():
# if the value of the text field in focus is numeric or if it is empty...
self.container_obj.current.border = ft.border.only(
ft.BorderSide(left, ft.colors.GREEN_700),
ft.BorderSide(top, ft.colors.GREEN_700),
ft.BorderSide(right, ft.colors.GREEN_700),
ft.BorderSide(bottom, ft.colors.GREEN_700)
)
self.update()
e.page.show_snack_bar(ft.SnackBar(ft.Text("Updated Border!"), open=True))
else:
# Show a snackbar with the error message.
e.page.show_snack_bar(
ft.SnackBar(ft.Text("ERROR: The value(ex: non-integer) entered is not valid!"), open=True))
def update_container_size(self, e: ft.ControlEvent):
"""
The function updates the container size when the width or height values are changed.
:param e: The event object
"""
if e.control.value.strip().isnumeric():
# if the value of the text field in focus is numeric...
self.container_obj.current.height = int(
self.field_height.value.strip()) if self.field_height.value.strip().isnumeric() else 160
self.container_obj.current.width = int(
self.field_width.value.strip()) if self.field_width.value.strip().isnumeric() else 160
self.container_obj.current.update()
e.page.show_snack_bar(ft.SnackBar(ft.Text("Updated Container Size!"), open=True))
else:
# Show a snackbar with the error message.
e.page.show_snack_bar(
ft.SnackBar(ft.Text("ERROR: The value(ex: non-integer) entered is not valid!"), open=True))
def copy_to_clipboard(self, e: ft.ControlEvent):
"""
It copies the border radius of the container to the clipboard.
:param e: The event object
"""
e.page.set_clipboard(f"{self.container_obj.current.border}")
e.page.show_snack_bar(ft.SnackBar(ft.Text(f"Copied: {self.container_obj.current.border}"), open=True))
def build(self):
all_fields = ft.Row(
controls=[
self.field_left, self.field_right, self.field_top, self.field_bottom
],
alignment=ft.MainAxisAlignment.CENTER,
)
return ft.Column(
[
ft.Column(
[
ft.Text("Container's Size:", weight=ft.FontWeight.BOLD, size=21),
ft.Row(
[self.field_width, self.field_height],
alignment=ft.MainAxisAlignment.CENTER,
),
ft.Divider(height=2, thickness=2),
ft.Text("Container's Border:", weight=ft.FontWeight.BOLD, size=21),
all_fields
],
alignment=ft.MainAxisAlignment.CENTER
),
ft.Row(
[
ft.Container(
ref=self.container_obj,
bgcolor=ft.colors.RED_ACCENT_700,
padding=ft.Padding(15, 0, 15, 0),
width=160,
height=160,
alignment=ft.Alignment(0, 0),
border=ft.border.all(0, ft.colors.TRANSPARENT),
)
],
alignment=ft.MainAxisAlignment.CENTER),
ft.Row(
[
ft.FilledButton(
"Copy Value to Clipboard",
icon=ft.icons.COPY,
on_click=self.copy_to_clipboard
),
ft.FilledTonalButton(
"Go to Docs",
icon=ft.icons.DATASET_LINKED_OUTLINED,
url="https://flet.dev/docs/controls/container/#border"
)
],
alignment=ft.MainAxisAlignment.CENTER,
)
],
alignment=ft.MainAxisAlignment.CENTER,
scroll=ft.ScrollMode.HIDDEN
)
if __name__ == "__main__":
def main(page: ft.Page):
page.add(TabContentBorder())
ft.app(main)
================================================
FILE: Flet-Utils/utils/circle_avatar_utils.py
================================================
from flet import *
import flet as ft
# todo: "rotate" from icon_utils
# the content of the circle avatar tab
class TabContentCircleAvatar(ft.UserControl):
def __init__(self):
super().__init__()
self.avatar_background_image_url = None
self.avatar_foreground_image_url = None
self.avatar_content = None
self.avatar_radius = None
self.avatar_color = None
self.avatar_bgcolor = None
self.avatar_tooltip = None
self.avatar_min_radius = None
self.avatar_max_radius = None
self.avatar_width = None
self.avatar_height = None
self.avatar_opacity = None
self.avatar_rotate = None
self.avatar_scale = None
self.avatar_offset = None
self.avatar_obj = ft.Ref[ft.CircleAvatar]()
# text field for tooltip property of the CircleAvatar object
self.field_tooltip = ft.TextField(
label="tooltip",
value="",
helper_text="Optional[str]",
on_change=self.update_avatar,
keyboard_type=ft.KeyboardType.TEXT,
expand=1
)
# text field for color property of the CircleAvatar object
self.field_color = ft.TextField(
label="color",
value="",
helper_text="Optional[str]",
on_submit=self.update_avatar,
# on_blur=self.update_icon,
keyboard_type=ft.KeyboardType.TEXT,
hint_text="colors.RED_50 or red50",
expand=1
)
# text field for the bgcolor property of the CircleAvatar object
self.field_bgcolor = ft.TextField(
label="bgcolor",
value="",
helper_text="Optional[str]",
hint_text="colors.RED_50 or red50",
on_submit=self.update_avatar,
# on_blur=self.update_icon,
keyboard_type=ft.KeyboardType.TEXT,
expand=1,
# width=170,
)
# text field for background_image_url property of the CircleAvatar object
self.field_background_image_url = ft.TextField(
label="background_image_url",
value="",
helper_text="Optional[str]",
on_submit=self.update_avatar,
# on_blur=self.update_icon,
keyboard_type=ft.KeyboardType.TEXT,
hint_text="",
expand=1,
text_style=ft.TextStyle(color=ft.colors.BLUE)
)
# text field for foreground_image_url property of the CircleAvatar object
self.field_foreground_image_url = ft.TextField(
label="foreground_image_url",
value="https://avatars.githubusercontent.com/u/5041459?s=88&v=4",
helper_text="Optional[str]",
on_submit=self.update_avatar,
# on_blur=self.update_icon,
keyboard_type=ft.KeyboardType.TEXT,
hint_text="",
expand=1,
text_style=ft.TextStyle(color=ft.colors.BLUE)
)
# text field for the radius property of the CircleAvatar object
self.field_radius = ft.TextField(
label="radius",
helper_text="Union[int, float]",
# value="4",
on_change=self.update_avatar,
# on_blur=self.update_icon,
keyboard_type=ft.KeyboardType.NUMBER,
expand=1
)
# text field for the max_radius property of the CircleAvatar object
self.field_max_radius = ft.TextField(
label="max_radius",
helper_text="Union[int, float]",
# value="4",
on_change=self.update_avatar,
# on_blur=self.update_icon,
keyboard_type=ft.KeyboardType.NUMBER,
expand=1
)
# text field for the min_radius property of the CircleAvatar object
self.field_min_radius = ft.TextField(
label="min_radius",
helper_text="Union[int, float]",
# value="4",
on_change=self.update_avatar,
# on_blur=self.update_icon,
keyboard_type=ft.KeyboardType.NUMBER,
expand=1
)
# text field for the content property of the CircleAvatar object
self.field_content = ft.TextField(
label="content",
value="",
helper_text="Optional[Control]",
hint_text="Text('Hello')",
on_submit=self.update_avatar,
# on_blur=self.update_icon,
keyboard_type=ft.KeyboardType.TEXT,
# width=80,
expand=1
)
# text field for the width property of the CircleAvatar object
self.field_width = ft.TextField(
label="width",
value="",
helper_text="Union[int, float]",
on_submit=self.update_avatar,
on_blur=self.update_avatar,
keyboard_type=ft.KeyboardType.NUMBER,
# width=80,
expand=1
)
# text field for the height property of the CircleAvatar object
self.field_height = ft.TextField(
label="height",
value="",
helper_text="Union[int, float]",
on_submit=self.update_avatar,
on_blur=self.update_avatar,
keyboard_type=ft.KeyboardType.NUMBER,
# width=80,
expand=1
)
# text field for the opacity property of the CircleAvatar object
self.field_opacity = ft.TextField(
label="opacity",
value="",
helper_text="Union[int, float]",
on_change=self.update_avatar,
# on_blur=self.update_icon,
keyboard_type=ft.KeyboardType.NUMBER,
# width=170,
expand=1
)
# text field for the offset property of the CircleAvatar object
self.field_offset = ft.TextField(
label="offset",
value="",
helper_text="Optional[Offset, tuple]",
on_submit=self.update_avatar,
# on_blur=self.update_icon,
keyboard_type=ft.KeyboardType.TEXT,
expand=1
)
# text field for the scale property of the CircleAvatar object
self.field_scale = ft.TextField(
label="scale",
value="",
helper_text="Union[int, float, Scale]",
on_submit=self.update_avatar,
# on_blur=self.update_icon,
keyboard_type=ft.KeyboardType.TEXT,
# width=110,
expand=1
)
def build(self):
all_fields = ft.Column(
controls=[
ft.Row(
[self.field_content, self.field_foreground_image_url, self.field_background_image_url],
),
ft.Row(
[self.field_bgcolor, self.field_color, self.field_radius, self.field_min_radius, self.field_max_radius, self.field_opacity]
),
ft.Row(
[self.field_height, self.field_width, self.field_offset, self.field_scale, self.field_tooltip, ],
),
],
alignment=ft.MainAxisAlignment.CENTER,
spacing=11
)
return ft.Column(
[
ft.Text("Circle Avatar Builder:", weight=ft.FontWeight.BOLD, size=21),
all_fields,
ft.Row(
[
ft.CircleAvatar(
ref=self.avatar_obj,
foreground_image_url="https://avatars.githubusercontent.com/u/5041459?s=88&v=4"
)
],
alignment=ft.MainAxisAlignment.CENTER,
),
ft.Row(
[
ft.FilledButton(
"Copy Value to Clipboard",
icon=ft.icons.COPY,
on_click=self.copy_to_clipboard
),
ft.FilledTonalButton(
"Go to Docs",
icon=ft.icons.DATASET_LINKED_OUTLINED,
url="https://flet.dev/docs/controls/circleavatar"
)
],
alignment=ft.MainAxisAlignment.CENTER,
)
],
alignment=ft.MainAxisAlignment.CENTER,
scroll=ft.ScrollMode.HIDDEN,
spacing=30
)
def update_avatar(self, e: ft.ControlEvent):
"""It updates the CircleAvatar object."""
self.avatar_opacity, self.avatar_radius, self.avatar_min_radius, self.avatar_max_radius = (
int(self.field_opacity.value.strip()) if self.field_opacity.value.strip().isnumeric() else None,
int(self.field_radius.value.strip()) if self.field_radius.value.strip().isnumeric() else None,
int(self.field_min_radius.value.strip()) if self.field_min_radius.value.strip().isnumeric() else None,
int(self.field_max_radius.value.strip()) if self.field_max_radius.value.strip().isnumeric() else None
)
self.avatar_foreground_image_url, self.avatar_background_image_url = self.field_foreground_image_url.value, self.field_background_image_url.value
self.avatar_color = self.field_color.value.strip() if self.field_color.value.strip() else None
self.avatar_bgcolor = self.field_bgcolor.value.strip() if self.field_bgcolor.value.strip() else None
self.avatar_tooltip = self.field_tooltip.value.strip() if self.field_tooltip.value.strip() else None
self.avatar_offset = self.field_offset.value.strip() if self.field_offset.value.strip() else "None"
self.avatar_scale = self.field_scale.value.strip() if self.field_scale.value.strip() else "None"
# content
try:
if self.field_content.value:
self.avatar_content = eval(self.field_content.value)
assert isinstance(self.avatar_content, ft.Control), "`content` must be a flet Control !"
else:
self.avatar_content = None
except Exception as x:
print(f"Content Error: {x}")
e.page.show_snack_bar(ft.SnackBar(ft.Text(f"ERROR: {x}"), open=True))
return
# radius
try:
if self.field_radius.value:
self.avatar_radius = eval(self.field_radius.value)
assert isinstance(self.avatar_radius,
(int, float)), "`radius` must be either of type float or int !"
else:
self.avatar_radius = None
except Exception as x:
print(f"Radius Error: {x}")
e.page.show_snack_bar(ft.SnackBar(ft.Text(f"ERROR: {x}"), open=True))
return
# min_radius
try:
if self.field_min_radius.value:
self.avatar_min_radius = eval(self.field_min_radius.value)
assert isinstance(self.avatar_min_radius,
(int, float)), "`min_radius` must be either of type float or int !"
else:
self.avatar_min_radius = None
except Exception as x:
print(f"Min Radius Error: {x}")
e.page.show_snack_bar(ft.SnackBar(ft.Text(f"ERROR: {x}"), open=True))
return
# max_radius
try:
if self.field_max_radius.value:
self.avatar_max_radius = eval(self.field_max_radius.value)
assert isinstance(self.avatar_max_radius,
(int, float)), "`max_radius` must be either of type float or int !"
else:
self.avatar_max_radius = None
except Exception as x:
print(f"Max Radius Error: {x}")
e.page.show_snack_bar(ft.SnackBar(ft.Text(f"ERROR: {x}"), open=True))
return
# width
try:
if self.field_width.value:
self.avatar_width = eval(self.field_width.value)
assert isinstance(self.avatar_width, (int, float)), "`width` must be either of type float or int !"
else:
self.avatar_width = None
except Exception as x:
print(f"Width Error: {x}")
e.page.show_snack_bar(ft.SnackBar(ft.Text(f"ERROR: {x}"), open=True))
return
# height
try:
if self.field_height.value:
self.avatar_height = eval(self.field_height.value)
assert isinstance(self.avatar_height, (int, float)), "`height` must be either of type float or int !"
else:
self.avatar_height = None
except Exception as x:
print(f"Height Error: {x}")
e.page.show_snack_bar(ft.SnackBar(ft.Text(f"ERROR: {x}"), open=True))
return
# color
try:
if self.avatar_color is not None:
self.avatar_color = eval(self.avatar_color) if '.' in self.avatar_color else self.avatar_color.lower()
# Getting all the colors from flet's colors module
list_started = False
all_flet_colors = list()
for value in vars(ft.colors).values():
if value == "primary":
list_started = True
if list_started:
all_flet_colors.append(value)
# checking if all the entered colors exist in flet
if self.avatar_color not in all_flet_colors:
raise ValueError("Entered color was not found! See the colors browser for help!")
except Exception as x:
print(f"Color Error: {x}")
e.page.show_snack_bar(ft.SnackBar(ft.Text(f"ERROR: {x}"), open=True))
return
# bgcolor
try:
if self.avatar_bgcolor is not None:
self.avatar_bgcolor = eval(
self.avatar_bgcolor) if '.' in self.avatar_bgcolor else self.avatar_bgcolor.lower()
# Getting all the colors from flet's colors module
list_started = False
all_flet_colors = list()
for value in vars(ft.colors).values():
if value == "primary":
list_started = True
if list_started:
all_flet_colors.append(value)
# checking if all the entered colors exist in flet
if self.avatar_bgcolor not in all_flet_colors:
raise ValueError("Entered color was not found! See the colors browser for help!")
except Exception as x:
print(f"Bgcolor Error: {x}")
e.page.show_snack_bar(ft.SnackBar(ft.Text(f"ERROR: {x}"), open=True))
return
# offset
try:
self.avatar_offset = eval(self.avatar_offset)
if not isinstance(self.avatar_offset, ft.Offset) \
and not isinstance(self.avatar_offset, tuple) \
and self.avatar_offset is not None:
raise ValueError("Wrong Value!")
elif isinstance(self.avatar_offset, tuple) and len(self.avatar_offset) == 2:
self.avatar_offset = eval(f"Offset({self.avatar_offset[0]}, {self.avatar_offset[1]})")
except Exception as x:
print(f"Offset Error: {x}")
e.page.show_snack_bar(
ft.SnackBar(
ft.Text("ERROR: `offset` must be an Offset object or in the form x,y. Please check your input."),
open=True))
return
# scale
try:
self.avatar_scale = eval(self.avatar_scale)
if not isinstance(self.avatar_scale, ft.Scale) \
and not isinstance(self.avatar_scale, (int, float)) \
and self.avatar_scale is not None:
raise ValueError("Wrong Value!")
except Exception as x:
print(f"Scale Error: {x}")
e.page.show_snack_bar(
ft.SnackBar(ft.Text("ERROR: `scale` must be an Scale object. Please check your input."), open=True))
return
# opacity
try:
if self.field_opacity.value:
self.avatar_opacity = eval(self.field_opacity.value)
assert isinstance(self.avatar_opacity, (int, float)), "`opacity` must be either of type float or int !"
else:
self.avatar_opacity = None
except Exception as x:
print(f"Opacity Error: {x}")
e.page.show_snack_bar(ft.SnackBar(ft.Text(f"ERROR: {x}"), open=True))
return
self.avatar_obj.current.color = self.avatar_color
self.avatar_obj.current.bgcolor = self.avatar_bgcolor
self.avatar_obj.current.tooltip = self.avatar_tooltip
self.avatar_obj.current.foreground_image_url = self.avatar_foreground_image_url
self.avatar_obj.current.background_image_url = self.avatar_background_image_url
self.avatar_obj.current.content = self.avatar_content
self.avatar_obj.current.radius = self.avatar_radius
self.avatar_obj.current.min_radius = self.avatar_min_radius
self.avatar_obj.current.max_radius = self.avatar_max_radius
self.avatar_obj.current.width = self.avatar_width
self.avatar_obj.current.height = self.avatar_height
self.avatar_obj.current.opacity = self.avatar_opacity
self.avatar_obj.current.scale = self.avatar_scale
self.avatar_obj.current.offset = self.avatar_offset
# todo self.avatar_obj.current.rotate = self.avatar_rotate
self.update()
e.page.show_snack_bar(ft.SnackBar(ft.Text("Updated CircleAvatar!"), open=True))
def copy_to_clipboard(self, e: ft.ControlEvent):
"""It copies the tooltip object/instance to the clipboard."""
o = f", opacity={self.avatar_opacity}"
s = f", scale={self.avatar_scale}"
off = f", offset={self.avatar_offset}"
t = f", tooltip='{self.avatar_tooltip}'"
bg = f", bgcolor='{self.avatar_bgcolor}'"
c = f", color='{self.avatar_color}'"
w = f", width={self.avatar_width}"
h = f", height={self.avatar_height}"
r = f", radius={self.avatar_radius}"
minr = f", min_radius={self.avatar_min_radius}"
maxr = f", max_radius={self.avatar_max_radius}"
burl = f", background_image_url='{self.avatar_background_image_url}'"
furl = f", foreground_image_url='{self.avatar_foreground_image_url}'"
others = f"{maxr if self.avatar_max_radius is not None else ''}{minr if self.avatar_min_radius is not None else ''}{furl if self.avatar_foreground_image_url else ''}{burl if self.avatar_background_image_url else ''}{r if self.avatar_radius is not None else ''}{w if self.avatar_width is not None else ''}{h if self.avatar_height is not None else ''}{c if self.avatar_color is not None else ''}{bg if self.avatar_bgcolor is not None else ''}{t if self.avatar_tooltip else ''}{o if self.avatar_opacity is not None else ''}{s if self.avatar_scale is not None else ''}{off if self.avatar_offset is not None else ''}"
val = f"CircleAvatar(radius={self.avatar_radius}{others if others else ''})"
e.page.set_clipboard(val)
e.page.show_snack_bar(ft.SnackBar(ft.Text(f"Copied: {val}"), open=True))
print(val)
if __name__ == "__main__":
def main(page: ft.Page):
page.theme_mode = ft.ThemeMode.LIGHT
page.add(TabContentCircleAvatar())
ft.app(main)
================================================
FILE: Flet-Utils/utils/colors_utils.py
================================================
import flet as ft
from itertools import islice
# the content of the ColorV1 tab
class TabContentColors1(ft.UserControl):
# all this below was obtained from https://github.com/ndonkoHenri/Flet-Color-Browser
def __init__(self, expand=True):
"""
If the expand parameter is set to True, then the expand attribute of the object is set to True. Otherwise, the
height attribute of the object is set to the value of the height parameter.
:param expand: If True, the widget will expand to fill its parent, defaults to True (optional)
"""
super().__init__(expand=expand)
def build(self):
def batches(iterable, batch_size):
"""
It takes an iterable and a batch size, and returns an iterator that yields batches of the iterable
:param iterable: An iterable object (e.g. a list)
:param batch_size: The number of items to process in each batch
"""
iterator = iter(iterable)
while batch := list(islice(iterator, batch_size)):
yield batch
# fetch all icon constants from colors.py module and store them in a dict(colors_dict)
colors_dict = dict()
list_started = False
for key, value in vars(ft.colors).items():
if key == "PRIMARY":
# 'PRIMARY' is the first color-variable (our starting point)
list_started = True
if list_started:
# when this list_started is True, we create new key-value pair in our dictionary
colors_dict[key] = value
# Creating a text field
search_txt = ft.TextField(
expand=1,
hint_text="Enter keyword and press search button",
autofocus=True,
on_submit=lambda e: display_colors(e.control.value),
tooltip="search field",
label="Color Search Field"
)
def search_click(_):
"""
Called when the search button is pressed, it displays the colors.
"""
display_colors(search_txt.value)
# Creating a row with a search text field and a search button.
search_query = ft.Row(
[search_txt, ft.FloatingActionButton(icon=ft.icons.SEARCH, on_click=search_click, tooltip="search")]
)
# Creating a grid view with 10 columns and 150 pixels as the maximum extent of each column.
search_results = ft.GridView(
expand=1, runs_count=10, max_extent=150, spacing=5, run_spacing=5, child_aspect_ratio=1,
)
status_bar = ft.Text()
def copy_to_clipboard(e):
"""
When the user clicks on a color, copy the color key to the clipboard
:param e: The event object
"""
color_key = e.control.data
print("Copied to clipboard:", color_key)
self.page.set_clipboard(e.control.data)
self.page.show_snack_bar(ft.SnackBar(ft.Text(f"Copied: {color_key}"), open=True))
def search_colors(search_term: str):
"""
It takes a search term as an argument, and then loops through the colors_dict dictionary,
checking if the search term is in the color name or the color value. If it is, it yields the color key
:param search_term: The search term that the user entered
:return color_key: str
"""
for color_key, color_value in colors_dict.items():
# the color_key has underscores while the color_value doesn't. We take this into consideration
if search_term and (search_term in color_value or search_term in color_key.lower()):
yield color_key
def display_colors(search_term: str):
"""
It takes a search term, disables the search box, cleans the search results(grid view),
and then loops through the search results in batches of 40, adding each color to the search results
:param search_term: str
"""
# disable the text field and the search button, and clean search results
search_query.disabled = True
self.update()
search_results.clean()
# Adding the colors to the grid view in batches of 40.
for batch in batches(search_colors(search_term.lower()), 40):
for color_key in batch:
flet_color_key = f"colors.{color_key}"
search_results.controls.append(
ft.TextButton(
content=ft.Container(
content=ft.Column(
[
ft.Icon(name=ft.icons.RECTANGLE, size=40, color=colors_dict[color_key], ),
ft.Text(
value=f"{colors_dict[color_key]}", size=14, width=100,
no_wrap=True, text_align=ft.TextAlign.CENTER, color=colors_dict[color_key],
),
],
spacing=5,
alignment=ft.MainAxisAlignment.CENTER,
horizontal_alignment=ft.CrossAxisAlignment.CENTER,
),
alignment=ft.alignment.center,
),
tooltip=f"{flet_color_key}\nClick to copy to a clipboard",
on_click=copy_to_clipboard,
data=flet_color_key,
)
)
status_bar.value = f"Colors found: {len(search_results.controls)}"
self.update()
# It checks if the search results are empty, and if they are, it shows a snack bar some message
if len(search_results.controls) == 0:
# if no color was found containing the user's search term
self.page.show_snack_bar(ft.SnackBar(ft.Text("No colors found"), open=True))
search_query.disabled = False
self.update()
return ft.Column(
[
search_query,
search_results,
status_bar,
],
expand=True,
)
# the tiles used in the ColorV2 tab
class Tile(ft.Container):
# all this below was obtained from https://github.com/ndonkoHenri/Flet-Color-Browser
def __init__(self, tile_text, color, page):
super().__init__()
self.text = ft.Text(tile_text, text_align=ft.TextAlign.CENTER, weight=ft.FontWeight.BOLD, italic=True, )
self.color_text = f"colors.{tile_text}"
self.bgcolor = color
self.expand = True
self.height = 40
self.content = self.text
self.page = page
self.tooltip = "Click to copy to Clipboard"
def _build(self):
def click_event(_):
"""
It copies the color's text to the clipboard.
:param _: The event that triggered the function
"""
print("Copied to clipboard:", self.color_text)
self.page.set_clipboard(self.color_text)
self.page.show_snack_bar(ft.SnackBar(ft.Text(f"Copied: {self.color_text}!"), open=True))
self.on_click = click_event
return self
# the content of the ColorV2 tab
class TabContentColors2(ft.UserControl):
# all this below was obtained from https://github.com/ndonkoHenri/Flet-Color-Browser
def __init__(self, page):
"""
The function creates a reference to the Tabs object that will be created later, and creates a list of colors
that will be used to create the tabs.
:param page: This is a reference to the page object that is passed to the constructor of the class
"""
super().__init__(expand=True)
# A reference to the page object that is passed to the constructor of the class.
self.page = page
# Creating a reference to the Tabs object that will be created later.
self.displayed_tabs = ft.Ref[ft.Tabs]()
# A list of colors that will be used to create the tabs.
self.original_tab_names = ['RED', "BLACK", "WHITE", 'PINK', 'PURPLE', 'DEEP_PURPLE', 'INDIGO', 'BLUE',
'LIGHT_BLUE', 'CYAN', 'TEAL', 'GREEN', 'LIGHT_GREEN', 'LIME', 'YELLOW',
'AMBER', "ORANGE", 'DEEP_ORANGE', 'BROWN', "GREY", 'BLUE_GREY']
def build(self):
# Getting all the colors from the colors' module.
list_started = False
all_flet_colors = list()
for key in vars(ft.colors).keys():
if key == "PRIMARY":
list_started = True
if list_started:
all_flet_colors.append(key)
def create_tabs(tab_names: list) -> list:
"""
It takes a list of strings where each string represents the name of a tab to be shown, and returns a list
of tabs, each tab containing a list of tiles(containers) having a specific background color associated
with the text in it.
:param tab_names: list of strings that will be used to create the tabs
:type tab_names: list
:return: A list of tabs
"""
created_tabs = []
found = []
# iterate over the tab_names(list containing the tabs to be shown)
for tab_name in tab_names:
tab_content = ft.ListView()
for color in all_flet_colors:
tile_bgcolor = color.lower().replace("_", "")
tile_content = Tile(color, tile_bgcolor, self.page)
# Checking if the color starts with the tab_name and if the tab_name is in the color.
if (tab_name in color) and color.startswith(tab_name):
tab_content.controls.append(tile_content)
found.append(color)
# Add a tab with the name of the color and the content of the tab is a list of tiles.
# Also remove underscores from the tab's name.
created_tabs.append(ft.Tab(tab_name.replace("_", " "), content=tab_content, ))
# Creating a tab called "OTHERS" and adding all the colors that were not added to any other tab to it.
others = [i for i in all_flet_colors if i not in found]
others_content = ft.ListView(controls=[Tile(x, x.lower().replace("_", ""), self.page) for x in others])
created_tabs.append(ft.Tab("OTHERS", content=others_content))
return created_tabs
# self.displayed_tabs.current.tabs = create_tabs(self.original_tab_names)
def filter_tabs(_):
"""
If the text in the search field is "ALL", show all tabs. If the search field is not empty, show only the
tabs that contain the search term.
"""
filtered_tab_names = []
if search_field.value and search_field.value.lower().strip() == "all":
filtered_tab_names = self.original_tab_names
else:
for tab_name in self.original_tab_names:
if search_field.value and search_field.value.lower().strip() in tab_name.lower().replace("_", " "):
filtered_tab_names.append(tab_name)
if filtered_tab_names:
# Removing all the tabs from the Tabs object.
self.displayed_tabs.current.clean()
self.page.update()
# Updating the tabs of the Tabs object.
self.displayed_tabs.current.tabs = create_tabs(filtered_tab_names)
self.displayed_tabs.current.update()
return
# creating a field which will t=help the user search for specific tabs
search_field = ft.TextField(
label="Search Tabs...",
prefix_icon=ft.icons.SEARCH,
on_submit=filter_tabs,
border_radius=50,
suffix=ft.IconButton(
icon=ft.icons.CHECK,
bgcolor=ft.colors.INVERSE_PRIMARY,
icon_color=ft.colors.ERROR,
on_click=filter_tabs
),
helper_text="Tip: Enter 'ALL' to show all the tabs", height=70, width=450,
keyboard_type=ft.KeyboardType.TEXT,
capitalization=ft.TextCapitalization.CHARACTERS,
)
return ft.Column(
controls=[
search_field,
ft.Tabs(ref=self.displayed_tabs, expand=True,
tabs=create_tabs(self.original_tab_names))
]
)
if __name__ == "__main__":
def main(page: ft.Page):
page.add(TabContentColors1())
ft.app(main)
================================================
FILE: Flet-Utils/utils/divider_utils.py
================================================
from flet import *
import flet as ft
# the content of the divider tab
class TabContentDivider(ft.UserControl):
def __init__(self):
super().__init__()
self.divider_color = "green"
self.divider_tooltip = None
self.divider_thickness = 4
self.divider_height = None
self.divider_opacity = None
self.top_con_obj = ft.Ref[ft.Container]()
self.divider_obj = ft.Ref[ft.Divider]()
self.bottom_con_obj = ft.Ref[ft.Container]()
# text field for tooltip property of the Divider object
self.field_tooltip = ft.TextField(
label="tooltip",
value="",
helper_text="Optional[str]",
on_change=self.update_divider,
keyboard_type=ft.KeyboardType.TEXT,
expand=1
)
# text field for color property of the Divider object
self.field_color = ft.TextField(
label="color",
value="green",
helper_text="Optional[str]",
on_submit=self.update_divider,
keyboard_type=ft.KeyboardType.TEXT,
hint_text="colors.RED_50 or red50",
expand=1
)
# text field for the thickness property of the Divider object
self.field_thickness = ft.TextField(
label="thickness",
helper_text="Union[int, float]",
value="4",
on_change=self.update_divider,
keyboard_type=ft.KeyboardType.NUMBER,
expand=1
)
# text field for the height property of the Divider object
self.field_height = ft.TextField(
label="height",
value="",
helper_text="Union[int, float]",
on_change=self.update_divider,
keyboard_type=ft.KeyboardType.NUMBER,
expand=1
)
# text field for the opacity property of the Divider object
self.field_opacity = ft.TextField(
label="opacity",
value="",
helper_text="Union[int, float]",
on_change=self.update_divider,
keyboard_type=ft.KeyboardType.NUMBER,
expand=1
)
# checkbox
self.containers_checkbox = ft.Checkbox(
label="Don't show top and bottom containers.",
on_change=self.update_divider,
)
def build(self):
all_fields = ft.Column(
controls=[
ft.Row(
[self.field_thickness, self.field_height, self.field_opacity]
),
ft.Row(
[self.field_color, self.field_tooltip, ],
),
self.containers_checkbox
],
alignment=ft.MainAxisAlignment.CENTER,
spacing=11,
)
w, h = 300, 50
return ft.Column(
[
ft.Row([ft.Text("Divider Builder:", weight=ft.FontWeight.BOLD, size=21)]),
all_fields,
ft.Column(
[
ft.Container(
ref=self.top_con_obj,
bgcolor=ft.colors.AMBER,
alignment=ft.alignment.center,
width=w,
height=h,
),
ft.Divider(
ref=self.divider_obj,
thickness=4,
color="green"
),
ft.Container(
ref=self.bottom_con_obj,
bgcolor=ft.colors.AMBER,
alignment=ft.alignment.center,
width=w,
height=h,
),
],
alignment=ft.MainAxisAlignment.CENTER,
horizontal_alignment=ft.CrossAxisAlignment.CENTER,
spacing=0,
width=w
),
ft.Row(
[
ft.FilledButton(
"Copy Value to Clipboard",
icon=ft.icons.COPY,
on_click=self.copy_to_clipboard
),
ft.FilledTonalButton(
"Go to Docs",
icon=ft.icons.DATASET_LINKED_OUTLINED,
url="https://flet.dev/docs/controls/divider/"
)
],
alignment=ft.MainAxisAlignment.CENTER,
)
],
alignment=ft.MainAxisAlignment.CENTER,
horizontal_alignment=ft.CrossAxisAlignment.CENTER,
scroll=ft.ScrollMode.HIDDEN,
spacing=30,
expand=True
)
def update_divider(self, e: ft.ControlEvent):
"""It updates the Divider object."""
self.divider_opacity, self.divider_thickness, self.divider_height = (
int(self.field_opacity.value.strip()) if self.field_opacity.value.strip().isnumeric() else None,
int(self.field_thickness.value.strip()) if self.field_thickness.value.strip().isnumeric() else None,
int(self.field_height.value.strip()) if self.field_height.value.strip().isnumeric() else None,
)
self.divider_color = self.field_color.value.strip() if self.field_color.value.strip() else None
self.divider_tooltip = self.field_tooltip.value.strip() if self.field_tooltip.value.strip() else None
# thickness
try:
if self.field_thickness.value:
self.divider_thickness = eval(self.field_thickness.value)
assert isinstance(self.divider_thickness,
(int, float)), "`thickness` must be either of type float or int !"
else:
self.divider_thickness = None
except Exception as x:
print(f"Thickness Error: {x}")
e.page.show_snack_bar(ft.SnackBar(ft.Text(f"ERROR: {x}"), open=True))
return
# height
try:
if self.field_height.value:
self.divider_height = eval(self.field_height.value)
assert isinstance(self.divider_height, (int, float)), "`height` must be either of type float or int !"
else:
self.divider_height = None
except Exception as x:
print(f"Height Error: {x}")
e.page.show_snack_bar(ft.SnackBar(ft.Text(f"ERROR: {x}"), open=True))
return
# color
try:
if self.divider_color is not None:
self.divider_color = eval(self.divider_color) if '.' in self.divider_color else self.divider_color.lower()
# Getting all the colors from flet's colors module
list_started = False
all_flet_colors = list()
for value in vars(ft.colors).values():
if value == "primary":
list_started = True
if list_started:
all_flet_colors.append(value)
# checking if all the entered colors exist in flet
if self.divider_color not in all_flet_colors:
raise ValueError("Entered color was not found! See the colors browser for help!")
except Exception as x:
print(f"Color Error: {x}")
e.page.show_snack_bar(ft.SnackBar(ft.Text(f"ERROR: {x}"), open=True))
return
# opacity
try:
if self.field_opacity.value:
self.divider_opacity = eval(self.field_opacity.value)
assert isinstance(self.divider_opacity, (int, float)), "`opacity` must be either of type float or int !"
else:
self.divider_opacity = None
except Exception as x:
print(f"Opacity Error: {x}")
e.page.show_snack_bar(ft.SnackBar(ft.Text(f"ERROR: {x}"), open=True))
return
self.divider_obj.current.color = self.divider_color
self.divider_obj.current.tooltip = self.divider_tooltip
self.divider_obj.current.thickness = self.divider_thickness
self.divider_obj.current.height = self.divider_height
self.divider_obj.current.opacity = self.divider_opacity
self.top_con_obj.current.visible = not self.containers_checkbox.value
self.bottom_con_obj.current.visible = not self.containers_checkbox.value
self.update()
e.page.show_snack_bar(ft.SnackBar(ft.Text("Updated Divider!"), open=True))
def copy_to_clipboard(self, e: ft.ControlEvent):
"""It copies the tooltip object/instance to the clipboard."""
o = f", opacity={self.divider_opacity}"
t = f", tooltip='{self.divider_tooltip}'"
c = f", color='{self.divider_color}'"
th = f", thickness={self.divider_thickness}"
others = f"{th if self.divider_thickness is not None else ''}{c if self.divider_color is not None else ''}{t if self.divider_tooltip else ''}{o if self.divider_opacity is not None else ''}"
val = f"Divider(height={self.divider_height}{others if others else ''})"
e.page.set_clipboard(val)
e.page.show_snack_bar(ft.SnackBar(ft.Text(f"Copied: {val}"), open=True))
print(val)
if __name__ == "__main__":
def main(page: ft.Page):
page.theme_mode = ft.ThemeMode.LIGHT
page.window_always_on_top = True
page.add(TabContentDivider())
ft.app(main)
================================================
FILE: Flet-Utils/utils/gradient_utils.py
================================================
import math
from flet import *
import flet as ft
# the content of the LinearGradient tab
class TabContentLinearGradient(ft.UserControl):
def __init__(self):
super().__init__()
self.container_obj = ft.Ref[ft.Container]()
# field for begin parameter of the LinearGradient object
self.field_begin = ft.TextField(
label="begin",
value='-1, 0.5',
width=200,
on_submit=self.update_gradient,
hint_text="ex: -1, 0.5",
helper_text="Alignment object or x,y",
keyboard_type=ft.KeyboardType.TEXT,
)
# field for end parameter of the LinearGradient object
self.field_end = ft.TextField(
label="end",
value='Alignment(0, 1)',
on_submit=self.update_gradient,
width=200,
hint_text="ex: Alignment(0, 1)",
helper_text="Alignment object or x,y",
keyboard_type=ft.KeyboardType.TEXT,
)
# radio buttons for the tile_mode parameter
self.tile_mode_radio_group = ft.RadioGroup(
ft.Row(
[
ft.Radio(value="clamp", label="clamp"),
ft.Radio(value="decal", label="decal"),
ft.Radio(value="mirror", label="mirror"),
ft.Radio(value="repeated", label="repeated"),
],
alignment=ft.MainAxisAlignment.CENTER,
),
value="clamp",
on_change=self.update_gradient,
)
# text field for colors property of the LinearGradient object
self.field_colors = ft.TextField(
label="colors",
value="colors.RED_ACCENT\nYellow",
width=190,
on_submit=self.update_gradient,
keyboard_type=ft.KeyboardType.TEXT,
multiline=True,
shift_enter=True,
min_lines=2,
hint_text="colors.RED_50\npurple"
)
# text field for stops property of the LinearGradient object
self.field_stops = ft.TextField(
label="stops",
value="0.2\n0.7",
width=90,
on_submit=self.update_gradient,
keyboard_type=ft.KeyboardType.NUMBER,
shift_enter=True,
min_lines=2,
hint_text="0.2\n0.7"
)
# text field for rotation property of the LinearGradient object
self.field_rotation = ft.TextField(
label="rotation",
value="0",
width=110,
on_change=self.update_gradient,
keyboard_type=ft.KeyboardType.NUMBER,
suffix_text="°",
helper_text="In degrees",
hint_text="ex: 180",
)
# text field for the width property of the Container object
self.field_width = ft.TextField(
label="Width",
hint_text=f"default=160",
value="160",
width=120,
height=50,
on_submit=self.update_container_size,
)
# text field for the height property of the Container object
self.field_height = ft.TextField(
label="Height",
hint_text=f"default=160",
value="160",
width=120,
height=50,
on_submit=self.update_container_size,
)
def update_gradient(self, e: ft.ControlEvent):
"""
It updates the gradient of the container object.
:param e: The event object
"""
begin = self.field_begin.value.strip() if self.field_begin.value.strip() else "alignment.center_left"
end = self.field_end.value.strip() if self.field_end.value.strip() else "alignment.center_right"
clrs = self.field_colors.value.strip().split("\n") if self.field_colors.value.strip() else []
stops = self.field_stops.value.strip().split("\n") if self.field_stops.value.strip() else []
rotation = self.field_rotation.value.strip() if self.field_rotation.value.strip() else None
# tile_mode - How this gradient should tile the plane beyond in the region before begin and after end.
tile_mode = self.tile_mode_radio_group.value
# end - An instance of Alignment class. The offset at which stop 1.0 of the gradient is placed.
try:
end = eval(end)
if not isinstance(end, ft.Alignment) and not isinstance(end, tuple):
raise ValueError("Wrong Value!")
elif isinstance(end, tuple) and len(end) == 2:
end = eval(f"Alignment({end[0]}, {end[1]})")
except Exception as x:
print(f"End Error: {x}")
e.page.show_snack_bar(
ft.SnackBar(
ft.Text("ERROR: `end` must be an Alignment object or in the form x,y. Please check your input."),
open=True))
return
# begin - An instance of Alignment class. The offset at which stop 0.0 of the gradient is placed.
try:
begin = eval(begin)
if not isinstance(begin, ft.Alignment) and not isinstance(begin, tuple):
raise ValueError("Wrong Value!")
elif isinstance(begin, tuple) and len(begin) == 2:
begin = eval(f"Alignment({begin[0]}, {begin[1]})")
except Exception as x:
print(f"Begin Error: {x}")
e.page.show_snack_bar(
ft.SnackBar(
ft.Text("ERROR: `begin` must be an Alignment object or in the form x,y. Please check your input."),
open=True))
return
# rotation: rotation - rotation for the gradient, in radians, around the center-point of its bounding box.
try:
if rotation is not None:
rotation = round((math.pi * float(rotation)) / 180, 3) # convert to rads
except Exception as x:
print(f"Rotation Error: {x}")
e.page.show_snack_bar(
ft.SnackBar(
ft.Text(
"ERROR: For simplicity, `rotation` must be in degrees! It will be "
"converted to radians internally."),
open=True))
return
# colors: must have at least two colors in it (otherwise, it's not a gradient!).
if len(clrs) < 2:
e.page.show_snack_bar(
ft.SnackBar(ft.Text(
"ERROR: `colors` must have at least two colors. This could be gotten from the Colors V1/V2 "
"Tab here."),
open=True))
return
elif len(clrs) >= 2:
try:
clrs = [eval(c) if '.' in c else c.lower() for c in clrs]
# Getting all the colors from the flet.colors module.
list_started = False
all_flet_colors = list()
for value in vars(ft.colors).values():
if value == "primary":
list_started = True
if list_started:
all_flet_colors.append(value)
# checking if all the entered colors exist in flet
for i in clrs:
if i not in all_flet_colors:
raise ValueError("Entered color was not found! See the colors browser for help!")
except Exception as x:
print(f"Colors Error: {x}")
e.page.show_snack_bar(ft.SnackBar(ft.Text(f"ERROR: {x}"), open=True))
return
# stops: must have the same length as colors.
if stops and len(stops) >= 2:
try:
stops = [eval(s) for s in stops]
is_not_range = True if list(filter(lambda a: not 0.0 <= a <= 1.0, stops)) else False
if is_not_range: raise ValueError("Some values are out of the specified range(0.0 - 1.0)!")
except Exception as x:
print(f"Stops Error: {x}")
e.page.show_snack_bar(
ft.SnackBar(
ft.Text(
"ERROR: There seems to be an error with your stops. Please check your entries and "
"make sure they are between 0.0 and 1.0!"),
open=True))
return
elif stops and len(stops) < 2:
e.page.show_snack_bar(
ft.SnackBar(ft.Text(
"ERROR: `stops` is either empty or has a number of values(between 0.0 and 1.0) equal to those "
"in `colors`. This could be gotten from the Colors V1/V2 Tab here."),
open=True))
return
# compare colors and stops
if stops and len(clrs) != len(stops):
e.page.show_snack_bar(
ft.SnackBar(
ft.Text(
"ERROR: The number of values in `colors` must be equal to that in `stops`!"),
open=True))
return
# make the gradient visible
try:
self.container_obj.current.gradient = ft.LinearGradient(
colors=clrs,
tile_mode=tile_mode,
rotation=rotation,
stops=stops,
begin=begin,
end=end
)
self.update()
e.page.show_snack_bar(ft.SnackBar(ft.Text("Updated Gradient!"), open=True))
except Exception as x:
print(f"Display Error: {x}")
e.page.show_snack_bar(ft.SnackBar(ft.Text("ERROR: Display error!"), open=True))
return
def update_container_size(self, e: ft.ControlEvent):
"""
The function updates the container size when the width or height values are changed.
:param e: The event object
"""
if e.control.value.strip().isnumeric():
# if the value of the text field in focus is numeric...
self.container_obj.current.height = int(
self.field_height.value.strip()) if self.field_height.value.strip().isnumeric() else 160
self.container_obj.current.width = int(
self.field_width.value.strip()) if self.field_width.value.strip().isnumeric() else 160
self.container_obj.current.update()
e.page.show_snack_bar(ft.SnackBar(ft.Text("Updated Container Size!"), open=True))
else:
# Show a snackbar with the error message.
e.page.show_snack_bar(
ft.SnackBar(ft.Text("ERROR: The value(ex: non-integer) entered is not valid!"), open=True))
def copy_to_clipboard(self, e: ft.ControlEvent):
"""
It copies the gradient of the container to the clipboard.
:param e: The event object
"""
e.page.set_clipboard(f"{self.container_obj.current.gradient}")
e.page.show_snack_bar(ft.SnackBar(ft.Text(f"Copied: {self.container_obj.current.gradient}"), open=True))
def build(self):
begin_stop_fields = ft.Row(
controls=[
self.field_begin, self.field_end
],
alignment=ft.MainAxisAlignment.CENTER,
)
all_textfields = ft.Row(
controls=[
self.field_colors, self.field_stops, self.field_rotation
],
alignment=ft.MainAxisAlignment.CENTER
)
return ft.Column(
[
ft.Column(
[
ft.Text("Container's Size:", weight=ft.FontWeight.BOLD, size=21),
ft.Row(
[self.field_width, self.field_height],
alignment=ft.MainAxisAlignment.CENTER
),
ft.Divider(height=2, thickness=2),
ft.Text("Linear Gradient Builder:", weight=ft.FontWeight.BOLD, size=21),
all_textfields,
self.tile_mode_radio_group,
begin_stop_fields,
],
alignment=ft.MainAxisAlignment.CENTER,
),
ft.Row(
[
ft.Container(
ref=self.container_obj,
bgcolor=ft.colors.RED_ACCENT_700,
padding=ft.Padding(15, 0, 15, 0),
width=160,
height=160,
alignment=ft.Alignment(0, 0),
gradient=ft.LinearGradient(
colors=['redaccent', 'yellow'],
tile_mode=ft.GradientTileMode.MIRROR,
stops=[0.2, 0.7],
begin=ft.Alignment(x=-1, y=0.5),
rotation=0,
end=ft.Alignment(x=0, y=1), type='linear'
)
),
],
alignment=ft.MainAxisAlignment.CENTER),
ft.Row(
[
ft.FilledButton(
"Copy Value to Clipboard",
icon=ft.icons.COPY,
on_click=self.copy_to_clipboard,
),
ft.FilledTonalButton(
"Go to Docs",
icon=ft.icons.DATASET_LINKED_OUTLINED,
url="https://flet.dev/docs/controls/container#lineargradient"
)
],
alignment=ft.MainAxisAlignment.CENTER,
),
],
alignment=ft.MainAxisAlignment.CENTER,
scroll=ft.ScrollMode.HIDDEN,
)
# the content of the RadialGradient tab
class TabContentRadialGradient(ft.UserControl):
def __init__(self):
super().__init__()
self.container_obj = ft.Ref[ft.Container]()
# field for center parameter of the RadialGradient object
self.field_center = ft.TextField(
label="center",
value='0,0',
width=200,
on_submit=self.update_gradient,
hint_text="ex: -1, 0.5",
helper_text="Alignment object or x,y",
keyboard_type=ft.KeyboardType.TEXT,
)
# text field for focal property of the RadialGradient object
self.field_focal = ft.TextField(
label="focal",
value='0,0',
width=200,
on_submit=self.update_gradient,
hint_text="ex: -1, 0.5",
helper_text="Alignment object or x,y",
keyboard_type=ft.KeyboardType.TEXT,
)
# text field for rotation property of the LinearGradient object
self.field_rotation = ft.TextField(
label="rotation",
value="0",
width=110,
on_change=self.update_gradient,
keyboard_type=ft.KeyboardType.NUMBER,
suffix_text="°",
helper_text="In degrees",
hint_text="ex: 180",
)
# radio buttons for the tile_mode parameter
self.tile_mode_radio_group = ft.RadioGroup(
ft.Row(
[
ft.Radio(value="clamp", label="clamp"),
ft.Radio(value="decal", label="decal"),
ft.Radio(value="mirror", label="mirror"),
ft.Radio(value="repeated", label="repeated"),
],
alignment=ft.MainAxisAlignment.CENTER
),
value="clamp",
on_change=self.update_gradient,
)
# text field for colors property of the RadialGradient object
self.field_colors = ft.TextField(
label="colors",
value="colors.RED_ACCENT\nYellow",
width=190,
on_submit=self.update_gradient,
keyboard_type=ft.KeyboardType.TEXT,
multiline=True,
shift_enter=True,
min_lines=2,
hint_text="colors.RED_50\npurple"
)
# text field for stops property of the RadialGradient object
self.field_stops = ft.TextField(
label="stops",
value="0.2\n0.7",
width=90,
on_submit=self.update_gradient,
keyboard_type=ft.KeyboardType.NUMBER,
shift_enter=True,
min_lines=2,
hint_text="0.2\n0.7"
)
# text field for radius property of the RadialGradient object
self.field_radius = ft.TextField(
label="radius",
value="",
width=90,
on_change=self.update_gradient,
keyboard_type=ft.KeyboardType.NUMBER,
hint_text="ex: 0.5",
)
# text field for focal radius property of the RadialGradient object
self.field_focal_radius = ft.TextField(
label="focal radius",
value="0.3",
width=90,
on_change=self.update_gradient,
keyboard_type=ft.KeyboardType.NUMBER,
hint_text="ex: 0.5",
)
# text field for the width property of the Container object
self.field_width = ft.TextField(
label="Width",
hint_text=f"default=160",
value="160",
width=120,
height=50,
on_submit=self.update_container_size,
)
# text field for the height property of the Container object
self.field_height = ft.TextField(
label="Height",
hint_text=f"default=160",
value="160",
width=120,
height=50,
on_submit=self.update_container_size,
)
def update_gradient(self, e: ft.ControlEvent):
"""
It updates the gradient of the container object.
:param e: The event object
"""
center = self.field_center.value.strip() if self.field_center.value.strip() else "0,0"
clrs = self.field_colors.value.strip().split("\n") if self.field_colors.value.strip() else []
stops = self.field_stops.value.strip().split("\n") if self.field_stops.value.strip() else []
radius = self.field_radius.value.strip() if self.field_radius.value.strip() else "0.5"
focal = self.field_focal.value.strip() if self.field_focal.value.strip() else "None"
focal_radius = self.field_focal_radius.value.strip() if self.field_focal_radius.value.strip() else "0.0"
rotation = self.field_rotation.value.strip() if self.field_rotation.value.strip() else None
tile_mode = self.tile_mode_radio_group.value
# center - An instance of Alignment class.
try:
center = eval(center)
if not isinstance(center, ft.Alignment) and not isinstance(center, tuple):
raise ValueError("Wrong Value!")
elif isinstance(center, tuple) and len(center) == 2:
center = eval(f"Alignment({center[0]}, {center[1]})")
except Exception as x:
print(f"center Error: {x}")
e.page.show_snack_bar(
ft.SnackBar(
ft.Text(
"ERROR: `center` must be an Alignment object or in the form x,y. Please check your input."),
open=True))
return
# radius: The radius of the gradient, as a fraction of the shortest side of the paint box.
try:
radius = float(radius)
except Exception as x:
print(f"Radius Error: {x}")
e.page.show_snack_bar(
ft.SnackBar(
ft.Text(
"ERROR: There seems to be an error. Please check your entry for `radius`!"),
open=True))
return
# colors: must have at least two colors in it (otherwise, it's not a gradient!).
if len(clrs) < 2:
e.page.show_snack_bar(
ft.SnackBar(ft.Text(
"ERROR: `colors` must have at least two colors. This could be gotten from the Colors V1/V2 "
"Tab here."),
open=True))
return
elif len(clrs) >= 2:
try:
clrs = [eval(c) if '.' in c else c.lower() for c in clrs]
# Getting all the colors from the flet.colors module.
list_started = False
all_flet_colors = list()
for value in vars(ft.colors).values():
if value == "primary":
list_started = True
if list_started:
all_flet_colors.append(value)
# checking if all the entered colors exist in flet
for i in clrs:
if i not in all_flet_colors:
raise ValueError("Entered color was not found! See the colors browser for help!")
except Exception as x:
print(f"Colors Error: {x}")
e.page.show_snack_bar(ft.SnackBar(ft.Text(f"ERROR: {x}"), open=True))
return
# stops: must have the same length as colors.
if stops and len(stops) >= 2:
try:
stops = [eval(s) for s in stops]
is_not_range = True if list(filter(lambda a: not 0.0 <= a <= 1.0, stops)) else False
print(f"{stops=}")
if is_not_range: raise ValueError("Some values are out of the specified range(0.0 - 1.0)!")
except Exception as x:
print(f"Stops Error: {x}")
e.page.show_snack_bar(
ft.SnackBar(
ft.Text(
"ERROR: There seems to be an error with your stops. Please check your entries and "
"make sure they are between 0.0 and 1.0!"),
open=True))
return
elif stops and len(stops) < 2:
e.page.show_snack_bar(
ft.SnackBar(ft.Text(
"ERROR: `stops` is either empty or has a number of values(between 0.0 and 1.0) equal to those "
"in `colors`. This could be gotten from the Colors V1/V2 "
"Tab here."),
open=True))
return
# focal - The focal point of the gradient.
try:
focal = eval(focal)
if not isinstance(focal, ft.Alignment) and not isinstance(focal, tuple):
raise ValueError("Wrong Value!")
elif isinstance(focal, tuple) and len(focal) == 2:
focal = eval(f"Alignment({focal[0]}, {focal[1]})")
except Exception as x:
print(f"Focal Error: {x}")
e.page.show_snack_bar(
ft.SnackBar(
ft.Text("ERROR: `focal` must be an Alignment object or in the form x,y. Please check your input."),
open=True))
return
# focal_radius - The radius of the focal point of gradient.
try:
focal_radius = float(focal_radius)
except Exception as x:
print(f"Focal Radius Error: {x}")
e.page.show_snack_bar(
ft.SnackBar(
ft.Text(
"ERROR: There seems to be an error. Please check your entry for `focal_radius`!"),
open=True))
return
# rotation: rotation - rotation for the gradient, in radians, around the center-point of its bounding box.
try:
if rotation is not None:
rotation = round((math.pi * float(rotation)) / 180, 3) # convert to rads
except Exception as x:
print(f"Rotation Error: {x}")
e.page.show_snack_bar(
ft.SnackBar(
ft.Text(
"ERROR: For simplicity, `rotation` must be in degrees! It will be "
"converted to radians internally."),
open=True))
return
# compare colors and stops
if stops and len(clrs) != len(stops):
e.page.show_snack_bar(
ft.SnackBar(
ft.Text(
"ERROR: The number of values in `colors` must be equal to that in `stops`!"),
open=True))
return
# make the gradient visible
try:
self.container_obj.current.gradient = ft.RadialGradient(
colors=clrs,
tile_mode=tile_mode,
radius=radius,
stops=stops,
center=center,
focal=focal,
focal_radius=focal_radius,
rotation=rotation
)
print(self.container_obj.current.gradient)
self.update()
e.page.show_snack_bar(ft.SnackBar(ft.Text("Updated Gradient!"), open=True))
except Exception as x:
print(f"Display Error: {x}")
e.page.show_snack_bar(ft.SnackBar(ft.Text("ERROR: Display error!"), open=True))
return
def update_container_size(self, e: ft.ControlEvent):
"""
The function updates the container size when the width or height values are changed.
:param e: The event object
"""
if e.control.value.strip().isnumeric():
# if the value of the text field in focus is numeric...
self.container_obj.current.height = int(
self.field_height.value.strip()) if self.field_height.value.strip().isnumeric() else 160
self.container_obj.current.width = int(
self.field_width.value.strip()) if self.field_width.value.strip().isnumeric() else 160
self.container_obj.current.update()
e.page.show_snack_bar(ft.SnackBar(ft.Text("Updated Container Size!"), open=True))
else:
# Show a snackbar with the error message.
e.page.show_snack_bar(
ft.SnackBar(ft.Text("ERROR: The value(ex: non-integer) entered is not valid!"), open=True))
def copy_to_clipboard(self, e: ft.ControlEvent):
"""
It copies the gradient of the container to the clipboard.
:param e: The event object
"""
e.page.set_clipboard(f"{self.container_obj.current.gradient}")
e.page.show_snack_bar(ft.SnackBar(ft.Text(f"Copied: {self.container_obj.current.gradient}"), open=True))
def build(self):
# a row containing all the fields created above
center_focal_rotation_fields = ft.Row(
controls=[
self.field_center, self.field_focal, self.field_rotation
],
alignment=ft.MainAxisAlignment.CENTER,
)
# a row containing all the fields created above
all_textfields = ft.Row(
controls=[
self.field_colors, self.field_stops, self.field_radius, self.field_focal_radius
],
alignment=ft.MainAxisAlignment.CENTER,
)
return ft.Column(
[
ft.Column(
[
ft.Text("Container's Size:", weight=ft.FontWeight.BOLD, size=21),
ft.Row(
[self.field_width, self.field_height],
alignment=ft.MainAxisAlignment.CENTER,
),
ft.Divider(height=2, thickness=2),
ft.Text("Radial Gradient Builder:", weight=ft.FontWeight.BOLD, size=21),
all_textfields,
self.tile_mode_radio_group,
center_focal_rotation_fields
],
alignment=ft.MainAxisAlignment.CENTER
),
ft.Row(
[
ft.Container(
ref=self.container_obj,
bgcolor=ft.colors.RED_ACCENT_700,
padding=ft.padding.Padding(15, 0, 15, 0),
width=160,
height=160,
gradient=ft.RadialGradient(colors=['redaccent', 'yellow'], stops=[0.2, 0.7],
focal_radius=0.3)
)
],
alignment=ft.MainAxisAlignment.CENTER),
ft.Row(
[
ft.FilledButton(
"Copy Value to Clipboard",
icon=ft.icons.COPY,
on_click=self.copy_to_clipboard
),
ft.FilledTonalButton(
"Go to Docs",
icon=ft.icons.DATASET_LINKED_OUTLINED,
url="https://flet.dev/docs/controls/container#radialgradient"
)
],
alignment=ft.MainAxisAlignment.CENTER,
)
],
alignment=ft.MainAxisAlignment.CENTER,
scroll=ft.ScrollMode.HIDDEN
)
# the content of the SweepGradient tab
class TabContentSweepGradient(ft.UserControl):
def __init__(self):
super().__init__()
self.container_obj = ft.Ref[ft.Container]()
# field for center parameter of the SweepGradient object
self.field_center = ft.TextField(
label="center",
value='0,0',
width=200,
on_submit=self.update_gradient,
hint_text="ex: -1, 0.5",
helper_text="Alignment object or x,y",
keyboard_type=ft.KeyboardType.TEXT,
)
# text field for start_angle property of the SweepGradient object
self.field_start_angle = ft.TextField(
label="start angle",
value="0",
width=110,
on_change=self.update_gradient,
keyboard_type=ft.KeyboardType.NUMBER,
suffix_text="°",
helper_text="In degrees",
hint_text="ex: 180",
)
# text field for end_angle property of the SweepGradient object
self.field_end_angle = ft.TextField(
label="end angle",
value="",
width=110,
on_change=self.update_gradient,
keyboard_type=ft.KeyboardType.NUMBER,
suffix_text="°",
helper_text="In degrees",
hint_text="ex: 320",
)
# text field for colors property of the SweepGradient object
self.field_colors = ft.TextField(
label="colors",
value="colors.RED_ACCENT\nYellow",
width=190,
on_submit=self.update_gradient,
keyboard_type=ft.KeyboardType.TEXT,
multiline=True,
shift_enter=True,
min_lines=2,
hint_text="colors.RED_50\npurple"
)
# text field for stops property of the SweepGradient object
self.field_stops = ft.TextField(
label="stops",
value="0.2\n0.7",
width=90,
on_submit=self.update_gradient,
keyboard_type=ft.KeyboardType.NUMBER,
shift_enter=True,
min_lines=2,
hint_text="0.2\n0.7"
)
# text field for rotation property of the SweepGradient object
self.field_rotation = ft.TextField(
label="rotation",
value="",
width=110,
on_change=self.update_gradient,
keyboard_type=ft.KeyboardType.NUMBER,
suffix_text="°",
helper_text="In degrees",
hint_text="ex: 180",
)
# radio buttons for the tile_mode parameter
self.tile_mode_radio_group = ft.RadioGroup(
ft.Row(
[
ft.Radio(value="clamp", label="clamp"),
ft.Radio(value="decal", label="decal"),
ft.Radio(value="mirror", label="mirror"),
ft.Radio(value="repeated", label="repeated"),
],
alignment=ft.MainAxisAlignment.CENTER
),
value="clamp",
on_change=self.update_gradient,
)
# text field for the width property of the Container object
self.field_width = ft.TextField(
label="Width",
hint_text=f"default=160",
value="160",
width=120,
height=50,
on_submit=self.update_container_size,
)
# text field for the height property of the Container object
self.field_height = ft.TextField(
label="Height",
hint_text=f"default=160",
value="160",
width=120,
height=50,
on_submit=self.update_container_size,
)
def update_gradient(self, e: ft.ControlEvent):
"""
It updates the gradient of the container object.
:param e: The event object
"""
center = self.field_center.value.strip() if self.field_center.value.strip() else "0,0"
clrs = self.field_colors.value.strip().split("\n") if self.field_colors.value.strip() else []
stops = self.field_stops.value.strip().split("\n") if self.field_stops.value.strip() else []
start_angle = self.field_start_angle.value.strip() if self.field_start_angle.value.strip() else "0"
end_angle = self.field_end_angle.value.strip() if self.field_end_angle.value.strip() else "180"
rotation = self.field_rotation.value.strip() if self.field_rotation.value.strip() else None
tile_mode = self.tile_mode_radio_group.value
# center - An instance of Alignment class.
try:
center = eval(center)
if not isinstance(center, ft.Alignment) and not isinstance(center, tuple):
raise ValueError("Wrong Value!")
elif isinstance(center, tuple) and len(center) == 2:
center = eval(f"Alignment({center[0]}, {center[1]})")
except Exception as x:
print(f"center Error: {x}")
e.page.show_snack_bar(
ft.SnackBar(
ft.Text(
"ERROR: `center` must be an Alignment object or in the form x,y. Please check your input."),
open=True))
return
# colors: must have at least two colors in it (otherwise, it's not a gradient!).
if len(clrs) < 2:
e.page.show_snack_bar(
ft.SnackBar(ft.Text(
"ERROR: `colors` must have at least two colors. This could be gotten from the Colors V1/V2 "
"Tab here."),
open=True))
return
elif len(clrs) >= 2:
try:
clrs = [eval(c) if '.' in c else c.lower() for c in clrs]
# Getting all the colors from the flet.colors module.
list_started = False
all_flet_colors = list()
for value in vars(ft.colors).values():
if value == "primary":
list_started = True
if list_started:
all_flet_colors.append(value)
# checking if all the entered colors exist in flet
for i in clrs:
if i not in all_flet_colors:
raise ValueError("Entered color was not found! See the colors browser for help!")
except Exception as x:
print(f"Colors Error: {x}")
e.page.show_snack_bar(ft.SnackBar(ft.Text(f"ERROR: {x}"), open=True))
return
# stops: must have the same length as colors.
if stops and len(stops) >= 2:
try:
stops = [eval(s) for s in stops]
is_not_range = True if list(filter(lambda a: not 0.0 <= a <= 1.0, stops)) else False
print(f"{stops=}")
if is_not_range: raise ValueError("Some values are out of the specified range(0.0 - 1.0)!")
except Exception as x:
print(f"Stops Error: {x}")
e.page.show_snack_bar(
ft.SnackBar(
ft.Text(
"ERROR: There seems to be an error with your stops. Please check your entries and "
"make sure they are between 0.0 and 1.0!"),
open=True))
return
elif stops and len(stops) < 2:
e.page.show_snack_bar(
ft.SnackBar(ft.Text(
"ERROR: `stops` is either empty or has a number of values(between 0.0 and 1.0) equal to those "
"in `colors`. This could be gotten from the Colors V1/V2 "
"Tab here."),
open=True))
return
# rotation: rotation - rotation for the gradient, in radians, around the center-point of its bounding box.
try:
if rotation is not None:
rotation = round((math.pi * float(rotation)) / 180, 3) # convert to rads
except Exception as x:
print(f"Rotation Error: {x}")
e.page.show_snack_bar(
ft.SnackBar(
ft.Text(
"ERROR: For simplicity, `rotation` must be in degrees! It will be "
"converted to radians internally."),
open=True))
return
# start_angle : The angle in radians at which stop 0.0 of the gradient is placed. Defaults to 0.0.
try:
if start_angle is not None:
start_angle = round((math.pi * float(start_angle)) / 180, 3) # convert to rads
except Exception as x:
print(f"Start_angle Error: {x}")
e.page.show_snack_bar(
ft.SnackBar(
ft.Text(
"ERROR: For simplicity, `start_angle` must be in degrees! It will be "
"converted to radians internally."),
open=True))
return
# end_angle : The angle in radians at which stop 1.0 of the gradient is placed. Defaults to math.pi * 2.
try:
if end_angle is not None:
end_angle = round((math.pi * float(end_angle)) / 180, 3) # convert to rads
except Exception as x:
print(f"End_angle Error: {x}")
e.page.show_snack_bar(
ft.SnackBar(
ft.Text(
"ERROR: For simplicity, `end_angle` must be in degrees! It will be "
"converted to radians internally."),
open=True))
return
# compare colors and stops
if stops and len(clrs) != len(stops):
e.page.show_snack_bar(
ft.SnackBar(
ft.Text(
"ERROR: The number of values in `colors` must be equal to that in `stops`!"),
open=True))
return
# make the gradient visible
try:
self.container_obj.current.gradient = ft.SweepGradient(
colors=clrs,
tile_mode=tile_mode,
start_angle=start_angle,
end_angle=end_angle,
stops=stops,
center=center,
rotation=rotation
)
self.update()
e.page.show_snack_bar(ft.SnackBar(ft.Text("Updated Gradient!"), open=True))
except Exception as x:
print(f"Display Error: {x}")
e.page.show_snack_bar(
ft.SnackBar(
ft.Text(
"ERROR: Display error!"),
open=True))
return
def update_container_size(self, e: ft.ControlEvent):
"""
The function updates the container size when the width or height values are changed.
:param e: The event object
"""
if e.control.value.strip().isnumeric():
# if the value of the text field in focus is numeric...
self.container_obj.current.height = int(
self.field_height.value.strip()) if self.field_height.value.strip().isnumeric() else 160
self.container_obj.current.width = int(
self.field_width.value.strip()) if self.field_width.value.strip().isnumeric() else 160
self.container_obj.current.update()
e.page.show_snack_bar(ft.SnackBar(ft.Text("Updated Container Size!"), open=True))
else:
# Show a snackbar with the error message.
e.page.show_snack_bar(
ft.SnackBar(ft.Text("ERROR: The value(ex: non-integer) entered is not valid!"), open=True))
def copy_to_clipboard(self, e: ft.ControlEvent):
"""
It copies the gradient of the container to the clipboard.
:param e: The event object
"""
e.page.set_clipboard(f"{self.container_obj.current.gradient}")
e.page.show_snack_bar(ft.SnackBar(ft.Text(f"Copied: {self.container_obj.current.gradient}"), open=True))
def build(self):
center_focal_rotation_fields = ft.Row(
controls=[
self.field_center, self.field_start_angle, self.field_end_angle
],
alignment=ft.MainAxisAlignment.CENTER,
)
all_textfields = ft.Row(
controls=[
self.field_colors, self.field_stops, self.field_rotation,
],
alignment=ft.MainAxisAlignment.CENTER,
)
return ft.Column(
[
ft.Column(
[
ft.Text("Container's Size:", weight=ft.FontWeight.BOLD, size=21),
ft.Row(
[self.field_width, self.field_height],
alignment=ft.MainAxisAlignment.CENTER,
),
ft.Divider(height=2, thickness=2),
ft.Text("Sweep Gradient Builder:", weight=ft.FontWeight.BOLD, size=21),
all_textfields,
self.tile_mode_radio_group,
center_focal_rotation_fields
],
alignment=ft.MainAxisAlignment.CENTER
),
ft.Row(
[
ft.Container(
ref=self.container_obj,
bgcolor=ft.colors.RED_ACCENT_700,
padding=ft.padding.Padding(15, 0, 15, 0),
width=160,
height=160,
gradient=ft.SweepGradient(colors=['redaccent', 'yellow'], )
)
],
alignment=ft.MainAxisAlignment.CENTER),
ft.Row(
[
ft.FilledButton(
"Copy Value to Clipboard",
icon=ft.icons.COPY,
on_click=self.copy_to_clipboard
),
ft.FilledTonalButton(
"Go to Docs",
icon=ft.icons.DATASET_LINKED_OUTLINED,
url="https://flet.dev/docs/controls/container#sweepgradient"
)
],
alignment=ft.MainAxisAlignment.CENTER,
),
],
alignment=ft.MainAxisAlignment.CENTER,
scroll=ft.ScrollMode.HIDDEN
)
if __name__ == "__main__":
def main(page: ft.Page):
page.scroll = ft.ScrollMode.HIDDEN
page.add(
TabContentLinearGradient(),
TabContentRadialGradient(),
TabContentSweepGradient()
)
ft.app(main)
================================================
FILE: Flet-Utils/utils/icon_utils.py
================================================
import math
from flet import *
import flet as ft
# the content of the icon tab
class TabContentIcon(ft.UserControl):
def __init__(self):
super().__init__()
self.icon_color = "red900"
self.icon_name = "cake_rounded"
self.icon_size = 65
self.icon_tooltip = None
self.icon_opacity = None
self.icon_rotate = None
self.icon_scale = None
self.icon_offset = None
self.icon_obj = ft.Ref[ft.Icon]()
# text field for tooltip property of the Icon object
self.field_tooltip = ft.TextField(
label="tooltip",
value="",
helper_text="Optional[str]",
on_change=self.update_icon,
keyboard_type=ft.KeyboardType.TEXT,
expand=1
)
# text field for color property of the Icon object
self.field_color = ft.TextField(
label="color",
value="red900",
on_submit=self.update_icon,
# on_blur=self.update_icon,
keyboard_type=ft.KeyboardType.TEXT,
hint_text="colors.RED_50 or red50",
expand=1
)
# text field for the size property of the Icon object
self.field_size = ft.TextField(
label="size",
value="65",
helper_text="Union[int, float]",
on_submit=self.update_icon,
# on_blur=self.update_icon,
keyboard_type=ft.KeyboardType.NUMBER,
# expand=1
width=170,
)
# text field for the name property of the Icon object
self.field_name = ft.TextField(
label="name",
hint_text="ft.icons.COPY or COPY or copy",
value="cake_rounded",
on_submit=self.update_icon,
# on_blur=self.update_icon,
keyboard_type=ft.KeyboardType.TEXT,
expand=2
)
# text field for the opacity property of the Icon object
self.field_opacity = ft.TextField(
label="opacity",
value="",
helper_text="Union[int, float]",
on_change=self.update_icon,
# on_blur=self.update_icon,
keyboard_type=ft.KeyboardType.NUMBER,
width=170,
# expand=1
)
# text field for the rotate property of the Icon object
self.field_rotate = ft.TextField(
label="rotate | angle in degrees",
value="",
helper_text="Union[int, float, Rotate]",
on_submit=self.update_icon,
# on_blur=self.update_icon,
keyboard_type=ft.KeyboardType.TEXT,
expand=1
)
# text field for the offset property of the Icon object
self.field_offset = ft.TextField(
label="offset",
value="",
helper_text="Optional[Offset, tuple]",
on_submit=self.update_icon,
# on_blur=self.update_icon,
keyboard_type=ft.KeyboardType.TEXT,
expand=1
)
# text field for the scale property of the Icon object
self.field_scale = ft.TextField(
label="scale",
value="",
helper_text="Union[int, float, Scale]",
on_submit=self.update_icon,
# on_blur=self.update_icon,
keyboard_type=ft.KeyboardType.TEXT,
# width=110,
expand=1
)
def build(self):
all_fields = ft.Column(
controls=[
ft.Row(
[self.field_name, self.field_color],
),
ft.Row(
[self.field_tooltip, self.field_scale],
),
ft.Row(
[self.field_rotate, self.field_offset],
),
ft.Row(
[self.field_size, self.field_opacity],
alignment=ft.MainAxisAlignment.CENTER
)
],
alignment=ft.MainAxisAlignment.CENTER,
spacing=11
)
return ft.Column(
[
ft.Text("Icon Builder:", weight=ft.FontWeight.BOLD, size=21),
all_fields,
ft.Row(
[
ft.Icon(
ref=self.icon_obj,
name="cake_rounded",
size=65,
color="red900"
)
],
alignment=ft.MainAxisAlignment.CENTER,
),
ft.Row(
[
ft.FilledButton(
"Copy Value to Clipboard",
icon=ft.icons.COPY,
on_click=self.copy_to_clipboard
),
ft.FilledTonalButton(
"Go to Docs",
icon=ft.icons.DATASET_LINKED_OUTLINED,
url="https://flet.dev/docs/controls/icon"
)
],
alignment=ft.MainAxisAlignment.CENTER,
)
],
alignment=ft.MainAxisAlignment.CENTER,
scroll=ft.ScrollMode.HIDDEN,
spacing=25
)
def update_icon(self, e: ft.ControlEvent):
"""
It updates the Icon object.
:param e: The event object
"""
self.icon_size= int(self.field_size.value.strip()) if self.field_size.value.strip().isnumeric() else 65
self.icon_color = self.field_color.value.strip() if self.field_color.value.strip() else None
self.icon_name = self.field_name.value.strip() if self.field_name.value.strip() else "cake_rounded"
self.icon_tooltip = self.field_tooltip.value.strip() if self.field_tooltip.value.strip() else None
self.icon_offset = self.field_offset.value.strip() if self.field_offset.value.strip() else "None"
self.icon_rotate = self.field_rotate.value.strip() if self.field_rotate.value.strip() else "None"
self.icon_scale = self.field_scale.value.strip() if self.field_scale.value.strip() else "None"
# name
try:
if self.icon_name is not None:
self.icon_name = eval(self.icon_name) if '.' in self.icon_name else self.icon_name.lower()
# Getting all the icons from flet's icons module
list_started = False
all_flet_icons = list()
for value in vars(ft.icons).values():
if value == "ten_k":
list_started = True
if list_started:
all_flet_icons.append(value)
# checking if all the entered icons exist in flet
if self.icon_name not in all_flet_icons:
raise ValueError("Wrong Value!")
except Exception as x:
print(f"Name Error: {x}")
e.page.show_snack_bar(
ft.SnackBar(
ft.Text(
"ERROR: There seems to be an error with your icon's name. See the Icon tabs for "
f"help with choosing an icon name!"),
open=True))
return
# color
try:
if self.icon_color is not None:
self.icon_color = eval(self.icon_color) if '.' in self.icon_color else self.icon_color.lower()
# Getting all the colors from flet's colors module
list_started = False
all_flet_colors = list()
for value in vars(ft.colors).values():
if value == "primary":
list_started = True
if list_started:
all_flet_colors.append(value)
# checking if all the entered colors exist in flet
if self.icon_color not in all_flet_colors:
raise ValueError("Entered color was not found! See the colors browser for help!")
except Exception as x:
print(f"Color Error: {x}")
e.page.show_snack_bar(ft.SnackBar(ft.Text(f"ERROR: {x}"), open=True))
return
# offset
try:
self.icon_offset = eval(self.icon_offset)
if not isinstance(self.icon_offset, ft.Offset) \
and not isinstance(self.icon_offset, tuple) \
and self.icon_offset is not None:
raise ValueError("Wrong Value!")
elif isinstance(self.icon_offset, tuple) and len(self.icon_offset) == 2:
self.icon_offset = eval(f"Offset({self.icon_offset[0]}, {self.icon_offset[1]})")
except Exception as x:
print(f"Offset Error: {x}")
e.page.show_snack_bar(
ft.SnackBar(
ft.Text("ERROR: `offset` must be an Offset object or in the form x,y. Please check your input."),
open=True))
return
# rotate - input is assumed to be in degrees (which is in turn converted to rads internally)
try:
self.icon_rotate = eval(self.icon_rotate)
deg_to_rads = lambda d: round((math.pi * float(d)) / 180, 3)
if not isinstance(self.icon_rotate, ft.Rotate) \
and not isinstance(self.icon_rotate, (int, float)) \
and self.icon_rotate is not None:
raise ValueError("Wrong Value!")
elif isinstance(self.icon_rotate, ft.Rotate):
self.icon_rotate.angle = deg_to_rads(self.icon_rotate.angle)
elif isinstance(self.icon_rotate, (int, float)):
self.icon_rotate = deg_to_rads(self.icon_rotate)
elif isinstance(self.icon_rotate, tuple) and len(self.icon_rotate) == 2:
self.icon_rotate = eval(f"Rotate({deg_to_rads(self.icon_rotate[0])}, {self.icon_rotate[1]})")
except Exception as x:
print(f"Rotate Error: {x}")
e.page.show_snack_bar(
ft.SnackBar(
ft.Text(
"ERROR: `rotate` must be an Rotate object or in the form angle,alignment. Please check your input."),
open=True))
return
# scale
try:
self.icon_scale = eval(self.icon_scale)
if not isinstance(self.icon_scale, ft.Scale) \
and not isinstance(self.icon_scale, (int, float)) \
and self.icon_scale is not None:
raise ValueError("Wrong Value!")
except Exception as x:
print(f"Scale Error: {x}")
e.page.show_snack_bar(
ft.SnackBar(
ft.Text(
"ERROR: `scale` must be an Scale object. Please check your input."),
open=True))
return
# opacity
try:
if self.field_opacity.value:
self.icon_opacity = eval(self.field_opacity.value)
assert isinstance(self.icon_opacity, (int, float)), "`opacity` must be either of type float or int !"
else:
self.icon_opacity = None
except Exception as x:
print(f"Opacity Error: {x}")
e.page.show_snack_bar(ft.SnackBar(ft.Text(f"ERROR: {x}"), open=True))
return
self.icon_obj.current.color = self.icon_color
self.icon_obj.current.tooltip = self.icon_tooltip
self.icon_obj.current.name = self.icon_name
self.icon_obj.current.size = self.icon_size
self.icon_obj.current.opacity = self.icon_opacity
self.icon_obj.current.scale = self.icon_scale
self.icon_obj.current.rotate = self.icon_rotate
self.icon_obj.current.offset = self.icon_offset
self.update()
e.page.show_snack_bar(ft.SnackBar(ft.Text("Updated Icon!"), open=True))
def copy_to_clipboard(self, e: ft.ControlEvent):
"""It copies the tooltip object/instance to the clipboard."""
o = f", opacity={self.icon_opacity}"
s = f", scale={self.icon_scale}"
r = f", rotate={self.icon_rotate}"
off = f", offset={self.icon_offset}"
t = f", tooltip='{self.icon_tooltip}'"
c = f", color='{self.icon_color}'"
others = f"{c if self.icon_color is not None else ''}{t if self.icon_tooltip is not None else ''}{o if self.icon_opacity is not None else ''}{s if self.icon_scale is not None else ''}{off if self.icon_offset is not None else ''}{r if self.icon_rotate is not None else ''}"
val = f"Icon(name='{self.icon_name}', size={self.icon_size}{others if others else ''})"
e.page.set_clipboard(val)
e.page.show_snack_bar(ft.SnackBar(ft.Text(f"Copied: {val}"), open=True))
print(val)
if __name__ == "__main__":
def main(page: ft.Page):
page.add(TabContentIcon())
ft.app(main)
================================================
FILE: Flet-Utils/utils/icons_browser_utils.py
================================================
from itertools import islice
import flet as ft
# the content of the Icons tab
class TabContentIconsBrowser(ft.UserControl):
# all this below was obtained from https://github.com/flet-dev/examples/tree/main/python/apps/icons-browser
def __init__(self):
super().__init__()
def build(self):
def batches(iterable, batch_size):
"""
It takes an iterable and a batch size, and returns an iterator that yields batches of the iterable
:param iterable: An iterable object (e.g. a list) that you want to split into batches
:param batch_size: The number of items to process in each batch
"""
iterator = iter(iterable)
while batch := list(islice(iterator, batch_size)):
yield batch
# fetch all icon constants from icons.py module
icons_list = []
list_started = False
for key, value in vars(ft.icons).items():
if key == "TEN_K":
list_started = True
if list_started:
icons_list.append(value)
# search field
search_txt = ft.TextField(
expand=1,
hint_text="Enter keyword and press search button",
autofocus=True,
on_submit=lambda e: display_icons(e.control.value),
)
def search_click(_):
"""
It takes the value of the search box and passes it as parameter to the display_icons function
:param _:
:type _: The event that triggered the function
"""
display_icons(search_txt.value)
search_query = ft.Row(
[search_txt, ft.IconButton(icon=ft.icons.SEARCH, on_click=search_click)]
)
# the grid in which the results will be displayed
search_results = ft.GridView(
expand=1,
runs_count=10,
max_extent=150,
spacing=5,
run_spacing=5,
child_aspect_ratio=1,
)
status_bar = ft.Text()
def copy_to_clipboard(e):
"""
When the user clicks on an icon, the icon's value is copied to the clipboard,
and a snackbar is shown to account for the changes.
:param e: The event object
"""
icon_key = e.control.data
print("Copy to clipboard:", icon_key)
self.page.set_clipboard(e.control.data)
self.page.show_snack_bar(ft.SnackBar(ft.Text(f"Copied: {icon_key}"), open=True))
def search_icons(search_term: str):
"""
It takes a search term and returns a generator object that yields the icon names that
contain the search term
:param search_term: The search term that the user entered
:type search_term: str
"""
for icon_name in icons_list:
if search_term != "" and search_term in icon_name:
yield icon_name
def display_icons(search_term: str):
"""
It takes a search term, disables the search box, cleans the search results, and then loops through the
search results in batches of 200, adding each icon to the search results(the displayed grid).
:param search_term: str - the search term to use
:type search_term: str
"""
# clean search results
search_query.disabled = True
self.update()
search_results.clean()
for batch in batches(search_icons(search_term.lower()), 200):
for icon_name in batch:
icon_key = f"icons.{icon_name.upper()}"
search_results.controls.append(
ft.TextButton(
content=ft.Container(
content=ft.Column(
[
ft.Icon(name=icon_name, size=35),
ft.Text(
value=f"{icon_name}",
size=12,
width=100,
no_wrap=True,
text_align=ft.TextAlign.CENTER,
color=ft.colors.ON_SURFACE_VARIANT,
),
],
spacing=5,
alignment=ft.MainAxisAlignment.CENTER,
horizontal_alignment=ft.CrossAxisAlignment.CENTER,
),
alignment=ft.alignment.center,
),
tooltip=f"{icon_key}\nClick to copy to a clipboard",
on_click=copy_to_clipboard,
data=icon_key,
)
)
status_bar.value = f"Icons found: {len(search_results.controls)}"
self.update()
# if there are no results, a snackbar shows up to let the user be aware
if len(search_results.controls) == 0:
self.page.show_snack_bar(ft.SnackBar(ft.Text("No icons found"), open=True))
search_query.disabled = False
self.update()
return ft.Column(
[
search_query,
search_results,
status_bar,
],
expand=True,
)
if __name__ == "__main__":
def main(page: ft.Page):
page.add(TabContentIconsBrowser())
ft.app(main)
================================================
FILE: Flet-Utils/utils/padding_utils.py
================================================
import flet as ft
from flet import padding
# the content of the padding tab
class TabContentPadding(ft.UserControl):
def __init__(self):
super().__init__()
self.container_front = ft.Ref[ft.Container]()
self.container_back = ft.Ref[ft.Container]()
self.container_text = ft.Ref[ft.Text]()
# text field for left parameter of the Padding object
self.field_left = ft.TextField(
label="left",
value="",
width=120,
height=50,
on_change=self.update_front_container_padding,
keyboard_type=ft.KeyboardType.NUMBER,
)
# text field for top parameter of the Padding object
self.field_top = ft.TextField(
label="top",
value="",
width=120,
height=50,
on_change=self.update_front_container_padding,
keyboard_type=ft.KeyboardType.NUMBER,
)
# text field for right parameter of the Padding object
self.field_right = ft.TextField(
label="right",
value="",
width=120,
height=50,
on_change=self.update_front_container_padding,
keyboard_type=ft.KeyboardType.NUMBER,
)
# text field for bottom parameter of the Padding object
self.field_bottom = ft.TextField(
label="bottom",
value="",
width=120,
height=50,
on_change=self.update_front_container_padding,
keyboard_type=ft.KeyboardType.NUMBER,
)
# text field for the width property of the Container object
self.field_width = ft.TextField(
label="Width",
hint_text=f"default=160",
value="160",
width=120,
height=50,
on_submit=self.update_front_container_size,
)
# text field for the height property of the Container object
self.field_height = ft.TextField(
label="Height",
hint_text=f"default=160",
value="160",
width=120,
height=50,
on_submit=self.update_front_container_size,
)
def update_front_container_padding(self, e: ft.ControlEvent):
"""
It updates the padding of the container object.
:param e: The event object
"""
# if the value of the text field in focus is numeric or if it is empty...
if e.control.value.strip().isnumeric() or not e.control.value.strip():
# update the container's padding values
self.container_back.current.padding = ft.padding.Padding(
int(self.field_left.value.strip()) if self.field_left.value.strip().isnumeric() else 0,
int(self.field_top.value.strip()) if self.field_top.value.strip().isnumeric() else 0,
int(self.field_right.value.strip()) if self.field_right.value.strip().isnumeric() else 0,
int(self.field_bottom.value.strip()) if self.field_bottom.value.strip().isnumeric() else 0,
)
# update the text in the container
self.container_text.current.value = f"{int(self.field_left.value.strip()) if self.field_left.value.strip().isnumeric() else 0}, {int(self.field_top.value.strip()) if self.field_top.value.strip().isnumeric() else 0}, {int(self.field_right.value.strip()) if self.field_right.value.strip().isnumeric() else 0}, {int(self.field_bottom.value.strip()) if self.field_bottom.value.strip().isnumeric() else 0} "
self.update()
# show a snackbar to account for the changes
e.page.show_snack_bar(ft.SnackBar(ft.Text("Updated Padding!"), open=True))
else:
# Show a snackbar with an error message, in case the above condition is not met.
e.page.show_snack_bar(
ft.SnackBar(ft.Text("ERROR: The value(ex: non-integer) entered is not valid!"), open=True))
def update_front_container_size(self, e: ft.ControlEvent):
"""
The function updates the container size when the width or height values are changed.
:param e: The event object
"""
if e.control.value.strip().isnumeric():
# if the value of the text field in focus is numeric...
self.container_front.current.height = int(
self.field_height.value.strip()) if self.field_height.value.strip().isnumeric() else 160
self.container_front.current.width = int(
self.field_width.value.strip()) if self.field_width.value.strip().isnumeric() else 160
self.container_front.current.update()
e.page.show_snack_bar(ft.SnackBar(ft.Text("Updated Container's Size!"), open=True))
else:
# Show a snackbar with the error message.
e.page.show_snack_bar(
ft.SnackBar(ft.Text("ERROR: The value(ex: non-integer) entered is not valid!"), open=True))
def copy_to_clipboard(self, e: ft.ControlEvent):
"""
It copies the padding of the container to the clipboard.
:param e: The event object
"""
e.page.set_clipboard(f"{self.container_back.current.padding}")
# show a snackbar to account for the changes
e.page.show_snack_bar(ft.SnackBar(ft.Text(f"Copied: {self.container_back.current.padding}"), open=True))
def build(self):
all_fields = ft.Row(
controls=[
self.field_left, self.field_top, self.field_right, self.field_bottom
],
alignment=ft.MainAxisAlignment.CENTER,
)
return ft.Column(
[
ft.Column(
[
ft.Text("Container's Size:", weight=ft.FontWeight.BOLD, size=21),
ft.Row(
[self.field_width, self.field_height],
alignment=ft.MainAxisAlignment.CENTER,
),
ft.Divider(height=2),
ft.Text("Container's Padding:", weight=ft.FontWeight.BOLD, size=21),
all_fields
],
alignment=ft.MainAxisAlignment.CENTER
),
ft.Row(
[
ft.Container(
content=ft.Container(
ft.Text(
"0, 0, 0, 0",
ref=self.container_text,
weight=ft.FontWeight.BOLD,
size=18,
color="black"
),
ref=self.container_front,
bgcolor=ft.colors.BLUE_700,
padding=ft.Padding(0, 0, 0, 0),
alignment=ft.Alignment(0, 0),
width=float(self.field_width.value),
height=float(self.field_height.value),
),
expand=True,
height=250,
ref=self.container_back,
bgcolor=ft.colors.RED_ACCENT_700,
padding=ft.Padding(0, 0, 0, 0),
alignment=ft.Alignment(0, 0), # align its contents in the center
border_radius=ft.border_radius.BorderRadius(0, 0, 0, 0),
)
],
alignment=ft.MainAxisAlignment.CENTER
),
ft.Row(
[
ft.FilledButton(
"Copy Value to Clipboard",
icon=ft.icons.COPY,
on_click=self.copy_to_clipboard
),
ft.FilledTonalButton(
"Go to Docs",
icon=ft.icons.DATASET_LINKED_OUTLINED,
url="https://flet.dev/docs/controls/container/#padding"
)
],
alignment=ft.MainAxisAlignment.CENTER,
)
],
alignment=ft.MainAxisAlignment.CENTER,
scroll=ft.ScrollMode.HIDDEN,
)
if __name__ == "__main__":
def main(page: ft.Page):
page.add(TabContentPadding())
ft.app(main)
================================================
FILE: Flet-Utils/utils/progress_bar_utils.py
================================================
from flet import *
import flet as ft
# the content of the progress bar tab
class TabContentProgressBar(ft.UserControl):
def __init__(self):
super().__init__()
self.bar_color = "green"
self.bar_bgcolor = None
self.bar_bar_height = None
self.bar_tooltip = None
self.bar_value = None
self.bar_width = None
self.bar_height = None
self.bar_opacity = None
self.bar_rotate = None
self.bar_scale = None
self.bar_offset = None
self.bar_obj = ft.Ref[ft.ProgressBar]()
# text field for tooltip property of the Progress Bar object
self.field_tooltip = ft.TextField(
label="tooltip",
value="",
helper_text="Optional[str]",
on_change=self.update_bar,
keyboard_type=ft.KeyboardType.TEXT,
expand=1
)
# text field for color property of the Progress Bar object
self.field_color = ft.TextField(
label="color",
value="green",
helper_text="Optional[str]",
on_submit=self.update_bar,
# on_blur=self.update_icon,
keyboard_type=ft.KeyboardType.TEXT,
hint_text="colors.RED_50 or red50",
expand=1
)
# text field for the bgcolor property of the Progress Bar object
self.field_bgcolor = ft.TextField(
label="bgcolor",
value="",
helper_text="Optional[str]",
hint_text="colors.RED_50 or red50",
on_submit=self.update_bar,
# on_blur=self.update_icon,
keyboard_type=ft.KeyboardType.TEXT,
expand=1,
# width=170,
)
# text field for the bar_height property of the Progress Bar object
self.field_bar_height = ft.TextField(
label="bar_height",
helper_text="Union[int, float]",
# value="4",
on_change=self.update_bar,
# on_blur=self.update_icon,
keyboard_type=ft.KeyboardType.NUMBER,
expand=1
)
# text field for the value property of the Progress Bar object
self.field_value = ft.TextField(
label="value",
value="",
helper_text="Union[int, float]",
on_change=self.update_bar,
# on_blur=self.update_icon,
keyboard_type=ft.KeyboardType.NUMBER,
# width=80,
expand=1
)
# text field for the width property of the Progress Bar object
self.field_width = ft.TextField(
label="width",
value="420",
helper_text="Union[int, float]",
on_submit=self.update_bar,
on_blur=self.update_bar,
keyboard_type=ft.KeyboardType.NUMBER,
# width=80,
expand=1
)
# text field for the height property of the Progress Bar object
self.field_height = ft.TextField(
label="height",
value="",
helper_text="Union[int, float]",
on_submit=self.update_bar,
on_blur=self.update_bar,
keyboard_type=ft.KeyboardType.NUMBER,
# width=80,
expand=1
)
# text field for the opacity property of the Progress Bar object
self.field_opacity = ft.TextField(
label="opacity",
value="",
helper_text="Union[int, float]",
on_change=self.update_bar,
# on_blur=self.update_icon,
keyboard_type=ft.KeyboardType.NUMBER,
# width=170,
expand=1
)
# text field for the offset property of the Progress Bar object
self.field_offset = ft.TextField(
label="offset",
value="",
helper_text="Optional[Offset, tuple]",
on_submit=self.update_bar,
# on_blur=self.update_icon,
keyboard_type=ft.KeyboardType.TEXT,
expand=1
)
# text field for the scale property of the Progress Bar object
self.field_scale = ft.TextField(
label="scale",
value="",
helper_text="Union[int, float, Scale]",
on_submit=self.update_bar,
# on_blur=self.update_icon,
keyboard_type=ft.KeyboardType.TEXT,
# width=110,
expand=1
)
def build(self):
all_fields = ft.Column(
controls=[
ft.Row(
[self.field_value, self.field_bar_height, self.field_opacity],
),
ft.Row(
[self.field_bgcolor, self.field_color, self.field_tooltip],
),
ft.Row(
[self.field_offset, self.field_scale, self.field_height, self.field_width],
),
],
alignment=ft.MainAxisAlignment.CENTER,
spacing=11
)
return ft.Column(
[
ft.Text("Progress Bar Builder:", weight=ft.FontWeight.BOLD, size=21),
all_fields,
ft.Row(
[
ft.ProgressBar(
ref=self.bar_obj,
color="green",
# bar_height=4,
width=420
)
],
alignment=ft.MainAxisAlignment.CENTER,
),
ft.Row(
[
ft.FilledButton(
"Copy Value to Clipboard",
icon=ft.icons.COPY,
on_click=self.copy_to_clipboard
),
ft.FilledTonalButton(
"Go to Docs",
icon=ft.icons.DATASET_LINKED_OUTLINED,
url="https://flet.dev/docs/controls/progressbar"
)
],
alignment=ft.MainAxisAlignment.CENTER,
)
],
alignment=ft.MainAxisAlignment.CENTER,
scroll=ft.ScrollMode.HIDDEN,
spacing=30
)
def update_bar(self, e: ft.ControlEvent):
"""It updates the Progress Bar object."""
self.bar_opacity = int(self.field_value.value.strip()) if self.field_value.value.strip().isnumeric() else None
self.bar_color = self.field_color.value.strip() if self.field_color.value.strip() else None
self.bar_bgcolor = self.field_bgcolor.value.strip() if self.field_bgcolor.value.strip() else None
self.bar_tooltip = self.field_tooltip.value.strip() if self.field_tooltip.value.strip() else None
self.bar_offset = self.field_offset.value.strip() if self.field_offset.value.strip() else "None"
self.bar_scale = self.field_scale.value.strip() if self.field_scale.value.strip() else "None"
# value
try:
if self.field_value.value:
self.bar_value = eval(self.field_value.value)
assert isinstance(self.bar_value, (int, float)), "`value` must be either of type float or int !"
else:
self.bar_value = None
except Exception as x:
print(f"Value Error: {x}")
e.page.show_snack_bar(ft.SnackBar(ft.Text(f"ERROR: {x}"),open=True))
return
# bar_height
try:
if self.field_bar_height.value:
self.bar_bar_height = eval(self.field_bar_height.value)
assert isinstance(self.bar_bar_height, (int, float)), "`bar_height` must be either of type float or int !"
else:
self.bar_bar_height = None
except Exception as x:
print(f"Bar Height Error: {x}")
e.page.show_snack_bar(ft.SnackBar(ft.Text(f"ERROR: {x}"), open=True))
return
# width
try:
if self.field_width.value:
self.bar_width = eval(self.field_width.value)
assert isinstance(self.bar_width, (int, float)), "`width` must be either of type float or int !"
else:
self.bar_width = None
except Exception as x:
print(f"Width Error: {x}")
e.page.show_snack_bar(ft.SnackBar(ft.Text(f"ERROR: {x}"), open=True))
return
# height
try:
if self.field_height.value:
self.bar_height = eval(self.field_height.value)
assert isinstance(self.bar_height, (int, float)), "`height` must be either of type float or int !"
else:
self.bar_height = None
except Exception as x:
print(f"Height Error: {x}")
e.page.show_snack_bar(ft.SnackBar(ft.Text(f"ERROR: {x}"), open=True))
return
# color
try:
if self.bar_color is not None:
self.bar_color = eval(self.bar_color) if '.' in self.bar_color else self.bar_color.lower()
# Getting all the colors from flet's colors module
list_started = False
all_flet_colors = list()
for value in vars(ft.colors).values():
if value == "primary":
list_started = True
if list_started:
all_flet_colors.append(value)
# checking if all the entered colors exist in flet
if self.bar_color not in all_flet_colors:
raise ValueError("Entered color was not found! See the colors browser for help!")
except Exception as x:
print(f"Color Error: {x}")
e.page.show_snack_bar(ft.SnackBar(ft.Text(f"ERROR: {x}"), open=True))
return
# bgcolor
try:
if self.bar_bgcolor is not None:
self.bar_bgcolor = eval(self.bar_bgcolor) if '.' in self.bar_bgcolor else self.bar_bgcolor.lower()
# Getting all the colors from flet's colors module
list_started = False
all_flet_colors = list()
for value in vars(ft.colors).values():
if value == "primary":
list_started = True
if list_started:
all_flet_colors.append(value)
# checking if all the entered colors exist in flet
if self.bar_bgcolor not in all_flet_colors:
raise ValueError("Entered color was not found! See the colors browser for help!")
except Exception as x:
print(f"Bgcolor Error: {x}")
e.page.show_snack_bar(ft.SnackBar(ft.Text(f"ERROR: {x}"), open=True))
return
# offset
try:
self.bar_offset = eval(self.bar_offset)
if not isinstance(self.bar_offset, ft.Offset) \
and not isinstance(self.bar_offset, tuple) \
and self.bar_offset is not None:
raise ValueError("Wrong Value!")
elif isinstance(self.bar_offset, tuple) and len(self.bar_offset) == 2:
self.bar_offset = eval(f"Offset({self.bar_offset[0]}, {self.bar_offset[1]})")
except Exception as x:
print(f"Offset Error: {x}")
e.page.show_snack_bar(
ft.SnackBar(
ft.Text("ERROR: `offset` must be an Offset object or in the form x,y. Please check your input."),
open=True))
return
# scale
try:
self.bar_scale = eval(self.bar_scale)
if not isinstance(self.bar_scale, ft.Scale) \
and not isinstance(self.bar_scale, (int, float)) \
and self.bar_scale is not None:
raise ValueError("Wrong Value!")
except Exception as x:
print(f"Scale Error: {x}")
e.page.show_snack_bar(
ft.SnackBar(
ft.Text(
"ERROR: `scale` must be an Scale object. Please check your input."),
open=True))
return
# opacity
try:
if self.field_opacity.value:
self.bar_opacity = eval(self.field_opacity.value)
assert isinstance(self.bar_opacity, (int, float)), "`opacity` must be either of type float or int !"
else:
self.bar_opacity = None
except Exception as x:
print(f"Opacity Error: {x}")
e.page.show_snack_bar(ft.SnackBar(ft.Text(f"ERROR: {x}"), open=True))
return
self.bar_obj.current.color = self.bar_color
self.bar_obj.current.bgcolor = self.bar_bgcolor
self.bar_obj.current.tooltip = self.bar_tooltip
self.bar_obj.current.value = self.bar_value
self.bar_obj.current.bar_height = self.bar_bar_height
self.bar_obj.current.width = self.bar_width
self.bar_obj.current.height = self.bar_height
self.bar_obj.current.opacity = self.bar_opacity
self.bar_obj.current.scale = self.bar_scale
self.bar_obj.current.offset = self.bar_offset
self.update()
e.page.show_snack_bar(ft.SnackBar(ft.Text("Updated Progress Bar!"), open=True))
def copy_to_clipboard(self, e: ft.ControlEvent):
"""It copies the tooltip object/instance to the clipboard."""
o = f", opacity={self.bar_opacity}"
s = f", scale={self.bar_scale}"
off = f", offset={self.bar_offset}"
t = f", tooltip='{self.bar_tooltip}'"
bg= f", bgcolor='{self.bar_bgcolor}'"
c = f", color='{self.bar_color}'"
w = f", width={self.bar_width}"
h = f", height={self.bar_height}"
others = f"{w if self.bar_width is not None else ''}{h if self.bar_height is not None else ''}{c if self.bar_color is not None else ''}{bg if self.bar_bgcolor is not None else ''}{t if self.bar_tooltip is not None else ''}{o if self.bar_opacity is not None else ''}{s if self.bar_scale is not None else ''}{off if self.bar_offset is not None else ''}"
val = f"Progressbar(value={self.bar_value}, bar_height={self.bar_bar_height}{others if others else ''})"
e.page.set_clipboard(val)
e.page.show_snack_bar(ft.SnackBar(ft.Text(f"Copied: {val}"), open=True))
print(val)
if __name__ == "__main__":
def main(page: ft.Page):
page.theme_mode = ft.ThemeMode.LIGHT
page.add(TabContentProgressBar())
ft.app(main)
================================================
FILE: Flet-Utils/utils/progress_ring_utils.py
================================================
from flet import *
import flet as ft
# todo: width, height
# the content of the progress ring tab
class TabContentProgressRing(ft.UserControl):
def __init__(self):
super().__init__()
self.ring_color = None
self.ring_bgcolor = None
self.ring_stroke_width = None
self.ring_tooltip = None
self.ring_value = None
self.ring_width = None
self.ring_height = None
self.ring_opacity = None
self.ring_rotate = None
self.ring_scale = None
self.ring_offset = None
self.ring_obj = ft.Ref[ft.ProgressRing]()
# text field for tooltip property of the Progress Ring object
self.field_tooltip = ft.TextField(
label="tooltip",
value="",
helper_text="Optional[str]",
on_change=self.update_ring,
keyboard_type=ft.KeyboardType.TEXT,
expand=1
)
# text field for color property of the Progress Ring object
self.field_color = ft.TextField(
label="color",
value="",
helper_text="Optional[str]",
on_submit=self.update_ring,
# on_blur=self.update_icon,
keyboard_type=ft.KeyboardType.TEXT,
hint_text="colors.RED_50 or red50",
expand=1
)
# text field for the bgcolor property of the Progress Ring object
self.field_bgcolor = ft.TextField(
label="bgcolor",
value="",
helper_text="Optional[str]",
hint_text="colors.RED_50 or red50",
on_submit=self.update_ring,
# on_blur=self.update_icon,
keyboard_type=ft.KeyboardType.TEXT,
expand=1,
# width=170,
)
# text field for the stroke_width property of the Progress Ring object
self.field_stroke_width = ft.TextField(
label="stroke_width",
helper_text="Union[int, float]",
value="",
on_change=self.update_ring,
# on_blur=self.update_icon,
keyboard_type=ft.KeyboardType.NUMBER,
expand=1
)
# text field for the value property of the Progress Ring object
self.field_value = ft.TextField(
label="value",
value="",
helper_text="Union[int, float]",
on_change=self.update_ring,
# on_blur=self.update_icon,
keyboard_type=ft.KeyboardType.NUMBER,
# width=80,
expand=1
)
# text field for the width property of the Progress Bar object
self.field_width = ft.TextField(
label="width",
value="",
helper_text="Union[int, float]",
on_submit=self.update_ring,
on_blur=self.update_ring,
keyboard_type=ft.KeyboardType.NUMBER,
# width=80,
expand=1
)
# text field for the height property of the Progress Bar object
self.field_height = ft.TextField(
label="height",
value="",
helper_text="Union[int, float]",
on_submit=self.update_ring,
on_blur=self.update_ring,
keyboard_type=ft.KeyboardType.NUMBER,
# width=80,
expand=1
)
# text field for the opacity property of the Progress Ring object
self.field_opacity = ft.TextField(
label="opacity",
value="",
helper_text="Union[int, float]",
on_change=self.update_ring,
# on_blur=self.update_icon,
keyboard_type=ft.KeyboardType.NUMBER,
# width=170,
expand=1
)
# text field for the offset property of the Progress Ring object
self.field_offset = ft.TextField(
label="offset",
value="",
helper_text="Optional[Offset, tuple]",
on_submit=self.update_ring,
# on_blur=self.update_icon,
keyboard_type=ft.KeyboardType.TEXT,
expand=1
)
# text field for the scale property of the Progress Ring object
self.field_scale = ft.TextField(
label="scale",
value="",
helper_text="Union[int, float, Scale]",
on_submit=self.update_ring,
# on_blur=self.update_icon,
keyboard_type=ft.KeyboardType.TEXT,
# width=110,
expand=1
)
def build(self):
all_fields = ft.Column(
controls=[
ft.Row(
[self.field_value, self.field_stroke_width, self.field_opacity],
),
ft.Row(
[self.field_bgcolor, self.field_color, self.field_tooltip],
),
ft.Row(
[self.field_offset, self.field_scale, self.field_width, self.field_height],
),
],
alignment=ft.MainAxisAlignment.CENTER,
spacing=11
)
return ft.Column(
[
ft.Text("Progress Ring Builder:", weight=ft.FontWeight.BOLD, size=21),
all_fields,
ft.Row(
[
ft.ProgressRing(
ref=self.ring_obj,
)
],
alignment=ft.MainAxisAlignment.CENTER,
),
ft.Row(
[
ft.FilledButton(
"Copy Value to Clipboard",
icon=ft.icons.COPY,
on_click=self.copy_to_clipboard
),
ft.FilledTonalButton(
"Go to Docs",
icon=ft.icons.DATASET_LINKED_OUTLINED,
url="https://flet.dev/docs/controls/progressring"
)
],
alignment=ft.MainAxisAlignment.CENTER,
)
],
alignment=ft.MainAxisAlignment.CENTER,
scroll=ft.ScrollMode.HIDDEN,
spacing=30
)
def update_ring(self, e: ft.ControlEvent):
"""It updates the Progress Ring object."""
self.ring_opacity = int(self.field_value.value.strip()) if self.field_value.value.strip().isnumeric() else None
self.ring_color = self.field_color.value.strip() if self.field_color.value.strip() else None
self.ring_bgcolor = self.field_bgcolor.value.strip() if self.field_bgcolor.value.strip() else None
self.ring_tooltip = self.field_tooltip.value.strip() if self.field_tooltip.value.strip() else None
self.ring_offset = self.field_offset.value.strip() if self.field_offset.value.strip() else "None"
self.ring_scale = self.field_scale.value.strip() if self.field_scale.value.strip() else "None"
# value
try:
if self.field_value.value:
self.ring_value = eval(self.field_value.value)
assert isinstance(self.ring_value, (int, float)), "`value` must be either of type float or int !"
else:
self.ring_value = None
except Exception as x:
print(f"Value Error: {x}")
e.page.show_snack_bar(ft.SnackBar(ft.Text(f"ERROR: {x}"), open=True))
return
# stroke_width
try:
if self.field_stroke_width.value:
self.ring_stroke_width = eval(self.field_stroke_width.value)
assert isinstance(self.ring_stroke_width,
(int, float)), "`stroke_width` must be either of type float or int !"
else:
self.ring_stroke_width = None
except Exception as x:
print(f"Stroke Width Error: {x}")
e.page.show_snack_bar(ft.SnackBar(ft.Text(f"ERROR: {x}"), open=True))
return
# width
try:
if self.field_width.value:
self.ring_width = eval(self.field_width.value)
assert isinstance(self.ring_width, (int, float)), "`width` must be either of type float or int !"
else:
self.ring_width = None
except Exception as x:
print(f"Width Error: {x}")
e.page.show_snack_bar(ft.SnackBar(ft.Text(f"ERROR: {x}"), open=True))
return
# height
try:
if self.field_height.value:
self.ring_height = eval(self.field_height.value)
assert isinstance(self.ring_height, (int, float)), "`height` must be either of type float or int !"
else:
self.ring_height = None
except Exception as x:
print(f"Height Error: {x}")
e.page.show_snack_bar(ft.SnackBar(ft.Text(f"ERROR: {x}"), open=True))
return
# color
try:
if self.ring_color is not None:
self.ring_color = eval(self.ring_color) if '.' in self.ring_color else self.ring_color.lower()
# Getting all the colors from flet's colors module
list_started = False
all_flet_colors = list()
for value in vars(ft.colors).values():
if value == "primary":
list_started = True
if list_started:
all_flet_colors.append(value)
# checking if all the entered colors exist in flet
if self.ring_color not in all_flet_colors:
raise ValueError("Entered color was not found! See the colors browser for help!")
except Exception as x:
print(f"Color Error: {x}")
e.page.show_snack_bar(ft.SnackBar(ft.Text(f"ERROR: {x}"), open=True))
return
# bgcolor
try:
if self.ring_bgcolor is not None:
self.ring_bgcolor = eval(self.ring_bgcolor) if '.' in self.ring_bgcolor else self.ring_bgcolor.lower()
# Getting all the colors from flet's colors module
list_started = False
all_flet_colors = list()
for value in vars(ft.colors).values():
if value == "primary":
list_started = True
if list_started:
all_flet_colors.append(value)
# checking if all the entered colors exist in flet
if self.ring_bgcolor not in all_flet_colors:
raise ValueError("Entered color was not found! See the colors browser for help!")
except Exception as x:
print(f"Bgcolor Error: {x}")
e.page.show_snack_bar(ft.SnackBar(ft.Text(f"ERROR: {x}"), open=True))
return
# offset
try:
self.ring_offset = eval(self.ring_offset)
if not isinstance(self.ring_offset, ft.Offset) \
and not isinstance(self.ring_offset, tuple) \
and self.ring_offset is not None:
raise ValueError("Wrong Value!")
elif isinstance(self.ring_offset, tuple) and len(self.ring_offset) == 2:
self.ring_offset = eval(f"Offset({self.ring_offset[0]}, {self.ring_offset[1]})")
except Exception as x:
print(f"Offset Error: {x}")
e.page.show_snack_bar(
ft.SnackBar(
ft.Text("ERROR: `offset` must be an Offset object or in the form x,y. Please check your input."),
open=True))
return
# scale
try:
self.ring_scale = eval(self.ring_scale)
if not isinstance(self.ring_scale, ft.Scale) \
and not isinstance(self.ring_scale, (int, float)) \
and self.ring_scale is not None:
raise ValueError("Wrong Value!")
except Exception as x:
print(f"Scale Error: {x}")
e.page.show_snack_bar(
ft.SnackBar(
ft.Text(
"ERROR: `scale` must be an Scale object. Please check your input."),
open=True))
return
# opacity
try:
if self.field_opacity.value:
self.ring_opacity = eval(self.field_opacity.value)
assert isinstance(self.ring_opacity, (int, float)), "`opacity` must be either of type float or int !"
else:
self.ring_opacity = None
except Exception as x:
print(f"Opacity Error: {x}")
e.page.show_snack_bar(ft.SnackBar(ft.Text(f"ERROR: {x}"), open=True))
return
self.ring_obj.current.color = self.ring_color
self.ring_obj.current.bgcolor = self.ring_bgcolor
self.ring_obj.current.tooltip = self.ring_tooltip
self.ring_obj.current.value = self.ring_value
self.ring_obj.current.stroke_width = self.ring_stroke_width
self.ring_obj.current.width = self.ring_width
self.ring_obj.current.height = self.ring_height
self.ring_obj.current.opacity = self.ring_opacity
self.ring_obj.current.scale = self.ring_scale
self.ring_obj.current.offset = self.ring_offset
self.update()
e.page.show_snack_bar(ft.SnackBar(ft.Text("Updated Progress Ring!"), open=True))
def copy_to_clipboard(self, e: ft.ControlEvent):
"""It copies the tooltip object/instance to the clipboard."""
o = f", opacity={self.ring_opacity}"
s = f", scale={self.ring_scale}"
off = f", offset={self.ring_offset}"
t = f", tooltip='{self.ring_tooltip}'"
bg = f", bgcolor='{self.ring_bgcolor}'"
c = f", color='{self.ring_color}'"
w = f", width={self.ring_width}"
h = f", height={self.ring_height}"
sw = f", stroke_width={self.ring_stroke_width}"
others = f"{sw if self.ring_stroke_width is not None else ''}{w if self.ring_width is not None else ''}{h if self.ring_height is not None else ''}{c if self.ring_color is not None else ''}{bg if self.ring_bgcolor is not None else ''}{t if self.ring_tooltip is not None else ''}{o if self.ring_opacity is not None else ''}{s if self.ring_scale is not None else ''}{off if self.ring_offset is not None else ''}"
val = f"ProgressRing(value={self.ring_value}{others if others else ''})"
e.page.set_clipboard(val)
e.page.show_snack_bar(ft.SnackBar(ft.Text(f"Copied: {val}"), open=True))
print(val)
if __name__ == "__main__":
def main(page: ft.Page):
page.theme_mode = ft.ThemeMode.LIGHT
page.add(TabContentProgressRing())
ft.app(main)
================================================
FILE: Flet-Utils/utils/shadermask_utils.py
================================================
# import all the controls: if the shader mask requires controls which are not imported, an error is raised
from flet import *
import flet as ft
# the content of the ShaderMask tab
class TabContentShaderMask(ft.UserControl):
def __init__(self):
super().__init__()
self.shader_mask_obj = ft.Ref[ft.ShaderMask]()
# dropdown values for the blend_mode parameter
self.bm_dropdown = ft.Dropdown(
options=[
ft.dropdown.Option("modulate"),
ft.dropdown.Option("clear"),
ft.dropdown.Option("color"),
ft.dropdown.Option("colorBurn"),
ft.dropdown.Option("colorDodge"),
ft.dropdown.Option("darken"),
ft.dropdown.Option("difference"),
ft.dropdown.Option("dst"),
ft.dropdown.Option("dstATop"),
ft.dropdown.Option("dstIn"),
ft.dropdown.Option("dstOut"),
ft.dropdown.Option("dstOver"),
ft.dropdown.Option("exclusion"),
ft.dropdown.Option("hardLight"),
ft.dropdown.Option("hue"),
ft.dropdown.Option("lighten"),
ft.dropdown.Option("luminosity"),
ft.dropdown.Option("multiply"),
ft.dropdown.Option("overlay"),
ft.dropdown.Option("plus"),
ft.dropdown.Option("saturation"),
ft.dropdown.Option("screen"),
ft.dropdown.Option("softLight"),
ft.dropdown.Option("src"),
ft.dropdown.Option("srcATop"),
ft.dropdown.Option("srcIn"),
ft.dropdown.Option("srcOut"),
ft.dropdown.Option("srcOver"),
ft.dropdown.Option("values"),
ft.dropdown.Option("xor"),
],
value="modulate",
on_change=self.update_mask,
width=150,
helper_text="blend mode",
)
# text field for gradient property of the ShaderMask object
self.field_shader = ft.TextField(
label="shader",
value="LinearGradient(begin=alignment.top_center, end=alignment.bottom_center, colors=[colors.BLUE_100,"
"colors.TRANSPARENT], stops=[0.5, 1.0])",
on_submit=self.update_mask,
keyboard_type=ft.KeyboardType.TEXT,
on_blur=self.update_mask,
hint_text="LinearGradient(.....)",
helper_text="Linear/Radial/Sweep Gradient object"
)
# text field for the border radius property of the ShaderMask object
self.field_border_radius = ft.TextField(
label="border radius",
value="border_radius.all(10)",
on_submit=self.update_mask,
on_blur=self.update_mask,
keyboard_type=ft.KeyboardType.TEXT,
hint_text="5,10,2,3",
helper_text="BorderRadius object or (left, top, right, bottom)"
)
# text field for content property of the ShaderMask object
self.field_content = ft.TextField(
label="content",
value="Image(src='https://picsum.photos/100/200?2')",
on_submit=self.update_mask,
on_blur=self.update_mask,
keyboard_type=ft.KeyboardType.TEXT,
helper_text="A control for the content",
hint_text="Image(src='https://picsum.photos/100/200?2')",
)
self.border_radius = 10
self.shader = ft.LinearGradient(
begin=ft.alignment.top_center,
end=ft.alignment.bottom_center,
colors=[colors.BLACK, colors.TRANSPARENT],
stops=[0.5, 1.0],
)
self.blend_mode = "dstIn"
self.content = ft.Image(src="https://picsum.photos/100/200?2")
def update_mask(self, e: ft.ControlEvent):
"""
It updates the gradient of the container object.
:param e: The event object
"""
content = self.field_content.value.strip() if self.field_content.value.strip() else None
b_radius = self.field_border_radius.value.strip() if self.field_border_radius.value.strip() else None
shader = self.field_shader.value.strip() if self.field_shader.value.strip() else None
blend_mode = self.bm_dropdown.value
# border radius
try:
b_radius = eval(b_radius)
except Exception as x:
print(f"BorderRadius Error: {x}")
e.page.show_snack_bar(
ft.SnackBar(
ft.Text(
"ERROR: `border_radius` must be an BorderRadius object or in the form (left, top, right, "
"bottom). Please check your input."),
open=True)
)
return
else:
if not isinstance(b_radius, ft.BorderRadius) and \
not isinstance(b_radius, tuple):
e.page.show_snack_bar(
ft.SnackBar(
ft.Text(
"ERROR: `border_radius` must be an BorderRadius object or in the form (left, top, "
"right, bottom). This could be gotten from the BorderRadius Tab here."
),
open=True
)
)
return
elif isinstance(b_radius, tuple) and len(b_radius) == 4:
b_radius = eval(
f"BorderRadius({b_radius[0]}, {b_radius[1]},{b_radius[2]}, {b_radius[3]})")
# shader
try:
shader = eval(shader)
if shader is not None and not isinstance(shader, (ft.LinearGradient, ft.RadialGradient, ft.SweepGradient)):
raise ValueError("Wrong Value")
except Exception as x:
print(f"Shader Error: {x}")
e.page.show_snack_bar(
ft.SnackBar(
ft.Text("ERROR: `shader` must be a Gradient(LinearGradient,RadialGradient,SweepGradient) "
"object. Please check your input."),
open=True)
)
return
# content
try:
content = eval(content)
self.content = self.shader_mask_obj.current.content = content
except Exception as x:
print(f"Content Error: {x}")
e.page.show_snack_bar(
ft.SnackBar(
ft.Text(
"ERROR: `content` must be a valid Control object. Please check your input."),
open=True))
return
self.blend_mode = self.shader_mask_obj.current.blend_mode = blend_mode
self.border_radius = self.shader_mask_obj.current.border_radius = b_radius
self.shader = self.shader_mask_obj.current.shader = shader
self.update()
e.page.show_snack_bar(ft.SnackBar(ft.Text("Updated ShaderMask!"), open=True))
def copy_to_clipboard(self, e: ft.ControlEvent):
"""
It copies the gradient of the container to the clipboard.
:param e: The event object
"""
e.page.set_clipboard(
f"ShaderMask(content={self.field_content.value.strip()}, blend_mode={self.blend_mode}, shader={self.shader}, border_radius={self.border_radius})")
e.page.show_snack_bar(ft.SnackBar(ft.Text(
f"Copied: ShaderMask(content={self.field_content.value.strip()}, blend_mode={self.blend_mode}, shader={self.shader}, border_radius={self.border_radius})"),
open=True))
def build(self):
return ft.Column(
[
self.field_content,
self.field_shader,
ft.Row(
[self.field_border_radius, self.bm_dropdown],
alignment=ft.MainAxisAlignment.CENTER
),
ft.Row(
[
ft.ShaderMask(
ft.Image(src="https://picsum.photos/100/200?2"),
blend_mode=ft.BlendMode.DST_IN,
shader=ft.LinearGradient(
begin=ft.alignment.top_center,
end=ft.alignment.bottom_center,
colors=[colors.BLACK, colors.TRANSPARENT],
stops=[0.5, 1.0],
),
border_radius=10,
ref=self.shader_mask_obj
)
],
alignment=ft.MainAxisAlignment.CENTER),
ft.Row(
[
ft.FilledButton(
"Copy Value to Clipboard",
icon=icons.COPY,
on_click=self.copy_to_clipboard,
),
ft.FilledTonalButton(
"Go to Docs",
icon=icons.DATASET_LINKED_OUTLINED,
url="https://flet.dev/docs/controls/shadermask"
)
],
alignment=ft.MainAxisAlignment.CENTER,
),
],
alignment=ft.MainAxisAlignment.CENTER,
scroll=ft.ScrollMode.HIDDEN,
)
if __name__ == "__main__":
def main(page: ft.Page):
page.add(TabContentShaderMask())
ft.app(main)
================================================
FILE: Flet-Utils/utils/shadow_utils.py
================================================
from flet import *
import flet as ft
# todo: change link to docs
# the content of the shadow tab
class TabContentShadow(ft.UserControl):
def __init__(self):
super().__init__()
self.shadow_color = None
self.shadow_offset = None
self.shadow_blur_radius = None
self.shadow_spread_radius = None
self.shadow_blur_style = None
self.container_bgcolor = None
self.shadow_obj = ft.Ref[ft.Container]()
# text field for offset property of the BoxShadow object
self.field_offset = ft.TextField(
label="offset",
value="",
helper_text="Optional[Offset, tuple]",
on_submit=self.update_shadow,
keyboard_type=ft.KeyboardType.TEXT,
expand=1
)
# text field for color property of the BoxShadow object
self.field_color = ft.TextField(
label="color",
value="",
helper_text="Optional[str]",
on_submit=self.update_shadow,
keyboard_type=ft.KeyboardType.TEXT,
hint_text="colors.RED_50 or red50",
expand=1
)
# text field for the spread_radius property of the BoxShadow object
self.field_spread_radius = ft.TextField(
label="spread_radius",
helper_text="Union[int, float]",
value="",
on_change=self.update_shadow,
keyboard_type=ft
gitextract_f_v8w953/
├── .gitattributes
├── .gitignore
├── Flet-Utils/
│ ├── Dockerfile
│ ├── README.md
│ ├── assets/
│ │ ├── index.html
│ │ └── manifest.json
│ ├── fly.toml
│ ├── main.py
│ ├── requirements.txt
│ └── utils/
│ ├── alignment_utils.py
│ ├── blur_utils.py
│ ├── border_radius_utils.py
│ ├── border_utils.py
│ ├── circle_avatar_utils.py
│ ├── colors_utils.py
│ ├── divider_utils.py
│ ├── gradient_utils.py
│ ├── icon_utils.py
│ ├── icons_browser_utils.py
│ ├── padding_utils.py
│ ├── progress_bar_utils.py
│ ├── progress_ring_utils.py
│ ├── shadermask_utils.py
│ ├── shadow_utils.py
│ ├── shape_utils.py
│ ├── tooltip_utils.py
│ └── vertical_divider_utils.py
├── Forms/
│ ├── README.md
│ ├── login_utils.py
│ ├── login_with_captcha.py
│ └── requirements.txt
├── IP Revealer/
│ ├── README.md
│ ├── assets/
│ │ └── fonts/
│ │ ├── Plus_Jakarta_Sans/
│ │ │ └── OFL.txt
│ │ └── Stick/
│ │ └── OFL.txt
│ ├── main.py
│ ├── main_with_ipify.py
│ └── requirements.txt
├── LICENSE
├── Markdown Editor/
│ ├── Dockerfile
│ ├── README.md
│ ├── assets/
│ │ ├── index.html
│ │ └── manifest.json
│ ├── fly.toml
│ ├── main.py
│ ├── requirements.txt
│ └── utils.py
├── QR Code Generator/
│ ├── Dockerfile
│ ├── README.md
│ ├── assets/
│ │ ├── index.html
│ │ └── manifest.json
│ ├── fly.toml
│ ├── main.py
│ └── requirements.txt
├── README.md
├── Random Image Viewer/
│ ├── README.md
│ ├── assets/
│ │ ├── fonts/
│ │ │ ├── JetBrains_Mono/
│ │ │ │ └── OFL.txt
│ │ │ ├── Kalam/
│ │ │ │ └── OFL.txt
│ │ │ └── Space_Grotesk/
│ │ │ └── OFL.txt
│ │ ├── index.html
│ │ └── manifest.json
│ ├── main.py
│ ├── requirements.txt
│ └── utils.py
├── Short Jokes/
│ ├── README.md
│ ├── assets/
│ │ ├── fonts/
│ │ │ ├── JetBrains_Mono/
│ │ │ │ └── OFL.txt
│ │ │ ├── Kalam/
│ │ │ │ └── OFL.txt
│ │ │ └── Space_Grotesk/
│ │ │ └── OFL.txt
│ │ ├── index.html
│ │ └── manifest.json
│ ├── joke.py
│ ├── main.py
│ ├── requirements.txt
│ └── utils.py
├── StartUp Name Generator/
│ ├── README.md
│ ├── main.py
│ ├── requirements.txt
│ └── utils.py
└── URL shortener/
├── Dockerfile
├── README.md
├── assets/
│ └── index.html
├── fly.toml
├── main.py
└── requirements.txt
SYMBOL INDEX (177 symbols across 33 files)
FILE: Flet-Utils/main.py
function main (line 22) | def main(page: ft.Page):
FILE: Flet-Utils/utils/alignment_utils.py
class TabContentAlignment (line 5) | class TabContentAlignment(ft.UserControl):
method __init__ (line 6) | def __init__(self):
method copy_to_clipboard (line 30) | def copy_to_clipboard(self, e: ft.ControlEvent):
method update_alignment (line 40) | def update_alignment(self, e: ft.ControlEvent):
method build (line 56) | def build(self):
function main (line 119) | def main(page: ft.Page):
FILE: Flet-Utils/utils/blur_utils.py
class TabContentBlur (line 10) | class TabContentBlur(ft.UserControl):
method __init__ (line 12) | def __init__(self):
method build (line 55) | def build(self):
method update_blur (line 121) | def update_blur(self, e: ft.ControlEvent):
method copy_to_clipboard (line 160) | def copy_to_clipboard(self, e: ft.ControlEvent):
function main (line 169) | def main(page: ft.Page):
FILE: Flet-Utils/utils/border_radius_utils.py
class TabContentBorderRadius (line 5) | class TabContentBorderRadius(ft.UserControl):
method __init__ (line 6) | def __init__(self):
method update_border_radius (line 66) | def update_border_radius(self, e: ft.ControlEvent):
method update_container_size (line 89) | def update_container_size(self, e: ft.ControlEvent):
method copy_to_clipboard (line 108) | def copy_to_clipboard(self, e: ft.ControlEvent):
method build (line 117) | def build(self):
function main (line 182) | def main(page: ft.Page):
FILE: Flet-Utils/utils/border_utils.py
class TabContentBorder (line 7) | class TabContentBorder(ft.UserControl):
method __init__ (line 9) | def __init__(self):
method update_border (line 75) | def update_border(self, e: ft.ControlEvent):
method update_container_size (line 101) | def update_container_size(self, e: ft.ControlEvent):
method copy_to_clipboard (line 120) | def copy_to_clipboard(self, e: ft.ControlEvent):
method build (line 129) | def build(self):
function main (line 186) | def main(page: ft.Page):
FILE: Flet-Utils/utils/circle_avatar_utils.py
class TabContentCircleAvatar (line 8) | class TabContentCircleAvatar(ft.UserControl):
method __init__ (line 10) | def __init__(self):
method build (line 198) | def build(self):
method update_avatar (line 249) | def update_avatar(self, e: ft.ControlEvent):
method copy_to_clipboard (line 449) | def copy_to_clipboard(self, e: ft.ControlEvent):
function main (line 475) | def main(page: ft.Page):
FILE: Flet-Utils/utils/colors_utils.py
class TabContentColors1 (line 6) | class TabContentColors1(ft.UserControl):
method __init__ (line 9) | def __init__(self, expand=True):
method build (line 18) | def build(self):
class Tile (line 155) | class Tile(ft.Container):
method __init__ (line 159) | def __init__(self, tile_text, color, page):
method _build (line 170) | def _build(self):
class TabContentColors2 (line 187) | class TabContentColors2(ft.UserControl):
method __init__ (line 190) | def __init__(self, page):
method build (line 211) | def build(self):
function main (line 309) | def main(page: ft.Page):
FILE: Flet-Utils/utils/divider_utils.py
class TabContentDivider (line 6) | class TabContentDivider(ft.UserControl):
method __init__ (line 8) | def __init__(self):
method build (line 78) | def build(self):
method update_divider (line 150) | def update_divider(self, e: ft.ControlEvent):
method copy_to_clipboard (line 232) | def copy_to_clipboard(self, e: ft.ControlEvent):
function main (line 248) | def main(page: ft.Page):
FILE: Flet-Utils/utils/gradient_utils.py
class TabContentLinearGradient (line 7) | class TabContentLinearGradient(ft.UserControl):
method __init__ (line 8) | def __init__(self):
method update_gradient (line 101) | def update_gradient(self, e: ft.ControlEvent):
method update_container_size (line 240) | def update_container_size(self, e: ft.ControlEvent):
method copy_to_clipboard (line 259) | def copy_to_clipboard(self, e: ft.ControlEvent):
method build (line 268) | def build(self):
class TabContentRadialGradient (line 342) | class TabContentRadialGradient(ft.UserControl):
method __init__ (line 343) | def __init__(self):
method update_gradient (line 455) | def update_gradient(self, e: ft.ControlEvent):
method update_container_size (line 625) | def update_container_size(self, e: ft.ControlEvent):
method copy_to_clipboard (line 644) | def copy_to_clipboard(self, e: ft.ControlEvent):
method build (line 653) | def build(self):
class TabContentSweepGradient (line 723) | class TabContentSweepGradient(ft.UserControl):
method __init__ (line 724) | def __init__(self):
method update_gradient (line 832) | def update_gradient(self, e: ft.ControlEvent):
method update_container_size (line 992) | def update_container_size(self, e: ft.ControlEvent):
method copy_to_clipboard (line 1011) | def copy_to_clipboard(self, e: ft.ControlEvent):
method build (line 1020) | def build(self):
function main (line 1086) | def main(page: ft.Page):
FILE: Flet-Utils/utils/icon_utils.py
class TabContentIcon (line 7) | class TabContentIcon(ft.UserControl):
method __init__ (line 9) | def __init__(self):
method build (line 112) | def build(self):
method update_icon (line 169) | def update_icon(self, e: ft.ControlEvent):
method copy_to_clipboard (line 314) | def copy_to_clipboard(self, e: ft.ControlEvent):
function main (line 331) | def main(page: ft.Page):
FILE: Flet-Utils/utils/icons_browser_utils.py
class TabContentIconsBrowser (line 6) | class TabContentIconsBrowser(ft.UserControl):
method __init__ (line 9) | def __init__(self):
method build (line 12) | def build(self):
function main (line 153) | def main(page: ft.Page):
FILE: Flet-Utils/utils/padding_utils.py
class TabContentPadding (line 6) | class TabContentPadding(ft.UserControl):
method __init__ (line 7) | def __init__(self):
method update_front_container_padding (line 68) | def update_front_container_padding(self, e: ft.ControlEvent):
method update_front_container_size (line 94) | def update_front_container_size(self, e: ft.ControlEvent):
method copy_to_clipboard (line 112) | def copy_to_clipboard(self, e: ft.ControlEvent):
method build (line 122) | def build(self):
function main (line 196) | def main(page: ft.Page):
FILE: Flet-Utils/utils/progress_bar_utils.py
class TabContentProgressBar (line 6) | class TabContentProgressBar(ft.UserControl):
method __init__ (line 8) | def __init__(self):
method build (line 142) | def build(self):
method update_bar (line 195) | def update_bar(self, e: ft.ControlEvent):
method copy_to_clipboard (line 357) | def copy_to_clipboard(self, e: ft.ControlEvent):
function main (line 376) | def main(page: ft.Page):
FILE: Flet-Utils/utils/progress_ring_utils.py
class TabContentProgressRing (line 8) | class TabContentProgressRing(ft.UserControl):
method __init__ (line 10) | def __init__(self):
method build (line 144) | def build(self):
method update_ring (line 194) | def update_ring(self, e: ft.ControlEvent):
method copy_to_clipboard (line 358) | def copy_to_clipboard(self, e: ft.ControlEvent):
function main (line 378) | def main(page: ft.Page):
FILE: Flet-Utils/utils/shadermask_utils.py
class TabContentShaderMask (line 7) | class TabContentShaderMask(ft.UserControl):
method __init__ (line 8) | def __init__(self):
method update_mask (line 97) | def update_mask(self, e: ft.ControlEvent):
method copy_to_clipboard (line 172) | def copy_to_clipboard(self, e: ft.ControlEvent):
method build (line 184) | def build(self):
function main (line 232) | def main(page: ft.Page):
FILE: Flet-Utils/utils/shadow_utils.py
class TabContentShadow (line 8) | class TabContentShadow(ft.UserControl):
method __init__ (line 10) | def __init__(self):
method build (line 89) | def build(self):
method update_shadow (line 143) | def update_shadow(self, e: ft.ControlEvent):
method copy_to_clipboard (line 252) | def copy_to_clipboard(self, e: ft.ControlEvent):
function main (line 261) | def main(page: ft.Page):
FILE: Flet-Utils/utils/shape_utils.py
class TabContentShape (line 5) | class TabContentShape(ft.UserControl):
method __init__ (line 6) | def __init__(self):
method update_shape (line 23) | def update_shape(self, e: ft.ControlEvent):
method copy_to_clipboard (line 38) | def copy_to_clipboard(self, e: ft.ControlEvent):
method build (line 51) | def build(self):
function main (line 96) | def main(page: ft.Page):
FILE: Flet-Utils/utils/tooltip_utils.py
class TabContentTooltip (line 8) | class TabContentTooltip(ft.UserControl):
method __init__ (line 10) | def __init__(self):
method build (line 265) | def build(self):
method update_tooltip (line 356) | def update_tooltip(self, e: ft.ControlEvent):
method update_container_size (line 538) | def update_container_size(self, e: ft.ControlEvent):
method copy_to_clipboard (line 558) | def copy_to_clipboard(self, e: ft.ControlEvent):
function main (line 572) | def main(page: ft.Page):
FILE: Flet-Utils/utils/vertical_divider_utils.py
class TabContentVerticalDivider (line 6) | class TabContentVerticalDivider(ft.UserControl):
method __init__ (line 8) | def __init__(self):
method build (line 78) | def build(self):
method update_vertical_divider (line 150) | def update_vertical_divider(self, e: ft.ControlEvent):
method copy_to_clipboard (line 232) | def copy_to_clipboard(self, e: ft.ControlEvent):
function main (line 248) | def main(page: ft.Page):
FILE: Forms/login_utils.py
class LoginWithCaptcha (line 12) | class LoginWithCaptcha(ft.Column):
method __init__ (line 13) | def __init__(self, on_success: Callable = None, on_error: Callable = N...
method update (line 161) | def update(self):
method did_mount (line 169) | def did_mount(self):
method will_unmount (line 177) | def will_unmount(self):
method handle_textfield_change (line 192) | def handle_textfield_change(self, e):
method handle_fields_validation (line 200) | def handle_fields_validation(self):
method handle_login (line 221) | def handle_login(self, e):
method generate_captcha (line 240) | def generate_captcha(self, length: int = 4):
method generate_new_captcha (line 275) | def generate_new_captcha(self, e=None):
method handle_audio_state_change (line 285) | def handle_audio_state_change(self, e):
method handle_audio (line 294) | def handle_audio(self, e):
method show_snackbar_message (line 304) | def show_snackbar_message(self, text: str = "Message:", duration: int ...
FILE: Forms/login_with_captcha.py
function main (line 5) | def main(page: ft.Page):
FILE: IP Revealer/main.py
function main (line 5) | def main(page: ft.Page):
FILE: IP Revealer/main_with_ipify.py
function main (line 6) | def main(page: ft.Page):
FILE: Markdown Editor/main.py
function main (line 7) | def main(page: ft.Page):
FILE: Markdown Editor/utils.py
function close_dialog (line 8) | def close_dialog(e):
function open_dialog (line 15) | def open_dialog(e):
function show_progress (line 22) | def show_progress(e):
function unshow_progress (line 29) | def unshow_progress(e):
function file_picker_result_import (line 35) | def file_picker_result_import(e: ft.FilePickerResultEvent):
function on_upload_progress (line 63) | def on_upload_progress(e: ft.FilePickerUploadEvent):
function upload_file (line 77) | def upload_file(e):
function overwrite_textfield_and_md (line 95) | def overwrite_textfield_and_md(page, file_name_or_path, is_web=True):
FILE: QR Code Generator/main.py
function main (line 8) | def main(page: ft.Page):
FILE: Random Image Viewer/main.py
function main (line 5) | def main(page: ft.Page):
FILE: Random Image Viewer/utils.py
class ImageCard (line 7) | class ImageCard(ft.Card):
method __init__ (line 13) | def __init__(self, img_id: int):
method launch_img_url (line 71) | def launch_img_url(self, e):
method copy_img_url (line 78) | def copy_img_url(self, e):
method delete_img_card (line 83) | def delete_img_card(self, e):
method hover_elevation (line 90) | def hover_elevation(self, e):
FILE: Short Jokes/joke.py
function fetch_joke (line 10) | def fetch_joke() -> Optional[dict]:
function validate_joke (line 21) | def validate_joke(joke: dict) -> None:
function render_joke (line 27) | def render_joke(joke: dict) -> Optional[str]:
function return_joke (line 43) | def return_joke():
FILE: Short Jokes/main.py
function main (line 7) | def main(page: ft.Page):
FILE: Short Jokes/utils.py
class JokeCard (line 4) | class JokeCard(ft.Card):
method __init__ (line 10) | def __init__(self, joke_id: int, joke: str = "This is a Joke bro. Haha...
method _build (line 16) | def _build(self):
method copy_joke (line 62) | def copy_joke(self, e):
method delete_joke_card (line 72) | def delete_joke_card(self, e):
method hover_elevation (line 84) | def hover_elevation(self, e):
FILE: StartUp Name Generator/main.py
function main (line 7) | def main(page: ft.Page):
FILE: URL shortener/main.py
class ShortLinkRow (line 7) | class ShortLinkRow(ft.Row):
method __init__ (line 10) | def __init__(self, shortened_link, link_source):
method copy (line 39) | def copy(self, value):
function main (line 48) | def main(page: ft.Page):
Condensed preview — 83 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (409K chars).
[
{
"path": ".gitattributes",
"chars": 66,
"preview": "# Auto detect text files and perform LF normalization\n* text=auto\n"
},
{
"path": ".gitignore",
"chars": 2815,
"preview": "/.idea\n# Byte-compiled / optimized / DLL files\n__pycache__/\n*.py[cod]\n*$py.class\n\n# C extensions\n*.so\n\n# Distribution / "
},
{
"path": "Flet-Utils/Dockerfile",
"chars": 164,
"preview": "FROM python:3-alpine\n\nWORKDIR /app\n\nCOPY requirements.txt ./\n\nRUN pip install --no-cache-dir -r requirements.txt\n\nCOPY ."
},
{
"path": "Flet-Utils/README.md",
"chars": 1180,
"preview": "# Flet-Utils (Flutils)\n**Link to Online Demo [here](https://flutils.pages.dev/)!**\n\nWhen developing with Flet([website]("
},
{
"path": "Flet-Utils/assets/index.html",
"chars": 2900,
"preview": "<html><head>\n <base href=\"/\">\n\n <meta charset=\"UTF-8\">\n <meta content=\"IE=Edge\" http-equiv=\"X-UA-Compatible\">\n <meta"
},
{
"path": "Flet-Utils/assets/manifest.json",
"chars": 800,
"preview": "{\n \"name\": \"Flet Utilities\",\n \"short_name\": \"Flet Utils\",\n \"start_url\": \".\",\n \"display\": \"standalone\",\n \"background"
},
{
"path": "Flet-Utils/fly.toml",
"chars": 645,
"preview": "app = \"flutils\"\nkill_signal = \"SIGINT\"\nkill_timeout = 5\nprocesses = []\n\n[env]\n FLET_SERVER_PORT = \"8080\"\n\n[experimental"
},
{
"path": "Flet-Utils/main.py",
"chars": 6793,
"preview": "import flet as ft\nfrom utils.padding_utils import TabContentPadding\nfrom utils.alignment_utils import TabContentAlignmen"
},
{
"path": "Flet-Utils/requirements.txt",
"chars": 11,
"preview": "flet==0.9.0"
},
{
"path": "Flet-Utils/utils/alignment_utils.py",
"chars": 4628,
"preview": "import flet as ft\n\n\n# the content of the alignment tab\nclass TabContentAlignment(ft.UserControl):\n def __init__(self)"
},
{
"path": "Flet-Utils/utils/blur_utils.py",
"chars": 6236,
"preview": "import random\n\nfrom flet import *\nimport flet as ft\n\n\n# todo: change link to docs\n\n# the content of the blur tab\nclass "
},
{
"path": "Flet-Utils/utils/border_radius_utils.py",
"chars": 7722,
"preview": "import flet as ft\n\n\n# the content of the border radius tab\nclass TabContentBorderRadius(ft.UserControl):\n def __init_"
},
{
"path": "Flet-Utils/utils/border_utils.py",
"chars": 7456,
"preview": "import flet as ft\n\n\n# todo: add respective colors to each\n\n# the content of the border tab\nclass TabContentBorder(ft.Use"
},
{
"path": "Flet-Utils/utils/circle_avatar_utils.py",
"chars": 19767,
"preview": "from flet import *\nimport flet as ft\n\n\n# todo: \"rotate\" from icon_utils\n\n# the content of the circle avatar tab\nclass Ta"
},
{
"path": "Flet-Utils/utils/colors_utils.py",
"chars": 13070,
"preview": "import flet as ft\nfrom itertools import islice\n\n\n# the content of the ColorV1 tab\nclass TabContentColors1(ft.UserControl"
},
{
"path": "Flet-Utils/utils/divider_utils.py",
"chars": 9715,
"preview": "from flet import *\nimport flet as ft\n\n\n# the content of the divider tab\nclass TabContentDivider(ft.UserControl):\n\n de"
},
{
"path": "Flet-Utils/utils/gradient_utils.py",
"chars": 44531,
"preview": "import math\nfrom flet import *\nimport flet as ft\n\n\n# the content of the LinearGradient tab\nclass TabContentLinearGradien"
},
{
"path": "Flet-Utils/utils/icon_utils.py",
"chars": 13107,
"preview": "import math\nfrom flet import *\nimport flet as ft\n\n\n# the content of the icon tab\nclass TabContentIcon(ft.UserControl):\n\n"
},
{
"path": "Flet-Utils/utils/icons_browser_utils.py",
"chars": 5827,
"preview": "from itertools import islice\nimport flet as ft\n\n\n# the content of the Icons tab\nclass TabContentIconsBrowser(ft.UserCont"
},
{
"path": "Flet-Utils/utils/padding_utils.py",
"chars": 8633,
"preview": "import flet as ft\nfrom flet import padding\n\n\n# the content of the padding tab\nclass TabContentPadding(ft.UserControl):\n "
},
{
"path": "Flet-Utils/utils/progress_bar_utils.py",
"chars": 14743,
"preview": "from flet import *\nimport flet as ft\n\n\n# the content of the progress bar tab\nclass TabContentProgressBar(ft.UserControl)"
},
{
"path": "Flet-Utils/utils/progress_ring_utils.py",
"chars": 14895,
"preview": "from flet import *\nimport flet as ft\n\n\n# todo: width, height\n\n# the content of the progress ring tab\nclass TabContentPro"
},
{
"path": "Flet-Utils/utils/shadermask_utils.py",
"chars": 9561,
"preview": "# import all the controls: if the shader mask requires controls which are not imported, an error is raised\nfrom flet imp"
},
{
"path": "Flet-Utils/utils/shadow_utils.py",
"chars": 10398,
"preview": "from flet import *\nimport flet as ft\n\n\n# todo: change link to docs\n\n# the content of the shadow tab\nclass TabContentSha"
},
{
"path": "Flet-Utils/utils/shape_utils.py",
"chars": 3188,
"preview": "import flet as ft\n\n\n# the content of the Shape tab\nclass TabContentShape(ft.UserControl):\n def __init__(self):\n "
},
{
"path": "Flet-Utils/utils/tooltip_utils.py",
"chars": 24361,
"preview": "import math\nimport flet as ft\nfrom flet import *\nfrom flet import border_radius, border, padding, margin, alignment\n\n\n# "
},
{
"path": "Flet-Utils/utils/vertical_divider_utils.py",
"chars": 10236,
"preview": "from flet import *\nimport flet as ft\n\n\n# the content of the vertical_divider tab\nclass TabContentVerticalDivider(ft.User"
},
{
"path": "Forms/README.md",
"chars": 402,
"preview": "# Forms\n\nLogin and Registration Forms. Could be customized for re-use.\n \n## Content (WIP)\n- [x] Login Form with Captcha;"
},
{
"path": "Forms/login_utils.py",
"chars": 15250,
"preview": "import base64\nimport os\nimport random\nimport string\nfrom typing import Callable\n\nimport flet as ft\nfrom captcha.audio im"
},
{
"path": "Forms/login_with_captcha.py",
"chars": 929,
"preview": "import flet as ft\nfrom login_utils import LoginWithCaptcha\n\n\ndef main(page: ft.Page):\n page.title = \"Forms\"\n # pag"
},
{
"path": "Forms/requirements.txt",
"chars": 41,
"preview": "flet>=0.9.0\ncaptcha>=0.5.0\npandas>=10.0.0"
},
{
"path": "IP Revealer/README.md",
"chars": 551,
"preview": "# IP Revealer\n\nHelps you know the public ip address of your device. \n\nTry it from [here](https://ip-revealer.henrindonko"
},
{
"path": "IP Revealer/assets/fonts/Plus_Jakarta_Sans/OFL.txt",
"chars": 4402,
"preview": "Copyright 2020 The Plus Jakarta Sans Project Authors (https://github.com/tokotype/PlusJakartaSans)\n\nThis Font Software i"
},
{
"path": "IP Revealer/assets/fonts/Stick/OFL.txt",
"chars": 4387,
"preview": "Copyright 2020 The Stick Project Authors (https://github.com/fontworks-fonts/Stick)\n\nThis Font Software is licensed unde"
},
{
"path": "IP Revealer/main.py",
"chars": 5071,
"preview": "import time\nimport flet as ft\n\n\ndef main(page: ft.Page):\n page.title = \"IP Revealer\"\n page.theme_mode = ft.ThemeMo"
},
{
"path": "IP Revealer/main_with_ipify.py",
"chars": 2617,
"preview": "import time\nimport flet as ft\nimport requests\n\n\ndef main(page: ft.Page):\n page.title = \"IP Revealer\"\n page.window_"
},
{
"path": "IP Revealer/requirements.txt",
"chars": 11,
"preview": "flet>=0.7.4"
},
{
"path": "LICENSE",
"chars": 1068,
"preview": "MIT License\n\nCopyright (c) 2023 ndonkoHenri\n\nPermission is hereby granted, free of charge, to any person obtaining a cop"
},
{
"path": "Markdown Editor/Dockerfile",
"chars": 164,
"preview": "FROM python:3-alpine\n\nWORKDIR /app\n\nCOPY requirements.txt ./\n\nRUN pip install --no-cache-dir -r requirements.txt\n\nCOPY ."
},
{
"path": "Markdown Editor/README.md",
"chars": 2172,
"preview": "# Markdown Editor\n\n[Markdown](https://en.wikipedia.org/wiki/Markdown) is a lightweight markup language for creating form"
},
{
"path": "Markdown Editor/assets/index.html",
"chars": 3604,
"preview": "<html><head>\n <base href=\"/\">\n\n <meta charset=\"UTF-8\">\n <meta content=\"IE=Edge\" http-equiv=\"X-UA-Compatible\">\n\n <!--"
},
{
"path": "Markdown Editor/assets/manifest.json",
"chars": 835,
"preview": "{\n \"name\": \"Markdown Editor\",\n \"short_name\": \"Markdown Editor\",\n \"start_url\": \".\",\n \"display\": \"standalone\",\n \"back"
},
{
"path": "Markdown Editor/fly.toml",
"chars": 717,
"preview": "# fly.toml file generated for md-editor on 2022-10-23T17:37:00+02:00\n\napp = \"md-editor\"\nkill_signal = \"SIGINT\"\nkill_time"
},
{
"path": "Markdown Editor/main.py",
"chars": 9257,
"preview": "import flet as ft\nimport utils\n\n\n# todo: output as pdf | add error dialog to handle errors\n\ndef main(page: ft.Page):\n "
},
{
"path": "Markdown Editor/requirements.txt",
"chars": 28,
"preview": "flet>=0.3.2\nmarkdown2>=2.4.6"
},
{
"path": "Markdown Editor/utils.py",
"chars": 5158,
"preview": "import flet as ft\n\nfile_path = None\nerror_code = None\n\n\n# dialog\ndef close_dialog(e):\n \"\"\"Closes the Alert Dialog.\"\"\""
},
{
"path": "QR Code Generator/Dockerfile",
"chars": 163,
"preview": "FROM python:3-alpine\n\nWORKDIR /app\n\nCOPY requirements.txt ./\nRUN pip install --no-cache-dir -r requirements.txt\n\nCOPY . "
},
{
"path": "QR Code Generator/README.md",
"chars": 630,
"preview": "# QR Code Generator\nA 'quick response' code also known as [a QR Code](https://en.wikipedia.org/wiki/QR_code) has widely "
},
{
"path": "QR Code Generator/assets/index.html",
"chars": 3562,
"preview": "<html><head>\n <base href=\"/\">\n\n <meta charset=\"UTF-8\">\n <meta content=\"IE=Edge\" http-equiv=\"X-UA-Compatible\">\n\n <!--"
},
{
"path": "QR Code Generator/assets/manifest.json",
"chars": 815,
"preview": "{\n \"name\": \"QR Code Generator\",\n \"short_name\": \"QR Code Generator\",\n \"start_url\": \".\",\n \"display\": \"standalone\",\n \""
},
{
"path": "QR Code Generator/fly.toml",
"chars": 719,
"preview": "# fly.toml file generated for qrcode-gen on 2022-10-23T17:49:38+02:00\n\napp = \"qrcode-gen\"\nkill_signal = \"SIGINT\"\nkill_ti"
},
{
"path": "QR Code Generator/main.py",
"chars": 6392,
"preview": "import os\nimport flet as ft\nimport pyqrcode\n\n\n# todo: add filepicker for image save on desktop\n\ndef main(page: ft.Page):"
},
{
"path": "QR Code Generator/requirements.txt",
"chars": 47,
"preview": "flet>=0.3.2\npyqrcode>=1.2.1\npypng>=0.20220715.0"
},
{
"path": "README.md",
"chars": 1381,
"preview": "# Flet-Samples\n\n Showcasing applications I made with the Flet([website](https://flet.dev), [github](https://github.com/f"
},
{
"path": "Random Image Viewer/README.md",
"chars": 1411,
"preview": "# Random Image Viewer/Generator\n\nI deployed an online version of this application [here](https://random-image-generator."
},
{
"path": "Random Image Viewer/assets/fonts/JetBrains_Mono/OFL.txt",
"chars": 4398,
"preview": "Copyright 2020 The JetBrains Mono Project Authors (https://github.com/JetBrains/JetBrainsMono)\n\nThis Font Software is li"
},
{
"path": "Random Image Viewer/assets/fonts/Kalam/OFL.txt",
"chars": 4373,
"preview": "Copyright (c) 2014, Indian Type Foundry (info@indiantypefoundry.com).\n\nThis Font Software is licensed under the SIL Open"
},
{
"path": "Random Image Viewer/assets/fonts/Space_Grotesk/OFL.txt",
"chars": 4402,
"preview": "Copyright 2020 The Space Grotesk Project Authors (https://github.com/floriankarsten/space-grotesk)\n\nThis Font Software i"
},
{
"path": "Random Image Viewer/assets/index.html",
"chars": 4184,
"preview": "\n<!DOCTYPE html>\n<html>\n\n<head>\n <base href=\"/\">\n\n <meta charset=\"UTF-8\">\n <meta content=\"IE=Edge\" http-equiv=\"X-UA-C"
},
{
"path": "Random Image Viewer/assets/manifest.json",
"chars": 825,
"preview": "{\n \"name\": \"Random Image Generator\",\n \"short_name\": \"Random Image Generator\",\n \"start_url\": \".\",\n \"display\": \"standa"
},
{
"path": "Random Image Viewer/main.py",
"chars": 3665,
"preview": "import flet as ft\nfrom utils import ImageCard\n\n\ndef main(page: ft.Page):\n # little configurations\n page.title = \"R"
},
{
"path": "Random Image Viewer/requirements.txt",
"chars": 11,
"preview": "flet>=0.3.2"
},
{
"path": "Random Image Viewer/utils.py",
"chars": 4029,
"preview": "import random\nimport flet as ft\n\n\n# todo: add grayscale and blur\n\nclass ImageCard(ft.Card):\n # elevation when this ca"
},
{
"path": "Short Jokes/README.md",
"chars": 1720,
"preview": "# Short Jokes\n\nI deployed a live version of this application [here](https://short-jokes.henrindonko.repl.co/). Feel free"
},
{
"path": "Short Jokes/assets/fonts/JetBrains_Mono/OFL.txt",
"chars": 4398,
"preview": "Copyright 2020 The JetBrains Mono Project Authors (https://github.com/JetBrains/JetBrainsMono)\n\nThis Font Software is li"
},
{
"path": "Short Jokes/assets/fonts/Kalam/OFL.txt",
"chars": 4373,
"preview": "Copyright (c) 2014, Indian Type Foundry (info@indiantypefoundry.com).\n\nThis Font Software is licensed under the SIL Open"
},
{
"path": "Short Jokes/assets/fonts/Space_Grotesk/OFL.txt",
"chars": 4402,
"preview": "Copyright 2020 The Space Grotesk Project Authors (https://github.com/floriankarsten/space-grotesk)\n\nThis Font Software i"
},
{
"path": "Short Jokes/assets/index.html",
"chars": 3589,
"preview": "<html><head>\n <base href=\"/\">\n\n <meta charset=\"UTF-8\">\n <meta content=\"IE=Edge\" http-equiv=\"X-UA-Compatible\">\n\n <!--"
},
{
"path": "Short Jokes/assets/manifest.json",
"chars": 822,
"preview": "{\n \"name\": \"Short Jokes\",\n \"short_name\": \"Short Jokes\",\n \"start_url\": \".\",\n \"display\": \"standalone\",\n \"background_c"
},
{
"path": "Short Jokes/joke.py",
"chars": 1392,
"preview": "import json\nfrom typing import Optional\n\nimport urllib3\n\n# documentation available here : https://v2.jokeapi.dev/\nJOKE_U"
},
{
"path": "Short Jokes/main.py",
"chars": 5127,
"preview": "import flet as ft\nfrom utils import JokeCard, ethical_signature\nfrom joke import return_joke\n\n\n\ndef main(page: ft.Page):"
},
{
"path": "Short Jokes/requirements.txt",
"chars": 11,
"preview": "flet>=0.3.2"
},
{
"path": "Short Jokes/utils.py",
"chars": 3450,
"preview": "import flet as ft\n\n\nclass JokeCard(ft.Card):\n # elevation when this card is not hovered\n NORMAL_ELEVATION = 3\n "
},
{
"path": "StartUp Name Generator/README.md",
"chars": 1060,
"preview": "# StartUp Name Generator Clone\n\nI made this after watching an [interview](https://www.youtube.com/watch?v=kxsLRRY2xZA&t="
},
{
"path": "StartUp Name Generator/main.py",
"chars": 4003,
"preview": "# made by @ndonkoHenri aka TheEthicalBoy\n\nimport flet as ft\nimport utils\n\n\ndef main(page: ft.Page):\n def tile_clicked"
},
{
"path": "StartUp Name Generator/requirements.txt",
"chars": 11,
"preview": "flet==0.3.2"
},
{
"path": "StartUp Name Generator/utils.py",
"chars": 1509,
"preview": "# I pushed some stuffs into here to make th main.py file cleaner\n\nimport flet as ft\n\n# the list view for the main page\nm"
},
{
"path": "URL shortener/Dockerfile",
"chars": 163,
"preview": "FROM python:3-alpine\n\nWORKDIR /app\n\nCOPY requirements.txt ./\nRUN pip install --no-cache-dir -r requirements.txt\n\nCOPY . "
},
{
"path": "URL shortener/README.md",
"chars": 308,
"preview": "# Flet URL shortener\n\nUsing long URLs is sometimes annoying, boring and tedious. \nThis tool is here to help shorten thes"
},
{
"path": "URL shortener/assets/index.html",
"chars": 3864,
"preview": "<html><head>\n <base href=\"/\">\n\n <meta charset=\"UTF-8\">\n <meta content=\"IE=Edge\" http-equiv=\"X-UA-Compatible\">\n\n <!--"
},
{
"path": "URL shortener/fly.toml",
"chars": 721,
"preview": "# fly.toml file generated for url-shorten on 2022-10-23T17:54:34+02:00\n\napp = \"url-shorten\"\nkill_signal = \"SIGINT\"\nkill_"
},
{
"path": "URL shortener/main.py",
"chars": 6727,
"preview": "import flet as ft\nimport pyshorteners # pip install pyshorteners\n\nshortener = pyshorteners.Shortener()\n\n\nclass ShortLin"
},
{
"path": "URL shortener/requirements.txt",
"chars": 31,
"preview": "flet>=0.4.0\npyshorteners>=1.0.1"
}
]
About this extraction
This page contains the full source code of the ndonkoHenri/Flet-Samples GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 83 files (379.7 KB), approximately 82.6k tokens, and a symbol index with 177 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.