@@ -54,21 +54,26 @@ class LightState(TypedDict):
5454
5555
5656async def update_bulb (bulb , brightness = None , hue = None , saturation = None ):
57- if brightness != None :
58- await bulb .set_brightness (brightness )
59- if hue != None or saturation != None :
60- state : LightState = await bulb .get_light_state ()
61- await bulb .set_hsv (
62- hue if hue != None else state ["hue" ],
63- saturation if saturation != None else state ["saturation" ],
64- brightness if brightness != None else state ["brightness" ],
65- )
57+ # note: all arguments need to ints
58+ assert brightness is None or isinstance (brightness , int )
59+ assert hue is None or isinstance (hue , int )
60+ assert saturation is None or isinstance (saturation , int )
61+
62+ state : LightState = await bulb .get_light_state ()
63+ await bulb .set_hsv (
64+ hue if hue != None else state ["hue" ],
65+ saturation if saturation != None else state ["saturation" ],
66+ brightness if brightness != None else state ["brightness" ],
67+ )
6668
6769
6870class ScrollableFrame (tkinter .ttk .Frame ):
6971 def __init__ (self , container , * args , ** kwargs ):
7072 super ().__init__ (container , * args , ** kwargs )
71- self .canvas = tkinter .Canvas (self )
73+ background = tkinter .ttk .Style ().lookup ("TFrame" , "background" )
74+ self .canvas = tkinter .Canvas (
75+ self , background = background , bd = 0 , highlightthickness = 0
76+ )
7277 self .scrollable_frame = tkinter .ttk .Frame (self .canvas )
7378 self .scrollable_frame .bind (
7479 "<Configure>" ,
@@ -126,7 +131,7 @@ def _on_mouse_scroll(self, event):
126131 self .canvas .yview_scroll (int (- 1 * (event .delta / 120 )), "units" )
127132
128133
129- class EditableText (tkinter .Frame ):
134+ class EditableText (tkinter .ttk . Frame ):
130135 def __init__ (self , container , initial_text_value , callback ):
131136 super (self .__class__ , self ).__init__ (container )
132137
@@ -149,22 +154,27 @@ def _edit_mode_finish(self, event=None):
149154
150155 def _render_static_mode (self ):
151156 """render non-editable text"""
152- label_font = tkinter .font .Font (
153- family = "Helvetica" , name = "appHighlightFont" , size = 12 , weight = "bold"
157+ big_label_style_name = "my.TLabel"
158+ style = tkinter .ttk .Style ()
159+ default_font_name = style .lookup ("TLabel" , "font" )
160+ default_font = tkinter .font .nametofont (default_font_name )
161+ custom_font = {** default_font .actual (), "size" : 12 }
162+ style .configure (big_label_style_name , font = custom_font )
163+
164+ text_label = tkinter .ttk .Label (
165+ self , text = self .text .get (), style = big_label_style_name
154166 )
155-
156- text_label = tkinter .Label (self , text = self .text .get (), font = label_font )
157167 text_label .pack (side = tkinter .LEFT )
158168
159- edit_label = tkinter .Label (self , image = self .pencil_icon )
169+ edit_label = tkinter .ttk . Label (self , image = self .pencil_icon )
160170 edit_label .bind ("<ButtonRelease-1>" , self ._edit_mode_start )
161171 edit_label .pack (side = tkinter .LEFT )
162172
163173 self .child_widgets .append (text_label )
164174 self .child_widgets .append (edit_label )
165175
166176 def _render_edit_mode (self ):
167- text_entry = tkinter .Entry (self , textvariable = self .text )
177+ text_entry = tkinter .ttk . Entry (self , textvariable = self .text )
168178 text_entry .pack (side = tkinter .LEFT )
169179 text_entry .bind ("<Return>" , self ._edit_mode_finish )
170180
@@ -177,33 +187,46 @@ def pencil_icon(self):
177187 tkinter.Label is not sufficient.
178188 (https://stackoverflow.com/a/31959529/2796349)
179189 """
190+ style = tkinter .ttk .Style ()
191+ foreground = style .lookup ("TFrame" , "foreground" )
192+ background = style .lookup ("TFrame" , "background" )
193+
180194 if not hasattr (self , "_pencil_icon" ):
181195 self ._pencil_icon = tkinter .BitmapImage (
182- data = b"#define image_width 16\n #define image_height 16\n static char image_bits[] = {\n 0x00,0x1c,0x00,0x3e,0x00,0x7f,0x80,0xf7,0xc0,0xf3,0xe0,0x79,0xf0,0x3c,0x78,\n 0x1e,0x3c,0x0f,0x9c,0x07,0xcc,0x03,0xfc,0x01,0xfc,0x00,0x7c,0x00,0xff,0xff,\n 0xff,0xff\n };"
196+ data = b"#define image_width 16\n #define image_height 16\n static char image_bits[] = {\n 0x00,0x1c,0x00,0x3e,0x00,0x7f,0x80,0xf7,0xc0,0xf3,0xe0,0x79,0xf0,0x3c,0x78,\n 0x1e,0x3c,0x0f,0x9c,0x07,0xcc,0x03,0xfc,0x01,0xfc,0x00,0x7c,0x00,0xff,0xff,\n 0xff,0xff\n };" ,
197+ background = background ,
198+ foreground = foreground ,
183199 )
184200 return self ._pencil_icon
185201
186202
187- class BulbFrame (tkinter .Frame ):
203+ class BulbFrame (tkinter .ttk . Frame ):
188204 async def _hue_callback (self ):
189- return await update_bulb (self .bulb , None , self .hue_slider .get ())
205+ return await update_bulb (self .bulb , None , int ( self .hue_slider .get () ))
190206
191207 async def _saturation_callback (self ):
192- return await update_bulb (self .bulb , saturation = self .saturation_slider .get ())
208+ return await update_bulb (
209+ self .bulb , int (saturation = self .saturation_slider .get ())
210+ )
193211
194212 async def _brightness_callback (self ):
195- return await update_bulb (self .bulb , self .brightness_slider .get ())
213+ logger .info ("Brightness callback: {}" .format (self .brightness_slider .get ()))
214+ return await update_bulb (self .bulb , int (self .brightness_slider .get ()))
196215
197216 async def _power_callback (self ):
198- self .power_button [ "state" ] = tkinter . DISABLED
217+ self .power_button . state ([ "disabled" ])
199218
200219 try :
201220 await (self .bulb .turn_off () if self .bulb .is_on else self .bulb .turn_on ())
202221 await self .bulb .update ()
203222 finally :
204- self .power_button ["relief" ] = "sunken" if self .bulb .is_on else "raised"
223+ self .power_button .state (
224+ [
225+ "!disabled" ,
226+ "pressed" if self .bulb .is_on else "!pressed" ,
227+ ]
228+ )
205229 self .power_button ["text" ] = "Turn Off" if self .bulb .is_on else "Turn On"
206- self .power_button ["state" ] = tkinter .NORMAL
207230
208231 @classmethod
209232 def for_bulb (cls , loop , bulb : kasa .SmartBulb , config , * args , ** kwargs ):
@@ -215,11 +238,11 @@ def for_bulb(cls, loop, bulb: kasa.SmartBulb, config, *args, **kwargs):
215238 self = cls (* args , ** kwargs )
216239 self .bulb = bulb
217240
218- self .hue_label = tkinter .Label (self , text = "hue" )
219- self .saturation_label = tkinter .Label (self , text = "saturation" )
220- self .brightness_label = tkinter .Label (self , text = "brightness" )
241+ self .hue_label = tkinter .ttk . Label (self , text = "hue" )
242+ self .saturation_label = tkinter .ttk . Label (self , text = "saturation" )
243+ self .brightness_label = tkinter .ttk . Label (self , text = "brightness" )
221244
222- self .hue_slider = tkinter .Scale (
245+ self .hue_slider = tkinter .ttk . Scale (
223246 self , from_ = 0 , to = 360 , orient = tkinter .HORIZONTAL
224247 )
225248 self .hue_slider .bind (
@@ -230,7 +253,7 @@ def for_bulb(cls, loop, bulb: kasa.SmartBulb, config, *args, **kwargs):
230253 )
231254 self .hue_slider .set (self .bulb .hsv [0 ])
232255
233- self .saturation_slider = tkinter .Scale (
256+ self .saturation_slider = tkinter .ttk . Scale (
234257 self , from_ = 0 , to = 100 , orient = tkinter .HORIZONTAL
235258 )
236259 self .saturation_slider .bind (
@@ -241,7 +264,7 @@ def for_bulb(cls, loop, bulb: kasa.SmartBulb, config, *args, **kwargs):
241264 )
242265 self .saturation_slider .set (self .bulb .hsv [1 ])
243266
244- self .brightness_slider = tkinter .Scale (
267+ self .brightness_slider = tkinter .ttk . Scale (
245268 self , from_ = 0 , to = 100 , orient = tkinter .HORIZONTAL
246269 )
247270 self .brightness_slider .bind (
@@ -260,12 +283,13 @@ def for_bulb(cls, loop, bulb: kasa.SmartBulb, config, *args, **kwargs):
260283 self , bulb_name , lambda new_device_name : logger .info (new_device_name )
261284 ).grid (column = 0 , row = 0 , columnspan = 4 )
262285
263- self .power_button = tkinter .Button (
286+ self .power_button = tkinter .ttk . Button (
264287 self ,
265288 text = "Turn Off" if self .bulb .is_on else "Turn On" ,
266- width = 12 ,
267- relief = "sunken" if self .bulb .is_on else "raised" ,
289+ # relief="sunken" if self.bulb.is_on else "raised" ,
290+ # pressed= self.bulb.is_on
268291 )
292+ self .power_button .state (["pressed" if self .bulb .is_on else "!pressed" ])
269293 self .power_button .bind (
270294 "<ButtonRelease-1>" ,
271295 lambda event , self = self , loop = loop : asyncio .run_coroutine_threadsafe (
@@ -328,7 +352,7 @@ async def process_devices():
328352
329353 # TODO make sure that self.device_queue exists before exiting this function
330354
331- self .refresh_button = tkinter .Button (
355+ self .refresh_button = tkinter .ttk . Button (
332356 self , text = "Refresh" , command = self .start_refresh
333357 )
334358 self .refresh_button .pack (fill = tkinter .X )
@@ -359,11 +383,11 @@ async def add_device(self, device):
359383
360384 async def _do_refresh (self ):
361385 logger .info ("KasaDevices._do_refresh() called" )
362- self .refresh_button [ "state" ] = tkinter . DISABLED
386+ self .refresh_button . state ([ "disabled" ])
363387 self .refresh_button ["text" ] = "Refreshing..."
364388 await self .clear_devices ()
365389 await kasa .Discover .discover (on_discovered = self .device_queue .put )
366- self .refresh_button [ "state" ] = tkinter . NORMAL
390+ self .refresh_button . state ([ "!disabled" ])
367391 self .refresh_button ["text" ] = "Refresh"
368392
369393 async def clear_devices (self ):
0 commit comments