Example #1
0
    def test_cjk_forms(self):
        """
        Check form widgets work with CJK characters.
        """
        # Create a dummy screen.
        screen = MagicMock(spec=Screen, colours=8, unicode_aware=False)
        scene = MagicMock(spec=Scene)
        canvas = Canvas(screen, 10, 40, 0, 0)

        # Create the form we want to test.
        form = Frame(canvas, canvas.height, canvas.width, has_border=False)
        layout = Layout([100], fill_frame=True)
        mc_list = MultiColumnListBox(4, [3, 5, 0], [
            (["1", "2", "3"], 1),
            ([u"你", u"確", u"定"], 2),
        ],
                                     titles=[u"你確定嗎?", u"你確定嗎?", u"你確定嗎?"])
        text = Text()
        text_box = TextBox(3)
        form.add_layout(layout)
        layout.add_widget(mc_list)
        layout.add_widget(text)
        layout.add_widget(text_box)
        form.fix()
        form.register_scene(scene)
        form.reset()

        # Set some interesting values...
        text.value = u"你確定嗎? 你確定嗎? 你確定嗎?"
        text_box.value = [u"你確定嗎", u"?"]

        # Check that the CJK characters render correctly - no really this is correctly aligned!
        self.maxDiff = None
        form.update(0)
        self.assert_canvas_equals(
            canvas, u"你你 你你確確 你你確確定定嗎嗎??                      \n" +
            u"1  2    3                               \n" +
            u"你你 確確   定定                              \n" +
            u"                                        \n" +
            u"你你確確定定嗎嗎?? 你你確確定定嗎嗎?? 你你確確定定嗎嗎??        \n" +
            u"你你確確定定嗎嗎                                \n" +
            u"??                                      \n" +
            u"                                        \n" +
            u"                                        \n" +
            u"                                        \n")

        # Check that mouse input takes into account the glyph width
        self.process_mouse(form, [(5, 4, MouseEvent.LEFT_CLICK)])
        self.process_keys(form, ["b"])
        self.process_mouse(form, [(2, 4, MouseEvent.LEFT_CLICK)])
        self.process_keys(form, ["p"])
        form.save()
        self.assertEqual(text.value, u"你p確b定嗎? 你確定嗎? 你確定嗎?")

        self.process_mouse(form, [(2, 5, MouseEvent.LEFT_CLICK)])
        self.process_keys(form, ["p"])
        self.process_mouse(form, [(1, 6, MouseEvent.LEFT_CLICK)])
        self.process_keys(form, ["b"])
        form.save()
        self.assertEqual(text_box.value, [u"你p確定嗎", u"b?"])
Example #2
0
    def test_disabled_text(self):
        """
        Check disabled TextBox can be used for pre-formatted output.
        """
        # Create a dummy screen.
        screen = MagicMock(spec=Screen, colours=8, unicode_aware=False)
        scene = MagicMock(spec=Scene)
        canvas = Canvas(screen, 10, 40, 0, 0)

        # Create the form we want to test.
        form = Frame(canvas, canvas.height, canvas.width, has_border=False)
        layout = Layout([100], fill_frame=True)
        form.add_layout(layout)
        text_box = TextBox(1, as_string=True)
        text_box.disabled = True
        layout.add_widget(text_box)
        form.fix()
        form.register_scene(scene)
        form.reset()

        # Check that input has no effect on the programmed value.
        text_box.value = "A test"
        self.process_keys(form, ["A"])
        form.save()
        self.assertEqual(text_box.value, "A test")

        # Check that we can provide a custom colour.  Since the default palette has no "custom"
        # key, this will throw an exception.
        self.assertEqual(text_box._pick_colours("blah"),
                         form.palette["disabled"])
        with self.assertRaises(KeyError) as cm:
            text_box.custom_colour = "custom"
            text_box._pick_colours("blah")
        self.assertIn("custom", str(cm.exception))
Example #3
0
def DeathMenu(game, screen, debug, oldpalette):
    None

    def endgame():
        screen.close()
        quit()
        sys.exit(0)
        None

    def Restart():
        game = GameState.GameState()
        MainMenu(game, screen, debug, oldpalette)
        None

    Dmenu = Frame(screen,
                  screen.height * 2 // 3,
                  screen.width * 2 // 3,
                  hover_focus=True,
                  has_border=True,
                  title="YOU HAVE DIED",
                  reduce_cpu=False)

    mapping = Layout([100], fill_frame=True)

    for entry in Dmenu.palette:
        if entry != "focus_button":
            Dmenu.palette[entry] = (1, 1, 1)
        else:
            Dmenu.palette[entry] = (0, 1, 5)
    Dmenu.add_layout(mapping)
    mapping.add_widget(
        Label(str("Your Final Score Is:  " + str(game.score)), 1))
    bottomrow = Layout([1, 1, 1, 1])
    Dmenu.add_layout(bottomrow)
    bottomrow.add_widget(Button("Exit", endgame), 1)
    bottomrow.add_widget(Button("Restart", Restart), 3)
    Dmenu.fix()

    #return Mmenu
    #Mmenu._on_pic

    Scenes = [Scene([Dmenu], -1)]

    screen.play(Scenes)
    return Dmenu.data
