5252from PIL import ImageTk
5353
5454import library .log
55+
5556library .log .logger .setLevel (logging .NOTSET ) # Disable system monitor logging for the editor
5657
5758# Create a logger for the editor
6061
6162# Hardcode specific configuration for theme editor
6263from library import config
64+
6365config .CONFIG_DATA ["display" ]["REVISION" ] = "SIMU" # For theme editor, always use simulated LCD
6466config .CONFIG_DATA ["config" ]["HW_SENSORS" ] = "STATIC" # For theme editor always use stub data
6567config .CONFIG_DATA ["config" ]["THEME" ] = sys .argv [1 ] # Theme is given as argument
6668
6769from library .display import display # Only import display after hardcoded config is set
6870
71+ RGB_LED_MARGIN = 12
72+
6973
7074def refresh_theme ():
7175 config .load_theme ()
@@ -92,6 +96,20 @@ def refresh_theme():
9296 stats .Date .stats ()
9397
9498
99+ def get_width (self ) -> int :
100+ if config .THEME_DATA ["display" ]["DISPLAY_ORIENTATION" ] == 'portrait' :
101+ return config .CONFIG_DATA ["display" ]["DISPLAY_WIDTH" ]
102+ else :
103+ return config .CONFIG_DATA ["display" ]["DISPLAY_HEIGHT" ]
104+
105+
106+ def get_height (self ) -> int :
107+ if config .THEME_DATA ["display" ]["DISPLAY_ORIENTATION" ] == 'portrait' :
108+ return config .CONFIG_DATA ["display" ]["DISPLAY_HEIGHT" ]
109+ else :
110+ return config .CONFIG_DATA ["display" ]["DISPLAY_WIDTH" ]
111+
112+
95113if __name__ == "__main__" :
96114 def on_closing ():
97115 logger .debug ("Exit Theme Editor..." )
@@ -101,6 +119,78 @@ def on_closing():
101119 os ._exit (0 )
102120
103121
122+ x0 = 0
123+ y0 = 0
124+
125+
126+ def draw_zone (x0 , y0 , x1 , y1 ):
127+ x = min (x0 , x1 )
128+ y = min (y0 , y1 )
129+ width = max (x0 , x1 ) - min (x0 , x1 )
130+ height = max (y0 , y1 ) - min (y0 , y1 )
131+ if width > 0 and height > 0 :
132+ label_zone .place (x = x + RGB_LED_MARGIN , y = y + RGB_LED_MARGIN , width = width , height = height )
133+ else :
134+ label_zone .place_forget ()
135+
136+
137+ def on_button1_press (event ):
138+ global x0 , y0
139+ x0 , y0 = event .x , event .y
140+ label_zone .place_forget ()
141+
142+
143+ def on_button1_press_and_drag (event ):
144+ global x0 , y0
145+ x1 , y1 = event .x , event .y
146+
147+ # Do not draw zone outside of theme preview
148+ if x1 < 0 :
149+ x1 = 0
150+ elif x1 >= display .lcd .get_width ():
151+ x1 = display .lcd .get_width () - 1
152+ if y1 < 0 :
153+ y1 = 0
154+ elif y1 >= display .lcd .get_height ():
155+ y1 = display .lcd .get_height () - 1
156+
157+ label_coord .config (text = 'Drawing zone from [{},{}] to [{},{}]' .format (x0 , y0 , x1 , y1 ))
158+ draw_zone (x0 , y0 , x1 , y1 )
159+
160+
161+ def on_button1_release (event ):
162+ global x0 , y0
163+ x1 , y1 = event .x , event .y
164+ if x1 != x0 or y1 != y0 :
165+ # Do not draw zone outside of theme preview
166+ if x1 < 0 :
167+ x1 = 0
168+ elif x1 >= display .lcd .get_width ():
169+ x1 = display .lcd .get_width () - 1
170+ if y1 < 0 :
171+ y1 = 0
172+ elif y1 >= display .lcd .get_height ():
173+ y1 = display .lcd .get_height () - 1
174+
175+ # Display drawn zone and coordinates
176+ draw_zone (x0 , y0 , x1 , y1 )
177+
178+ # Display relative zone coordinates, to set in theme
179+ x = min (x0 , x1 )
180+ y = min (y0 , y1 )
181+ width = max (x0 , x1 ) - min (x0 , x1 )
182+ height = max (y0 , y1 ) - min (y0 , y1 )
183+ label_coord .config (text = 'Zone: X={}, Y={}, width={} height={}' .format (x , y , width , height ))
184+ else :
185+ # Display click coordinates
186+ label_coord .config (
187+ text = 'X={}, Y={} (click and drag to draw a zone)' .format (x0 , y0 , abs (x1 - x0 ), abs (y1 - y0 )))
188+
189+
190+ def on_zone_click (event ):
191+ label_zone .place_forget ()
192+
193+
104194 # Apply system locale to this program
105195 locale .setlocale (locale .LC_ALL , '' )
106196
@@ -129,9 +219,11 @@ def on_closing():
129219 viewer = tkinter .Tk ()
130220 viewer .title ("Turing SysMon Theme Editor" )
131221 viewer .iconphoto (True , tkinter .PhotoImage (file = "res/icons/monitor-icon-17865/64.png" ))
132- viewer .geometry (str (display .lcd .get_width () + 24 ) + "x" + str (display .lcd .get_height () + 44 ))
222+ viewer .geometry (str (display .lcd .get_width () + 2 * RGB_LED_MARGIN ) + "x" + str (
223+ display .lcd .get_height () + 2 * RGB_LED_MARGIN + 40 ))
133224 viewer .protocol ("WM_DELETE_WINDOW" , on_closing )
134225 viewer .call ('wm' , 'attributes' , '.' , '-topmost' , '1' ) # Preview window always on top
226+ viewer .config (cursor = "cross" )
135227
136228 # Display RGB backplate LEDs color as background color
137229 led_color = config .THEME_DATA ['display' ].get ("DISPLAY_RGB_LED" , (255 , 255 , 255 ))
@@ -141,12 +233,24 @@ def on_closing():
141233
142234 # Display preview in the window
143235 display_image = ImageTk .PhotoImage (display .lcd .screen_image )
144- viewer_picture = tkinter .Label (viewer , image = display_image )
145- viewer_picture .place (x = 10 , y = 10 )
236+ viewer_picture = tkinter .Label (viewer , image = display_image , borderwidth = 0 )
237+ viewer_picture .place (x = RGB_LED_MARGIN , y = RGB_LED_MARGIN )
238+
239+ # Allow to click on preview to show coordinates and draw zones
240+ viewer_picture .bind ("<ButtonPress-1>" , on_button1_press )
241+ viewer_picture .bind ("<B1-Motion>" , on_button1_press_and_drag )
242+ viewer_picture .bind ("<ButtonRelease-1>" , on_button1_release )
243+
244+ label_coord = tkinter .Label (viewer , text = "Click or draw a zone to show coordinates" )
245+ label_coord .place (x = 0 , y = display .lcd .get_height () + 2 * RGB_LED_MARGIN ,
246+ width = display .lcd .get_width () + 2 * RGB_LED_MARGIN )
146247
147- label = tkinter .Label (viewer , text = "This preview will reload when theme file is updated" )
148- label .place (x = 0 , y = display .lcd .get_height () + 24 , width = display .lcd .get_width () + 24 )
248+ label_info = tkinter .Label (viewer , text = "This preview will reload when theme file is updated" )
249+ label_info .place (x = 0 , y = display .lcd .get_height () + 2 * RGB_LED_MARGIN + 20 ,
250+ width = display .lcd .get_width () + 2 * RGB_LED_MARGIN )
149251
252+ label_zone = tkinter .Label (viewer , bg = '#%02x%02x%02x' % tuple (map (lambda x : 255 - x , led_color )))
253+ label_zone .bind ("<ButtonRelease-1>" , on_zone_click )
150254 viewer .update ()
151255
152256 logger .debug ("You can now edit the theme file in the editor. When you save your changes, the preview window will "
@@ -170,6 +274,7 @@ def on_closing():
170274 if isinstance (led_color , str ):
171275 led_color = tuple (map (int , led_color .split (', ' )))
172276 viewer .configure (bg = '#%02x%02x%02x' % led_color )
277+ label_zone .configure (bg = '#%02x%02x%02x' % tuple (map (lambda x : 255 - x , led_color )))
173278
174279 # Regularly update the viewer window even if content unchanged
175280 viewer .update ()
0 commit comments