Exemplo n.º 1
0
class MapEditor(gui.Desktop):

    items = core.load_items()
    items = core.transformed_items(items,
                                   cell_size=request("map_editor.cell_size"))
    theme = gui.Theme(preference.theme())

    def __init__(self, board=None, callback=None, **params):
        pygame.display.set_mode(
            (request("map_editor.width"), request("map_editor.height")))
        gui.Desktop.__init__(self, theme=self.theme, **params)
        self.callback = callback or (lambda *_, **__: None)
        self.connect(gui.QUIT, self.quit)
        self.board = board
        self.filename = None
        container = gui.Container(width=request("map_editor.width"),
                                  height=request("map_editor.height"))

        spacer = request("map_editor.space_size")

        self.new_dialog = NewMapDialog()
        self.new_dialog.connect(gui.CHANGE, self.action_new)
        self.open_dialog = FileDialog("Choose map",
                                      "Choose",
                                      path=folder('map'),
                                      preview=Preview(display_players=False),
                                      exts=['map', 'preset', 'state'])
        self.open_dialog.connect(gui.CHANGE, self.new_map)
        self.save_dialog = FileDialog("Enter filename to save with",
                                      "Choose",
                                      path=folder('map'),
                                      exts=['map'],
                                      save=True)
        self.save_dialog.connect(gui.CHANGE, self.action_saveas)

        # self.help_dialog = HelpDialog()
        # QUESTION: may be put it into json: {"<menu>": "<method name>", ...}
        self.menus = menus = gui.Menus([
            ('File/New', self.new_dialog.open, None),
            ('File/Open', self.open_dialog.open, None),
            ('File/Save', self.action_save, None),
            ('File/Save As', self.save_as, None),
            ('File/Exit', self.quit, None), ('Add/Extend', self.extend, None),
            ('Add/Add top row', self.add_top_row, None),
            ('Add/Add bottom row', self.add_bottom_row, None),
            ('Add/Add left column', self.add_left_column, None),
            ('Add/Add right column', self.add_right_column, None),
            ('Add/Add cells', self.add_cells, None),
            ('Remove/Reduce', self.reduce, None),
            ('Remove/Remove top row', self.remove_top_row, None),
            ('Remove/Remove bottom row', self.remove_bottom_row, None),
            ('Remove/Remove left column', self.remove_left_column, None),
            ('Remove/Remove right column', self.remove_right_column, None),
            ('Remove/Remove the same checkers', self.remove_same_checkers,
             None),
            ('Remove/Remove checkers with the same owner',
             self.remove_same_player_checkers, None),
            ('Remove/Remove checkers with the same level',
             self.remove_same_level_checkers, None),
            ('Remove/Remove all checkers', self.remove_checkers, None),
            ('Remove/Remove cells', self.remove_cells, None),
            ('Edit/Permute cells', self.permute_cells, None),
            ('Edit/Permute players', self.permute_players, None),
            ('Edit/Permute checkers', self.permute_checkers, None)
            # ('Help/Help', self.help_dialog.open)
        ])
        container.add(self.menus, 0, 0)
        self.menus.rect.w, self.menus.rect.h = menus.resize()
        self.filename_input = gui.Input("")
        container.add(self.filename_input, self.menus.rect.w + spacer, 0)

        # # new ::
        # self.mode = mode = gui.Group(name="brushes", value='player')
        # cell_tool = gui.Tool(self.mode, "Cell", 'cell')
        # empty_tool = gui.Tool(self.mode, "Empty", 'none')
        # player_tool = gui.Tool(self.mode, "Player", 'player')
        # # :: new
        self.mode = mode = gui.Toolbox([('Cell', 'cell'), ('Empty', 'none'),
                                        ('Player', 'player')],
                                       cols=1,
                                       value='player')  # NOTE: DEPERECATED
        self.mode.connect(gui.CHANGE, self.set_brush)
        self.player = request("map_editor.player")
        self.amount = request("map_editor.amount")
        container.add(mode, 0, self.menus.rect.bottom + spacer)
        # # new ::
        # container.add(cell_tool, 0, self.menus.rect.bottom + spacer)
        # container.add(empty_tool, 0, cell_tool.rect.bottom + spacer)
        # container.add(cell_tool, 0, empty_tool.rect.bottom + spacer)
        # # :: new
        mode.rect.x, mode.rect.y = mode.style.x, mode.style.y
        mode.rect.w, mode.rect.h = mode.resize()

        self.player_table = gui.Table()
        self.player_table.td(gui.Label("Holes"))
        self.player_table.tr()
        self.selector = gui.Select(value=request("map_editor.amount"))
        for i in sorted(self.items.keys()):
            self.selector.add(str(i), i)
        self.selector.connect(gui.CHANGE, self.new_amount)
        self.player_table.td(self.selector, style=td_style)
        self.player_table.tr()
        self.player_table.tr()
        self.player_button = gui.Button('Player')
        self.player_table.td(self.player_button, style=td_style)
        self.player_button.connect(gui.CLICK, self.choose_player)
        self.player_table.tr()
        self.player_input = gui.Input(str(self.player), size=5)
        add_event_handler(self.player_input, enter_pressed,
                          lambda e: self.new_player())
        self.player_table.td(self.player_input, style=td_style)
        self.player_table.tr()
        self.checker = ImageWidget(image=self.items[self.amount][self.player],
                                   width=request("map_editor.view_width"),
                                   height=request("map_editor.view_height"))
        self.player_table.td(self.checker, style=td_style)
        self.player_table.tr()
        # self.color = gui.Color("#000000", width=mode.rect.w, height=mode.rect.w)
        # self.color.connect(gui.CLICK, self.choose_player)
        # self.player_table.td(self.color, style=td_style)
        container.add(self.player_table, 0, mode.rect.bottom + spacer)

        self.painter = Painter(
            width=container.rect.w - mode.rect.w - spacer * 2,
            height=container.rect.h - self.menus.rect.h - spacer * 2,
            style={'border': 1})
        container.add(self.painter, mode.rect.w + spacer,
                      self.menus.rect.h + spacer)
        if board:
            self.painter.set_map(board)
        self.painter.rect.w, self.painter.rect.h = self.painter.resize()

        self.widget = container

    def extend(self, *pargs):
        if self.painter.board is not None:
            self.painter.set_map(self.painter.board.extend())

    def reduce(self, *pargs):
        if self.painter.board is not None:
            self.painter.set_map(self.painter.board.reduce())

    def add_top_row(self, *pargs):
        if self.painter.board is not None:
            self.painter.set_map(self.painter.board.add_top_row())

    def add_bottom_row(self, *pargs):
        if self.painter.board is not None:
            self.painter.set_map(self.painter.board.add_bottom_row())

    def add_left_column(self, *pargs):
        if self.painter.board is not None:
            self.painter.set_map(self.painter.board.add_left_column())

    def add_right_column(self, *pargs):
        if self.painter.board is not None:
            self.painter.set_map(self.painter.board.add_right_column())

    def remove_top_row(self, *pargs):
        if self.painter.board is not None:
            self.painter.set_map(self.painter.board.remove_top_row())

    def remove_bottom_row(self, *pargs):
        if self.painter.board is not None:
            self.painter.set_map(self.painter.board.remove_bottom_row())

    def remove_left_column(self, *pargs):
        if self.painter.board is not None:
            self.painter.set_map(self.painter.board.remove_left_column())

    def remove_right_column(self, *pargs):
        if self.painter.board is not None:
            self.painter.set_map(self.painter.board.remove_right_column())

    def remove_same_checkers(self, *pargs):
        if self.painter.board is not None:
            self.painter.set_map(
                self.painter.board.empty_cells(
                    condition=lambda cell: cell == (self.player, self.amount)))

    def remove_same_player_checkers(self, *pargs):
        if self.painter.board is not None:
            self.painter.set_map(
                self.painter.board.empty_cells(
                    condition=lambda cell: cell[0] == self.player))

    def remove_same_level_checkers(self, *pargs):
        if self.painter.board is not None:
            self.painter.set_map(
                self.painter.board.empty_cells(
                    condition=lambda cell: cell[1] == self.amount))

    def remove_checkers(self, *pargs):
        if self.painter.board is not None:
            self.painter.set_map(self.painter.board.empty_cells())

    def remove_cells(self, *pargs):
        if self.painter.board is not None:
            self.painter.set_map(self.painter.board.remove_all_cells())

    def add_cells(self, *pargs):
        if self.painter.board is not None:
            self.painter.set_map(self.painter.board.fill_cells())

    def permute_players(self, *pargs):
        if self.painter.board is not None:
            self.painter.set_map(self.painter.board.permute_players())

    def permute_checkers(self, *pargs):
        if self.painter.board is not None:
            self.painter.set_map(self.painter.board.permute_checkers())

    def permute_cells(self, *pargs):
        if self.painter.board is not None:
            self.painter.set_map(self.painter.board.permute_cells())

    def choose_player(self):
        if self.painter.board is not None:
            title = gui.Label("Choose player")
            table = gui.Table()
            players = list(sorted(self.painter.board.players))
            radios = gui.Group(value=self.player_input.value)
            for player in players:
                table.td(gui.Radio(radios, value=str(player)), style=td_style)
            table.tr()
            for player in players:
                table.td(
                    ImageWidget(image=self.items[self.amount][player],
                                style=td_style,
                                width=request("map_editor.view_width"),
                                height=request("map_editor.view_height")))
            button = gui.Button("  Apply  ")
            table.tr()
            table.td(button, style=td_style)
            dialog = gui.Dialog(title, table)

            def on_click():
                dialog.value = int(radios.value)
                dialog.send(gui.CHANGE)
                dialog.close()

            button.connect(gui.CLICK, on_click)
            dialog.connect(gui.CHANGE, lambda: self.new_player(dialog.value))
            dialog.open()

    def parse_player(self):
        s = self.player_input.value
        if s.isdigit():
            return int(s)
        else:
            print("WARNING: Wrong `player`: '{}', `player` must be an integer".
                  format(s))

    def new_player(self, player=None):
        if player is None: player = self.parse_player()
        if player in range(len(self.items[1])):
            self.player = player
            self.player_input.value = str(self.player)
            self.checker.new_image(self.items[self.amount][self.player])
            if self.painter.board is not None:
                self.set_brush()
        else:
            print(
                "WARNING: Wrong `player`: '{}', applicable players: {}".format(
                    player, list(range(len(self.items[1])))))

    def new_amount(self):
        if self.selector.value in self.items.keys():
            self.amount = self.selector.value
            self.checker.new_image(self.items[self.amount][self.player])
            self.set_brush()
        else:
            print("WARNING: Wrong amount: {}, applicable amounts: {}".format(
                self.selector.value, list(self.items.keys())))

    def set_brush(self):
        self.painter.set_brush(brush=self.mode.value,
                               player=self.player,
                               amount=self.amount)

    def action_new(self):
        self.new_dialog.close()
        self.filename = self.new_dialog.filename
        self.filename_input.value = op.split(self.filename)[-1]
        board = self.new_dialog.value
        self.painter.set_map(board)
        self.set_brush()

    def action_save(self, *pargs):
        if self.painter.board is not None:
            core.save_map(self.painter.board, self.filename, full=True)
        else:
            print("WARNING: Nothing done, nothing to save")

    def quit(self, *_, **__):
        gui.Desktop.quit(self)
        # BUG with closing: doesn't resize
        sys_exit()
        # self.callback(board=self.board, filename=self.filename)

    def save_as(self, *pargs):
        if self.painter.board is not None:
            self.save_dialog.new_filename(self.filename_input.value)
            self.save_dialog.open()
        else:
            print("WARNING: Nothing done, nothing to save")

    def action_saveas(self):
        self.save_dialog.close()
        self.filename = self.save_dialog.value
        self.filename_input.value = op.split(self.filename)[-1]
        core.save_map(self.painter.board, self.filename, full=True)

    def new_map(self):
        self.open_dialog.close()
        self.filename = self.open_dialog.value
        loader = self.open_dialog.format.map_loader
        self.painter.set_map(board=loader(self.filename))
        self.set_brush()
        name, ext = op.splitext(self.filename)
        self.filename = request("map_editor.autosave_pattern").format(
            name=name, ext=request("formats.map.extension"))
        self.filename_input.value = op.split(self.filename)[-1]