Example #4
0
def demo(screen, scene):
    frame = Frame(screen,
                  screen.height // 3,
                  screen.width // 3,
                  hover_focus=True,
                  has_border=False,
                  title="Main Menu")

    frame.palette = palette

    layout3 = Layout([100])
    frame.add_layout(layout3)

    layout3.add_widget(Label("Test"), 0)
    layout3.add_widget(Divider(draw_line=False))

    layout1 = Layout([100], fill_frame=True)
    frame.add_layout(layout1)

    layout1.add_widget(
        ListBox(Widget.FILL_FRAME, [("One", 1), ("Two", 3), ("Three", 2),
                                    ("Four", 4), ("Five", 5), ("Six", 6),
                                    ("Seven", 7), ("Eight", 8), ("Nine", 9),
                                    ("Ten", 10), ("Eleven", 11),
                                    ("Twelve", 12), ("Thirteen", 13),
                                    ("Fourteen", 14), ("Fifteen", 15),
                                    ("Sixteen", 16), ("Seventeen", 17),
                                    ("Eighteen", 18), ("Nineteen", 19),
                                    ("Twenty", 20), ("Loop", 1)],
                name="List Thing"))
    layout1.add_widget(Divider(draw_line=False))

    layout2 = Layout([1, 1, 1, 1])
    frame.add_layout(layout2)

    layout2.add_widget(Button("OK", leave), 1)
    layout2.add_widget(Button("Cancel", leave), 2)

    frame.fix()

    scenes = [Scene([frame], -1, name="Test")]

    screen.play(scenes, stop_on_resize=True, start_scene=scene)
Example #5
0
def demo(screen):
    scenes = []
    frame = Frame(screen, 20, 80, can_scroll=False, title="Sender")
    layout = Layout([40, 10, 40, 10], fill_frame=True)
    frame.add_layout(layout)

    optionen = [("Erster", 1), ("Zweiter", 2)]

    sender = ["Erster hihihihihihi", "Zweiter", "Dritter"]

    for s in sender:
        layout.add_widget(Label(s, align=u'^'))

    layout.add_widget(Label("<<<<", align='<'), 1)

    layout.add_widget(Button("hihi!", None))

    frame.fix()

    effects = [frame]

    scenes.append(Scene(effects, -1))
    screen.play(scenes)
