예제 #1
0
def start_main() -> None:
    """Starts the TK and Trio loops.

    See https://github.com/richardsheridan/trio-guest/.
    """
    def tk_func() -> None:
        """Called to execute the callback."""
        queue.popleft()()

    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)

    queue: collections.deque[Callable[[], Any]] = collections.deque()
    tk_func_name = TK_ROOT.register(tk_func)

    LOGGER.debug('Starting Trio loop.')
    trio.lowlevel.start_guest_run(
        app_main,
        run_sync_soon_threadsafe=run_sync_soon_threadsafe,
        run_sync_soon_not_threadsafe=run_sync_soon_not_threadsafe,
        done_callback=done_callback,
    )
    TK_ROOT.mainloop()
예제 #2
0
파일: BEE2.py 프로젝트: BEEmod/BEE2.4
def start_main() -> None:
    LOGGER.debug('Starting Trio loop.')
    trio.lowlevel.start_guest_run(
        app_main,
        run_sync_soon_threadsafe=TK_ROOT.after_idle,
        done_callback=done_callback,
    )
    TK_ROOT.mainloop()
예제 #3
0
def run_screen(
    pipe_send: multiprocessing.connection.Connection,
    pipe_rec: multiprocessing.connection.Connection,
    # Pass in various bits of translated text
    # so we don't need to do it here.
    translations,
):
    """Runs in the other process, with an end of a pipe for input."""
    global PIPE_REC, PIPE_SEND
    PIPE_SEND = pipe_send
    PIPE_REC = pipe_rec
    TRANSLATION.update(translations)

    force_ontop = True

    def check_queue():
        """Update stages from the parent process."""
        nonlocal force_ontop
        had_values = False
        while PIPE_REC.poll():  # Pop off all the values.
            had_values = True
            operation, scr_id, args = PIPE_REC.recv()
            if operation == 'init':
                # Create a new loadscreen.
                is_main, title, stages = args
                screen = (SplashScreen if is_main else LoadScreen)(scr_id,
                                                                   title,
                                                                   force_ontop,
                                                                   stages)
                SCREENS[scr_id] = screen
            elif operation == 'set_force_ontop':
                [force_ontop] = args
                for screen in SCREENS.values():
                    screen.win.attributes('-topmost', force_ontop)
            else:
                try:
                    func = getattr(SCREENS[scr_id], 'op_' + operation)
                except AttributeError:
                    raise ValueError('Bad command "{}"!'.format(operation))
                try:
                    func(*args)
                except Exception:
                    raise Exception(operation)

        # Continually re-run this function in the TK loop.
        # If we didn't find anything in the pipe, wait longer.
        # Otherwise we hog the CPU.
        TK_ROOT.after(1 if had_values else 200, check_queue)

    TK_ROOT.after(10, check_queue)
    TK_ROOT.mainloop()  # Infinite loop, until the entire process tree quits.
예제 #4
0
if __name__ == '__main__':
    srctools.logger.init_logging()
    LOGGER = srctools.logger.get_logger('BEE2')
    init(True, log_level='DEBUG')

    # Generate a bunch of log messages to test the window.
    def errors():
        # Use a generator to easily run these functions with a delay.
        yield LOGGER.info('Info Message')
        yield LOGGER.critical('Critical Message')
        yield LOGGER.warning('Warning')

        try:
            raise ValueError('An error')
        except ValueError:
            yield LOGGER.exception('Error message')

        yield LOGGER.warning('Post-Exception warning')
        yield LOGGER.info('Info')
        yield LOGGER.debug('Debug Message')

    err_iterator = errors()

    def next_error():
        # Use False since functions return None usually
        if next(err_iterator, False) is not False:
            TK_ROOT.after(1000, next_error)

    TK_ROOT.after(1000, next_error)
    TK_ROOT.mainloop()
