infra/dotfile/.themes/openbox-lean/openbox-3/set.py

234 lines
4.8 KiB
Python
Raw Permalink Normal View History

2025-12-01 13:23:24 +07:00
#!/usr/bin/env python
import gi; gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, Gdk
from functools import reduce
import sys, os, re
Colors = {
'AB' : { 'Name' : 'Active Back', 'Default' : '#579c8e' },
'AF' : { 'Name' : 'Active Fore', 'Default' : '#ffffff' },
'AL' : { 'Name' : 'Active Line', 'Default' : '#292929' },
'NB' : { 'Name' : 'Normal Back', 'Default' : '#383838' },
'NF' : { 'Name' : 'Normal Fore', 'Default' : '#dadada' },
'NL' : { 'Name' : 'Normal Line', 'Default' : '#292929' },
}
Options = {
'B?' : { 'Name' : 'Borders', 'Default' : True },
'H?' : { 'Name' : 'Active Handle', 'Default' : False },
'G?' : { 'Name' : 'Gradients', 'Default' : False },
'R?' : { 'Name' : 'Raised', 'Default' : False },
}
def Init (l):
for r in l.values():
r['Initial'] = r['Value'] = r['Default']
Init(Colors)
Init(Options)
Dir = os.path.dirname(os.path.realpath(sys.argv[0]))
InPath = Dir + '/themerc.in'
OutPath = Dir + '/themerc'
def InitV (k, vs, f, s):
if k in vs: vs[k]['Initial'] = vs[k]['Value'] = f(s)
with open(Dir + '/themerc') as f:
for l in f.readlines():
if l[0] != '#': continue
ss = l.strip().split(' ')
k, v = ss[0].lstrip('#'), ss[1]
InitV(k, Colors, lambda s: s, v)
InitV(k, Options, lambda s: (v == 'True'), v)
def Read (path):
with open(path) as f:
return f.read()
def Rgb8 (c):
return [int(c[i:i+2], 16) for i in (1, 3, 5)]
def Hex8FromRgb8 (c):
return '#%02x%02x%02x' % tuple(c)
def Hex8FromRgb (c):
return Hex8FromRgb8 (
map(lambda f: int(f * 0xFF), c)
)
def Subst (src, op, cl, fun):
s = src.split(op)
o = s[0]
for si in range(1, len(s)):
b = s[si].split(cl)
o = o + fun(b[0]) + b[1]
return o
def SubstCond (s):
kv = s.split(' ', 1)
yn = kv[1].split('!')
return yn[0] if Options[kv[0]]['Value'] else yn[1]
def SubstColor (s):
def pone (c):
if (c.startswith('#')): return Rgb8(c)
else: return Rgb8(Colors[c]['Value'])
def addc (a, b):
return map(lambda c0, c1: c0 + c1, a, b)
def divc (c, d):
return map(lambda c: int(c / d), c)
cs = [pone(c) for c in s.split(' ')];
return Hex8FromRgb8(divc(reduce(addc, cs), len(cs)))
def ExVals (vs):
return '\n'.join (
map (
lambda k: '#' + k + ' ' + str(vs[k]['Value']), vs
)
) + '\n'
def Apply ():
s = Read(InPath)
s = Subst(s, '[', ']', SubstCond)
s = Subst(s, '{', '}', SubstColor)
s = ExVals(Colors) + ExVals(Options) + '\n' + s
with open(OutPath, 'w') as of: of.write(s)
os.system('openbox --reconfigure')
def Reveal ():
for c in Colors.values():
c['Button'].set_color(Gdk.color_parse(c['Value']))
for o in Options.values():
o['Switch'].set_state(o['Value'])
def Reset (key):
for c in list(Colors.values()) + list(Options.values()):
c['Value'] = c[key]
Reveal()
def FromGtk ():
m = Gtk.Menu()
i = Gtk.MenuItem()
w = Gtk.Window()
m.add(i)
ms = m.get_style_context()
rs = i.get_style_context()
ws = w.get_style_context()
def ccc (key, gc):
Colors[key]['Value'] = Hex8FromRgb([gc.red, gc.green, gc.blue])
ccc('AB', rs.get_background_color(Gtk.StateFlags.PRELIGHT))
ccc('AF', rs.get_color(Gtk.StateFlags.PRELIGHT))
ccc('AL', ms.get_border_color(Gtk.StateFlags.PRELIGHT))
ccc('NB', ws.get_background_color(Gtk.StateFlags.NORMAL))
ccc('NF', ws.get_color(Gtk.StateFlags.NORMAL))
ccc('NL', ms.get_border_color(Gtk.StateFlags.NORMAL))
Reveal()
W = Gtk.Window(title = "Lean OB")
W.set_icon_name("applications-graphics")
W.connect("destroy", lambda e: Gtk.main_quit())
W.set_resizable(False)
W.set_border_width(8)
T = Gtk.Grid()
T.set_row_spacing(4)
T.set_column_spacing(4)
T.Rows = 0
def AddRow (t, label, o):
t.attach(Gtk.Label(label + ':'), 0, t.Rows, 1, 1)
t.attach(o, 1, T.Rows, 1, 1)
t.Rows = t.Rows + 1
def SetC (ck, c):
Colors[ck]['Value'] = Hex8FromRgb(c.to_floats())
def SetO (ok, o):
Options[ok]['Value'] = o
for ck in sorted(Colors):
c = Colors[ck]
cbtn = c['Button'] = Gtk.ColorButton(color = Gdk.color_parse(c['Value']))
cbtn.connect('color-set', lambda b, k: SetC(k, b.get_color()), ck)
AddRow(T, c['Name'], cbtn)
for ok in sorted(Options):
o = Options[ok]
osw = o['Switch'] = Gtk.Switch(state = o['Value'])
osw.connect('state-set', lambda s, v, k: SetO(k, v), ok)
AddRow(T, o['Name'], osw)
DefaultBtn = Gtk.Button("Default")
RevertBtn = Gtk.Button("Revert")
FromGtkBtn = Gtk.Button("From GTK")
ApplyBtn = Gtk.Button("Apply")
DefaultBtn.connect('clicked', lambda e: Reset('Default'))
RevertBtn.connect('clicked', lambda e: Reset('Initial'))
FromGtkBtn.connect('clicked', lambda e: FromGtk())
ApplyBtn.connect('clicked', lambda e: Apply())
V = Gtk.VBox(spacing = 8)
V.pack_start(DefaultBtn, True, True, 0)
V.pack_start(FromGtkBtn, True, True, 0)
V.pack_start(T, True, True, 0)
V.pack_start(RevertBtn, True, True, 0)
V.pack_start(ApplyBtn, True, True, 0)
W.add(V)
W.show_all()
Gtk.main()