Skip to content

Commit 4914880

Browse files
Mike ProsserMike Prosser
authored andcommitted
misc feedback
1 parent 7c8dc96 commit 4914880

File tree

6 files changed

+61
-59
lines changed

6 files changed

+61
-59
lines changed

examples/all_types/all_types_panel.py

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,4 @@
3737
st.text_input(label=name, value=default_value, key=name)
3838

3939
with col3:
40-
value = panel.get_value(name)
41-
value_with_default = panel.get_value(name, default_value=default_value)
42-
st.write(value_with_default)
43-
if str(value) != str(value_with_default):
44-
st.write("(", value, ")")
40+
st.write(panel.get_value(name, default_value=default_value))

examples/nidaqmx/nidaqmx_continuous_analog_input_panel.py

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -38,28 +38,28 @@
3838
is_running = panel.get_value("is_running", False)
3939

4040
if is_running:
41-
st.button(r"⏹️ $\large{\textbf{Stop}}$", key="stop_button")
41+
st.button(r"⏹️ Stop", key="stop_button")
4242
else:
43-
st.button(r"▶️ $\large{\textbf{Run}}$", key="run_button")
43+
st.button(r"▶️ Run", key="run_button")
4444

4545
thermocouple_data = panel.get_value("thermocouple_data", [0.0])
4646
voltage_data = panel.get_value("voltage_data", [0.0])
4747
sample_rate = panel.get_value("sample_rate", 0.0)
4848

4949
# Create two-column layout for the entire interface
50-
left_col, right_col = st.columns([1, 1])
50+
left_column, right_column = st.columns([1, 1])
5151

5252
# Left column - Channel tabs and Timing Settings
53-
with left_col:
53+
with left_column:
5454
# Channel Settings tabs
5555
with st.container(border=True):
5656
st.header("Channel Settings")
5757
voltage_tab, thermocouple_tab = st.tabs(["Voltage", "Thermocouple"])
5858

