def run_sync_soon_threadsafe(func: Callable[[], Any]) -> None: """Run the specified func in the next loop, from other threads.""" queue.append(func) TK_ROOT.call("after", "idle", tk_func_name)
def run_sync_soon_not_threadsafe(func: Callable[[], Any]) -> None: """Run the specified func in the next loop.""" queue.append(func) # The zero here apparently avoids blocking the event loop if an endless stream of # callbacks is triggered. TK_ROOT.call("after", "idle", "after", 0, tk_func_name)
def init(cback: Callable[[dict[str, str]], None]) -> None: """Build the properties window widgets.""" global callback callback = cback win.title("BEE2") win.resizable(False, False) tk_tools.set_window_icon(win) win.protocol("WM_DELETE_WINDOW", exit_win) if utils.MAC: # Switch to use the 'modal' window style on Mac. TK_ROOT.call('::tk::unsupported::MacWindowStyle', 'style', win, 'moveableModal', '') # Stop our init from triggering UI sounds. sound.block_fx() frame = ttk.Frame(win, padding=10) frame.grid(row=0, column=0, sticky='NSEW') frame.rowconfigure(0, weight=1) frame.columnconfigure(0, weight=1) labels['noOptions'] = ttk.Label(frame, text=gettext('No Properties available!')) widgets['saveButton'] = ttk.Button(frame, text=gettext('Close'), command=exit_win) widgets['titleLabel'] = ttk.Label(frame, text='') widgets['titleLabel'].grid(columnspan=9) widgets['div_1'] = ttk.Separator(frame, orient="vertical") widgets['div_2'] = ttk.Separator(frame, orient="vertical") widgets['div_h'] = ttk.Separator(frame, orient="horizontal") for key, (prop_type, prop_name) in PROP_TYPES.items(): # Translate property names from Valve's files. if prop_name.startswith('PORTAL2_'): prop_name = gameMan.translate(prop_name) + ':' labels[key] = ttk.Label(frame, text=prop_name) if prop_type is PropTypes.CHECKBOX: values[key] = tk.IntVar(value=DEFAULTS[key]) out_values[key] = srctools.bool_as_int(DEFAULTS[key]) widgets[key] = ttk.Checkbutton( frame, variable=values[key], command=func_partial(set_check, key), ) widgets[key].bind('<Return>', func_partial( toggle_check, key, values[key], )) elif prop_type is PropTypes.OSCILLATE: values[key] = tk.IntVar(value=DEFAULTS[key]) out_values[key] = srctools.bool_as_int(DEFAULTS[key]) widgets[key] = ttk.Checkbutton( frame, variable=values[key], command=func_partial(save_rail, key), ) elif prop_type is PropTypes.PANEL: frm = ttk.Frame(frame) widgets[key] = frm values[key] = tk.StringVar(value=DEFAULTS[key]) for pos, (angle, disp_angle) in enumerate(PANEL_ANGLES): ttk.Radiobutton( frm, variable=values[key], value=str(angle), text=gameMan.translate(disp_angle), command=func_partial(save_angle, key, angle), ).grid(row=0, column=pos) frm.columnconfigure(pos, weight=1) elif prop_type is PropTypes.GELS: frm = ttk.Frame(frame) widgets[key] = frm values[key] = tk.IntVar(value=DEFAULTS[key]) for pos, text in enumerate(PAINT_OPTS): ttk.Radiobutton( frm, variable=values[key], value=pos, text=gameMan.translate(text), command=func_partial(save_paint, key, pos), ).grid(row=0, column=pos) frm.columnconfigure(pos, weight=1) out_values[key] = str(DEFAULTS[key]) elif prop_type is PropTypes.PISTON: widgets[key] = pist_scale = ttk.Scale( frame, from_=0, to=4, orient="horizontal", command=func_partial(save_pist, key), ) values[key] = DEFAULTS[key] out_values[key] = str(DEFAULTS[key]) if ((key == 'toplevel' and DEFAULTS['startup']) or (key == 'bottomlevel' and not DEFAULTS['startup'])): pist_scale.set( max(DEFAULTS['toplevel'], DEFAULTS['bottomlevel'])) if ((key == 'toplevel' and not DEFAULTS['startup']) or (key == 'bottomlevel' and DEFAULTS['startup'])): pist_scale.set( min(DEFAULTS['toplevel'], DEFAULTS['bottomlevel'])) elif prop_type is PropTypes.TIMER: widgets[key] = ttk.Scale( frame, from_=0, to=30, orient="horizontal", command=func_partial(save_tim, key), ) values[key] = DEFAULTS[key] values['startup'] = DEFAULTS['startup']