예제 #5
0
파일: dragdrop.py 프로젝트: BEEmod/BEE2.4
def test() -> None:
    """Test the GUI."""
    from BEE2_config import GEN_OPTS
    from packages import find_packages, PACKAGE_SYS

    # Setup images to read from packages.
    print('Loading packages for images.')
    GEN_OPTS.load()
    find_packages(GEN_OPTS['Directories']['package'])
    img.load_filesystems(PACKAGE_SYS)
    print('Done.')

    left_frm = ttk.Frame(TK_ROOT)
    right_canv = tkinter.Canvas(TK_ROOT)

    left_frm.grid(row=0, column=0, sticky='NSEW', padx=8)
    right_canv.grid(row=0, column=1, sticky='NSEW', padx=8)
    TK_ROOT.rowconfigure(0, weight=1)
    TK_ROOT.columnconfigure(1, weight=1)

    slot_dest = []
    slot_src = []

    class TestItem:
        def __init__(
            self,
            name: str,
            pak_id: str,
            icon: str,
            group: str=None,
            group_icon: str=None,
        ) -> None:
            self.name = name
            self.dnd_icon = img.Handle.parse_uri(utils.PackagePath(pak_id, ('items/clean/{}.png'.format(icon))), 64, 64)
            self.dnd_group = group
            if group_icon:
                self.dnd_group_icon = img.Handle.parse_uri(utils.PackagePath(pak_id, 'items/clean/{}.png'.format(group_icon)), 64, 64)

        def __repr__(self) -> str:
            return '<Item {}>'.format(self.name)

    manager = Manager[TestItem](TK_ROOT, config_icon=True)

    def func(ev):
        def call(slot):
            print('Cback: ', ev, slot)
        return call

    for event in Event:
        manager.reg_callback(event, func(event))

    PAK_CLEAN = 'BEE2_CLEAN_STYLE'
    PAK_ELEM = 'VALVE_TEST_ELEM'
    items = [
        TestItem('Dropper', PAK_CLEAN, 'dropper'),
        TestItem('Entry', PAK_CLEAN, 'entry_door'),
        TestItem('Exit', PAK_CLEAN, 'exit_door'),
        TestItem('Large Obs', PAK_CLEAN, 'large_obs_room'),
        TestItem('Faith Plate', PAK_ELEM, 'faithplate'),

        TestItem('Standard Cube', PAK_ELEM, 'cube', 'ITEM_CUBE', 'cubes'),
        TestItem('Companion Cube', PAK_ELEM, 'companion_cube', 'ITEM_CUBE', 'cubes'),
        TestItem('Reflection Cube', PAK_ELEM, 'reflection_cube', 'ITEM_CUBE', 'cubes'),
        TestItem('Edgeless Cube', PAK_ELEM, 'edgeless_safety_cube', 'ITEM_CUBE', 'cubes'),
        TestItem('Franken Cube', PAK_ELEM, 'frankenturret', 'ITEM_CUBE', 'cubes'),

        TestItem('Repulsion Gel', PAK_ELEM, 'paintsplat_bounce', 'ITEM_PAINT_SPLAT', 'paints'),
        TestItem('Propulsion Gel', PAK_ELEM, 'paintsplat_speed', 'ITEM_PAINT_SPLAT', 'paints'),
        TestItem('Reflection Gel', PAK_ELEM, 'paintsplat_reflection', 'ITEM_PAINT_SPLAT', 'paints'),
        TestItem('Conversion Gel', PAK_ELEM, 'paintsplat_portal', 'ITEM_PAINT_SPLAT', 'paints'),
        TestItem('Cleansing Gel', PAK_ELEM, 'paintsplat_water', 'ITEM_PAINT_SPLAT', 'paints'),
    ]

    for y in range(8):
        for x in range(4):
            slot = manager.slot(left_frm, source=False, label=(format(x + 4*y, '02') if y < 3 else ''))
            slot.grid(column=x, row=y, padx=1, pady=1)
            slot_dest.append(slot)

    for i, item in enumerate(items):
            slot = manager.slot(right_canv, source=True, label=format(i+1, '02'))
            slot_src.append(slot)
            slot.contents = item

    def configure(e):
        manager.flow_slots(right_canv, slot_src)

    configure(None)
    right_canv.bind('<Configure>', configure)

    ttk.Button(
        TK_ROOT,
        text='Debug',
        command=lambda: print('Dest:', [slot.contents for slot in slot_dest])
    ).grid(row=2, column=0)
    ttk.Button(
        TK_ROOT,
        text='Debug',
        command=lambda: print('Source:', [slot.contents for slot in slot_src])
    ).grid(row=2, column=1)

    name_lbl = ttk.Label(TK_ROOT, text='')
    name_lbl.grid(row=3, column=0)

    def enter(slot):
        if slot.contents is not None:
            name_lbl['text'] = 'Name: ' + slot.contents.name

    def exit(slot):
        name_lbl['text'] = ''

    manager.reg_callback(Event.HOVER_ENTER, enter)
    manager.reg_callback(Event.HOVER_EXIT, exit)
    manager.reg_callback(Event.CONFIG, lambda slot: messagebox.showinfo('Hello World', str(slot.contents)))

    TK_ROOT.deiconify()
    TK_ROOT.mainloop()
예제 #6
0
def run_background(
    pipe_send: multiprocessing.connection.Connection,
    pipe_rec: multiprocessing.connection.Connection,
    log_pipe_send: multiprocessing.connection.Connection,
    log_pipe_rec: multiprocessing.connection.Connection,
    # Pass in various bits of translated text
    # so we don't need to do it here.
    translations: dict,
):
    """Runs in the other process, with an end of a pipe for input."""
    global PIPE_REC, PIPE_SEND
    PIPE_SEND = pipe_send
    PIPE_REC = pipe_rec
    TRANSLATION.update(translations)

    force_ontop = True

    log_window = LogWindow(translations, log_pipe_send)

    def check_queue():
        """Update stages from the parent process."""
        nonlocal force_ontop
        had_values = False
        try:
            while PIPE_REC.poll():  # Pop off all the values.
                had_values = True
                operation, scr_id, args = PIPE_REC.recv()
                if operation == 'init':
                    # Create a new loadscreen.
                    is_main, title, stages = args
                    screen = (SplashScreen if is_main else LoadScreen)(
                        scr_id, title, force_ontop, stages)
                    SCREENS[scr_id] = screen
                elif operation == 'quit_daemon':
                    # Shutdown.
                    TK_ROOT.quit()
                    return
                elif operation == 'set_force_ontop':
                    [force_ontop] = args
                    for screen in SCREENS.values():
                        screen.win.attributes('-topmost', force_ontop)
                else:
                    try:
                        func = getattr(SCREENS[scr_id], 'op_' + operation)
                    except AttributeError:
                        raise ValueError(f'Bad command "{operation}"!')
                    try:
                        func(*args)
                    except Exception:
                        raise Exception(operation)
            while log_pipe_rec.poll():
                log_window.handle(log_pipe_rec.recv())
        except BrokenPipeError:
            # A pipe failed, means the main app quit. Terminate ourselves.
            print('BG: Lost pipe!')
            TK_ROOT.quit()
            return

        # Continually re-run this function in the TK loop.
        # If we didn't find anything in the pipe, wait longer.
        # Otherwise we hog the CPU.
        TK_ROOT.after(1 if had_values else 200, check_queue)

    TK_ROOT.after(10, check_queue)
    TK_ROOT.mainloop()  # Infinite loop, until the entire process tree quits.