5959
voltage_tab.header("Voltage")
6060
with voltage_tab:
61-
channel_left, channel_right = st.columns(2)
62-
with channel_left:
61+
channel_left_column, channel_right_column = st.columns(2)
62+
with channel_left_column:
6363
st.selectbox(options=["Dev1/ai0"], label="Physical Channels", disabled=True)
6464
st.number_input(
6565
"Min Value",
@@ -75,7 +75,7 @@
7575
disabled=panel.get_value("is_running", False),
7676
key="voltage_max_value",
7777
)
78-
with channel_right:
78+
with channel_right_column:
7979
ni.enum_selectbox(
8080
panel,
8181
label="Terminal Configuration",
@@ -86,8 +86,8 @@
8686

8787
thermocouple_tab.header("Thermocouple")
8888
with thermocouple_tab:
89-
channel_left, channel_middle, channel_right = st.columns(3)
90-
with channel_left:
89+
channel_left_column, channel_middle_column, channel_right_column = st.columns(3)
90+
with channel_left_column:
9191
st.selectbox(options=["Dev1/ai1"], label="Physical Channel", disabled=True)
9292
st.number_input(
9393
"Min Value",
@@ -103,7 +103,7 @@
103103
disabled=panel.get_value("is_running", False),
104104
key="thermocouple_max_value",
105105
)
106-
with channel_middle:
106+
with channel_middle_column:
107107
ni.enum_selectbox(
108108
panel,
109109
label="Units",
@@ -118,7 +118,7 @@
118118
disabled=panel.get_value("is_running", False),
119119
key="thermocouple_type",
120120
)
121-
with channel_right:
121+
with channel_right_column:
122122
ni.enum_selectbox(
123123
panel,
124124
label="CJC Source",
@@ -137,8 +137,8 @@
137137
# Timing Settings section in left column
138138
with st.container(border=True):
139139
st.header("Timing Settings")
140-
timing_left, timing_right = st.columns(2)
141-
with timing_left:
140+
timing_left_column, timing_right_column = st.columns(2)
141+
with timing_left_column:
142142
st.selectbox(
143143
options=["OnboardClock"],
144144
label="Sample Clock Source",
@@ -152,7 +152,7 @@
152152
disabled=panel.get_value("is_running", False),
153153
key="sample_rate_input",
154154
)
155-
with timing_right:
155+
with timing_right_column:
156156
st.number_input(
157157
"Samples per Loop",
158158
value=3000,
@@ -168,7 +168,7 @@
168168
)
169169

170170
# Right column - Graph and Logging Settings
171-
with right_col:
171+
with right_column:
172172
with st.container(border=True):
173173
# Graph section
174174
st.header("Voltage & Thermocouple")
@@ -217,18 +217,18 @@
217217
# Logging Settings section in right column
218218
with st.container(border=True):
219219
st.header("Logging Settings")
220-
logging_left, logging_right = st.columns(2)
221-
with logging_left:
220+
logging_left_column, logging_right_column = st.columns(2)
221+
with logging_left_column:
222222
ni.enum_selectbox(
223223
panel,
224224
label="Logging Mode",
225225
value=LoggingMode.OFF,
226226
disabled=panel.get_value("is_running", False),
227227
key="logging_mode",
228228
)
229-
with logging_right:
230-
col1, col2 = st.columns([3, 1])
231-
with col1:
229+
with logging_right_column:
230+
left_sub_column, right_sub_column = st.columns([3, 1])
231+
with left_sub_column:
232232
tdms_file_path = st.text_input(
233233
label="TDMS File Path",
234234
disabled=panel.get_value("is_running", False),

src/nipanel/_panel_value_accessor.py

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from __future__ import annotations
22

3+
import collections
34
import enum
45
from abc import ABC
56
from typing import TypeVar, overload
@@ -16,7 +17,13 @@
1617
class PanelValueAccessor(ABC):
1718
"""This class allows you to access values for a panel's controls."""
1819

19-
__slots__ = ["_panel_client", "_panel_id", "_notify_on_set_value", "__weakref__"]
20+
__slots__ = [
21+
"_panel_client",
22+
"_panel_id",
23+
"_notify_on_set_value",
24+
"_last_values",
25+
"__weakref__",
26+
]
2027

2128
def __init__(
2229
self,
@@ -39,6 +46,7 @@ def __init__(
3946
)
4047
self._panel_id = panel_id
4148
self._notify_on_set_value = notify_on_set_value
49+
self._last_values = collections.defaultdict(lambda: object())
4250

4351
@property
4452
def panel_id(self) -> str:
@@ -93,3 +101,16 @@ def set_value(self, value_id: str, value: object) -> None:
93101
self._panel_client.set_value(
94102
self._panel_id, value_id, value, notify=self._notify_on_set_value
95103
)
104+
self._last_values[value_id] = value
105+
106+
def set_value_if_changed(self, value_id: str, value: object) -> None:
107+
"""Set the value for a control on the panel only if it has changed since the last call.
108+
109+
This method helps reduce unnecessary updates when the value hasn't changed.
110+
111+
Args:
112+
value_id: The id of the value
113+
value: The value to set
114+
"""
115+
if value != self._last_values[value_id]:
116+
self.set_value(value_id, value)

src/nipanel/_streamlit_panel_value_accessor.py

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
from __future__ import annotations
22

3-
import collections
43
from typing import final
54

65
import grpc
@@ -18,8 +17,6 @@ class StreamlitPanelValueAccessor(PanelValueAccessor):
1817
This class should only be used within a Streamlit script.
1918
"""
2019

21-
__slots__ = ["_last_values"]
22-
2320
def __init__(
2421
self,
2522
panel_id: str,
@@ -46,19 +43,3 @@ def __init__(
4643
grpc_channel_pool=grpc_channel_pool,
4744
grpc_channel=grpc_channel,
4845
)
49-
self._last_values: collections.defaultdict[str, object] = collections.defaultdict(
50-
lambda: object()
51-
)
52-
53-
def set_value_if_changed(self, value_id: str, value: object) -> None:
54-
"""Set the value for a control on the panel only if it has changed since the last call.
55-
56-
This method helps reduce unnecessary updates when the value hasn't changed.
57-
58-
Args:
59-
value_id: The id of the value
60-
value: The value to set
61-
"""
62-
if value != self._last_values[value_id]:
63-
self.set_value(value_id, value)
64-
self._last_values[value_id] = value

src/nipanel/controls/_enum_selectbox.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,17 @@
77

88
from nipanel._streamlit_panel_value_accessor import StreamlitPanelValueAccessor
99

10-
T = TypeVar("T", bound=Enum)
10+
TEnumType = TypeVar("TEnumType", bound=Enum)
1111

1212

1313
def enum_selectbox(
1414
panel: StreamlitPanelValueAccessor,
1515
label: str,
16-
value: T,
16+
value: TEnumType,
1717
key: str,
1818
disabled: bool = False,
1919
format_func: Callable[[Any], str] = lambda x: x[0],
20-
) -> T:
20+
) -> TEnumType:
2121
"""Create a selectbox for an Enum.
2222
2323
The selectbox will display the names of all the enum values, and when a value is selected,

src/nipanel/controls/_flag_checkboxes.py

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,23 @@
11
"""A set of checkboxes for selecting Flag enum values."""
22

33
from enum import Flag
4-
from typing import TypeVar, Callable
4+
from typing import TypeVar, Callable, Optional
55

66
import streamlit as st
77

88
from nipanel._streamlit_panel_value_accessor import StreamlitPanelValueAccessor
99

10-
T = TypeVar("T", bound=Flag)
10+
TFlagType = TypeVar("TFlagType", bound=Flag)
1111

1212

1313
def flag_checkboxes(
1414
panel: StreamlitPanelValueAccessor,
1515
label: str,
16-
value: T,
16+
value: TFlagType,
1717
key: str,
18-
disabled: bool = False,
18+
disabled_values: Optional[TFlagType] = None,
1919
label_formatter: Callable[[Flag], str] = lambda x: str(x.name),
20-
) -> T:
20+
) -> TFlagType:
2121
"""Create a set of checkboxes for a Flag enum.
2222
2323
This will display a checkbox for each individual flag value in the enum. When checkboxes
@@ -29,7 +29,8 @@ def flag_checkboxes(
2929
label: Label to display above the checkboxes
3030
value: The default Flag enum value (also determines the specific Flag enum type)
3131
key: Key to use for storing the Flag value in the panel
32-
disabled: Whether the checkboxes should be disabled
32+
disabled_values: A Flag enum value indicating which flags should be disabled.
33+
If None or flag_type(0), no checkboxes are disabled.
3334
label_formatter: Function that formats the flag to a string for display. Default
3435
uses flag.name.
3536
@@ -49,20 +50,23 @@ def flag_checkboxes(
4950

5051
# Create a container for flag checkboxes
5152
flag_container = st.container(border=True)
52-
selected_flags = flag_type(0) # Start with no flags
5353

54-
# If default value is set, use it as the initial state
55-
if value:
56-
selected_flags = value
54+
# Use the provided value as the initial state for selected flags
55+
selected_flags = value
5756

5857
# Create a checkbox for each flag
5958
for flag in flag_values:
6059
is_selected = bool(selected_flags & flag)
60+
61+
is_disabled = False
62+
if disabled_values is not None:
63+
is_disabled = bool(disabled_values & flag)
64+
6165
if flag_container.checkbox(
6266
label=label_formatter(flag),
6367
value=is_selected,
6468
key=f"{key}_{flag.name}",
65-
disabled=disabled,
69+
disabled=is_disabled,
6670
):
6771
selected_flags |= flag
6872
else:

0 commit comments

Comments
 (0)