@@ -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