Example #6
0
class TextUi(MpfController):
    """Handles the text-based UI."""

    config_name = "text_ui"

    __slots__ = [
        "start_time", "machine", "_tick_task", "screen", "mpf_process",
        "ball_devices", "switches", "config", "_pending_bcp_connection",
        "_asset_percent", "_player_widgets", "_machine_widgets", "_bcp_status",
        "frame", "layout", "scene", "footer_memory", "switch_widgets",
        "mode_widgets", "ball_device_widgets", "footer_cpu", "footer_mc_cpu",
        "footer_uptime", "delay", "_layout_change"
    ]

    def __init__(self, machine: "MachineController") -> None:
        """Initialize TextUi."""
        super().__init__(machine)
        self.delay = DelayManager(machine)
        self.config = machine.config.get('text_ui', {})

        self.screen = None

        if not machine.options['text_ui'] or not Scene:
            return

        # hack to add themes until https://github.com/peterbrittain/asciimatics/issues/207 is implemented
        THEMES["mpf_theme"] = defaultdict(
            lambda:
            (Screen.COLOUR_WHITE, Screen.A_NORMAL, Screen.COLOUR_BLACK), {
                "active_switch":
                (Screen.COLOUR_BLACK, Screen.A_NORMAL, Screen.COLOUR_GREEN),
                "pf_active":
                (Screen.COLOUR_GREEN, Screen.A_NORMAL, Screen.COLOUR_BLACK),
                "pf_inactive":
                (Screen.COLOUR_WHITE, Screen.A_NORMAL, Screen.COLOUR_BLACK),
                "label":
                (Screen.COLOUR_WHITE, Screen.A_NORMAL, Screen.COLOUR_BLACK),
                "title":
                (Screen.COLOUR_WHITE, Screen.A_NORMAL, Screen.COLOUR_RED),
                "title_exit":
                (Screen.COLOUR_BLACK, Screen.A_NORMAL, Screen.COLOUR_RED),
                "footer_cpu":
                (Screen.COLOUR_CYAN, Screen.A_NORMAL, Screen.COLOUR_BLACK),
                "footer_path":
                (Screen.COLOUR_YELLOW, Screen.A_NORMAL, Screen.COLOUR_BLACK),
                "footer_memory":
                (Screen.COLOUR_GREEN, Screen.A_NORMAL, Screen.COLOUR_BLACK),
                "footer_mc_cpu":
                (Screen.COLOUR_MAGENTA, Screen.A_NORMAL, Screen.COLOUR_BLACK),
            })

        self.start_time = datetime.now()
        self.machine = machine

        self.mpf_process = Process()
        self.ball_devices = list()  # type: List[BallDevice]

        self.switches = {}  # type: Dict[str, Switch]

        self.machine.events.add_handler('init_phase_2', self._init)
        # self.machine.events.add_handler('init_phase_3', self._init2)
        self.machine.events.add_handler('loading_assets',
                                        self._asset_load_change)
        self.machine.events.add_handler('bcp_connection_attempt',
                                        self._bcp_connection_attempt)
        self.machine.events.add_handler('asset_loading_complete',
                                        self._asset_load_complete)
        self.machine.events.add_handler('bcp_clients_connected',
                                        self._bcp_connected)
        self.machine.events.add_handler('shutdown', self.stop)
        self.machine.add_crash_handler(self.stop)
        self.machine.events.add_handler('player_number', self._update_player)
        self.machine.events.add_handler('player_ball', self._update_player)
        self.machine.events.add_handler('player_score', self._update_player)
        self.machine.events.add_handler('ball_ended', self._update_player)

        self._pending_bcp_connection = False
        self._asset_percent = 0
        self._bcp_status = (0, 0, 0)  # type: Tuple[float, int, int]
        self.switch_widgets = []  # type: List[Widget]
        self.mode_widgets = []  # type: List[Widget]
        self.ball_device_widgets = []  # type: List[Widget]
        self._machine_widgets = []  # type: List[Widget]
        self._player_widgets = []  # type: List[Widget]
        self.footer_memory = None
        self.footer_cpu = None
        self.footer_mc_cpu = None
        self.footer_uptime = None
        self._layout_change = True

        self._tick_task = self.machine.clock.schedule_interval(self._tick, 1)
        self._create_window()
        self._draw_screen()

    def _init(self, **kwargs):
        del kwargs
        for mode in self.machine.modes.values():
            self.machine.events.add_handler(
                "mode_{}_started".format(mode.name), self._mode_change)
            self.machine.events.add_handler(
                "mode_{}_stopped".format(mode.name), self._mode_change)

        self.machine.switch_controller.add_monitor(self._update_switches)
        self.machine.register_monitor("machine_vars",
                                      self._update_machine_vars)
        self.machine.variables.machine_var_monitor = True
        self.machine.bcp.interface.register_command_callback(
            "status_report", self._bcp_status_report)

        for bd in [
                x for x in self.machine.ball_devices.values()
                if not x.is_playfield()
        ]:
            self.ball_devices.append(bd)

        self.ball_devices.sort()

        self._update_switch_layout()
        self._schedule_draw_screen()

    async def _bcp_status_report(self, client, cpu, rss, vms):
        del client
        self._bcp_status = cpu, rss, vms

    def _update_stats(self):
        # Runtime
        rt = (datetime.now() - self.start_time)
        mins, sec = divmod(rt.seconds + rt.days * 86400, 60)
        hours, mins = divmod(mins, 60)
        self.footer_uptime.text = 'RUNNING {:d}:{:02d}:{:02d}'.format(
            hours, mins, sec)

        # System Stats
        self.footer_memory.text = 'Free Memory (MB): {} CPU:{:3d}%'.format(
            round(virtual_memory().available / 1048576),
            round(cpu_percent(interval=None, percpu=False)))

        # MPF process stats
        self.footer_cpu.text = 'MPF (CPU RSS/VMS): {}% {}/{} MB    '.format(
            round(self.mpf_process.cpu_percent()),
            round(self.mpf_process.memory_info().rss / 1048576),
            round(self.mpf_process.memory_info().vms / 1048576))

        # MC process stats
        if self._bcp_status != (0, 0, 0):
            self.footer_mc_cpu.text = 'MC (CPU RSS/VMS) {}% {}/{} MB '.format(
                round(self._bcp_status[0]),
                round(self._bcp_status[1] / 1048576),
                round(self._bcp_status[2] / 1048576))
        else:
            self.footer_mc_cpu.text = ""

    def _update_switch_layout(self):
        num = 0
        self.switch_widgets = []
        self.switches = {}
        self.switch_widgets.append((Label("SWITCHES"), 1))
        self.switch_widgets.append((Divider(), 1))
        self.switch_widgets.append((Label(""), 2))
        self.switch_widgets.append((Divider(), 2))

        for sw in sorted(self.machine.switches.values()):
            if sw.invert:
                name = sw.name + '*'
            else:
                name = sw.name

            col = 1 if num <= int(len(self.machine.switches) / 2) else 2

            switch_widget = Label(name)
            if sw.state:
                switch_widget.custom_colour = "active_switch"

            self.switch_widgets.append((switch_widget, col))
            self.switches[sw.name] = (sw, switch_widget)

            num += 1

        self._schedule_draw_screen()

    def _update_switches(self, change, *args, **kwargs):
        del args
        del kwargs
        try:
            sw, switch_widget = self.switches[change.name]
        except KeyError:
            return
        if sw.state:
            switch_widget.custom_colour = "active_switch"
        else:
            switch_widget.custom_colour = "label"

        self._schedule_draw_screen()

    def _draw_switches(self):
        """Draw all switches."""
        for widget, column in self.switch_widgets:
            self.layout.add_widget(widget, column)

    def _mode_change(self, *args, **kwargs):
        # Have to call this on the next frame since the mode controller's
        # active list isn't updated yet
        del args
        del kwargs
        self.mode_widgets = []
        self.mode_widgets.append(Label("ACTIVE MODES"))
        self.mode_widgets.append(Divider())
        try:
            modes = self.machine.mode_controller.active_modes
        except AttributeError:
            modes = None

        if modes:
            for mode in modes:
                self.mode_widgets.append(
                    Label('{} ({})'.format(mode.name, mode.priority)))
        else:
            self.mode_widgets.append(Label("No active modes"))

        # empty line at the end
        self.mode_widgets.append(Label(""))

        self._layout_change = True
        self._schedule_draw_screen()

    def _draw_modes(self):
        for widget in self.mode_widgets:
            self.layout.add_widget(widget, 0)

    def _draw_ball_devices(self):
        for widget in self.ball_device_widgets:
            self.layout.add_widget(widget, 3)

    def _update_ball_devices(self, **kwargs):
        del kwargs
        # TODO: do not create widgets. just update contents
        self.ball_device_widgets = []
        self.ball_device_widgets.append(Label("BALL COUNTS"))
        self.ball_device_widgets.append(Divider())

        try:
            for pf in self.machine.playfields.values():
                widget = Label('{}: {} '.format(pf.name, pf.balls))
                if pf.balls:
                    widget.custom_colour = "pf_active"
                else:
                    widget.custom_colour = "pf_inactive"
                self.ball_device_widgets.append(widget)

        except AttributeError:
            pass

        for bd in self.ball_devices:
            widget = Label('{}: {} ({})'.format(bd.name, bd.balls, bd.state))
            if bd.balls:
                widget.custom_colour = "pf_active"
            else:
                widget.custom_colour = "pf_inactive"

            self.ball_device_widgets.append(widget)

        self.ball_device_widgets.append(Label(""))

        self._layout_change = True
        self._schedule_draw_screen()

    def _update_player(self, **kwargs):
        del kwargs
        self._player_widgets = []
        self._player_widgets.append(Label("CURRENT PLAYER"))
        self._player_widgets.append(Divider())

        try:
            player = self.machine.game.player
            self._player_widgets.append(
                Label('PLAYER: {}'.format(player.number)))
            self._player_widgets.append(Label('BALL: {}'.format(player.ball)))
            self._player_widgets.append(
                Label('SCORE: {:,}'.format(player.score)))
        except AttributeError:
            self._player_widgets.append(Label("NO GAME IN PROGRESS"))
            return

        player_vars = player.vars.copy()
        player_vars.pop('score', None)
        player_vars.pop('number', None)
        player_vars.pop('ball', None)

        names = self.config.get('player_vars', player_vars.keys())
        for name in names:
            self._player_widgets.append(
                Label("{}: {}".format(name, player_vars[name])))

        self._layout_change = True
        self._schedule_draw_screen()

    def _draw_player(self, **kwargs):
        del kwargs
        for widget in self._player_widgets:
            self.layout.add_widget(widget, 3)

    def _update_machine_vars(self, **kwargs):
        """Update machine vars."""
        del kwargs
        self._machine_widgets = []
        self._machine_widgets.append(Label("MACHINE VARIABLES"))
        self._machine_widgets.append(Divider())
        machine_vars = self.machine.variables.machine_vars
        # If config defines explict vars to show, only show those. Otherwise, all
        names = self.config.get('machine_vars', machine_vars.keys())
        for name in names:
            self._machine_widgets.append(
                Label("{}: {}".format(name, machine_vars[name]['value'])))
        self._layout_change = True
        self._schedule_draw_screen()

    def _draw_machine_variables(self):
        """Draw machine vars."""
        for widget in self._machine_widgets:
            self.layout.add_widget(widget, 0)

    def _create_window(self):
        self.screen = Screen.open()
        self.frame = Frame(self.screen,
                           self.screen.height,
                           self.screen.width,
                           has_border=False,
                           title="Test")
        self.frame.set_theme("mpf_theme")

        title_layout = Layout([1, 5, 1])
        self.frame.add_layout(title_layout)

        title_left = Label("")
        title_left.custom_colour = "title"
        title_layout.add_widget(title_left, 0)

        title = 'Mission Pinball Framework v{}'.format(
            mpf._version.__version__)  # noqa
        title_text = Label(title, align="^")
        title_text.custom_colour = "title"
        title_layout.add_widget(title_text, 1)

        exit_label = Label("< CTRL + C > TO EXIT", align=">")
        exit_label.custom_colour = "title_exit"

        title_layout.add_widget(exit_label, 2)

        self.layout = MpfLayout([1, 1, 1, 1], fill_frame=True)
        self.frame.add_layout(self.layout)

        footer_layout = Layout([1, 1, 1])
        self.frame.add_layout(footer_layout)
        self.footer_memory = Label("", align=">")
        self.footer_memory.custom_colour = "footer_memory"
        self.footer_uptime = Label("", align=">")
        self.footer_uptime.custom_colour = "footer_memory"
        self.footer_mc_cpu = Label("")
        self.footer_mc_cpu.custom_colour = "footer_mc_cpu"
        self.footer_cpu = Label("")
        self.footer_cpu.custom_colour = "footer_cpu"
        footer_path = Label(self.machine.machine_path)
        footer_path.custom_colour = "footer_path"
        footer_empty = Label("")
        footer_empty.custom_colour = "footer_memory"

        footer_layout.add_widget(footer_path, 0)
        footer_layout.add_widget(self.footer_cpu, 0)
        footer_layout.add_widget(footer_empty, 1)
        footer_layout.add_widget(self.footer_mc_cpu, 1)
        footer_layout.add_widget(self.footer_uptime, 2)
        footer_layout.add_widget(self.footer_memory, 2)

        self.scene = Scene([self.frame], -1)
        self.screen.set_scenes([self.scene], start_scene=self.scene)

        # prevent main from scrolling out the footer
        self.layout.set_max_height(self.screen.height - 2)

    def _schedule_draw_screen(self):
        # schedule the draw in 10ms if it is not scheduled
        self.delay.add_if_doesnt_exist(10, self._draw_screen, "draw_screen")

    def _draw_screen(self):
        if not self.screen:
            # probably drawing during game end
            return

        if self._layout_change:
            self.layout.clear_columns()
            self._draw_modes()
            self._draw_machine_variables()
            self._draw_switches()
            self._draw_ball_devices()
            self._draw_player()
            self.frame.fix()
            self._layout_change = False

        self.screen.force_update()
        self.screen.draw_next_frame()

    def _tick(self):
        if self.screen.has_resized():
            self._create_window()

        self._update_ball_devices()
        self._update_stats()

        self._schedule_draw_screen()

        self.machine.bcp.transport.send_to_clients_with_handler(
            handler="_status_request", bcp_command="status_request")

    def _bcp_connection_attempt(self, name, host, port, **kwargs):
        del name
        del kwargs
        self._pending_bcp_connection = PopUpDialog(
            self.screen,
            'WAITING FOR MEDIA CONTROLLER {}:{}'.format(host, port), [])
        self.scene.add_effect(self._pending_bcp_connection)
        self._schedule_draw_screen()

    def _bcp_connected(self, **kwargs):
        del kwargs
        self.scene.remove_effect(self._pending_bcp_connection)
        self._schedule_draw_screen()

    def _asset_load_change(self, percent, **kwargs):
        del kwargs
        if self._asset_percent:
            self.scene.remove_effect(self._asset_percent)
        self._asset_percent = PopUpDialog(
            self.screen, 'LOADING ASSETS: {}%'.format(percent), [])
        self.scene.add_effect(self._asset_percent)
        self._schedule_draw_screen()

    def _asset_load_complete(self, **kwargs):
        del kwargs
        self.scene.remove_effect(self._asset_percent)
        self._schedule_draw_screen()

    def stop(self, **kwargs):
        """Stop the Text UI and restore the original console screen."""
        del kwargs
        if self.screen:
            self.machine.clock.unschedule(self._tick_task)
            self.screen.close(True)
            self.screen = None
