Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

### Bug fixes

* Fix `TooltipTheme.decoration` so it applies to controls using `ft.Tooltip(...)` when the tooltip does not explicitly set `decoration` or `bgcolor` ([#6432](https://github.com/flet-dev/flet/issues/6432), [#6482](https://github.com/flet-dev/flet/pull/6482)) by @ndonkoHenri.
* Fix `flet-geolocator.Geolocator` reliability on web and desktop: `get_last_known_position()` no longer crashes with `TypeError: argument after ** must be a mapping, not NoneType` and now returns `Optional[GeolocatorPosition]`; `get_current_position()` no longer hangs forever on web (Dart-side workaround for the upstream [`geolocator_web` 4.1.3](https://pub.dev/packages/geolocator_web) `inMicroseconds`/`inMilliseconds` timeout typo) and uses sensible web defaults (`time_limit: 30s`, `maximum_age: 5m`); the previously-dropped `configuration` argument now actually reaches `getCurrentPosition` on the Dart side; the position stream is gated behind a registered `on_position_change`/`on_error` handler (with cancel-on-update to prevent leaks); and platform exceptions (`LocationServiceDisabledException`, `PermissionDeniedException`, `PermissionDefinitionsNotFoundException`, `PermissionRequestInProgressException`, `PositionUpdateException`, `TimeoutException`) are now translated into actionable error messages and surfaced to Python as `RuntimeError` without the default `Exception:` prefix ([#6487](https://github.com/flet-dev/flet/pull/6487)) by @FeodorFitsner.

## 0.85.0
Expand Down
42 changes: 24 additions & 18 deletions packages/flet/lib/src/utils/tooltip.dart
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import 'package:flutter/material.dart';
import 'enums.dart';

import '../models/control.dart';
import 'box.dart';
import 'colors.dart';
import 'edge_insets.dart';
import 'enums.dart';
import 'mouse.dart';
import 'numbers.dart';
import 'text.dart';
Expand All @@ -27,27 +27,33 @@ Tooltip? parseTooltip(dynamic value, BuildContext context, Widget widget) {

var theme = Theme.of(context);

/// The tooltip shape defaults to a rounded rectangle with a border radius of
/// 4.0. Tooltips will also default to an opacity of 90%
var defaultDecoration = BoxDecoration(
var hasDecoration = value["decoration"] != null || value["bgcolor"] != null;
BoxDecoration? finalDecoration;
if (hasDecoration) {
/// The tooltip has the following defaults: rounded rectangle shape,
/// border radius of 4.0, opacity of 90%.
var defaultDecoration = BoxDecoration(
borderRadius: BorderRadius.circular(4.0),
color: parseColor(
value["bgcolor"],
theme,
theme.brightness == Brightness.light
? Colors.grey[700]
: Colors.white));
var decoration = parseBoxDecoration(value["decoration"], context);
var finalDecoration = defaultDecoration.copyWith(
color: decoration?.color,
borderRadius: decoration?.borderRadius,
border: decoration?.border,
boxShadow: decoration?.boxShadow,
gradient: decoration?.gradient,
image: decoration?.image,
shape: decoration?.shape,
backgroundBlendMode: decoration?.backgroundBlendMode,
);
(theme.brightness == Brightness.light
? Colors.grey[700]!
: Colors.white)
.withValues(alpha: 0.9))!,
);
var decoration = parseBoxDecoration(value["decoration"], context);
finalDecoration = defaultDecoration.copyWith(
color: decoration?.color,
borderRadius: decoration?.borderRadius,
border: decoration?.border,
boxShadow: decoration?.boxShadow,
gradient: decoration?.gradient,
image: decoration?.image,
shape: decoration?.shape,
backgroundBlendMode: decoration?.backgroundBlendMode,
);
}
return Tooltip(
message: value["message"],
enableFeedback: parseBool(value["enable_feedback"]),
Expand Down
82 changes: 82 additions & 0 deletions sdk/python/examples/extensions/map/attribution/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import flet as ft
import flet_map as ftm


def main(page: ft.Page):
def launch_url(url: str):
page.run_task(ft.UrlLauncher().launch_url, url)

page.add(
ft.SafeArea(
expand=True,
content=ftm.Map(
expand=True,
initial_zoom=11,
initial_center=ftm.MapLatitudeLongitude(
latitude=40.7128, longitude=-74.0060
),
layers=[
ftm.TileLayer(
url_template="https://tile.openstreetmap.org/{z}/{x}/{y}.png",
user_agent_package_name="flet-map-examples/1.0",
on_image_error=lambda e: print(f"TileLayer Error: {e.data}"),
),
ftm.SimpleAttribution(
text="OpenStreetMap contributors",
text_style=ft.TextStyle(
color=ft.Colors.WHITE, weight=ft.FontWeight.BOLD, size=15
),
alignment=ft.Alignment.TOP_RIGHT,
bgcolor=ft.Colors.BLUE,
on_click=lambda: launch_url(
"https://www.openstreetmap.org/copyright"
),
),
ftm.RichAttribution(
alignment=ftm.AttributionAlignment.BOTTOM_RIGHT,
popup_bgcolor=ft.Colors.WHITE,
popup_border_radius=8,
popup_initial_display_duration=4000,
permanent_height=28,
attributions=[
ftm.ImageSourceAttribution(
image=ft.Image(
src="iVBORw0KGgoAAAANSUhEUgAAABkAAAAgCAYAAADnnNMGAAAACXBIWXMAAAORAAADkQFnq8zdAAAAGXRFWHRTb2Z0d2FyZQB3d3cuaW5rc2NhcGUub3Jnm+48GgAAA6dJREFUSImllltoHFUYx3/fzOzm0lt23ZrQ1AQbtBehNpvQohgkBYVo410RwQctNE3Sh0IfiiBoIAjqi6TYrKnFy4O3oiiRavDJFi3mXomIBmOxNZe63ay52GR3Zj4f2sTEzmx3m//TYf7/c35zvgPnO6KqrESXqpq3muocAikv6m+/zytj3ejik1VN21G31YA9CgJ6xC+bMyQZPVCuarciPAMYC99V6Vw5pLbFSibHmlVoRVj9P3cmPBM8tSJI/M6mzabpfoAQ9fIF7WK4bd5vvuFnLGgy2vi0abg94A0AcJGvMq3hDxGRyar9r4F+iLAm0yIiRk8m37tctS1WsrIhhrI30+Srmg+J87OXUf3lWGS1q89dC6ltsSanxk4Aj2QBABii96300g87P/rtlrWr8l+vyDMfdlXSyyEikqxsiOUAQJCBhfHdXRfCq1LSsSlcWG+KBAGStvvrMkgiuv8lUc2mREukPwLUfHG+uTQv8Eown7VL3XlbBxYhf1c17hbVF3MDwA9bts280TnaU1YYqPby07aeFlUlHt27wSQ4CLo+F8AvoTCvHmyKF+ZbEb/M77P2LgvAwmrTHAHflN3KZxVbMC2jMFNOpgPnrMSOhvvFkMezXdwV4ePbtvHtxnJAMQ0j4JtVnO+eLb5oiSlt5HDbv7t1O90lpYCCCKbhfzW5kAIwUAazR0BlfII8Ow0I6uoVmI9MyAMwbMs8CExmDbk4zgu931MyO4OI4KrYflkRjOoTI+uM9d1vjotwKPu9QMk/sxzuO8POiVFcdZ1M2YBVsMEAKOqLvaPIe7mACuw0z/80SMH58SMplxlfiDhVi7dw2pltRhjKBQTQdrSja2KKTfE551NHuaZ0QVPvWYQUn31/Vm2nDvgjF4grVJx6suSvrvrSJ/6cSW2Oz9mf264uNrB806xZ1k/CZ49dUKgDEtlCROX2hfHpx8pGuuo3PpqYulw8fjndOp1yhgtNKRevJ1FyR2Ola+jXAjdnwTkZ6o896GdWdxDw7IxFg+0DpmXchTKSBWQnIuJn9u4j7dt+13UfHXEkXQOcuQ4kMhVtqsgUyPiQiPQfHw1NB2sRjmXKuTg1NwwBYLhtPtQX26eqTwGXPDOqvmcC4Hnwfrrad94GrVsOYTqUTkQY+iTlNe/6O1miSP/x0VB/+wMIDwHn/vtV1iQC4Xv95uUEWVCoL9Y5Z+gdovoyMHUFJHv88jmVy0vTuw7cZNv2YaA61Bfb7ZX5F8SaUv2xwZevAAAAAElFTkSuQmCC", # noqa: E501
width=74,
height=28,
fit=ft.BoxFit.CONTAIN,
),
height=28,
tooltip="Flet Logo",
on_click=lambda: launch_url("https://flet.dev"),
),
ftm.TextSourceAttribution(
text="OpenStreetMap contributors",
text_style=ft.TextStyle(size=12),
on_click=lambda: launch_url(
"https://www.openstreetmap.org/copyright"
),
),
ftm.TextSourceAttribution(
text="flet-map",
text_style=ft.TextStyle(
color=ft.Colors.RED,
size=15,
weight=ft.FontWeight.BOLD,
decoration=ft.TextDecoration.UNDERLINE,
),
prepend_copyright=False,
on_click=lambda: launch_url(
"https://flet.dev/docs/controls/map/"
),
),
],
),
],
),
)
)


if __name__ == "__main__":
ft.run(main)
26 changes: 26 additions & 0 deletions sdk/python/examples/extensions/map/attribution/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
[project]
name = "map-attribution"
version = "1.0.0"
description = "Compares simple and rich flet-map attribution layers with clickable text and image source attributions."
requires-python = ">=3.10"
keywords = ["map", "attribution", "rich attribution", "source attribution", "flet-map"]
authors = [{ name = "Flet team", email = "hello@flet.dev" }]
dependencies = ["flet", "flet-map"]

[dependency-groups]
dev = ["flet-cli", "flet-desktop", "flet-web"]

[tool.flet.gallery]
categories = ["Extensions/Map"]

[tool.flet.metadata]
title = "Attribution"
controls = ["SafeArea", "Image", "Map", "TileLayer", "SimpleAttribution", "RichAttribution", "TextSourceAttribution", "ImageSourceAttribution"]
layout_pattern = "single-panel"
complexity = "basic"
features = ["simple attribution layer", "rich attribution popup", "text and image source attributions", "attribution click handlers"]

[tool.flet]
org = "dev.flet"
company = "Flet"
copyright = "Copyright (C) 2023-2026 by Flet"
1 change: 1 addition & 0 deletions sdk/python/packages/flet-map/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
### Added

- Added image overlay support for maps with `OverlayImageLayer`, `OverlayImage`, and `RotatedOverlayImage` ([#6319](https://github.com/flet-dev/flet/issues/6319), [#6421](https://github.com/flet-dev/flet/pull/6421)) by @ndonkoHenri.
- Added `SimpleAttribution.text_style` for styling simple map attribution text by @ndonkoHenri.

## 0.81.1

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from dataclasses import field
from typing import Optional, Union
from typing import Optional

import flet as ft
from flet_map.map_layer import MapLayer
Expand All @@ -13,11 +13,16 @@ class SimpleAttribution(MapLayer):
A simple attribution layer displayed on the Map.
"""

text: Union[str, ft.Text]
text: str
"""
The attribution message to be displayed.
"""

text_style: Optional[ft.TextStyle] = None
"""
The style to use for :attr:`text`.
"""

alignment: ft.Alignment = field(default_factory=lambda: ft.Alignment.BOTTOM_RIGHT)
"""
The alignment of this attribution on the map.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,19 @@ class SimpleAttributionControl extends StatelessWidget {
@override
Widget build(BuildContext context) {
debugPrint("SimpleAttributionControl build: ${control.id}");
var text = control.buildTextOrWidget("text");
final text = control.getString("text");

if (text == null) {
return const ErrorControl("SimpleAttribution.text must be provided");
}

return BaseControl(
control: control,
child: SimpleAttributionWidget(
source: text is Text ? text : const Text("Placeholder Text"),
source: Text(
text,
style: control.getTextStyle("text_style", Theme.of(context)),
),
Comment on lines +13 to +25
onTap: () => control.triggerEvent("click"),
backgroundColor: control.getColor(
"bgcolor", context, Theme.of(context).colorScheme.surface)!,
Expand Down
38 changes: 27 additions & 11 deletions sdk/python/packages/flet/src/flet/controls/material/tooltip.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
from dataclasses import field
from typing import Optional, Union

from flet.controls.base_control import value
from flet.controls.border_radius import (
BorderRadius,
)
from flet.controls.box import BoxConstraints, BoxDecoration
from flet.controls.duration import DurationValue
from flet.controls.margin import MarginValue
Expand Down Expand Up @@ -44,20 +40,40 @@ class TooltipTriggerMode:
@value
class Tooltip:
"""
Provide text labels which help explain the function of a button or other user \
interface action.
Provide text labels which help explain the function of a button
or other user interface action.
"""

message: str
"""
The text to display in the tooltip.
The text to display in this tooltip.
"""

decoration: Optional[BoxDecoration] = field(
default_factory=lambda: BoxDecoration(border_radius=BorderRadius.all(4.0))
)
decoration: Optional[BoxDecoration] = None
"""
The tooltip's background decoration.
The background decoration of this tooltip.

If `None`, :attr:`flet.TooltipTheme.decoration` is used.
If that is also `None`, a default decoration will be picked based
on the current theme mode:

In light theme mode:

```python
ft.BoxDecoration(
border_radius=ft.BorderRadius.all(4.0),
bgcolor=ft.Colors.with_opacity(0.9, ft.Colors.GREY_700),
)
```

In dark theme mode:

```python
ft.BoxDecoration(
border_radius=ft.BorderRadius.all(4.0),
bgcolor=ft.Colors.with_opacity(0.9, ft.Colors.WHITE),
)
```
"""

enable_feedback: Optional[bool] = None
Expand Down
4 changes: 4 additions & 0 deletions website/docs/controls/map/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@ More details [here](tilelayer.md).

<CodeExample path={frontMatter.examples + '/basic/main.py'} language="python" />

### Attributions

<CodeExample path={frontMatter.examples + '/attribution/main.py'} language="python" />

### Camera Controls

<CodeExample path={frontMatter.examples + '/camera_controls/main.py'} language="python" />
Expand Down
Loading