mirror of
https://github.com/onyx-and-iris/voicemeeter-compact.git
synced 2026-03-09 19:59:13 +00:00
bus mode button now reads current mode from tkVar (more reliable). bus mono button fixed (possible to set stereo reverse)
654 lines
24 KiB
Python
654 lines
24 KiB
Python
import abc
|
|
import logging
|
|
import tkinter as tk
|
|
from functools import partial
|
|
from tkinter import ttk
|
|
|
|
import sv_ttk
|
|
|
|
from .banner import Banner
|
|
from .channels import _make_channelframe
|
|
from .config import BusConfig, StripConfig
|
|
from .data import _base_values, _configuration
|
|
from .navigation import Navigation
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
class AbstractBuilder(abc.ABC):
|
|
@abc.abstractmethod
|
|
def setup(self):
|
|
"""register as observable"""
|
|
pass
|
|
|
|
@abc.abstractmethod
|
|
def teardown(self):
|
|
"""deregister as observable"""
|
|
pass
|
|
|
|
|
|
class MainFrameBuilder(AbstractBuilder):
|
|
"""Responsible for building the frames that sit directly on the mainframe"""
|
|
|
|
def __init__(self, app):
|
|
self.kind = app.kind
|
|
self.app = app
|
|
self.logger = logger.getChild(self.__class__.__name__)
|
|
|
|
def setup(self):
|
|
self.app.title(
|
|
f'Voicemeeter{self.kind}.Compact [{"Local" if not _base_values.vban_connected else "Network"} Connection]'
|
|
)
|
|
self.app.resizable(False, False)
|
|
if _configuration.themes_enabled:
|
|
if sv_ttk.get_theme() not in ('light', 'dark'):
|
|
sv_ttk.set_theme(_configuration.theme_mode)
|
|
self.logger.info(
|
|
f'Sunvalley {sv_ttk.get_theme().capitalize()} Theme applied'
|
|
)
|
|
|
|
def create_channelframe(self, type_):
|
|
if type_ == 'strip':
|
|
self.app.strip_frame = _make_channelframe(self.app, type_)
|
|
else:
|
|
self.app.bus_frame = _make_channelframe(self.app, type_)
|
|
self.logger.info(f'Finished building channelframe type {type_}')
|
|
|
|
def create_separator(self):
|
|
self.app.sep = ttk.Separator(self.app, orient='vertical')
|
|
self.app.sep.grid(row=0, column=1, sticky=(tk.N, tk.S))
|
|
self.app.columnconfigure(1, minsize=15)
|
|
self.logger.info('Finished building separator')
|
|
|
|
def create_navframe(self):
|
|
self.app.nav_frame = Navigation(self.app)
|
|
self.logger.info('Finished building navframe')
|
|
|
|
def create_configframe(self, type_, index, id):
|
|
if type_ == 'strip':
|
|
self.app.config_frame = StripConfig(self.app, index, id)
|
|
if self.app.strip_frame:
|
|
[
|
|
frame.conf.set(False)
|
|
for i, frame in enumerate(self.app.strip_frame.labelframes)
|
|
if i != index
|
|
]
|
|
if self.app.bus_frame:
|
|
[
|
|
frame.conf.set(False)
|
|
for _, frame in enumerate(self.app.bus_frame.labelframes)
|
|
]
|
|
else:
|
|
self.app.config_frame = BusConfig(self.app, index, id)
|
|
if self.app.bus_frame:
|
|
[
|
|
frame.conf.set(False)
|
|
for i, frame in enumerate(self.app.bus_frame.labelframes)
|
|
if i != index
|
|
]
|
|
if self.app.strip_frame:
|
|
[
|
|
frame.conf.set(False)
|
|
for _, frame in enumerate(self.app.strip_frame.labelframes)
|
|
]
|
|
if not _configuration.themes_enabled:
|
|
if self.app.strip_frame:
|
|
[
|
|
frame.styletable.configure(
|
|
f'{frame.identifier}Conf{frame.index}.TButton',
|
|
background=f'{"white" if not frame.conf.get() else "yellow"}',
|
|
)
|
|
for _, frame in enumerate(self.app.strip_frame.labelframes)
|
|
]
|
|
if self.app.bus_frame:
|
|
[
|
|
frame.styletable.configure(
|
|
f'{frame.identifier}Conf{frame.index}.TButton',
|
|
background=f'{"white" if not frame.conf.get() else "yellow"}',
|
|
)
|
|
for _, frame in enumerate(self.app.bus_frame.labelframes)
|
|
]
|
|
self.logger.info(f'Finished building configframe for {type_}[{index}]')
|
|
self.app.after(5, self.reset_config_frames)
|
|
|
|
def reset_config_frames(self):
|
|
[
|
|
frame.teardown()
|
|
for frame in self.app.configframes
|
|
if frame != self.app.config_frame
|
|
]
|
|
|
|
def create_banner(self):
|
|
self.app.banner = Banner(self.app)
|
|
self.app.banner.grid(row=4, column=0, columnspan=3)
|
|
self.logger.info('Finished building banner')
|
|
|
|
def teardown(self):
|
|
pass
|
|
|
|
|
|
class NavigationFrameBuilder(AbstractBuilder):
|
|
"""Responsible for building navigation frame widgets"""
|
|
|
|
def __init__(self, navframe):
|
|
self.navframe = navframe
|
|
|
|
def setup(self):
|
|
self.navframe.submix = tk.BooleanVar()
|
|
self.navframe.channel = tk.BooleanVar()
|
|
self.navframe.extend = tk.BooleanVar(value=_configuration.extended)
|
|
self.navframe.info = tk.BooleanVar()
|
|
|
|
self.navframe.channel_text = tk.StringVar(
|
|
value=f'{self.navframe.parent.strip_frame.identifier.upper()}'
|
|
)
|
|
self.navframe.extend_text = tk.StringVar(
|
|
value=f'{"REDUCE" if self.navframe.extend.get() else "EXTEND"}'
|
|
)
|
|
self.navframe.info_text = tk.StringVar()
|
|
|
|
def create_submix_button(self):
|
|
self.navframe.submix_button = ttk.Checkbutton(
|
|
self.navframe,
|
|
text='SUBMIX',
|
|
command=self.navframe.show_submix,
|
|
style=f'{"Toggle.TButton" if _configuration.themes_enabled else "Submix.TButton"}',
|
|
variable=self.navframe.submix,
|
|
)
|
|
self.navframe.submix_button.grid(column=0, row=0)
|
|
if self.navframe.parent.kind.name != 'potato':
|
|
self.navframe.submix_button['state'] = 'disabled'
|
|
|
|
def create_channel_button(self):
|
|
self.navframe.channel_button = ttk.Checkbutton(
|
|
self.navframe,
|
|
textvariable=self.navframe.channel_text,
|
|
command=self.navframe.switch_channel,
|
|
style=f'{"Toggle.TButton" if _configuration.themes_enabled else "Channel.TButton"}',
|
|
variable=self.navframe.channel,
|
|
)
|
|
self.navframe.channel_button.grid(column=0, row=1, rowspan=1)
|
|
|
|
def create_extend_button(self):
|
|
self.navframe.extend_button = ttk.Checkbutton(
|
|
self.navframe,
|
|
textvariable=self.navframe.extend_text,
|
|
command=self.navframe.extend_frame,
|
|
style=f'{"Toggle.TButton" if _configuration.themes_enabled else "Extend.TButton"}',
|
|
variable=self.navframe.extend,
|
|
)
|
|
self.navframe.extend_button.grid(column=0, row=2)
|
|
|
|
def create_info_button(self):
|
|
self.navframe.info_button = ttk.Checkbutton(
|
|
self.navframe,
|
|
textvariable=self.navframe.info_text,
|
|
style=f'{"Toggle.TButton" if _configuration.themes_enabled else "Rec.TButton"}',
|
|
variable=self.navframe.info,
|
|
)
|
|
self.navframe.info_button.grid(column=0, row=3)
|
|
|
|
def grid_configure(self):
|
|
[
|
|
child.grid_configure(padx=1, pady=1, sticky=(tk.N, tk.S, tk.W, tk.E))
|
|
for child in self.navframe.winfo_children()
|
|
if isinstance(child, ttk.Checkbutton)
|
|
]
|
|
if _configuration.themes_enabled:
|
|
self.navframe.rowconfigure(1, minsize=_configuration.channel_height)
|
|
else:
|
|
self.navframe.rowconfigure(1, minsize=_configuration.channel_height + 10)
|
|
|
|
def teardown(self):
|
|
pass
|
|
|
|
|
|
class ChannelLabelFrameBuilder(AbstractBuilder):
|
|
"""Responsible for building channel labelframe widgets"""
|
|
|
|
def __init__(self, labelframe, index, id):
|
|
self.labelframe = labelframe
|
|
self.index = index
|
|
self.identifier = id
|
|
self.using_theme = False
|
|
|
|
def setup(self):
|
|
"""Create class variables for widgets"""
|
|
self.labelframe.gain = tk.DoubleVar()
|
|
self.labelframe.level = tk.DoubleVar(value=0)
|
|
self.labelframe.mute = tk.BooleanVar()
|
|
self.labelframe.conf = tk.BooleanVar()
|
|
self.labelframe.gainlabel = tk.StringVar()
|
|
|
|
"""for gainlayers"""
|
|
self.labelframe.on = tk.BooleanVar()
|
|
|
|
def add_progressbar(self):
|
|
"""Adds a progress bar widget to a single label frame"""
|
|
self.labelframe.pb = ttk.Progressbar(
|
|
self.labelframe,
|
|
maximum=72, # Range: 0 = -60dB, 72 = +12dB (72dB total range)
|
|
orient='vertical',
|
|
mode='determinate',
|
|
variable=self.labelframe.level,
|
|
)
|
|
self.labelframe.pb.grid(column=0, row=0)
|
|
|
|
def add_scale(self):
|
|
"""Adds a scale widget to a single label frame"""
|
|
self.scale = ttk.Scale(
|
|
self.labelframe,
|
|
from_=12.0,
|
|
to=-60.0,
|
|
orient='vertical',
|
|
variable=self.labelframe.gain,
|
|
command=self.labelframe.scale_callback,
|
|
length=_configuration.channel_height,
|
|
)
|
|
self.scale.grid(column=1, row=0)
|
|
self.scale.bind('<Double-Button-1>', self.labelframe.reset_gain)
|
|
self.scale.bind('<Button-1>', self.labelframe.scale_press)
|
|
self.scale.bind('<ButtonRelease-1>', self.labelframe.scale_release)
|
|
self.scale.bind(
|
|
'<MouseWheel>',
|
|
partial(
|
|
self.labelframe.pause_updates,
|
|
self.labelframe._on_mousewheel,
|
|
),
|
|
)
|
|
|
|
def add_gain_label(self):
|
|
self.labelframe.gain_label = ttk.Label(
|
|
self.labelframe,
|
|
textvariable=self.labelframe.gainlabel,
|
|
)
|
|
self.labelframe.gain_label.grid(column=0, row=1, columnspan=2)
|
|
|
|
def add_mute_button(self):
|
|
"""Adds a mute button widget to a single label frame"""
|
|
self.button_mute = ttk.Checkbutton(
|
|
self.labelframe,
|
|
text='MUTE',
|
|
command=partial(self.labelframe.pause_updates, self.labelframe.toggle_mute),
|
|
style=f'{"Toggle.TButton" if _configuration.themes_enabled else f"{self.identifier}Mute{self.index}.TButton"}',
|
|
variable=self.labelframe.mute,
|
|
)
|
|
self.button_mute.grid(column=0, row=2, columnspan=2)
|
|
|
|
def add_conf_button(self):
|
|
self.button_conf = ttk.Checkbutton(
|
|
self.labelframe,
|
|
text='CONFIG',
|
|
command=self.labelframe.open_config,
|
|
style=f'{"Toggle.TButton" if _configuration.themes_enabled else f"{self.identifier}Conf{self.index}.TButton"}',
|
|
variable=self.labelframe.conf,
|
|
)
|
|
self.button_conf.grid(column=0, row=3, columnspan=2)
|
|
|
|
def add_on_button(self):
|
|
self.button_on = ttk.Checkbutton(
|
|
self.labelframe,
|
|
text='ON',
|
|
command=partial(self.labelframe.pause_updates, self.labelframe.set_on),
|
|
style=f'{"Toggle.TButton" if _configuration.themes_enabled else f"{self.identifier}On{self.index}.TButton"}',
|
|
variable=self.labelframe.on,
|
|
)
|
|
self.button_on.grid(column=0, row=2, columnspan=2)
|
|
|
|
def teardown(self):
|
|
self.labelframe.grid_remove()
|
|
|
|
|
|
class ChannelConfigFrameBuilder(AbstractBuilder):
|
|
"""Responsible for building channel configframe widgets"""
|
|
|
|
def __init__(self, configframe):
|
|
self.configframe = configframe
|
|
(
|
|
self.configframe.phys_in,
|
|
self.configframe.virt_in,
|
|
) = self.configframe.parent.kind.ins
|
|
(
|
|
self.configframe.phys_out,
|
|
self.configframe.virt_out,
|
|
) = self.configframe.parent.kind.outs
|
|
|
|
def setup(self):
|
|
"register configframe as observable"
|
|
pass
|
|
|
|
def teardown(self):
|
|
"""Deregister as observable, then destroy frame"""
|
|
self.configframe.parent.subject.remove(self.configframe)
|
|
self.configframe.destroy()
|
|
|
|
def grid_configure(self):
|
|
[
|
|
child.grid_configure(padx=1, pady=1, sticky=(tk.W, tk.E))
|
|
for child in self.configframe.winfo_children()
|
|
if isinstance(child, ttk.Checkbutton)
|
|
]
|
|
self.configframe.grid(sticky=(tk.W))
|
|
[
|
|
self.configframe.columnconfigure(i, minsize=_configuration.channel_width)
|
|
for i in range(self.configframe.phys_out + self.configframe.virt_out)
|
|
]
|
|
|
|
|
|
class StripConfigFrameBuilder(ChannelConfigFrameBuilder):
|
|
"""Responsible for building channel configframe widgets"""
|
|
|
|
def setup(self):
|
|
if self.configframe.parent.kind.name == 'basic':
|
|
self.configframe.slider_params = ('audibility',)
|
|
self.configframe.slider_vars = (tk.DoubleVar(),)
|
|
else:
|
|
self.configframe.slider_params = ('comp.knob', 'gate.knob', 'limit')
|
|
self.configframe.slider_vars = [
|
|
tk.DoubleVar() for _ in self.configframe.slider_params
|
|
]
|
|
|
|
self.configframe.phys_out_params = [
|
|
f'A{i + 1}' for i in range(self.configframe.phys_out)
|
|
]
|
|
self.configframe.phys_out_params_vars = [
|
|
tk.BooleanVar() for _ in self.configframe.phys_out_params
|
|
]
|
|
|
|
self.configframe.virt_out_params = [
|
|
f'B{i + 1}' for i in range(self.configframe.virt_out)
|
|
]
|
|
self.configframe.virt_out_params_vars = [
|
|
tk.BooleanVar() for _ in self.configframe.virt_out_params
|
|
]
|
|
|
|
self.configframe.bool_params = ('mono', 'solo')
|
|
self.configframe.bool_param_vars = list(
|
|
tk.BooleanVar() for _ in self.configframe.bool_params
|
|
)
|
|
|
|
if self.configframe.parent.kind.name in ('banana', 'potato'):
|
|
if self.configframe.index == self.configframe.phys_in:
|
|
self.configframe.params = list(
|
|
map(lambda x: x.replace('mono', 'mc'), self.configframe.bool_params)
|
|
)
|
|
if self.configframe.parent.kind.name == 'banana':
|
|
pass
|
|
# karaoke modes not in RT Packet yet. May implement in future
|
|
"""
|
|
if self.index == self.phys_in + 1:
|
|
self.params = list(
|
|
map(lambda x: x.replace("mono", "k"), self.params)
|
|
)
|
|
self.param_vars[self.params.index("k")] = tk.IntVar
|
|
"""
|
|
else:
|
|
if (
|
|
self.configframe.index
|
|
== self.configframe.phys_in + self.configframe.virt_in - 1
|
|
):
|
|
self.configframe.params = list(
|
|
map(
|
|
lambda x: x.replace('mono', 'mc'),
|
|
self.configframe.bool_params,
|
|
)
|
|
)
|
|
|
|
def create_comp_slider(self):
|
|
comp_label = ttk.Label(self.configframe, text='Comp')
|
|
comp_scale = ttk.Scale(
|
|
self.configframe,
|
|
from_=0.0,
|
|
to=10.0,
|
|
orient='horizontal',
|
|
length=_configuration.channel_width,
|
|
variable=self.configframe.slider_vars[
|
|
self.configframe.slider_params.index('comp.knob')
|
|
],
|
|
command=partial(self.configframe.scale_callback, 'comp.knob'),
|
|
)
|
|
comp_scale.bind(
|
|
'<Double-Button-1>', partial(self.configframe.reset_scale, 'comp.knob', 0)
|
|
)
|
|
comp_scale.bind('<Button-1>', self.configframe.scale_press)
|
|
comp_scale.bind('<ButtonRelease-1>', self.configframe.scale_release)
|
|
comp_scale.bind('<Enter>', partial(self.configframe.scale_enter, 'comp.knob'))
|
|
comp_scale.bind('<Leave>', self.configframe.scale_leave)
|
|
|
|
comp_label.grid(column=0, row=0)
|
|
comp_scale.grid(column=1, row=0)
|
|
|
|
def create_gate_slider(self):
|
|
gate_label = ttk.Label(self.configframe, text='Gate')
|
|
gate_scale = ttk.Scale(
|
|
self.configframe,
|
|
from_=0.0,
|
|
to=10.0,
|
|
orient='horizontal',
|
|
length=_configuration.channel_width,
|
|
variable=self.configframe.slider_vars[
|
|
self.configframe.slider_params.index('gate.knob')
|
|
],
|
|
command=partial(self.configframe.scale_callback, 'gate.knob'),
|
|
)
|
|
gate_scale.bind(
|
|
'<Double-Button-1>', partial(self.configframe.reset_scale, 'gate.knob', 0)
|
|
)
|
|
gate_scale.bind('<Button-1>', self.configframe.scale_press)
|
|
gate_scale.bind('<ButtonRelease-1>', self.configframe.scale_release)
|
|
gate_scale.bind('<Enter>', partial(self.configframe.scale_enter, 'gate.knob'))
|
|
gate_scale.bind('<Leave>', self.configframe.scale_leave)
|
|
|
|
gate_label.grid(column=2, row=0)
|
|
gate_scale.grid(column=3, row=0)
|
|
|
|
def create_limit_slider(self):
|
|
limit_label = ttk.Label(self.configframe, text='Limit')
|
|
limit_scale = ttk.Scale(
|
|
self.configframe,
|
|
from_=-40,
|
|
to=12,
|
|
orient='horizontal',
|
|
length=_configuration.channel_width,
|
|
variable=self.configframe.slider_vars[
|
|
self.configframe.slider_params.index('limit')
|
|
],
|
|
command=partial(self.configframe.scale_callback, 'limit'),
|
|
)
|
|
limit_scale.bind(
|
|
'<Double-Button-1>', partial(self.configframe.reset_scale, 'limit', 12)
|
|
)
|
|
limit_scale.bind('<Button-1>', self.configframe.scale_press)
|
|
limit_scale.bind('<ButtonRelease-1>', self.configframe.scale_release)
|
|
limit_scale.bind('<Enter>', partial(self.configframe.scale_enter, 'limit'))
|
|
limit_scale.bind('<Leave>', self.configframe.scale_leave)
|
|
|
|
limit_label.grid(column=4, row=0)
|
|
limit_scale.grid(column=5, row=0)
|
|
|
|
def create_audibility_slider(self):
|
|
aud_label = ttk.Label(self.configframe, text='Audibility')
|
|
aud_scale = ttk.Scale(
|
|
self.configframe,
|
|
from_=0.0,
|
|
to=10.0,
|
|
orient='horizontal',
|
|
length=_configuration.channel_width,
|
|
variable=self.configframe.slider_vars[
|
|
self.configframe.slider_params.index('audibility')
|
|
],
|
|
command=partial(self.configframe.scale_callback, 'audibility'),
|
|
)
|
|
aud_scale.bind(
|
|
'<Double-Button-1>', partial(self.configframe.reset_scale, 'audibility', 0)
|
|
)
|
|
aud_scale.bind('<Button-1>', self.configframe.scale_press)
|
|
aud_scale.bind('<ButtonRelease-1>', self.configframe.scale_release)
|
|
aud_scale.bind('<Enter>', partial(self.configframe.scale_enter, 'audibility'))
|
|
aud_scale.bind('<Leave>', self.configframe.scale_leave)
|
|
|
|
aud_label.grid(column=0, row=0)
|
|
aud_scale.grid(column=1, row=0)
|
|
|
|
def create_a_buttons(self):
|
|
self.configframe.a_buttons = [
|
|
ttk.Checkbutton(
|
|
self.configframe,
|
|
text=param,
|
|
command=partial(
|
|
self.configframe.pause_updates, self.configframe.toggle_a, param
|
|
),
|
|
style=f'{"Toggle.TButton" if _configuration.themes_enabled else f"{param}.TButton"}',
|
|
variable=self.configframe.phys_out_params_vars[
|
|
self.configframe.phys_out_params.index(param)
|
|
],
|
|
)
|
|
for param in self.configframe.phys_out_params
|
|
]
|
|
[
|
|
button.grid(
|
|
column=i,
|
|
row=1,
|
|
)
|
|
for i, button in enumerate(self.configframe.a_buttons)
|
|
]
|
|
|
|
def create_b_buttons(self):
|
|
self.configframe.b_buttons = [
|
|
ttk.Checkbutton(
|
|
self.configframe,
|
|
text=param,
|
|
command=partial(
|
|
self.configframe.pause_updates, self.configframe.toggle_b, param
|
|
),
|
|
style=f'{"Toggle.TButton" if _configuration.themes_enabled else f"{param}.TButton"}',
|
|
variable=self.configframe.virt_out_params_vars[
|
|
self.configframe.virt_out_params.index(param)
|
|
],
|
|
)
|
|
for param in self.configframe.virt_out_params
|
|
]
|
|
[
|
|
button.grid(
|
|
column=len(self.configframe.a_buttons) + i,
|
|
row=1,
|
|
)
|
|
for i, button in enumerate(self.configframe.b_buttons)
|
|
]
|
|
|
|
def create_param_buttons(self):
|
|
param_buttons = [
|
|
ttk.Checkbutton(
|
|
self.configframe,
|
|
text=param,
|
|
command=partial(
|
|
self.configframe.pause_updates, self.configframe.toggle_p, param
|
|
),
|
|
style=f'{"Toggle.TButton" if _configuration.themes_enabled else f"{param}.TButton"}',
|
|
variable=self.configframe.bool_param_vars[i],
|
|
)
|
|
for i, param in enumerate(self.configframe.bool_params)
|
|
]
|
|
[
|
|
button.grid(
|
|
column=i,
|
|
row=2,
|
|
)
|
|
for i, button in enumerate(param_buttons)
|
|
]
|
|
|
|
|
|
class BusConfigFrameBuilder(ChannelConfigFrameBuilder):
|
|
"""Responsible for building channel configframe widgets"""
|
|
|
|
def setup(self):
|
|
# fmt: off
|
|
self.configframe.bus_mode_map = {
|
|
"normal": "Normal",
|
|
"amix": "Mix Down A",
|
|
"bmix": "Mix Down B",
|
|
"repeat": "Stereo Repeat",
|
|
"composite": "Composite",
|
|
"tvmix": "Up Mix TV",
|
|
"upmix21": "Up Mix 2.1",
|
|
"upmix41": "Up Mix 4.1",
|
|
"upmix61": "Up Mix 6.1",
|
|
"centeronly": "Center Only",
|
|
"lfeonly": "LFE Only",
|
|
"rearonly": "Rear Only",
|
|
}
|
|
self.configframe.bus_mode_map_reverse = {v: k for k, v in self.configframe.bus_mode_map.items()}
|
|
self.configframe.bus_modes = list(self.configframe.bus_mode_map.keys())
|
|
# fmt: on
|
|
self.configframe.int_params = ('mono',)
|
|
self.configframe.int_param_vars = [
|
|
tk.IntVar(value=getattr(self.configframe.target, param))
|
|
for param in self.configframe.int_params
|
|
]
|
|
self.configframe.mono_modes = ['mono: off', 'mono: on', 'stereo reverse']
|
|
self.configframe.bus_mono_label_text = tk.StringVar(
|
|
value=self.configframe.mono_modes[self.configframe.target.mono]
|
|
)
|
|
self.configframe.bool_params = ('eq.on', 'eq.ab')
|
|
self.configframe.bool_param_vars = [
|
|
tk.BooleanVar() for _ in self.configframe.bool_params
|
|
]
|
|
self.configframe.bus_mode_label_text = tk.StringVar(
|
|
value=self.configframe.bus_mode_map[self.configframe.current_bus_mode()]
|
|
)
|
|
|
|
def create_bus_mode_button(self):
|
|
self.configframe.busmode_button = ttk.Button(
|
|
self.configframe, textvariable=self.configframe.bus_mode_label_text
|
|
)
|
|
self.configframe.busmode_button.grid(
|
|
column=0, row=0, columnspan=2, sticky=(tk.W)
|
|
)
|
|
self.configframe.busmode_button.bind(
|
|
'<Button-1>',
|
|
partial(
|
|
self.configframe.pause_updates, self.configframe.rotate_bus_modes_right
|
|
),
|
|
)
|
|
self.configframe.busmode_button.bind(
|
|
'<Button-3>',
|
|
partial(
|
|
self.configframe.pause_updates, self.configframe.rotate_bus_modes_left
|
|
),
|
|
)
|
|
|
|
def create_bus_mono_button(self):
|
|
self.configframe.mono_button = ttk.Button(
|
|
self.configframe, textvariable=self.configframe.bus_mono_label_text
|
|
)
|
|
self.configframe.mono_button.bind(
|
|
'<Button-1>',
|
|
partial(self.configframe.pause_updates, self.configframe.rotate_mono_right),
|
|
)
|
|
self.configframe.mono_button.bind(
|
|
'<Button-3>',
|
|
partial(self.configframe.pause_updates, self.configframe.rotate_mono_left),
|
|
)
|
|
self.configframe.mono_button.grid(column=0, row=1, sticky=(tk.W))
|
|
|
|
def create_param_buttons(self):
|
|
param_buttons = [
|
|
ttk.Checkbutton(
|
|
self.configframe,
|
|
text=param,
|
|
command=partial(
|
|
self.configframe.pause_updates, self.configframe.toggle_p, param
|
|
),
|
|
style=f'{"Toggle.TButton" if _configuration.themes_enabled else f"{param}.TButton"}',
|
|
variable=self.configframe.bool_param_vars[i],
|
|
)
|
|
for i, param in enumerate(self.configframe.bool_params)
|
|
]
|
|
[
|
|
button.grid(
|
|
column=i + 1,
|
|
row=1,
|
|
)
|
|
for i, button in enumerate(param_buttons)
|
|
]
|