@@ -127,10 +127,12 @@ class PICALauncherApp:
127127 CLR_FRAME_BG = '#E5DCD3'
128128 CLR_ACCENT_GOLD = '#BA6B5E'
129129 CLR_ACCENT_GREEN = '#B68B6E'
130- # Module family tints: light -> mid -> deep warm-brown intensity ramp
131- CLR_FAMILY_SENSING = '#C9AE99' # T_Sensing (lightest)
132- CLR_FAMILY_CONTROL = '#C98576' # T_Control (light terracotta)
133- CLR_FAMILY_MASTER = '#B58468' # Master (light warm brown)
130+ # Module family marker colors (thin bar at the left of launch buttons).
131+ # Small marks tolerate strong colors: pale sand / vivid terracotta /
132+ # dark espresso are unmistakable even at 5 px wide.
133+ CLR_FAMILY_SENSING = '#D8C0A8' # T_Sensing (pale sand, lightest)
134+ CLR_FAMILY_CONTROL = '#B04A38' # T_Control (vivid terracotta red)
135+ CLR_FAMILY_MASTER = '#4A3222' # Master (dark espresso, darkest)
134136 # Universal hover highlight: deep maroon (same as the EXPERIMENTAL badge),
135137 # darker and redder than any resting fill so "hovered" is unmistakable
136138 CLR_HOVER = '#8B3A2F'
@@ -273,47 +275,20 @@ def setup_styles(self):
273275 style .map (
274276 'Scan.TButton' , background = [
275277 ('active' , '#8AB845' ), ('hover' , '#8AB845' )])
276- # --- Module family tints (monochrome warm-brown intensity ramp) ---
277- # Sensing (T_Sensing) = lightest, Control (T_Control) = mid,
278- # Master = deepest. Same padding/borders as App.TButton so only the
279- # background depth changes per family.
278+ # --- Launch buttons: cream body, left-aligned so the family marker
279+ # bars line up down each column ---
280280 style .configure (
281- 'Sensing .TButton' ,
281+ 'Launch .TButton' ,
282282 font = self .FONT_BASE ,
283283 padding = (10 , 5 ),
284- foreground = self .CLR_TEXT_DARK ,
285- background = self .CLR_FAMILY_SENSING ,
286- borderwidth = 0 ,
287- focusthickness = 0 ,
288- focuscolor = 'none' )
289- style .map (
290- 'Sensing.TButton' , background = [
291- ('active' , self .CLR_HOVER ), ('hover' , self .CLR_HOVER )], foreground = [
292- ('active' , '#FFFFFF' ), ('hover' , '#FFFFFF' )])
293- style .configure (
294- 'Control.TButton' ,
295- font = self .FONT_BASE ,
296- padding = (10 , 5 ),
297- foreground = self .CLR_TEXT_DARK ,
298- background = self .CLR_FAMILY_CONTROL ,
299- borderwidth = 0 ,
300- focusthickness = 0 ,
301- focuscolor = 'none' )
302- style .map (
303- 'Control.TButton' , background = [
304- ('active' , self .CLR_HOVER ), ('hover' , self .CLR_HOVER )], foreground = [
305- ('active' , '#FFFFFF' ), ('hover' , '#FFFFFF' )])
306- style .configure (
307- 'Master.TButton' ,
308- font = self .FONT_BASE ,
309- padding = (10 , 5 ),
310- foreground = self .CLR_TEXT_DARK ,
311- background = self .CLR_FAMILY_MASTER ,
284+ anchor = 'w' ,
285+ foreground = self .CLR_ACCENT_GOLD ,
286+ background = self .CLR_FRAME_BG ,
312287 borderwidth = 0 ,
313288 focusthickness = 0 ,
314289 focuscolor = 'none' )
315290 style .map (
316- 'Master .TButton' , background = [
291+ 'Launch .TButton' , background = [
317292 ('active' , self .CLR_HOVER ), ('hover' , self .CLR_HOVER )], foreground = [
318293 ('active' , '#FFFFFF' ), ('hover' , '#FFFFFF' )])
319294 style .configure (
@@ -523,19 +498,35 @@ def _load_logo(self, canvas):
523498 except Exception as e :
524499 self .log (f"ERROR: Failed to load logo. { e } " )
525500
526- # Maps a module family tag to its button style; anything else -> default.
527- _FAMILY_STYLES = {
528- 'sensing' : 'Sensing.TButton' ,
529- 'control' : 'Control.TButton' ,
530- 'master' : 'Master.TButton' ,
501+ # Maps a module family tag to its marker bar color; None -> transparent
502+ # spacer so unmarked labels still line up with marked ones.
503+ _FAMILY_COLORS = {
504+ 'sensing' : CLR_FAMILY_SENSING ,
505+ 'control' : CLR_FAMILY_CONTROL ,
506+ 'master' : CLR_FAMILY_MASTER ,
531507 }
532508
509+ def _get_family_marker (self , family ):
510+ """Returns a small PhotoImage bar in the family color (cached).
511+ The image is 8px wide with a 5px colored bar and a transparent gap;
512+ an unknown/None family yields a fully transparent spacer."""
513+ if not hasattr (self , '_marker_images' ):
514+ self ._marker_images = {}
515+ if family not in self ._marker_images :
516+ img = tk .PhotoImage (master = self .root , width = 8 , height = 18 )
517+ color = self ._FAMILY_COLORS .get (family )
518+ if color :
519+ img .put (color , to = (0 , 0 , 5 , 18 ))
520+ self ._marker_images [family ] = img
521+ return self ._marker_images [family ]
522+
533523 def _create_launch_button (self , parent , text , script_key , family = None ):
534- style = self ._FAMILY_STYLES .get (family , 'App.TButton' )
535524 return ttk .Button (
536525 parent ,
537526 text = text ,
538- style = style ,
527+ style = 'Launch.TButton' ,
528+ image = self ._get_family_marker (family ),
529+ compound = 'left' ,
539530 command = lambda : self .launch_script (
540531 self .SCRIPT_PATHS [script_key ]))
541532
0 commit comments