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
7 changes: 5 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,8 @@ ardupilot_methodic_configurator_setup_*.exe
build/
dist/
git_hash.txt

/.coverage

/.coverage
venv/
test.txt
test.xml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
from logging import basicConfig as logging_basicConfig
from logging import getLevelName as logging_getLevelName
from tkinter import ttk
from typing import Optional, Union
from typing import Union

from ardupilot_methodic_configurator import _, __version__
from ardupilot_methodic_configurator.backend_filesystem import LocalFilesystem
Expand All @@ -29,6 +29,7 @@
FC_CONNECTION_TYPE_PATHS,
)
from ardupilot_methodic_configurator.frontend_tkinter_component_editor_base import ComponentEditorWindowBase
from ardupilot_methodic_configurator.frontend_tkinter_pair_tuple_combobox import setup_combobox_mousewheel_handling

# from ardupilot_methodic_configurator.frontend_tkinter_show import show_tooltip
from ardupilot_methodic_configurator.frontend_tkinter_show import show_error_message, show_warning_message
Expand Down Expand Up @@ -179,34 +180,16 @@ def on_validate_combobox(event: tk.Event) -> bool:
cb.bind("<Return>", on_validate_combobox)
cb.bind("<ButtonRelease>", on_validate_combobox)

# Prevent mouse wheel from changing value when dropdown is not open
def handle_mousewheel(_event: tk.Event, widget: tk.Widget = cb) -> Optional[str]:
# Check if dropdown is open by examining the combobox's state
dropdown_is_open = getattr(widget, "dropdown_is_open", False)
if not dropdown_is_open:
return "break" # Prevent default behavior
return None # Allow default behavior when dropdown is open

# Set flag when dropdown opens or closes
def dropdown_opened(_event: tk.Event, widget: tk.Widget = cb) -> None:
widget.dropdown_is_open = True # type: ignore[attr-defined]

def dropdown_closed(_event: tk.Event, widget: tk.Widget = cb) -> None:
widget.dropdown_is_open = False # type: ignore[attr-defined]

# Initialize the flag
cb.dropdown_is_open = False # type: ignore[attr-defined]

# Bind to events for dropdown opening and closing
cb.bind("<<ComboboxDropdown>>", dropdown_opened)
cb.bind(
"<FocusOut>",
lambda e, p=path: (dropdown_closed(e), self._validate_combobox(e, p)), # type: ignore[misc,func-returns-value]
)
# Bind mouse wheel events
cb.bind("<MouseWheel>", handle_mousewheel) # Windows mouse wheel
cb.bind("<Button-4>", handle_mousewheel) # Linux mouse wheel up
cb.bind("<Button-5>", handle_mousewheel) # Linux mouse wheel down
# Set up mouse wheel handling to prevent unwanted value changes
setup_combobox_mousewheel_handling(cb)

# Override the FocusOut binding to also handle validation
def combined_focus_out(event: tk.Event) -> None:
# First handle the dropdown closing logic (already done by setup function)
# Then handle validation
self._validate_combobox(event, path)

cb.bind("<FocusOut>", combined_focus_out, add="+")

if path in FC_CONNECTION_TYPE_PATHS:
cb.bind( # immediate update of Protocol combobox choices after changing connection Type selection
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,54 @@
from platform import system as platform_system
from sys import exit as sys_exit
from tkinter import Label, Toplevel, ttk
from typing import Union
from typing import Optional, Union

from ardupilot_methodic_configurator import _
from ardupilot_methodic_configurator.common_arguments import add_common_arguments
from ardupilot_methodic_configurator.frontend_tkinter_autoresize_combobox import update_combobox_width


def setup_combobox_mousewheel_handling(combobox: ttk.Combobox) -> None:
"""
Set up mouse wheel handling for a combobox to prevent value changes when scrolling.

This function adds event bindings to prevent the combobox value from changing
when the user scrolls the mouse wheel over it while the dropdown is closed.
When the dropdown is closed, the mouse wheel event is propagated to the parent
widget to allow normal scrolling behavior in the containing widget.

Args:
combobox: The ttk.Combobox widget to configure

"""
# Track dropdown state to control mouse wheel behavior
combobox.dropdown_is_open = False # type: ignore[attr-defined]

def handle_mousewheel(event: tk.Event) -> Optional[str]:
"""Handle mouse wheel events - propagate to parent when dropdown is closed."""
if not combobox.dropdown_is_open: # type: ignore[attr-defined]
# Propagate the wheel event to the parent widget
combobox.master.event_generate("<MouseWheel>", delta=event.delta)
return "break" # Prevent default combobox behavior
return None # Allow default behavior when dropdown is open

def dropdown_opened(_event: Optional[tk.Event] = None) -> None:
"""Mark dropdown as open."""
combobox.dropdown_is_open = True # type: ignore[attr-defined]

def dropdown_closed(_event: Optional[tk.Event] = None) -> None:
"""Mark dropdown as closed."""
combobox.dropdown_is_open = False # type: ignore[attr-defined] # Bind mouse wheel events (Windows and Linux)

combobox.bind("<MouseWheel>", handle_mousewheel, add="+")
combobox.bind("<Button-4>", handle_mousewheel, add="+")
combobox.bind("<Button-5>", handle_mousewheel, add="+")

# Track dropdown open/close events
combobox.bind("<<ComboboxDropdown>>", dropdown_opened, add="+")
combobox.bind("<FocusOut>", dropdown_closed, add="+")


# SPDX-SnippetBegin
# SPDX-License-Identifier: MPL-2.0
# SPDX-SnippetCopyrightText: 2022 geraldew
Expand Down Expand Up @@ -58,6 +100,9 @@ def __init__(
self.set_entries_tuple(list_pair_tuple, selected_element)
self.bind("<Configure>", self.on_combo_configure, add="+")

# Apply mouse wheel handling to this combobox instance
setup_combobox_mousewheel_handling(self)

def set_entries_tuple(self, list_pair_tuple: list[tuple[str, str]], selected_element: Union[None, str]) -> None:
if isinstance(list_pair_tuple, list):
for tpl in list_pair_tuple:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,10 @@
from ardupilot_methodic_configurator.data_model_configuration_step import ConfigurationStepProcessor
from ardupilot_methodic_configurator.frontend_tkinter_base_window import BaseWindow
from ardupilot_methodic_configurator.frontend_tkinter_entry_dynamic import EntryWithDynamicalyFilteredListbox
from ardupilot_methodic_configurator.frontend_tkinter_pair_tuple_combobox import PairTupleCombobox
from ardupilot_methodic_configurator.frontend_tkinter_pair_tuple_combobox import (
PairTupleCombobox,
setup_combobox_mousewheel_handling,
)
from ardupilot_methodic_configurator.frontend_tkinter_rich_text import get_widget_font_family_and_size
from ardupilot_methodic_configurator.frontend_tkinter_scroll_frame import ScrollFrame
from ardupilot_methodic_configurator.frontend_tkinter_show import show_tooltip
Expand Down Expand Up @@ -409,6 +412,9 @@ def _create_new_value_entry( # pylint: disable=too-many-statements # noqa: PLR0
),
"+",
)

# Set up mouse wheel handling to prevent unwanted value changes
setup_combobox_mousewheel_handling(new_value_entry)
else:
new_value_entry = ttk.Entry(self.view_port, width=NEW_VALUE_WIDGET_WIDTH + 1, justify=tk.RIGHT)
self._update_new_value_entry_text(new_value_entry, param)
Expand Down
Loading
Loading