seven segment battery indicator for win11 with ashok's tcltk magicsplat runtime and claude 4 sonnet in vscode (plain text editing )
one hour hack in 2025 after ten years away
enjoy
package require Tk
package require Img
package require twapi
# --- 1) Create the systray icon once (Windows needs a *photo*). ---
# The -text is tooltip only; the actual digits are drawn into the image.
proc TrayCreate {} {
variable ::bat
array set ::bat {}
# Start with a dummy
set ph [image create photo -width 16 -height 16]
tk systray create -image $ph -text "Battery"
}
# --- 2) Create a photo image with seven-segment display numbers ---
proc MakeNumIcon {n {size 16}} {
# clamp + format
if {$n < 0} { set n 0 } elseif {$n > 100} { set n 100 }
# Create a photo image directly
set ph [image create photo -width $size -height $size]
# Fill with black background
$ph put black -to 0 0 $size $size
# Seven-segment display patterns for digits 0-9
# Each digit is represented as 7 segments: a,b,c,d,e,f,g
# aaa
# f b
# f b
# ggg
# e c
# e c
# ddd
array set segments {
0 {a b c d e f}
1 {b c}
2 {a b g e d}
3 {a b g c d}
4 {f g b c}
5 {a f g c d}
6 {a f g e d c}
7 {a b c}
8 {a b c d e f g}
9 {a b c d f g}
}
# Convert number to string with leading zero for single digits, and 100 shows as 00
if {$n == 100} {
set numstr "00"
} elseif {$n < 10} {
set numstr [format "%02d" $n]
} else {
set numstr [format "%d" $n]
}
set numlen [string length $numstr]
# Calculate digit size and positioning - always two digits
set digit_width [expr {($size - 6) / 2}]
set digit_height [expr {$size - 4}]
set start_y 2
# First digit
set start_x 1
DrawSevenSegmentDigit $ph [string index $numstr 0] $start_x $start_y $digit_width $digit_height segments
# Second digit
set start_x [expr {$start_x + $digit_width + 2}]
DrawSevenSegmentDigit $ph [string index $numstr 1] $start_x $start_y $digit_width $digit_height segments
return $ph
}
# Helper function to draw a single seven-segment digit
proc DrawSevenSegmentDigit {ph digit x y width height segmentsArray} {
upvar $segmentsArray segments
# Skip if digit is invalid
if {![info exists segments($digit)]} return
# Calculate segment dimensions
set seg_length [expr {$width - 2}]
set seg_height [expr {($height - 3) / 2}]
# Calculate actual coordinate values
set w [expr {$width - 1}]
set h [expr {$height - 1}]
set h1 [expr {$height / 2}]
set h2 [expr {$h1 + 1}]
# Define segment positions and draw them
foreach seg_name $segments($digit) {
switch $seg_name {
a {
# Top horizontal segment
DrawHorizontalSegment $ph [expr {$x + 1}] $y $seg_length
}
b {
# Upper right vertical segment
DrawVerticalSegment $ph [expr {$x + $w}] [expr {$y + 1}] $seg_height
}
c {
# Lower right vertical segment
DrawVerticalSegment $ph [expr {$x + $w}] [expr {$y + $h2}] $seg_height
}
d {
# Bottom horizontal segment
DrawHorizontalSegment $ph [expr {$x + 1}] [expr {$y + $h}] $seg_length
}
e {
# Lower left vertical segment
DrawVerticalSegment $ph $x [expr {$y + $h2}] $seg_height
}
f {
# Upper left vertical segment
DrawVerticalSegment $ph $x [expr {$y + 1}] $seg_height
}
g {
# Middle horizontal segment
DrawHorizontalSegment $ph [expr {$x + 1}] [expr {$y + $h1}] $seg_length
}
}
}
}
# Draw horizontal segment
proc DrawHorizontalSegment {ph x y length} {
for {set i 0} {$i < $length} {incr i} {
$ph put yellow -to [expr {$x + $i}] $y
}
}
# Draw vertical segment
proc DrawVerticalSegment {ph x y height} {
for {set i 0} {$i < $height} {incr i} {
$ph put yellow -to $x [expr {$y + $i}]
}
}
# --- 3) Cache icons and update the tray quickly. ---
proc TraySetBattery {percent} {
variable ::bat
set key [format %d [expr {int($percent)}]]
if {![info exists ::bat(icons,$key)]} {
set ::bat(icons,$key) [MakeNumIcon $key 16]
}
tk systray configure -image $::bat(icons,$key) -text "$key%"
}
# --- Demo function (for testing) ---
proc demoTick {} {
global x
TraySetBattery $x
incr x -1
if {$x < 0} { set x 100 }
after 100 demoTick
}
# --- Real battery monitoring function ---
proc batteryGo {} {
# Get battery status using TWAPI
try {
set power_status [twapi::get_power_status]
set battery_percent [dict get $power_status -batterylifepercent]
# Print timestamp and battery value to console
set timestamp [clock format [clock seconds] -format "%Y-%m-%d %H:%M:%S"]
puts "$timestamp Battery: \"$battery_percent\""
# Handle case where battery percent might be unknown
if {$battery_percent eq "unknown" || $battery_percent eq "" || $battery_percent < 0} {
set battery_percent 0
}
# Update the system tray icon
TraySetBattery $battery_percent
} trap {TWAPI} {result options} {
# If TWAPI fails, show error indicator
TraySetBattery 00
} on error {result options} {
# Generic error handling
TraySetBattery 00
}
# Schedule next update in 5 seconds (5000ms)
after 5000 batteryGo
}
console show
# --- Start real battery monitoring ---
TrayCreate
batteryGo
# --- Demo Mode ---
# To run the demo countdown instead of real battery monitoring, comment out
# the "batteryGo" line above and uncomment the following lines:
#
# set x 100
# demoTick