Example #7
0
def MainMenu(game, screen, debug, oldpalette):
    def endgame():
        screen.close()
        quit()
        sys.exit(0)
        None

    def endmenu():
        debug[0] = False
        game = GameState.GameState()
        game.hero.inventory = []
        Mmenu.save()
        looksy = Mmenu.data
        if looksy['seedval'] != "":
            converted = 0
            if str.isnumeric(looksy['seedval']):
                game.seed = int(looksy['seedval'])
            else:
                for char in looksy['seedval']:
                    converted += ord(char)
                game.seed = int(converted)
        random.seed(game.seed)
        if looksy['nameval'] != "":
            if len(looksy["nameval"]) >= 20:
                game.name = str(looksy['nameval'])[:21]
            else:
                game.name = str(looksy['nameval'])
        debug[0] = looksy['Debug']
        #visual.blackout(screen)
        main(game, debug, looksy, screen)
        test1.deadscreen(game, screen)
        DeathMenu(game, screen, debug, oldpalette)
        return Mmenu.data

    endval = True
    Mmenu = Frame(screen,
                  screen.height * 2 // 3,
                  screen.width * 2 // 3,
                  hover_focus=True,
                  has_border=True,
                  title="Game Settings",
                  reduce_cpu=False)

    #Mmenu.palette['background'] = (0,0,1)
    Mmenu.palette = oldpalette
    mapping = Layout([100], fill_frame=True)
    Mmenu.add_layout(mapping)
    mapping.add_widget(Text("Seed:", "seedval"))
    mapping.add_widget(Text("Adventurer Name:", "nameval"))
    mapping.add_widget(CheckBox("Debug Mode:", "Debug", "Debug"))

    bottomrow = Layout([1, 1, 1, 1])
    Mmenu.add_layout(bottomrow)
    bottomrow.add_widget(Button("Exit Game", endgame), 0)
    bottomrow.add_widget(Button("Start Level", endmenu), 3)
    Mmenu.fix()

    #Mmenu._on_pic

    Scenes = [Scene([Mmenu], -1)]

    screen.play(Scenes)
    return Mmenu.data
