|
| 1 | +"""A set of checkboxes for selecting Flag enum values.""" |
| 2 | + |
| 3 | +from enum import Flag |
| 4 | +from typing import TypeVar |
| 5 | + |
| 6 | +import streamlit as st |
| 7 | + |
| 8 | +from nipanel._panel_value_accessor import PanelValueAccessor |
| 9 | + |
| 10 | +T = TypeVar("T", bound=Flag) |
| 11 | + |
| 12 | + |
| 13 | +def flag_checkboxes( |
| 14 | + panel: PanelValueAccessor, |
| 15 | + label: str, |
| 16 | + value: T, |
| 17 | + key: str, |
| 18 | + disabled: bool = False, |
| 19 | +) -> T: |
| 20 | + """Create a set of checkboxes for a Flag enum. |
| 21 | +
|
| 22 | + This will display a checkbox for each individual flag value in the enum. When checkboxes |
| 23 | + are selected or deselected, the combined Flag value will be stored in the panel under |
| 24 | + the specified key. |
| 25 | +
|
| 26 | + Args: |
| 27 | + panel: The panel |
| 28 | + label: Label to display above the checkboxes |
| 29 | + value: The default Flag enum value (also determines the specific Flag enum type) |
| 30 | + key: Key to use for storing the Flag value in the panel |
| 31 | + disabled: Whether the checkboxes should be disabled |
| 32 | +
|
| 33 | + Returns: |
| 34 | + The selected Flag enum value with all selected flags combined |
| 35 | + """ |
| 36 | + flag_type = type(value) |
| 37 | + if not issubclass(flag_type, Flag): |
| 38 | + raise TypeError(f"Expected a Flag enum type, got {type(value)}") |
| 39 | + |
| 40 | + st.write(label + ":") |
| 41 | + |
| 42 | + # Get all individual flag values (skip composite values and zero value) |
| 43 | + flag_values = [ |
| 44 | + flag for flag in flag_type if flag.value & (flag.value - 1) == 0 and flag.value != 0 |
| 45 | + ] |
| 46 | + |
| 47 | + # Create a container for flag checkboxes |
| 48 | + flag_container = st.container() |
| 49 | + selected_flags = flag_type(0) # Start with no flags |
| 50 | + |
| 51 | + # If default value is set, use it as the initial state |
| 52 | + if value: |
| 53 | + selected_flags = value |
| 54 | + |
| 55 | + # Create a checkbox for each flag |
| 56 | + for flag in flag_values: |
| 57 | + is_selected = bool(selected_flags & flag) |
| 58 | + if flag_container.checkbox( |
| 59 | + label=str(flag.name), |
| 60 | + value=is_selected, |
| 61 | + key=f"{key}_{flag.name}", |
| 62 | + disabled=disabled, |
| 63 | + ): |
| 64 | + selected_flags |= flag |
| 65 | + else: |
| 66 | + selected_flags &= ~flag |
| 67 | + |
| 68 | + # Store the selected flags in the panel |
| 69 | + panel.set_value(key, selected_flags) |
| 70 | + return selected_flags |
0 commit comments