From e5b4ba37089a2b88ea4b067a3eef2f3e4d31ad0c Mon Sep 17 00:00:00 2001 From: VALLONGOL Date: Fri, 16 May 2025 13:07:26 +0200 Subject: [PATCH] add info panel --- flightmonitor/controller/app_controller.py | 74 ++++++-- flightmonitor/gui/main_window.py | 189 +++++++++++++++------ flightmonitor/map/map_canvas_manager.py | 11 +- 3 files changed, 205 insertions(+), 69 deletions(-) diff --git a/flightmonitor/controller/app_controller.py b/flightmonitor/controller/app_controller.py index 915657e..4f3bb37 100644 --- a/flightmonitor/controller/app_controller.py +++ b/flightmonitor/controller/app_controller.py @@ -386,18 +386,64 @@ class AppController: # --- NUOVO METODO PER INTERAZIONE MAPPA --- def on_map_right_click(self, latitude: float, longitude: float, screen_x: int, screen_y: int): - """ - Called by MapCanvasManager when the map is right-clicked. - Placeholder for future functionality like showing a context menu or details. - """ - module_logger.info(f"Controller: Map right-clicked at Geo ({latitude:.5f}, {longitude:.5f}), Screen ({screen_x}, {screen_y})") - # Qui potresti, ad esempio, preparare dati per un menu contestuale - # o chiedere a MainWindow di visualizzare un popup di informazioni. - if self.main_window and hasattr(self.main_window, 'show_map_context_menu'): - # self.main_window.show_map_context_menu(latitude, longitude, screen_x, screen_y) - pass # Implementa in futuro - elif self.main_window: # Fallback: aggiorna lo status bar con le coordinate - self.main_window.update_semaphore_and_status( - GUI_STATUS_OK, - f"Map right-click: Lat {latitude:.4f}, Lon {longitude:.4f}" + module_logger.info(f"Controller: Map right-clicked at Geo ({latitude:.5f}, {longitude:.5f})") + if self.main_window and hasattr(self.main_window, 'update_map_info_panel'): + # Ottieni le info generali della mappa dal map_manager_instance per lo zoom e la dimensione + map_info = {} + if hasattr(self.main_window, 'map_manager_instance') and self.main_window.map_manager_instance: + map_info = self.main_window.map_manager_instance.get_current_map_info() + + # Converti lat/lon in DMS (questa logica potrebbe essere centralizzata in map_utils) + # o MapCanvasManager potrebbe già fornire stringhe DMS + # Per ora, assumiamo che MapCanvasManager fornisca già le stringhe DMS corrette + # o che una funzione di utilità le generi. + # Se MapCanvasManager invia direttamente un dict con 'lat_dms_str' e 'lon_dms_str', usiamo quelli. + # Qui simuliamo la conversione se non fornita direttamente: + from ..map.map_utils import deg_to_dms_string # Assicurati che sia importabile + lat_dms_str = deg_to_dms_string(latitude, 'lat') if latitude is not None else "N/A" + lon_dms_str = deg_to_dms_string(longitude, 'lon') if longitude is not None else "N/A" + + self.main_window.update_map_info_panel( + lat_deg=latitude, + lon_deg=longitude, + lat_dms=lat_dms_str, + lon_dms=lon_dms_str, + zoom=map_info.get("zoom"), + map_size_str=f"{map_info.get('map_size_km_w', 'N/A'):.1f}km x {map_info.get('map_size_km_h', 'N/A'):.1f}km" + if map_info.get("map_size_km_w") is not None else "N/A" + ) + # Considera se mostrare un menu contestuale qui (come nel placeholder precedente) + + def update_general_map_info(self): + """Chiamato da MapCanvasManager (o periodicamente) per aggiornare info come zoom e dimensione mappa.""" + if self.main_window and \ + hasattr(self.main_window, 'map_manager_instance') and \ + self.main_window.map_manager_instance is not None and \ + hasattr(self.main_window, 'update_map_info_panel'): + + map_info = self.main_window.map_manager_instance.get_current_map_info() + + # Per le info generali, non aggiorniamo le coordinate del click (quelle sono per on_map_right_click) + # Quindi passiamo None o i valori correnti se li vogliamo mostrare permanentemente + # Qui, aggiorniamo solo zoom e dimensione mappa. + + # Otteniamo le coordinate del centro mappa se disponibili + center_lat = map_info.get("center_lat") + center_lon = map_info.get("center_lon") + lat_dms_str = "N/A" + lon_dms_str = "N/A" + if center_lat is not None and center_lon is not None: + from ..map.map_utils import deg_to_dms_string + lat_dms_str = deg_to_dms_string(center_lat, 'lat') + lon_dms_str = deg_to_dms_string(center_lon, 'lon') + + + self.main_window.update_map_info_panel( + lat_deg=center_lat, # Mostra il centro della mappa + lon_deg=center_lon, + lat_dms=lat_dms_str, + lon_dms=lon_dms_str, + zoom=map_info.get("zoom"), + map_size_str=f"{map_info.get('map_size_km_w', 'N/A'):.1f}km x {map_info.get('map_size_km_h', 'N/A'):.1f}km" + if map_info.get("map_size_km_w") is not None and map_info.get("map_size_km_h") is not None else "N/A" ) \ No newline at end of file diff --git a/flightmonitor/gui/main_window.py b/flightmonitor/gui/main_window.py index 9c88be3..9984e58 100644 --- a/flightmonitor/gui/main_window.py +++ b/flightmonitor/gui/main_window.py @@ -54,94 +54,125 @@ class MainWindow: controller: The application controller instance. """ self.root = root - self.controller = controller + self.controller = controller self.root.title("Flight Monitor") - # Stima e calcolo dimensioni finestra (come prima) + # Stima e calcolo dimensioni finestra controls_estimated_height = 50 bbox_estimated_height = 70 log_area_min_height = 80 - map_min_height = 200 # Altezza minima per il canvas della mappa + map_min_height = 300 # Minima altezza ragionevole per la mappa status_bar_actual_height = 30 + info_panel_min_width = 200 # Larghezza minima per il pannello info - min_function_notebook_height = controls_estimated_height + bbox_estimated_height + 20 - # Usa map_min_height per il calcolo delle viste - min_views_notebook_height = map_min_height + 20 + # Altezza per il pannello superiore che contiene Function Notebook e Info Panel + min_function_notebook_height = controls_estimated_height + bbox_estimated_height + 40 # Aggiunto padding - min_paned_top_panel_height = max(min_function_notebook_height, min_views_notebook_height) # Il pannello top deve contenere il più alto dei due + # Il pannello superiore ora è un PanedWindow orizzontale, la sua altezza è dettata dal Function Notebook + min_paned_top_horizontal_panel_height = min_function_notebook_height + + # Altezza per il pannello che contiene il Views Notebook (mappa) + min_views_notebook_panel_height = map_min_height + 20 # Tab per Views Notebook + min_paned_bottom_panel_height = log_area_min_height + status_bar_actual_height + 10 - min_total_height = min_paned_top_panel_height + min_paned_bottom_panel_height + 20 # Buffer per separatore e padding - # Usa DEFAULT_CANVAS_WIDTH da fm_config per la larghezza minima - min_total_width = getattr(fm_config, 'DEFAULT_CANVAS_WIDTH', 800) // 2 + 150 # Adattato - if min_total_width < 600: min_total_width = 600 # Un po' più largo + # Altezza totale minima: somma delle altezze dei pannelli nel PanedWindow verticale + min_total_height = min_paned_top_horizontal_panel_height + \ + min_views_notebook_panel_height + \ + min_paned_bottom_panel_height + \ + 30 # Spazio per i separatori dei PanedWindow e padding generale + + # Larghezza totale minima + # Larghezza Function Notebook + Info Panel + padding + # Assumiamo che il Function Notebook abbia bisogno di almeno 350-400px + min_func_notebook_width = 350 + min_total_width = min_func_notebook_width + info_panel_min_width + 30 # padding e separatore + if min_total_width < 650: min_total_width = 650 # Un valore minimo assoluto self.root.minsize(min_total_width, min_total_height) module_logger.debug(f"Minimum window size set to: {min_total_width}x{min_total_height}") - initial_width = getattr(fm_config, 'DEFAULT_CANVAS_WIDTH', 800) + 250 - initial_function_notebook_height = controls_estimated_height + bbox_estimated_height + 40 # Più spazio per padding/tabs - initial_views_notebook_height = getattr(fm_config, 'DEFAULT_CANVAS_HEIGHT', 600) + 40 # Più spazio - initial_log_height = 120 + # Calcolo dimensioni iniziali finestra + # Larghezza: abbastanza per Function Notebook, Info Panel, e un po' di mappa + initial_func_nb_width = 400 + initial_info_panel_width = 250 + initial_map_canvas_width = getattr(fm_config, 'DEFAULT_CANVAS_WIDTH', 800) + # La larghezza del ViewsNotebook (e quindi del canvas) sarà gestita dal PanedWindow + # La larghezza totale sarà la somma o il massimo necessario. + # Per ora, facciamo in modo che il canvas abbia una buona larghezza. + # La larghezza iniziale del PanedWindow orizzontale sarà data dalla somma. + # Poi l'utente può ridimensionare. + + initial_width = initial_func_nb_width + initial_info_panel_width + 20 # per il separatore + if initial_width < min_total_width : initial_width = min_total_width + # Se il canvas della mappa è più largo, la finestra si adatterà + # Questa logica di larghezza è un po' complessa con i paned window, + # affidiamoci ai pesi e al minsize. + # Usiamo una larghezza iniziale che permetta di vedere bene i controlli. + initial_width = 1200 # Un valore fisso per iniziare, poi l'utente ridimensiona. - initial_total_height = max(initial_function_notebook_height, initial_views_notebook_height) + \ - initial_log_height + status_bar_actual_height + 30 + + # Altezza iniziale: simile al calcolo del min_total_height ma con valori desiderati + initial_function_notebook_height = controls_estimated_height + bbox_estimated_height + 50 + initial_views_notebook_height = getattr(fm_config, 'DEFAULT_CANVAS_HEIGHT', 600) + 40 + initial_log_height = 150 + + initial_total_height = max(initial_function_notebook_height, 150) + \ + initial_views_notebook_height + \ + initial_log_height + status_bar_actual_height + 40 if initial_total_height < min_total_height: initial_total_height = min_total_height self.root.geometry(f"{initial_width}x{initial_total_height}") module_logger.debug(f"Initial window size set to: {initial_width}x{initial_total_height}") - # --- Main Layout: PanedWindow --- + # --- Main Layout: PanedWindow Verticale --- self.main_paned_window = ttk.PanedWindow(self.root, orient=tk.VERTICAL) - self.main_paned_window.pack(fill=tk.BOTH, expand=True, padx=10, pady=(5,0)) + self.main_paned_window.pack(fill=tk.BOTH, expand=True, padx=5, pady=5) # Aggiunto padding - self.paned_top_panel = ttk.Frame(self.main_paned_window) - self.main_paned_window.add(self.paned_top_panel, weight=3) + # --- 1. Pannello Superiore Orizzontale (per Controlli e Info Mappa) --- + self.top_horizontal_paned_window = ttk.PanedWindow(self.main_paned_window, orient=tk.HORIZONTAL) + self.main_paned_window.add(self.top_horizontal_paned_window, weight=0) # Non espandere verticalmente, altezza fissa basata sul contenuto - # --- Function Notebook --- - self.function_notebook = ttk.Notebook(self.paned_top_panel) - self.function_notebook.pack(side=tk.TOP, fill=tk.X, expand=False, padx=0, pady=(0,5)) + # --- 1a. Pannello Sinistro del Top Horizontal Paned Window (Function Notebook) --- + self.left_control_panel_frame = ttk.Frame(self.top_horizontal_paned_window, padding=(0,0,5,0)) # Padding a destra + self.top_horizontal_paned_window.add(self.left_control_panel_frame, weight=1) # Più spazio ai controlli + self.function_notebook = ttk.Notebook(self.left_control_panel_frame) + self.function_notebook.pack(fill=tk.BOTH, expand=True) # Lascia che riempia il suo pane + + # --- Schede del Function Notebook --- self.live_bbox_tab_frame = ttk.Frame(self.function_notebook, padding=5) self.function_notebook.add(self.live_bbox_tab_frame, text="Live: Area Monitor") - + # Contenuto di live_bbox_tab_frame (Controls e BBox input) self.controls_frame = ttk.Frame(self.live_bbox_tab_frame) self.controls_frame.pack(side=tk.TOP, fill=tk.X, pady=(0,5)) - self.control_frame = ttk.LabelFrame(self.controls_frame, text="Controls", padding=(10, 5)) self.control_frame.pack(side=tk.TOP, fill=tk.X) - self.mode_var = tk.StringVar(value="Live") self.live_radio = ttk.Radiobutton(self.control_frame, text="Live", variable=self.mode_var, value="Live", command=self._on_mode_change) self.live_radio.pack(side=tk.LEFT, padx=(0,5)) self.history_radio = ttk.Radiobutton(self.control_frame, text="History", variable=self.mode_var, value="History", command=self._on_mode_change) self.history_radio.pack(side=tk.LEFT, padx=5) - self.start_button = ttk.Button(self.control_frame, text="Start Monitoring", command=self._start_monitoring) self.start_button.pack(side=tk.LEFT, padx=5) self.stop_button = ttk.Button(self.control_frame, text="Stop Monitoring", command=self._stop_monitoring, state=tk.DISABLED) self.stop_button.pack(side=tk.LEFT, padx=5) - self.bbox_frame = ttk.LabelFrame(self.controls_frame, text="Geographic Area (Bounding Box)", padding=(10,5)) self.bbox_frame.pack(side=tk.TOP, fill=tk.X, pady=5) self.bbox_frame.columnconfigure(1, weight=1) self.bbox_frame.columnconfigure(3, weight=1) - ttk.Label(self.bbox_frame, text="Lat Min:").grid(row=0, column=0, padx=(0,2), pady=2, sticky=tk.W) self.lat_min_var = tk.StringVar(value=str(fm_config.DEFAULT_BBOX_LAT_MIN)) self.lat_min_entry = ttk.Entry(self.bbox_frame, textvariable=self.lat_min_var, width=10) self.lat_min_entry.grid(row=0, column=1, padx=(0,5), pady=2, sticky=tk.EW) - ttk.Label(self.bbox_frame, text="Lon Min:").grid(row=0, column=2, padx=(5,2), pady=2, sticky=tk.W) self.lon_min_var = tk.StringVar(value=str(fm_config.DEFAULT_BBOX_LON_MIN)) self.lon_min_entry = ttk.Entry(self.bbox_frame, textvariable=self.lon_min_var, width=10) self.lon_min_entry.grid(row=0, column=3, padx=(0,0), pady=2, sticky=tk.EW) - ttk.Label(self.bbox_frame, text="Lat Max:").grid(row=1, column=0, padx=(0,2), pady=2, sticky=tk.W) self.lat_max_var = tk.StringVar(value=str(fm_config.DEFAULT_BBOX_LAT_MAX)) self.lat_max_entry = ttk.Entry(self.bbox_frame, textvariable=self.lat_max_var, width=10) self.lat_max_entry.grid(row=1, column=1, padx=(0,5), pady=2, sticky=tk.EW) - ttk.Label(self.bbox_frame, text="Lon Max:").grid(row=1, column=2, padx=(5,2), pady=2, sticky=tk.W) self.lon_max_var = tk.StringVar(value=str(fm_config.DEFAULT_BBOX_LON_MAX)) self.lon_max_entry = ttk.Entry(self.bbox_frame, textvariable=self.lon_max_var, width=10) @@ -150,24 +181,55 @@ class MainWindow: self.live_airport_tab_frame = ttk.Frame(self.function_notebook, padding=5) self.function_notebook.add(self.live_airport_tab_frame, text="Live: Airport") ttk.Label(self.live_airport_tab_frame, text="Live from Airport - Coming Soon", font=("Arial", 10)).pack(expand=True) - self.history_tab_frame = ttk.Frame(self.function_notebook, padding=5) self.function_notebook.add(self.history_tab_frame, text="History") ttk.Label(self.history_tab_frame, text="History Analysis - Coming Soon", font=("Arial", 10)).pack(expand=True) - self.function_notebook.bind("<>", self._on_function_tab_change) - # --- Views Notebook --- - self.views_notebook = ttk.Notebook(self.paned_top_panel) + # --- 1b. Pannello Destro del Top Horizontal Paned Window (Info Mappa) --- + self.map_info_panel_frame = ttk.LabelFrame(self.top_horizontal_paned_window, text="Map Information", padding=10) + self.top_horizontal_paned_window.add(self.map_info_panel_frame, weight=0) # Meno peso, larghezza fissa o minima + + self.info_lat_label = ttk.Label(self.map_info_panel_frame, text="Lat (Click):") + self.info_lat_label.grid(row=0, column=0, sticky=tk.W, pady=2, padx=(0,2)) + self.info_lat_value = ttk.Label(self.map_info_panel_frame, text="N/A", width=22) + self.info_lat_value.grid(row=0, column=1, sticky=tk.W, pady=2) + self.info_lon_label = ttk.Label(self.map_info_panel_frame, text="Lon (Click):") + self.info_lon_label.grid(row=1, column=0, sticky=tk.W, pady=2, padx=(0,2)) + self.info_lon_value = ttk.Label(self.map_info_panel_frame, text="N/A", width=22) + self.info_lon_value.grid(row=1, column=1, sticky=tk.W, pady=2) + self.info_lat_dms_label = ttk.Label(self.map_info_panel_frame, text="Lat DMS:") + self.info_lat_dms_label.grid(row=2, column=0, sticky=tk.W, pady=2, padx=(0,2)) + self.info_lat_dms_value = ttk.Label(self.map_info_panel_frame, text="N/A", width=22) + self.info_lat_dms_value.grid(row=2, column=1, sticky=tk.W, pady=2) + self.info_lon_dms_label = ttk.Label(self.map_info_panel_frame, text="Lon DMS:") + self.info_lon_dms_label.grid(row=3, column=0, sticky=tk.W, pady=2, padx=(0,2)) + self.info_lon_dms_value = ttk.Label(self.map_info_panel_frame, text="N/A", width=22) + self.info_lon_dms_value.grid(row=3, column=1, sticky=tk.W, pady=2) + self.info_zoom_label = ttk.Label(self.map_info_panel_frame, text="Map Zoom:") + self.info_zoom_label.grid(row=4, column=0, sticky=tk.W, pady=2, padx=(0,2)) + self.info_zoom_value = ttk.Label(self.map_info_panel_frame, text="N/A", width=22) + self.info_zoom_value.grid(row=4, column=1, sticky=tk.W, pady=2) + self.info_map_size_label = ttk.Label(self.map_info_panel_frame, text="Map Area:") + self.info_map_size_label.grid(row=5, column=0, sticky=tk.W, pady=2, padx=(0,2)) + self.info_map_size_value = ttk.Label(self.map_info_panel_frame, text="N/A", width=22, wraplength=160) + self.info_map_size_value.grid(row=5, column=1, sticky=tk.W, pady=2) + self.map_info_panel_frame.columnconfigure(1, weight=1) # Permette all'etichetta valore di espandersi se necessario + + + # --- 2. Pannello Centrale (per Views Notebook - Mappa) --- + self.views_notebook_outer_frame = ttk.Frame(self.main_paned_window) # Un frame per contenere il views_notebook + self.main_paned_window.add(self.views_notebook_outer_frame, weight=3) # Più peso verticale alla mappa + + self.views_notebook = ttk.Notebook(self.views_notebook_outer_frame) self.views_notebook.pack(fill=tk.BOTH, expand=True, padx=0, pady=0) - self.map_view_frame = ttk.Frame(self.views_notebook, padding=5) + self.map_view_frame = ttk.Frame(self.views_notebook, padding=0) self.views_notebook.add(self.map_view_frame, text="Map View") self.flight_canvas = tk.Canvas( - self.map_view_frame, bg="gray75", # Sfondo leggermente più scuro per distinguerlo dal placeholder - width=getattr(fm_config, 'DEFAULT_CANVAS_WIDTH', 800), - height=getattr(fm_config, 'DEFAULT_CANVAS_HEIGHT', 600), + self.map_view_frame, bg="gray60", # Sfondo leggermente più scuro + width=100, height=100, # Iniziali piccole, si espanderanno con il pack highlightthickness=0 ) self.flight_canvas.pack(fill=tk.BOTH, expand=True) @@ -178,31 +240,31 @@ class MainWindow: "lat_min": fm_config.DEFAULT_BBOX_LAT_MIN, "lon_min": fm_config.DEFAULT_BBOX_LON_MIN, "lat_max": fm_config.DEFAULT_BBOX_LAT_MAX, "lon_max": fm_config.DEFAULT_BBOX_LON_MAX } - self.root.after(150, self._initialize_map_manager, default_map_bbox) # Aumentato leggermente il delay + self.root.after(250, self._initialize_map_manager, default_map_bbox) # Aumentato delay else: - module_logger.error("MapCanvasManager could not be imported. Map display will be a placeholder.") - self._update_map_placeholder("Map functionality disabled (Import Error).") + module_logger.error("MapCanvasManager class not available. Map display will be a placeholder.") + # Chiama _update_map_placeholder dopo che il canvas è stato packato, + # altrimenti winfo_width/height daranno 1. + self.root.after(50, lambda: self._update_map_placeholder("Map functionality disabled (Import Error).")) self.table_view_frame = ttk.Frame(self.views_notebook, padding=5) self.views_notebook.add(self.table_view_frame, text="Table View") ttk.Label(self.table_view_frame, text="Table View - Coming Soon", font=("Arial", 12)).pack(expand=True) - self.views_notebook.bind("<>", self._on_view_tab_change) - # --- Bottom Panel of Main PanedWindow --- - self.paned_bottom_panel = ttk.Frame(self.main_paned_window) - self.main_paned_window.add(self.paned_bottom_panel, weight=1) + # --- 3. Pannello Inferiore (Log e Status Bar) --- + self.paned_bottom_panel = ttk.Frame(self.main_paned_window) + self.main_paned_window.add(self.paned_bottom_panel, weight=1) self.status_bar_frame = ttk.Frame(self.paned_bottom_panel, padding=(5, 3)) self.status_bar_frame.pack(side=tk.TOP, fill=tk.X, pady=(0,5)) - + self.semaphore_canvas = tk.Canvas( self.status_bar_frame, width=SEMAPHORE_TOTAL_SIZE, height=SEMAPHORE_TOTAL_SIZE, - bg=self.root.cget('bg'), highlightthickness=0 # Usa colore di sfondo root + bg=self.root.cget('bg'), highlightthickness=0 ) self.semaphore_canvas.pack(side=tk.LEFT, padx=(0, 5)) - x0 = SEMAPHORE_PAD + SEMAPHORE_BORDER_WIDTH; y0 = SEMAPHORE_PAD + SEMAPHORE_BORDER_WIDTH x1 = x0 + SEMAPHORE_SIZE; y1 = y0 + SEMAPHORE_SIZE self._semaphore_oval_id = self.semaphore_canvas.create_oval( @@ -214,7 +276,6 @@ class MainWindow: self.log_frame = ttk.Frame(self.paned_bottom_panel, padding=(5,0,5,5)) self.log_frame.pack(side=tk.TOP, fill=tk.BOTH, expand=True, padx=0, pady=0) - log_font_family = "Consolas" if "Consolas" in tkFont.families() else "Courier New" self.log_text_widget = ScrolledText( self.log_frame, state=tk.DISABLED, height=8, wrap=tk.WORD, @@ -227,7 +288,8 @@ class MainWindow: self.root.protocol("WM_DELETE_WINDOW", self._on_closing) - self._on_mode_change() # Imposta stato iniziale tab e placeholder + # Chiamate iniziali dopo che tutti i widget sono stati creati e impacchettati + self.root.after(10, self._on_mode_change) # Piccolo ritardo per permettere al layout di stabilizzarsi self.update_semaphore_and_status("OK", "System Initialized. Ready.") module_logger.info("MainWindow fully initialized and displayed.") @@ -635,4 +697,23 @@ class MainWindow: if hasattr(self, 'map_manager_instance') and self.map_manager_instance: # MapCanvasManager avrà bisogno di un metodo per ricentrare mantenendo lo zoom attuale # self.map_manager_instance.recenter_and_redraw(lat, lon, self.map_manager_instance._current_zoom) - pass \ No newline at end of file + pass + + def update_map_info_panel(self, lat_deg: Optional[float], lon_deg: Optional[float], + lat_dms: str, lon_dms: str, + zoom: Optional[int], map_size_str: str): + """Aggiorna le etichette nel pannello informazioni mappa.""" + if hasattr(self, 'info_lat_value') and self.info_lat_value.winfo_exists(): + self.info_lat_value.config(text=f"{lat_deg:.5f}" if lat_deg is not None else "N/A") + if hasattr(self, 'info_lon_value') and self.info_lon_value.winfo_exists(): + self.info_lon_value.config(text=f"{lon_deg:.5f}" if lon_deg is not None else "N/A") + if hasattr(self, 'info_lat_dms_value') and self.info_lat_dms_value.winfo_exists(): + self.info_lat_dms_value.config(text=lat_dms) + if hasattr(self, 'info_lon_dms_value') and self.info_lon_dms_value.winfo_exists(): + self.info_lon_dms_value.config(text=lon_dms) + if hasattr(self, 'info_zoom_value') and self.info_zoom_value.winfo_exists(): + self.info_zoom_value.config(text=str(zoom) if zoom is not None else "N/A") + if hasattr(self, 'info_map_size_value') and self.info_map_size_value.winfo_exists(): + self.info_map_size_value.config(text=map_size_str) + + module_logger.debug(f"Map info panel updated: Lat={lat_deg}, Lon={lon_deg}, Zoom={zoom}, Size='{map_size_str}'") \ No newline at end of file diff --git a/flightmonitor/map/map_canvas_manager.py b/flightmonitor/map/map_canvas_manager.py index 6f046d2..7b2f7a9 100644 --- a/flightmonitor/map/map_canvas_manager.py +++ b/flightmonitor/map/map_canvas_manager.py @@ -352,7 +352,16 @@ class MapCanvasManager: logger.debug(f"Actual geographic bounds of final stitched map (self._current_map_geo_bounds): {self._current_map_geo_bounds}") self._map_pil_image = stitched_map_pil - self._redraw_canvas_content() + #self._redraw_canvas_content() + + if self._map_pil_image: # Solo se la mappa è stata caricata con successo + self._redraw_canvas_content() + if self.app_controller and hasattr(self.app_controller, 'update_general_map_info'): + self.app_controller.update_general_map_info() # Notifica il controller per aggiornare il pannello + else: + # Se la mappa non è stata caricata, il controller potrebbe voler mostrare "N/A" + if self.app_controller and hasattr(self.app_controller, 'update_general_map_info'): + self.app_controller.update_general_map_info() # Invia comunque per aggiornare con N/A se necessario def _redraw_canvas_content(self): logger.debug(f"_redraw_canvas_content called. Current zoom: {self._current_zoom}, Flights to draw: {len(self._current_flights_to_display)}")