Example #8
0
    def test_multi_column_list_box(self):
        """
        Check MultiColumnListBox works as expected.
        """
        # Create a dummy screen.
        screen = MagicMock(spec=Screen, colours=8, unicode_aware=False)
        scene = MagicMock(spec=Scene)
        canvas = Canvas(screen, 10, 40, 0, 0)

        # Create the form we want to test.
        form = Frame(canvas, canvas.height, canvas.width, has_border=False)
        layout = Layout([100], fill_frame=True)
        mc_list = MultiColumnListBox(
            Widget.FILL_FRAME, [3, "4", ">4", "<4", ">10%", "100%"], [
                (["1", "2", "3", "4", "5", "6"], 1),
                (["11", "222", "333", "444", "555", "6"], 2),
                (["111", "2", "3", "4", "5", "6"], 3),
                (["1", "2", "33333", "4", "5", "6"], 4),
                (["1", "2", "3", "4", "5", "6666666666666666666666"], 5),
            ],
            titles=["A", "B", "C", "D", "E", "F"],
            name="mc_list")
        form.add_layout(layout)
        layout.add_widget(mc_list)
        form.fix()
        form.register_scene(scene)
        form.reset()

        # Check we have a default value for our list.
        form.save()
        self.assertEqual(form.data, {"mc_list": 1})

        # Check that UP/DOWN change selection.
        self.process_keys(form, [Screen.KEY_DOWN])
        form.save()
        self.assertEqual(form.data, {"mc_list": 2})
        self.process_keys(form, [Screen.KEY_UP])
        form.save()
        self.assertEqual(form.data, {"mc_list": 1})

        # Check that PGUP/PGDN change selection.
        self.process_keys(form, [Screen.KEY_PAGE_DOWN])
        form.save()
        self.assertEqual(form.data, {"mc_list": 5})
        self.process_keys(form, [Screen.KEY_PAGE_UP])
        form.save()
        self.assertEqual(form.data, {"mc_list": 1})

        # Check that the widget is rendered correctly.
        form.update(0)
        self.assert_canvas_equals(
            canvas, "A  B      C D      E F                  \n" +
            "1  2      3 4      5 6                  \n" +
            "11 222  333 444  555 6                  \n" +
            "...2      3 4      5 6                  \n" +
            "1  2   3... 4      5 6                  \n" +
            "1  2      3 4      5 6666666666666666666\n" +
            "                                        \n" +
            "                                        \n" +
            "                                        \n" +
            "                                        \n")

        # Check that mouse input changes selection.
        self.process_mouse(form, [(2, 2, MouseEvent.LEFT_CLICK)])
        form.save()
        self.assertEqual(form.data, {"mc_list": 2})
        self.process_mouse(form, [(2, 1, MouseEvent.LEFT_CLICK)])
        form.save()
        self.assertEqual(form.data, {"mc_list": 1})

        # Check that the start_line can be read and set - and enforces good behaviour
        mc_list.start_line = 0
        self.assertEqual(mc_list.start_line, 0)
        mc_list.start_line = len(mc_list.options) - 1
        self.assertEqual(mc_list.start_line, len(mc_list.options) - 1)
        mc_list.start_line = 10000000
        self.assertEqual(mc_list.start_line, len(mc_list.options) - 1)

        # Check that options can be read and set.
        mc_list.options = [(["a", "b", "c", "d", "e", "f"], 0)]
        self.assertEqual(mc_list.options,
                         [(["a", "b", "c", "d", "e", "f"], 0)])
        mc_list.options = []
        self.assertEqual(mc_list.options, [])

        # Check that the form re-renders correctly afterwards.
        form.update(1)
        self.assert_canvas_equals(
            canvas, "A  B      C D      E F                  \n" +
            "                                        \n" +
            "                                        \n" +
            "                                        \n" +
            "                                        \n" +
            "                                        \n" +
            "                                        \n" +
            "                                        \n" +
            "                                        \n" +
            "                                        \n")

        # Check that the current focus ignores unknown events.
        event = object()
        self.assertEqual(event, form.process_event(event))
