Hi,
I need to know the widget (Shumate.SimpleMap) allocated size to determine a map bounding box. This calculation is done before the window containing the widget is shown on screen.
I try to connect to several signals (map, realize, show) but the widget’s methods get_allocated_height()
or get_allocated_width()
always return 0.
So, what signal / property should I connect to in order for these methods to return the allocated size ? Or do I have to wait for the window to be shown on screen to perform this calculation ?
Kind regards,
@vcottineau
ebassi
(Emmanuele Bassi)
September 5, 2022, 11:07pm
2
There is no signal for that.
The only way to know when a widget is allocated is to write your own widget subclass; then you can override the GtkWidgetClass.size_allocate()
virtual function and get the allocation size as given to you by the parent widget.
@ebassi ,
Thanks for your reply.
Can you provide a sample code to achieve your suggestion ?
Regards,
@vcottineau
ebassi
(Emmanuele Bassi)
September 6, 2022, 6:17pm
4
Not really, because it depends on what you want to achieve, and whether or not the widget you are using allows code to derive from it.
@ebassi ,
Below are some code extracts.
I am using a Shumate.SimpleMap
wich is a Gtk.Widget
.
Main window containing the Shumate.SimpleMap
in a Gtk.Box
:
@Gtk.Template(resource_path="/com/github/pygpxviewer/ui/GpxDetailedView.ui")
class GpxDetailedView(Adw.Window):
"""Display an interactive map and a chart to analyse a gpx file."""
__gtype_name__ = "GpxDetailedView"
_menu_button = Gtk.Template.Child()
_box_container = Gtk.Template.Child()
_points_label = Gtk.Template.Child()
_length_label = Gtk.Template.Child()
_up_hill_label = Gtk.Template.Child()
_down_hill_label = Gtk.Template.Child()
def __init__(self, path):
super().__init__()
Shumate.SimpleMap
widget:
class ShumateMap(Shumate.SimpleMap):
"""Display an interactive map.
Contains the following elements:
* Zoom
* License
* Scale
* Compass
"""
def __init__(self, window):
super().__init__()
self._settings = Gio.Settings.new("com.github.pygpxviewer.app.window.detailed.map")
self._gpx_helper = window.gpx_helper
self._path_layer = None
self._marker_layer = None
self._marker = None
self._set_map()
self._set_marker()
self._set_layers()
During the __init__()
, I am calling this method (in which I need the widget allocated height and width for calculations):
def set_center_and_zoom(self) -> None:
"""Set map center and zoom based on the path layer bounds.
Link: https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames
FixMe: Improve calculations if poles / 180th meridian is crossed
@return: None
@rtype: None
"""
def get_latitude_derivation(latitude):
radians = math.radians(latitude)
return math.asinh(math.tan(radians)) / math.pi / 2
def get_latitude_derivation_reverse(latitude_derivation):
radians = math.atan(math.sinh(latitude_derivation * 2 * math.pi))
return math.degrees(radians)
bounds = self._gpx_helper.gpx.get_bounds()
min_latitude = bounds.min_latitude
min_longitude = bounds.min_longitude
max_latitude = bounds.max_latitude
max_longitude = bounds.max_longitude
min_latitude_derivation = get_latitude_derivation(min_latitude)
max_latitude_derivation = get_latitude_derivation(max_latitude)
mean_latitude_derivation = (min_latitude_derivation + max_latitude_derivation) / 2
latitude_fraction = max_latitude_derivation - min_latitude_derivation
longitude_fraction = (max_longitude - min_longitude) / 360
tile_size = self.get_map_source().get_tile_size()
map_height = 363 * 0.95 # self.get_allocated_height() | Offset
map_width = 599 * 0.95 # self.get_allocated_width() | Offset
max_zoom_level = self.get_map_source().get_max_zoom_level()
latitude_zoom_level = math.log(map_height / tile_size / latitude_fraction) / math.log(2)
longitude_zoom_level = math.log(map_width / tile_size / longitude_fraction) / math.log(2)
zoom_level = min(max_zoom_level, latitude_zoom_level, longitude_zoom_level)
self.get_map().go_to_full(
get_latitude_derivation_reverse(mean_latitude_derivation),
(min_longitude + max_longitude) / 2,
zoom_level)
Regards,
@vcottineau
ebassi
(Emmanuele Bassi)
September 6, 2022, 9:42pm
6
You should override the size_allocate()
virtual function of Gtk.Widget by adding:
def do_size_allocate(self, width: int, height: int, baseline: int) -> None:
# Chain up
Shumate.SimpleMap.do_size_allocate(self, width, height, baseline)
# do something with width and height
system
(system)
Closed
September 20, 2022, 9:43pm
7
This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.