Intial version
This commit is contained in:
parent
c77fd30f8f
commit
f7f7acbdbf
148
main.py
148
main.py
|
@ -105,7 +105,6 @@ class App:
|
|||
slider_width = 50
|
||||
|
||||
# Extract initial color, brightness, and delay
|
||||
# The 'colors' entry can now be a list. We'll pick the first one for initial display.
|
||||
initial_colors = initial_settings.get("colors", ["#000000"])
|
||||
initial_hex_color = initial_colors[0] if initial_colors else "#000000"
|
||||
initial_brightness = initial_settings.get("brightness", 127)
|
||||
|
@ -200,12 +199,19 @@ class App:
|
|||
right_panel_frame = tk.Frame(main_tab_frame, bg=bg_color)
|
||||
right_panel_frame.pack(side=tk.LEFT, padx=20, pady=10, anchor="n", expand=True, fill="both")
|
||||
|
||||
# IDs section (unchanged)
|
||||
# IDs section - MODIFIED TO BE SIDE-BY-SIDE
|
||||
ids_frame = tk.Frame(right_panel_frame, bg=bg_color)
|
||||
ids_frame.pack(pady=10, fill=tk.X)
|
||||
tk.Label(ids_frame, text="Associated Names:", font=("Arial", 20), bg=bg_color, fg=fg_color).pack(pady=10)
|
||||
|
||||
# New inner frame for the IDs to be displayed horizontally
|
||||
ids_inner_frame = tk.Frame(ids_frame, bg=bg_color)
|
||||
ids_inner_frame.pack(fill=tk.X, expand=True) # Pack this frame to fill available width
|
||||
|
||||
for light_id in ids:
|
||||
tk.Label(ids_frame, text=str(light_id), font=("Arial", 18), bg=bg_color, fg=fg_color).pack(pady=2)
|
||||
tk.Label(ids_inner_frame, text=str(light_id), font=("Arial", 18), bg=bg_color, fg=fg_color).pack(
|
||||
side=tk.LEFT, padx=5, pady=2
|
||||
) # Pack labels horizontally
|
||||
|
||||
# --- New Frame to hold Patterns and Color Palette side-by-side ---
|
||||
patterns_and_palette_frame = tk.Frame(right_panel_frame, bg=bg_color)
|
||||
|
@ -327,7 +333,8 @@ class App:
|
|||
swatch_frame.config(highlightbackground=swatch_frame.cget("bg"), highlightthickness=0) # Reset to no highlight
|
||||
|
||||
def select_color_in_palette(self, tab, index: int):
|
||||
"""Selects a color in the palette, updates sliders, and highlights swatch."""
|
||||
"""Selects a color in the palette, updates sliders, and highlights swatch.
|
||||
This now also triggers an RGB update to the device."""
|
||||
if not (0 <= index < len(tab.colors_in_palette)):
|
||||
return
|
||||
|
||||
|
@ -343,6 +350,11 @@ class App:
|
|||
|
||||
print(f"Selected color index {index}: {hex_color}")
|
||||
|
||||
# Immediately send the update, as changing the selected color implies
|
||||
# a desire to change the light's current color, regardless of pattern.
|
||||
# This will also save the settings.
|
||||
self.schedule_update_rgb(tab, force_send=True)
|
||||
|
||||
def add_color_to_palette(self, tab):
|
||||
"""Adds a new black color to the palette and selects it, with a limit of 10 colors."""
|
||||
MAX_COLORS = 10 # Define the maximum number of colors allowed
|
||||
|
@ -351,6 +363,8 @@ class App:
|
|||
messagebox.showwarning("Color Limit Reached", f"You can add a maximum of {MAX_COLORS} colors to the palette.")
|
||||
return
|
||||
|
||||
# Simplified: just add black. If unique colors were required globally,
|
||||
# more complex logic would be needed here.
|
||||
tab.colors_in_palette.append("#000000") # Add black as default
|
||||
self.refresh_color_palette_display(tab)
|
||||
# Select the newly added color
|
||||
|
@ -369,7 +383,7 @@ class App:
|
|||
# Adjust selected index if the removed color was the last one
|
||||
if current_index >= len(tab.colors_in_palette):
|
||||
tab.widgets["selected_color_index"] = len(tab.colors_in_palette) - 1
|
||||
if tab.widgets["selected_color_index"] < 0: # Should not happen if check above works
|
||||
if tab.widgets["selected_color_index"] < 0: # Should not happen with 1-color check
|
||||
tab.widgets["selected_color_index"] = 0
|
||||
|
||||
self.refresh_color_palette_display(tab)
|
||||
|
@ -386,37 +400,37 @@ class App:
|
|||
def update_ui_for_pattern(self, tab, current_pattern: str):
|
||||
"""
|
||||
Manages the state of the UI elements based on the selected pattern.
|
||||
The Color Palette Editor is now always visible when 'transition' is selected,
|
||||
and RGB sliders update based on the selected color in the palette.
|
||||
When not 'transition', RGB sliders revert to the first color in settings.
|
||||
The Color Palette Editor is always visible. RGB sliders update
|
||||
based on the currently selected color in the palette, or the first
|
||||
color if the palette is empty or not in transition mode and a new tab/pattern is selected.
|
||||
"""
|
||||
# The color_palette_editor_frame is now *always* packed in create_light_control_widgets
|
||||
# when patterns_and_palette_frame is created with side-by-side packing.
|
||||
# So we no longer need to pack/pack_forget it here.
|
||||
# Its visibility is handled by its initial creation and packing alongside the patterns.
|
||||
# The color_palette_editor_frame is always packed, so no visibility control needed here.
|
||||
|
||||
# If the pattern is "transition", select the current color in the palette
|
||||
# and ensure the RGB sliders reflect that color.
|
||||
if current_pattern == "transition":
|
||||
# This handles refreshing the display and setting sliders to the selected color
|
||||
self.refresh_color_palette_display(tab)
|
||||
self.select_color_in_palette(tab, tab.widgets["selected_color_index"])
|
||||
# When the pattern changes, we need to ensure the RGB sliders reflect
|
||||
# the appropriate color based on the context.
|
||||
|
||||
if tab.colors_in_palette:
|
||||
# If in 'transition' mode, set sliders to the currently selected color in the palette.
|
||||
if current_pattern == "transition":
|
||||
self.select_color_in_palette(tab, tab.widgets["selected_color_index"])
|
||||
else:
|
||||
# If not in 'transition' mode, but a color is selected, update sliders to that.
|
||||
# Or, if this is a fresh load/tab change, ensure it's the first color.
|
||||
# This ensures the sliders consistently show the color that will be sent
|
||||
# for 'on'/'blink' based on the palette's first entry.
|
||||
hex_color = tab.colors_in_palette[tab.widgets["selected_color_index"]]
|
||||
r, g, b = color_utils.hex_to_rgb(hex_color)
|
||||
tab.widgets["red_slider"].set(r)
|
||||
tab.widgets["green_slider"].set(g)
|
||||
tab.widgets["blue_slider"].set(b)
|
||||
self._highlight_selected_color_swatch(tab) # Re-highlight even if index didn't change
|
||||
else:
|
||||
# When switching away from transition, ensure RGB sliders show the first color from settings
|
||||
# and reset selected_color_index.
|
||||
initial_colors = self.settings["lights"][self.notebook.tab(self.notebook.select(), "text")]["settings"].get(
|
||||
"colors", ["#000000"]
|
||||
)
|
||||
initial_hex_color = initial_colors[0] if initial_colors else "#000000"
|
||||
r, g, b = color_utils.hex_to_rgb(initial_hex_color)
|
||||
tab.widgets["red_slider"].set(r)
|
||||
tab.widgets["green_slider"].set(g)
|
||||
tab.widgets["blue_slider"].set(b)
|
||||
tab.widgets["selected_color_index"] = 0 # Reset selected color index to the first (default)
|
||||
self._highlight_selected_color_swatch(
|
||||
tab
|
||||
) # Remove highlight if active color is no longer relevant for editing
|
||||
# (or just highlight the 0th if you want)
|
||||
# Handle empty palette scenario (shouldn't happen with default ["#000000"])
|
||||
tab.widgets["red_slider"].set(0)
|
||||
tab.widgets["green_slider"].set(0)
|
||||
tab.widgets["blue_slider"].set(0)
|
||||
tab.widgets["selected_color_index"] = 0 # Ensure index is valid
|
||||
self._highlight_selected_color_swatch(tab)
|
||||
|
||||
# Brightness and Delay sliders are always visible.
|
||||
|
||||
|
@ -557,38 +571,42 @@ class App:
|
|||
selected_server = self.notebook.tab(self.notebook.select(), "text")
|
||||
names = self.settings["lights"][selected_server]["names"]
|
||||
|
||||
# ALWAYS send the full current palette, or at least the first color,
|
||||
# along with other relevant settings, when an RGB slider is moved.
|
||||
# The device firmware will interpret 'colors' based on its current pattern.
|
||||
# Determine which colors to send based on the current pattern.
|
||||
current_pattern = self.settings["lights"][selected_server]["settings"].get("pattern", "on")
|
||||
colors_to_send = []
|
||||
|
||||
# Determine which colors to send. It's generally safest to send the
|
||||
# full current palette, as the device might need all of them.
|
||||
colors_to_send = tab.colors_in_palette.copy() # Send a copy to be safe
|
||||
if current_pattern == "transition":
|
||||
colors_to_send = tab.colors_in_palette.copy()
|
||||
elif current_pattern in ["on", "blink"]: # Add other patterns that use a single color
|
||||
if tab.colors_in_palette:
|
||||
# For non-transition patterns, the device typically uses only the first color.
|
||||
# However, if a user picks a color from the palette, we want THAT color to be the one
|
||||
# sent and active. So, the selected color from the palette *becomes* the first color
|
||||
# in the list we send to the device for these modes.
|
||||
# This ensures the light matches the selected palette color.
|
||||
colors_to_send = [hex_color] # Send the color currently set by the sliders
|
||||
else:
|
||||
colors_to_send = ["#000000"] # Default if palette is empty
|
||||
else: # For other patterns like "off", "rainbow" where colors might not be primary
|
||||
# We still want to send the *current* palette state for saving,
|
||||
# but the device firmware might ignore it for these patterns.
|
||||
colors_to_send = tab.colors_in_palette.copy()
|
||||
|
||||
payload = {
|
||||
"save": True, # Always save this change to config
|
||||
"names": names,
|
||||
"settings": {
|
||||
"colors": colors_to_send,
|
||||
# We might also want to send the current brightness and delay
|
||||
# to ensure the device has the complete state, or at least
|
||||
# ensures these don't get 'unset' if they weren't explicitly changed.
|
||||
# This depends on your firmware's expected payload.
|
||||
"colors": colors_to_send, # This now dynamically changes based on pattern
|
||||
"brightness": tab.widgets["brightness_slider"].get(),
|
||||
"delay": tab.widgets["delay_slider"].get(),
|
||||
# Also include the current pattern, so the device knows how to apply colors
|
||||
"pattern": self.settings["lights"][selected_server]["settings"].get("pattern", "on"),
|
||||
"pattern": current_pattern, # Always send the current pattern
|
||||
},
|
||||
}
|
||||
|
||||
# Update the settings object with the new color list (and potentially other synced values)
|
||||
self.settings["lights"][selected_server]["settings"]["colors"] = tab.colors_in_palette.copy()
|
||||
# Also ensure brightness, delay, and pattern are up-to-date in settings before saving
|
||||
self.settings["lights"][selected_server]["settings"]["brightness"] = tab.widgets["brightness_slider"].get()
|
||||
self.settings["lights"][selected_server]["settings"]["delay"] = tab.widgets["delay_slider"].get()
|
||||
# Pattern is generally set by the pattern buttons, but including it in the save here
|
||||
# for completeness might be useful depending on your app's state management.
|
||||
# self.settings["lights"][selected_server]["settings"]["pattern"] = current_pattern # Already updated by send_pattern
|
||||
self.settings.save()
|
||||
|
||||
await self.websocket_client.send_data(payload)
|
||||
|
@ -669,18 +687,20 @@ class App:
|
|||
"delay": current_settings_for_tab.get("delay", 0),
|
||||
}
|
||||
|
||||
# Only include "colors" in the payload if the pattern specifically uses them
|
||||
# For "transition", send the entire palette
|
||||
# For "on", "off", "blink", usually just the first color from the palette is relevant
|
||||
# Determine colors to send based on the *newly selected* pattern
|
||||
if pattern_name == "transition":
|
||||
# Ensure we send the *current state* of the palette
|
||||
payload_settings["colors"] = current_tab_widget.colors_in_palette
|
||||
payload_settings["colors"] = current_tab_widget.colors_in_palette.copy()
|
||||
elif pattern_name in ["on", "blink"]: # Add other patterns that use a single color here
|
||||
if current_tab_widget.colors_in_palette:
|
||||
payload_settings["colors"] = [current_tab_widget.colors_in_palette[0]]
|
||||
else:
|
||||
payload_settings["colors"] = ["#000000"] # Default if palette is empty
|
||||
# For patterns like "off" or "rainbow", "colors" might not be needed or handled differently
|
||||
# When switching TO 'on' or 'blink', ensure the color sent is the one
|
||||
# currently displayed on the sliders (which reflects the selected palette color).
|
||||
r = current_tab_widget.widgets["red_slider"].get()
|
||||
g = current_tab_widget.widgets["green_slider"].get()
|
||||
b = current_tab_widget.widgets["blue_slider"].get()
|
||||
hex_color_from_sliders = f"#{r:02x}{g:02x}{b:02x}"
|
||||
payload_settings["colors"] = [hex_color_from_sliders]
|
||||
else:
|
||||
# For other patterns, send the full palette, device might ignore or use default
|
||||
payload_settings["colors"] = current_tab_widget.colors_in_palette.copy()
|
||||
|
||||
payload = {
|
||||
"save": True,
|
||||
|
@ -689,15 +709,13 @@ class App:
|
|||
}
|
||||
|
||||
# Update the settings object with the new pattern and current colors/brightness/delay
|
||||
# It's important to save the state that *was active* when the pattern was set,
|
||||
# or the state that should *persist* with the pattern.
|
||||
self.settings["lights"][tab_name]["settings"]["pattern"] = pattern_name
|
||||
# Ensure the saved colors are always the palette's current state
|
||||
self.settings["lights"][tab_name]["settings"]["colors"] = current_tab_widget.colors_in_palette
|
||||
# Always save the full current palette state in settings.
|
||||
self.settings["lights"][tab_name]["settings"]["colors"] = current_tab_widget.colors_in_palette.copy()
|
||||
self.settings.save()
|
||||
|
||||
self.highlight_pattern_button(current_tab_widget, pattern_name)
|
||||
self.update_ui_for_pattern(current_tab_widget, pattern_name) # Update visibility
|
||||
self.update_ui_for_pattern(current_tab_widget, pattern_name) # Update UI based on new pattern
|
||||
|
||||
await self.websocket_client.send_data(payload)
|
||||
print(f"Sent pattern payload: {payload}")
|
||||
|
|
Loading…
Reference in New Issue