Example #9
0
class ASCII():
    def __init__(self):
        self.screen = Screen.open()
        self.scenes = []
        self.akt_sender_str = "Deutschlandradio"
        self.akt_sender_nr = 0
        self.volume = 25
        self.number_of_stations = 0

        # Prepare frame for the presets
        self.preset_frame = Frame(self.screen,
                                  7,
                                  29,
                                  can_scroll=False,
                                  title="Tastenbelegung",
                                  x=0,
                                  y=10,
                                  reduce_cpu=True)
        self.pr_layout = Layout([10, 90], fill_frame=True)
        self.preset_frame.add_layout(self.pr_layout)

        # Prepare frame for the sender list
        self.sender_frame = Frame(self.screen,
                                  17,
                                  50,
                                  can_scroll=False,
                                  title="Senderliste",
                                  x=30,
                                  y=0,
                                  reduce_cpu=True)
        self.sender_layout0 = Layout([10, 80, 10], fill_frame=True)
        self.sender_frame.add_layout(self.sender_layout0)

        # Load the json config-file
        self.cfg = self.load_config()

        # Prepare the layouts, add spaces etc
        self.format_sl_layout(self.sender_layout0)

        # Nicht mehr nötig nach aktuellem Stand
        # format_pr_layout(pr_layout)

        # Create the sender-labels and fill them initially. Return them for
        # later changing
        self.sender_labels = self.gen_and_add_sender_labels(
            self.sender_layout0, self.parse_sender())
        self.preset_labels = self.gen_and_add_preset_labels(
            self.pr_layout, self.parse_presets())

        self.preset_frame.fix()
        self.sender_frame.fix()

    def load_config(self):
        if STANDARD_CONFIG.exists():
            with STANDARD_CONFIG.open() as f:
                konfig = json.load(f)
                print("Nutzer-Config geladen.")
        elif NOTFALL_CONFIG.exists():
            with NOTFALL_CONFIG.open() as f:
                konfig = json.load(f)
                print("Notfall-Config geladen")
        else:
            print("Katastrophaler Fehler: Keine Config-Dateien. Beende...")
            sys.exit(1)

        self.number_of_stations = len(konfig["senderliste"])
        return konfig

    # Krall Dir anhand des aktuellen Senderindizes die 6 Sendernamen vor und nach
    # dem gewählten Sender
    def parse_sender(self):
        namen = []
        j = 1

        for i in range(1, DISPLAY_SENDER_SYMM + 1):
            if self.akt_sender_nr - i >= 0:
                namen.append(self.cfg["senderliste"][self.akt_sender_nr -
                                                     i]["sendername"])
            else:
                index = self.number_of_stations - j
                namen.append(self.cfg["senderliste"][index]["sendername"])
                j += 1
        namen.reverse()

        for i in range(0, DISPLAY_SENDER_SYMM + 1):
            namen.append(
                self.cfg["senderliste"][(self.akt_sender_nr + i) %
                                        self.number_of_stations]["sendername"])

        for d in namen:
            debug.write(d)
        return namen

    # Hole die fünf Presets aus der Config. Setze Presets mit -1 auf den der
    # unbelegten Taste entsprechenden Index in der Senderliste
    def parse_presets(self):
        namen = []
        for n, i in zip(self.cfg["presetliste"], range(0, 5)):
            if n >= 0:
                namen.append(self.cfg["senderliste"][n]["sendername"])
            else:
                namen.append(self.cfg["senderliste"][i]["sendername"])
                debug.write(str(i))

        return namen

    def format_sl_layout(self, layout):
        layout.add_widget(Divider(False, 7), 0)
        layout.add_widget(Label('>>>', 1, align='<'), 0)

        layout.add_widget(Divider(False, 7), 2)
        layout.add_widget(Label('<<<', 1, align='>'), 2)

    # Fülle die Senderliste initial und gib die Label für die spätere Verarbeitung
    # zurück. Die Divider bleiben als Abstandshalter dauerhaft im Layout.
    def gen_and_add_sender_labels(self, layout, namen):
        labs = []
        for name in namen:
            labs.append(Label(name, 1))

        # Add first 6 stations
        for l in labs[:DISPLAY_SENDER_SYMM]:
            layout.add_widget(l, 1)

        # Add spaces and the central station (hehe, got it?)
        layout.add_widget(Divider(False, 1), 1)
        layout.add_widget(labs[DISPLAY_SENDER_SYMM], 1)
        layout.add_widget(Divider(False, 1), 1)

        # Add the rest of the stations
        for l in labs[DISPLAY_SENDER_SYMM + 1:]:
            layout.add_widget(l, 1)

        return labs

    # Füge die Spaltennummern der Presets hinzu, außerdem fülle die Presets initial
    # und gib die Liste mit den Presetlabels für die spätere Verarbeitung zurück
    def gen_and_add_preset_labels(self, layout, namen):
        preset_labs = []

        # Presetnamen einfügen in Spalte 1
        for name in namen:
            preset_labs.append(Label(name, 1))
            debug.write(name)

        for l in preset_labs:
            layout.add_widget(l, 1)

        # Spaltennummern der Presets einfügen in Spalte 0
        for i in range(1, 6):
            layout.add_widget(Label(str(i), 1), 0)

        return preset_labs

    def update_sender_labels(self):
        namen = self.parse_sender()

        for l, n in zip(self.sender_labels, namen):
            l.text = n

    def update_preset_labels(self):
        namen = parse_presets()

        for l, n in zip(self.sender_labels, namen):
            l.text = n

    def get_vol(self):
        return self.volume

    # muhahahahhahahahahaaaa!
    def asciisierer(self, s):
        tabelle = {
            ord('ä'): 'ae',
            ord('ö'): 'oe',
            ord('ü'): 'ue',
            ord('ß'): 'ss',
            ord('Ä'): 'AE',
            ord('Ö'): 'OE',
            ord('Ü'): 'UE',
            ord('ẞ'): 'SS',
        }

        return s.translate(tabelle)

    # Fill the display with the desired effects and draw the first frame
    def prepare_display(self):
        # Effects are all the stuff which will be shown on the display
        # Speed 0 means: Redraw only when draw_next_frame is executed
        effects = [
            self.preset_frame, self.sender_frame,
            Print(self.screen, Box(80, 8, True), x=0, y=17, speed=0),
            Print(self.screen,
                  ColourImageFile(self.screen, LOGO, 9, bg=7),
                  x=0,
                  y=0,
                  speed=0),
            Print(self.screen,
                  FigletText(self.asciisierer(self.akt_sender_str)),
                  x=1,
                  y=18,
                  speed=0),
            Print(self.screen,
                  BarChart(4,
                           80, [self.get_vol],
                           colour=2,
                           char=' ',
                           bg=7,
                           scale=100,
                           axes=BarChart.X_AXIS,
                           intervals=25,
                           labels=True,
                           border=False),
                  x=0,
                  y=26,
                  transparent=False,
                  speed=0)
        ]

        # Start displaying
        self.scenes.append(Scene(effects, -1))
        self.screen.set_scenes(self.scenes)

        # Update the screen for the first time
        self.screen.draw_next_frame()
