2023-09-25 17:20:23 -03:00

214 lines
8.4 KiB
Python

import logging
import gi
gi.require_version("Gtk", "3.0")
from gi.repository import Gtk, GLib
from math import pi
from ks_includes.KlippyGcodes import KlippyGcodes
from ks_includes.screen_panel import ScreenPanel
class Panel(ScreenPanel):
def __init__(self, screen, title):
super().__init__(screen, title)
self.da_size = self._gtk.img_scale * 2
self.preview = Gtk.DrawingArea(width_request=self.da_size, height_request=self.da_size)
self.preview.set_size_request(-1, self.da_size * 2)
self.preview.connect("draw", self.on_draw)
self.preview_label = Gtk.Label(label='')
self.preset_list = self._gtk.HomogeneousGrid()
self.color_data = [0, 0, 0, 0]
self.color_order = 'RGBW'
self.presets = {
"on": [1.0, 1.0, 1.0, 1.0],
"off": [0.0, 0.0, 0.0, 0.0]
}
self.scales = {}
self.buttons = []
self.leds = self._printer.get_leds()
self.current_led = self.leds[0] if len(self.leds) == 1 else None
self.open_selector(None, self.current_led)
def color_available(self, idx):
return (
(idx == 0 and 'R' in self.color_order)
or (idx == 1 and 'G' in self.color_order)
or (idx == 2 and 'B' in self.color_order)
or (idx == 3 and 'W' in self.color_order)
)
def activate(self):
if self.current_led is not None:
self.set_title(f"{self.current_led}")
def set_title(self, title):
self._screen.base_panel.set_title(self.prettify(title))
def back(self):
if len(self.leds) > 1 and self.current_led:
self.set_title(self._screen.panels[self._screen._cur_panels[-1]].title)
self.open_selector(led=None)
return True
return False
def open_selector(self, widget=None, led=None):
for child in self.content.get_children():
self.content.remove(child)
if led is None:
self.content.add(self.led_selector())
else:
self.content.add(self.color_selector(led))
self.content.show_all()
def led_selector(self):
self.current_led = None
columns = 3 if self._screen.vertical_mode else 4
grid = self._gtk.HomogeneousGrid()
for i, led in enumerate(self.leds):
name = led.split()[1] if len(led.split()) > 1 else led
button = self._gtk.Button(None, name.upper(), style=f"color{(i % 4) + 1}")
button.connect("clicked", self.open_selector, led)
grid.attach(button, (i % columns), int(i / columns), 1, 1)
scroll = self._gtk.ScrolledWindow()
scroll.add(grid)
return scroll
def color_selector(self, led):
logging.info(led)
self.current_led = led
self.set_title(f"{self.current_led}")
grid = self._gtk.HomogeneousGrid()
self.color_order = self._printer.get_led_color_order(led)
if self.color_order is None:
self.back()
return
scale_grid = self._gtk.HomogeneousGrid()
for idx, col_value in enumerate(self.color_data):
if not self.color_available(idx):
continue
color = [0, 0, 0, 0]
color[idx] = 1
button = self._gtk.Button()
preview = Gtk.DrawingArea(width_request=self.da_size, height_request=self.da_size)
preview.connect("draw", self.on_draw, color)
button.set_image(preview)
button.connect("clicked", self.apply_preset, color)
button.set_hexpand(False)
scale = Gtk.Scale.new_with_range(orientation=Gtk.Orientation.HORIZONTAL, min=0, max=255, step=1)
scale.set_value(round(col_value * 255))
scale.set_digits(0)
scale.set_hexpand(True)
scale.set_has_origin(True)
scale.get_style_context().add_class("fan_slider")
scale.connect("button-release-event", self.apply_scales)
scale.connect("value_changed", self.update_preview)
self.scales[idx] = scale
scale_grid.attach(button, 0, idx, 1, 1)
scale_grid.attach(scale, 1, idx, 3, 1)
grid.attach(scale_grid, 0, 0, 3, 1)
columns = 3 if self._screen.vertical_mode else 2
data_misc = self._screen.apiclient.send_request(
"server/database/item?namespace=mainsail&key=miscellaneous.entries")
if data_misc:
presets_data = data_misc['result']['value'][next(iter(data_misc["result"]["value"]))]['presets']
if presets_data:
self.presets.update(self.parse_presets(presets_data))
for i, key in enumerate(self.presets):
logging.info(f'Adding preset: {key}')
preview = Gtk.DrawingArea(width_request=self.da_size, height_request=self.da_size)
preview.connect("draw", self.on_draw, self.presets[key])
button = self._gtk.Button()
button.set_image(preview)
button.connect("clicked", self.apply_preset, self.presets[key])
self.preset_list.attach(button, i % columns, int(i / columns) + 1, 1, 1)
scroll = self._gtk.ScrolledWindow()
scroll.add(self.preset_list)
preview_box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)
preview_box.add(self.preview_label)
preview_box.add(self.preview)
preview_box.set_homogeneous(True)
box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
box.add(preview_box)
box.add(scroll)
if self._screen.vertical_mode:
grid.attach(box, 0, 1, 3, 1)
else:
grid.attach(box, 3, 0, 2, 1)
return grid
def on_draw(self, da, ctx, color=None):
if color is None:
color = self.color_data
ctx.set_source_rgb(color[0], color[1], color[2])
# Set the size of the rectangle
width = height = da.get_allocated_width() * .9
x = da.get_allocated_width() * .05
# Set the radius of the corners
radius = width / 2 * 0.2
ctx.arc(x + radius, radius, radius, pi, 3 * pi / 2)
ctx.arc(x + width - radius, radius, radius, 3 * pi / 2, 0)
ctx.arc(x + width - radius, height - radius, radius, 0, pi / 2)
ctx.arc(x + radius, height - radius, radius, pi / 2, pi)
ctx.close_path()
ctx.fill()
def update_preview(self, args):
self.update_color_data()
self.preview.queue_draw()
self.preview_label.set_label(self.rgbw_to_hex(self.color_data))
def process_update(self, action, data):
if action != 'notify_status_update':
return
if self.current_led in data and "color_data" in data[self.current_led]:
self.update_scales(data[self.current_led]["color_data"][0])
self.preview.queue_draw()
def update_scales(self, color_data):
for idx in self.scales:
self.scales[idx].set_value(int(color_data[idx] * 255))
self.color_data[idx] = color_data[idx]
def update_color_data(self):
for idx in self.scales:
self.color_data[idx] = round(self.scales[idx].get_value() / 255, 4)
def apply_preset(self, widget, color_data):
self.update_scales(color_data)
self.apply_scales()
def apply_scales(self, *args):
self.update_color_data()
self.set_led_color(self.color_data)
def set_led_color(self, color_data):
name = self.current_led.split()[1] if len(self.current_led.split()) > 1 else self.current_led
self._screen._send_action(None, "printer.gcode.script",
{"script": KlippyGcodes.set_led_color(name, color_data)})
@staticmethod
def parse_presets(presets_data) -> {}:
parsed = {}
for i, preset in enumerate(presets_data.values()):
name = i if preset["name"] == '' else preset["name"].lower()
parsed[name] = []
for color in ["red", "green", "blue", "white"]:
if color not in preset or preset[color] is None:
parsed[name].append(0)
continue
parsed[name].append(round(preset[color] / 255, 4))
return parsed
@staticmethod
def rgbw_to_hex(color):
hex_color = '#'
for value in color[:3]:
int_value = round(value * 255)
hex_color += hex(int_value)[2:].zfill(2)
alpha = round(color[3] * 255)
hex_color += hex(alpha)[2:].zfill(2)
return hex_color.upper()