Example #10
0
def demo(screen):
    scenes = []
    preset_frame = Frame(screen,
                         11,
                         26,
                         can_scroll=False,
                         title="Tastenbelegung",
                         x=SF_X,
                         y=SF_Y,
                         reduce_cpu=True)
    pr_layout = Layout([10, 90], fill_frame=True)
    preset_frame.add_layout(pr_layout)

    sender_frame = Frame(screen,
                         11,
                         26,
                         can_scroll=False,
                         title="Senderliste",
                         x=27,
                         y=6,
                         reduce_cpu=True)
    sender_layout0 = Layout([10, 90, 10], fill_frame=True)

    sender_frame.add_layout(sender_layout0)

    optionen = [(" ", 1), ("Zweiter", 2), ("Dritter", 3), ("Vierter", 4),
                ("Deutschlandradio", 5), ("Absolut Relax", 6), ("Siebter", 7),
                ("hmm", 8)]

    sender = [
        "123456789012345678901", "Erster", "Zweiter", "Dritter", "Vierter",
        "Fünfter", "Sechster"
    ]
    Senderkiste = ListBox(8, optionen, False)
    sender_layout0.add_widget(Senderkiste, 1)
    Senderkiste.blur()
    Senderkiste.start_line = 1

    format_sl_layout(sender_layout0)
    # format_pr_layout(pr_layout)
    for i, s in zip(range(1, 6), sender):
        pr_layout.add_widget(Label(str(i), 1, align=u'^'))
        pr_layout.add_widget(Label(s, 1, align='^'), 1)

    preset_frame.fix()
    sender_frame.fix()

    effects = [
        preset_frame,
        sender_frame,
        Print(screen, Box(26, 15, True), x=UHR_K_X, y=UHR_K_Y),
        Print(screen, Box(80, 8, True), x=0, y=17),
        Clock(screen, 67, 7, 6),
        Print(screen, FigletText("Retroradio!"), x=0, y=0),
        #            Print(screen, BarChart(4, 80, [get_vol], colour=2, scale=100,
        #                axes=BarChart.X_AXIS, intervals=25, labels=True, border=False), x=0, y=26,
        #                transparent=False),
        # Print(screen, SpeechBubble("Lautstärke"), x=0, y=23),
        Print(screen, FigletText("Deutschlandradio"), x=1, y=18),
        Print(screen,
              BarChart(4,
                       80, [get_vol],
                       colour=2,
                       char=' ',
                       bg=7,
                       scale=100,
                       axes=BarChart.X_AXIS,
                       intervals=25,
                       labels=True,
                       border=False),
              x=0,
              y=26,
              transparent=False,
              speed=2)
    ]

    scenes.append(Scene(effects, -1))
    screen.play(scenes)
Example #11
0
def run_display(screen):
    scenes = []
    AKT_SENDER = "Retro rockt!"

    # Prepare frame for the presets
    preset_frame = Frame(screen,
                         7,
                         29,
                         can_scroll=False,
                         title="Tastenbelegung",
                         x=0,
                         y=10,
                         reduce_cpu=True)
    pr_layout = Layout([10, 90], fill_frame=True)
    preset_frame.add_layout(pr_layout)

    # Prepare frame for the sender list
    sender_frame = Frame(screen,
                         17,
                         50,
                         can_scroll=False,
                         title="Senderliste",
                         x=30,
                         y=0,
                         reduce_cpu=True)
    sender_layout0 = Layout([10, 80, 10], fill_frame=True)
    sender_frame.add_layout(sender_layout0)

    # Load the json config-file
    cfg = load_config()

    # Prepare the layouts, add spaces etc
    format_sl_layout(sender_layout0)

    # Nicht mehr nötig nach aktuellem Stand
    # format_pr_layout(pr_layout)

    # Create the sender-labels and fill them initially. Return them for
    # later changing
    sender_labels = gen_and_add_sender_labels(sender_layout0,
                                              parse_sender(cfg, 0))
    preset_labels = gen_and_add_preset_labels(pr_layout, parse_presets(cfg))

    preset_frame.fix()
    sender_frame.fix()

    # Effects are all the stuff which will be shown on the display
    effects = [
        preset_frame,
        sender_frame,
        # Print(screen, Box(26, 15, True), x=54, y=0),
        Print(screen, Box(80, 8, True), x=0, y=17, speed=2),
        # Clock(screen, 68, 7, 5),
        Print(screen,
              ColourImageFile(screen, LOGO, 9, bg=7),
              x=0,
              y=0,
              speed=2),
        Print(screen, FigletText(asciisierer(AKT_SENDER)), x=1, y=18),
        Print(screen,
              BarChart(4,
                       80, [get_vol],
                       colour=2,
                       char=' ',
                       bg=7,
                       scale=100,
                       axes=BarChart.X_AXIS,
                       intervals=25,
                       labels=True,
                       border=False),
              x=0,
              y=26,
              transparent=False,
              speed=2)
    ]

    # Start displaying
    scenes.append(Scene(effects, -1))
    screen.play(scenes)