def test_hide(self, _init_pygame, default_ui_manager,
                  _display_surface_return_none):
        selection_list = UISelectionList(
            relative_rect=pygame.Rect(0, 0, 50, 80),
            item_list=[
                'item 1', 'item 2', 'item 3', 'item 4', 'item 5', 'item 6',
                'item 7', 'item 8', 'item 9', 'item 10', 'item 11', 'item 12',
                'item 13', 'item 14', 'item 15', 'item 16'
            ],
            manager=default_ui_manager,
            allow_multi_select=True)

        assert selection_list.visible == 1

        assert selection_list.list_and_scroll_bar_container.visible == 1
        assert selection_list.item_list_container.visible == 1

        assert selection_list.scroll_bar.visible == 1
        assert selection_list.scroll_bar.button_container.visible == 1
        assert selection_list.scroll_bar.bottom_button.visible == 1
        assert selection_list.scroll_bar.top_button.visible == 1
        assert selection_list.scroll_bar.sliding_button.visible == 1

        selection_list.hide()

        assert selection_list.visible == 0

        assert selection_list.list_and_scroll_bar_container.visible == 0
        assert selection_list.item_list_container.visible == 0

        assert selection_list.scroll_bar.visible == 0
        assert selection_list.scroll_bar.button_container.visible == 0
        assert selection_list.scroll_bar.bottom_button.visible == 0
        assert selection_list.scroll_bar.top_button.visible == 0
        assert selection_list.scroll_bar.sliding_button.visible == 0
    def test_kill(self, _init_pygame, default_ui_manager: IUIManagerInterface,
                  _display_surface_return_none):
        selection_list = UISelectionList(
            relative_rect=pygame.Rect(0, 0, 50, 80),
            item_list=[
                'item 1', 'item 2', 'item 3', 'item 4', 'item 5', 'item 6',
                'item 7', 'item 8', 'item 9', 'item 10', 'item 11', 'item 12',
                'item 13', 'item 14', 'item 15', 'item 16'
            ],
            manager=default_ui_manager,
            allow_multi_select=True)

        assert len(default_ui_manager.get_root_container().elements) == 2
        assert len(default_ui_manager.get_sprite_group().sprites()) == 13

        selection_list_sprites = [
            default_ui_manager.get_root_container(), selection_list,
            selection_list.list_and_scroll_bar_container,
            selection_list.item_list_container, selection_list.scroll_bar,
            selection_list.scroll_bar.button_container,
            *selection_list.item_list_container.elements,
            selection_list.scroll_bar.top_button,
            selection_list.scroll_bar.bottom_button,
            selection_list.scroll_bar.sliding_button
        ]
        assert default_ui_manager.get_sprite_group().sprites(
        ) == selection_list_sprites
        selection_list.kill()
        assert len(default_ui_manager.get_root_container().elements) == 0
        assert len(default_ui_manager.get_sprite_group().sprites()) == 1
        empty_ui_sprites = [default_ui_manager.get_root_container()]
        assert default_ui_manager.get_sprite_group().sprites(
        ) == empty_ui_sprites
    def test_update(self, _init_pygame, default_ui_manager,
                    _display_surface_return_none: None):
        selection_list = UISelectionList(
            relative_rect=pygame.Rect(50, 50, 150, 80),
            item_list=[
                'item 1', 'item 2', 'item 3', 'item 4', 'item 5', 'item 6',
                'item 7', 'item 8', 'item 9', 'item 10', 'item 11', 'item 12',
                'item 13', 'item 14', 'item 15', 'item 16'
            ],
            manager=default_ui_manager,
            allow_multi_select=True)

        assert selection_list.scroll_bar is not None

        visible_items = [
            item['text'] for item in selection_list.item_list
            if item['button_element'] is not None
        ]
        assert visible_items == ['item 1', 'item 2', 'item 3', 'item 4']
        # scroll the list a bit
        selection_list.scroll_bar.has_moved_recently = True
        selection_list.scroll_bar.start_percentage = 0.3
        selection_list.update(time_delta=0.05)

        visible_items = [
            item['text'] for item in selection_list.item_list
            if item['button_element'] is not None
        ]
        assert visible_items == [
            'item 5', 'item 6', 'item 7', 'item 8', 'item 9'
        ]
    def test_default_selection_changes(self, _init_pygame, default_ui_manager,
                                       default_display_surface,
                                       _display_surface_return_none):
        """
        Test that the default selection parameter does not permanently fix the list selection.
        """
        resolution = (400, 400)
        manager = UIManager(resolution)
        lst = [f'item {i}' for i in range(0, 20)]
        default = 10
        new_selection = 5

        # Test single selection list
        single_list = UISelectionList(relative_rect=pygame.Rect(
            100, 100, 400, 400),
                                      item_list=lst,
                                      default_selection=lst[default],
                                      manager=manager)

        event_data = {
            'ui_element':
            single_list.item_list_container.elements[new_selection]
        }
        select_event = pygame.event.Event(pygame_gui.UI_BUTTON_PRESSED,
                                          event_data)
        single_list.process_event(select_event)

        assert lst[new_selection] == single_list.get_single_selection()

        # Test multi-selection list
        default = [lst[10], lst[17]]
        selections = [4, 10, 15]

        multi_list = UISelectionList(relative_rect=pygame.Rect(
            100, 100, 400, 400),
                                     item_list=lst,
                                     default_selection=default,
                                     allow_multi_select=True,
                                     manager=manager)

        for selection in selections:
            event_data = {
                'ui_element':
                multi_list.item_list_container.elements[selection]
            }
            select_event = pygame.event.Event(pygame_gui.UI_BUTTON_PRESSED,
                                              event_data)
            multi_list.process_event(select_event)

        final_vals = multi_list.get_multi_selection()
        assert len(final_vals) == 3
        assert lst[10] not in final_vals
        assert lst[4] in final_vals
        assert lst[15] in final_vals
        assert lst[17] in final_vals
    def test_enable(self, _init_pygame: None, default_ui_manager: UIManager,
                    _display_surface_return_none: None):
        selection_list = UISelectionList(
            relative_rect=pygame.Rect(50, 50, 150, 400),
            item_list=['green', 'eggs', 'and', 'ham'],
            manager=default_ui_manager)

        assert selection_list.get_single_selection() is None

        selection_list.disable()
        selection_list.enable()
        assert selection_list.is_enabled is True
        assert selection_list.item_list_container.is_enabled is True

        # process a mouse button down event
        list_button = selection_list.item_list_container.elements[0]
        list_button.process_event(
            pygame.event.Event(pygame.MOUSEBUTTONDOWN, {
                'button': 1,
                'pos': list_button.rect.center
            }))

        # process a mouse button up event
        list_button.process_event(
            pygame.event.Event(pygame.MOUSEBUTTONUP, {
                'button': 1,
                'pos': list_button.rect.center
            }))

        for event in pygame.event.get():
            default_ui_manager.process_events(event)

        assert selection_list.get_single_selection() == 'green'
Exemple #6
0
    def setup(self):
        super().setup()
        buttons, self.button_mapping = self.button_list(
            [('Back', (Action.PRE_GAME, (self.campaign, ))),
             ('Buy', (self.buy, ())), ('Sell', (self.sell, ())),
             ('Equip', (self.equip, ()))], (0.15, 0.8), (100, 25))

        self.draw_money_display()
        self.buy_button = buttons[1]
        self.sell_button = buttons[2]
        self.equip_button = buttons[3]
        self.update_buttons()

        shop_items = self.level.shop_items
        shop_item_strings = [
            f'{item.name} ({item.cost}ξ)' for item in shop_items
        ]
        self.create_text('Shop', 24, bottomleft=(0.5, 0.25))
        shop_list = UISelectionList(relative_rect=self.proportional_rect(
            (0.5, 0.25), (0.35, 0.25)),
                                    item_list=shop_item_strings,
                                    manager=self.manager)

        for shop_item, list_item in zip(shop_items, shop_list.item_list):
            button = list_item["button_element"]
            self.button_mapping[button] = (self.item_selected,
                                           (shop_list, shop_item, button))

        self.create_text('Owned', 24, bottomleft=(0.5, 0.6))
        self.draw_owned_item_list()
    def test_show_hide_rendering(self, _init_pygame, default_ui_manager,
                                 _display_surface_return_none):
        resolution = (400, 400)
        empty_surface = pygame.Surface(resolution)
        empty_surface.fill(pygame.Color(0, 0, 0))

        surface = empty_surface.copy()
        manager = UIManager(resolution)

        selection_list = UISelectionList(
            relative_rect=pygame.Rect(100, 100, 400, 400),
            item_list=[
                'item 1', 'item 2', 'item 3', 'item 4', 'item 5', 'item 6',
                'item 7', 'item 8', 'item 9', 'item 10', 'item 11', 'item 12',
                'item 13', 'item 14', 'item 15', 'item 16'
            ],
            manager=manager,
            allow_multi_select=True,
            visible=0)
        manager.update(0.01)
        manager.draw_ui(surface)
        assert compare_surfaces(empty_surface, surface)

        surface.fill(pygame.Color(0, 0, 0))
        selection_list.show()
        manager.update(0.01)
        manager.draw_ui(surface)
        assert not compare_surfaces(empty_surface, surface)

        surface.fill(pygame.Color(0, 0, 0))
        selection_list.hide()
        manager.update(0.01)
        manager.draw_ui(surface)
        assert compare_surfaces(empty_surface, surface)
    def test_default_selection_sets_correctly(self):
        """
        Test that the default selection parameter ACTUALLY sets the values.
        """
        resolution = (400, 400)
        manager = UIManager(resolution)
        lst = [f'item {i}' for i in range(20)]
        selection = 'item 10'

        # Single-selection list default.
        single_list = UISelectionList(relative_rect=pygame.Rect(
            100, 100, 400, 400),
                                      item_list=lst,
                                      default_selection=selection,
                                      manager=manager)

        assert selection == single_list.get_single_selection()

        # Multi-selection list defaults.
        selection = ['item 3', 'item 10', 'item 15']
        multi_list = UISelectionList(relative_rect=pygame.Rect(
            100, 100, 400, 400),
                                     item_list=lst,
                                     default_selection=selection,
                                     allow_multi_select=True,
                                     manager=manager)

        assert selection == multi_list.get_multi_selection()
    def test_rebuild_from_changed_theme_data_bad_values(
            self, _init_pygame, _display_surface_return_none):
        manager = UIManager((800, 600),
                            os.path.join("tests", "data", "themes",
                                         "ui_selection_list_bad_values.json"))
        selection_list = UISelectionList(
            relative_rect=pygame.Rect(0, 0, 50, 80),
            item_list=[
                'item 1', 'item 2', 'item 3', 'item 4', 'item 5', 'item 6',
                'item 7', 'item 8', 'item 9', 'item 10', 'item 11', 'item 12',
                'item 13', 'item 14', 'item 15', 'item 16'
            ],
            manager=manager,
            allow_multi_select=True)

        assert selection_list.image is not None
Exemple #10
0
    def test_get_multi_selection(self, _init_pygame, default_ui_manager,
                                 _display_surface_return_none):
        selection_list = UISelectionList(
            relative_rect=pygame.Rect(50, 50, 150, 400),
            item_list=['green', 'eggs', 'and', 'ham'],
            manager=default_ui_manager,
            allow_multi_select=True)

        assert selection_list.get_multi_selection() == []

        event_data = {
            'user_type': pygame_gui.UI_BUTTON_PRESSED,
            'ui_element': selection_list.item_list_container.elements[0]
        }
        press_list_item_event = pygame.event.Event(pygame.USEREVENT,
                                                   event_data)
        default_ui_manager.process_events(press_list_item_event)

        assert selection_list.get_multi_selection() == ['green']

        event_data = {
            'user_type': pygame_gui.UI_BUTTON_PRESSED,
            'ui_element': selection_list.item_list_container.elements[1]
        }
        press_list_item_event = pygame.event.Event(pygame.USEREVENT,
                                                   event_data)
        default_ui_manager.process_events(press_list_item_event)
        assert selection_list.get_multi_selection() == ['green', 'eggs']

        single_selection_list = UISelectionList(
            relative_rect=pygame.Rect(50, 50, 150, 400),
            item_list=['green', 'eggs', 'and', 'ham'],
            manager=default_ui_manager)
        with pytest.raises(
                RuntimeError,
                match='Requesting multi selection, from single-selection list'
        ):
            single_selection_list.get_multi_selection()
Exemple #11
0
    def setup(self):
        super().setup()
        # current_level = active_player().level
        # current_level.screen = self

        campaign_strings = list()
        campaigns = sorted(Campaign.all_instances())
        for key, campaign in campaigns:
            num_levels = len(campaign.levels)
            levels_str = 'levels' if num_levels > 1 else 'level'
            campaign_strings.append(f'{campaign.name} ({num_levels} {levels_str})')
        # self.create_text('Shop', 24, bottomleft=(0.5, 0.25))
        campaign_list = UISelectionList(relative_rect=self.proportional_rect((0.5, 0.25), (0.35, 0.25)),
                                    item_list=campaign_strings, manager=self.manager)

        buttons, self.button_mapping = self.button_list(
            [('Play Campaign', (self.start_campaign, ())),
             ('Back', (Action.MAIN_MENU, None))], (0.15, 300), (100, 25))

        for (key, campaign), list_item in zip(campaigns, campaign_list.item_list):
            button = list_item["button_element"]
            self.button_mapping[button] = (self.campaign_selected, (campaign_list, campaign, button))
Exemple #12
0
    def draw_owned_item_list(self):
        if self.owned_list is not None:
            # Reset
            self.owned_list.kill()
            for button in self.owned_list_buttons:
                del self.button_mapping[button]
            self.owned_list_buttons.clear()

        owned_items = self.player.owned_weapons + self.player.owned_shields
        owned_item_strings = [
            f'{item.name} ({item.cost}ξ)' for item in owned_items
        ]
        self.owned_list = UISelectionList(relative_rect=self.proportional_rect(
            (0.5, 0.6), (0.35, 0.25)),
                                          item_list=owned_item_strings,
                                          manager=self.manager)

        for owned_item, list_item in zip(owned_items,
                                         self.owned_list.item_list):
            button = list_item["button_element"]
            self.button_mapping[button] = (self.item_selected,
                                           (self.owned_list, owned_item,
                                            button))
            self.owned_list_buttons.add(button)
    def test_set_item_list(self, _init_pygame, default_ui_manager,
                           _display_surface_return_none: None):
        selection_list = UISelectionList(
            relative_rect=pygame.Rect(50, 50, 150, 80),
            item_list=[
                'item 1', 'item 2', 'item 3', 'item 4', 'item 5', 'item 6',
                'item 7', 'item 8', 'item 9', 'item 10', 'item 11', 'item 12',
                'item 13', 'item 14', 'item 15', 'item 16'
            ],
            manager=default_ui_manager,
            allow_multi_select=True)

        assert selection_list.scroll_bar is not None
        visible_items = [
            item['text'] for item in selection_list.item_list
            if item['button_element'] is not None
        ]
        assert visible_items == ['item 1', 'item 2', 'item 3', 'item 4']

        selection_list.set_item_list([
            'new item 1', 'new item 2', 'new item 3', 'new item 4',
            'new item 5', 'new item 6', 'new item 7', 'new item 8',
            'new item 9', 'new item 10', 'new item 11', 'new item 12',
            'new item 13', 'new item 14', 'new item 15'
        ])

        assert selection_list.scroll_bar is not None
        visible_items = [
            item['text'] for item in selection_list.item_list
            if item['button_element'] is not None
        ]
        assert visible_items == [
            'new item 1', 'new item 2', 'new item 3', 'new item 4'
        ]

        selection_list.set_item_list(['another item 1', 'another item 2'])

        assert selection_list.scroll_bar is None
        visible_items = [
            item['text'] for item in selection_list.item_list
            if item['button_element'] is not None
        ]
        assert visible_items == ['another item 1', 'another item 2']
    def test_get_single_selection(self, _init_pygame, default_ui_manager,
                                  _display_surface_return_none):
        selection_list = UISelectionList(
            relative_rect=pygame.Rect(50, 50, 150, 400),
            item_list=['green', 'eggs', 'and', 'ham'],
            manager=default_ui_manager)

        assert selection_list.get_single_selection() is None

        event_data = {
            'ui_element': selection_list.item_list_container.elements[0]
        }
        press_list_item_event = pygame.event.Event(
            pygame_gui.UI_BUTTON_PRESSED, event_data)
        default_ui_manager.process_events(press_list_item_event)

        assert selection_list.get_single_selection() == 'green'

        selection_list.item_list[1]['selected'] = True
        with pytest.raises(
                RuntimeError,
                match=
                'More than one item selected in single-selection, selection list'
        ):
            selection_list.get_single_selection()

        multi_selection_list = UISelectionList(
            relative_rect=pygame.Rect(50, 50, 150, 400),
            item_list=['green', 'eggs', 'and', 'ham'],
            manager=default_ui_manager,
            allow_multi_select=True)
        with pytest.raises(
                RuntimeError,
                match='Requesting single selection, from multi-selection list'
        ):
            multi_selection_list.get_single_selection()
class MapSettingsWindow(UIWindow):
    def on_fall_add_btn_click(self):
        map_settings.settings.falls.append(
            EnemiesFall([
                EnemiesGroup([0] * len(enemy.enemies_definitions), 1.0,
                             [0.5, 1.0])
            ], 100))
        self.current_selected_group = 0
        self.update_settings()

    def on_fall_remove_btn_click(self):
        if len(map_settings.settings.falls) > 1:
            map_settings.settings.falls.remove(
                map_settings.settings.falls[self.current_selected_fall])
            self.current_selected_fall = 0
            self.current_selected_group = 0
            self.update_settings()

    def on_fall_list_item_select(self):
        for i in range(0, len(self.falls_ui_list.item_list)):
            if self.falls_ui_list.item_list[i]['selected']:
                self.current_selected_fall = i
                self.current_selected_group = 0
                self.update_groups_list()
                self.update_fall_panel()
                return

    def on_group_add_btn_click(self):
        map_settings.settings.falls[self.current_selected_fall].groups.append(
            EnemiesGroup([0] * len(enemy.enemies_definitions), 1.0,
                         [0.5, 1.0]))
        self.update_groups_list()
        self.update_group_panel()
        self.update_enemies_panel()

    def on_group_remove_btn_click(self):
        curr_fall = map_settings.settings.falls[self.current_selected_fall]
        if len(curr_fall.groups) > 1:
            curr_fall.groups.remove(
                curr_fall.groups[self.current_selected_group])
        self.current_selected_group = 0
        self.update_groups_list()

    def on_fall_gold_text_changed(self, e):
        if len(map_settings.settings.falls) > 0:
            if len(e.text) > 0 and e.text.isnumeric():
                map_settings.settings.falls[
                    self.current_selected_fall].gold_reward = int(e.text)
            else:
                map_settings.settings.falls[
                    self.current_selected_fall].gold_reward = 0
                self.update_fall_panel()

    def on_start_gold_text_changed(self, e):
        if len(e.text) > 0 and e.text.isnumeric():
            map_settings.settings.start_gold = int(e.text)
        else:
            map_settings.settings.start_gold = 0
            self.update_general_panel()

    def on_start_mana_text_changed(self, e):
        if len(e.text) > 0 and e.text.isnumeric():
            map_settings.settings.start_mana = int(e.text)
        else:
            map_settings.settings.start_mana = 0
            self.update_general_panel()

    def on_group_list_item_select(self, e):
        for i in range(0, len(self.groups_ui_list.item_list)):
            if self.groups_ui_list.item_list[i]['selected']:
                self.current_selected_group = i
                self.update_group_panel()
                self.update_enemies_panel()
                return

    def on_group_spawn_delay_changed(self, e):
        if len(map_settings.settings.falls) > 0:
            if len(map_settings.settings.falls[
                    self.current_selected_fall].groups) > 0:
                curr_group = map_settings.settings.falls[
                    self.current_selected_fall].groups[
                        self.current_selected_group]
                if len(e.text) > 0 and utils.is_float(e.text):
                    curr_group.spawn_delay = float(e.text)
                else:
                    curr_group.spawn_delay = 0.0
                    self.update_group_panel()

    def on_group_spawn_interval_left_changed(self, e):
        if len(map_settings.settings.falls) > 0:
            if len(map_settings.settings.falls[
                    self.current_selected_fall].groups) > 0:
                curr_group = map_settings.settings.falls[
                    self.current_selected_fall].groups[
                        self.current_selected_group]
                if len(e.text) > 0 and utils.is_float(e.text):
                    curr_group.interval[0] = float(e.text)
                else:
                    curr_group.interval[0] = 0.0
                    self.update_group_panel()

    def on_group_spawn_interval_right_changed(self, e):
        if len(map_settings.settings.falls) > 0:
            if len(map_settings.settings.falls[
                    self.current_selected_fall].groups) > 0:
                curr_group = map_settings.settings.falls[
                    self.current_selected_fall].groups[
                        self.current_selected_group]
                if len(e.text) > 0 and utils.is_float(e.text):
                    curr_group.interval[1] = float(e.text)
                else:
                    curr_group.interval[1] = 0.0
                    self.update_group_panel()

    def on_change_enemy_count(self, e, i):
        if len(map_settings.settings.falls) > 0:
            if len(map_settings.settings.falls[
                    self.current_selected_fall].groups) > 0:
                curr_group = map_settings.settings.falls[
                    self.current_selected_fall].groups[
                        self.current_selected_group]
                if len(e.text) > 0 and e.text.isnumeric():
                    curr_group.enemies_counts[i] = int(e.text)
                else:
                    curr_group.enemies_counts[i] = 0
                    self.update_enemies_panel()

    def on_max_tower_text_changed(self, e):
        if len(e.text) > 0 and e.text.isnumeric():
            map_settings.settings.max_tower = math_utils.clamp(
                int(e.text), 0, len(tower.tower_definitions))
        else:
            map_settings.settings.max_tower = len(tower.tower_definitions)
            self.update_general_panel()

    def on_max_spell_text_changed(self, e):
        if len(e.text) > 0 and e.text.isnumeric():
            map_settings.settings.max_spell = math_utils.clamp(
                int(e.text), 0, len(spell.spells_definitions))
        else:
            map_settings.settings.max_spell = len(spell.spells_definitions)
            self.update_general_panel()

    def __init__(self):
        windowWidth = 1340
        windowHeight = 600
        super().__init__(pygame.Rect(
            SCREEN_WIDTH * 0.5 - windowWidth * 0.5,
            SCREEN_HEIGHT * 0.5 - windowHeight * 0.5,
            windowWidth,
            windowHeight,
        ),
                         ui_manager,
                         window_display_title="Settings",
                         resizable=False)

        UILabel(pygame.Rect(0, 0, 80, 30),
                "General",
                ui_manager,
                container=self)

        general_panel = UIPanel(pygame.Rect(10, 30, 250, 600 - 100),
                                starting_layer_height=4,
                                manager=ui_manager,
                                container=self,
                                object_id="#thicker_panel")
        UILabel(pygame.Rect(10, 10, 80, 30),
                "Start Gold",
                ui_manager,
                container=general_panel)

        self.start_gold_text_line = UITextEntryLine(
            pygame.Rect(100, 10, 60, 20),
            manager=ui_manager,
            container=general_panel,
            #object_id='#file_path_text_line',
            anchors={
                'left': 'left',
                'right': 'left',
                'top': 'top',
                'bottom': 'bottom'
            })

        register_ui_callback(self.start_gold_text_line,
                             pygame_gui.UI_TEXT_ENTRY_CHANGED,
                             lambda e: self.on_start_gold_text_changed(e))

        UILabel(pygame.Rect(10, 40, 80, 30),
                "Start Mana",
                ui_manager,
                container=general_panel)
        self.start_mana_text_line = UITextEntryLine(
            pygame.Rect(100, 40, 60, 20),
            manager=ui_manager,
            container=general_panel,
            #object_id='#file_path_text_line',
            anchors={
                'left': 'left',
                'right': 'left',
                'top': 'top',
                'bottom': 'bottom'
            })

        register_ui_callback(self.start_mana_text_line,
                             pygame_gui.UI_TEXT_ENTRY_CHANGED,
                             lambda e: self.on_start_mana_text_changed(e))

        UILabel(pygame.Rect(10, 70, 80, 30),
                "Max Tower",
                ui_manager,
                container=general_panel)

        self.max_tower_text_line = UITextEntryLine(
            pygame.Rect(100, 70, 60, 20),
            manager=ui_manager,
            container=general_panel,
            #object_id='#file_path_text_line',
            anchors={
                'left': 'left',
                'right': 'left',
                'top': 'top',
                'bottom': 'bottom'
            })

        register_ui_callback(self.max_tower_text_line,
                             pygame_gui.UI_TEXT_ENTRY_CHANGED,
                             lambda e: self.on_max_tower_text_changed(e))

        UILabel(pygame.Rect(10, 100, 80, 30),
                "Max Spell",
                ui_manager,
                container=general_panel)

        self.max_spell_text_line = UITextEntryLine(
            pygame.Rect(100, 100, 60, 20),
            manager=ui_manager,
            container=general_panel,
            #object_id='#file_path_text_line',
            anchors={
                'left': 'left',
                'right': 'left',
                'top': 'top',
                'bottom': 'bottom'
            })

        register_ui_callback(self.max_spell_text_line,
                             pygame_gui.UI_TEXT_ENTRY_CHANGED,
                             lambda e: self.on_max_spell_text_changed(e))

        # ---------------------------- falls

        UILabel(pygame.Rect(250, 0, 80, 30),
                "Falls",
                ui_manager,
                container=self)

        self.falls_list = ["Dummy", "Dummy"]
        self.current_selected_fall = 0
        self.falls_ui_list = UISelectionList(
            pygame.Rect(270, 30, 250, 220),
            item_list=self.falls_list,
            manager=ui_manager,
            container=self,
            object_id="#thicker_panel",
        )

        register_ui_callback(self.falls_ui_list,
                             pygame_gui.UI_SELECTION_LIST_NEW_SELECTION,
                             lambda e: self.on_fall_list_item_select())

        self.fall_add_btn = UIButton(pygame.Rect(270, 250, 125, 30),
                                     "Add Fall",
                                     ui_manager,
                                     container=self)
        self.fall_remove_btn = UIButton(pygame.Rect(395, 250, 125, 30),
                                        "Remove Fall",
                                        ui_manager,
                                        container=self)

        register_ui_callback(self.fall_add_btn, pygame_gui.UI_BUTTON_PRESSED,
                             lambda e: self.on_fall_add_btn_click())
        register_ui_callback(self.fall_remove_btn,
                             pygame_gui.UI_BUTTON_PRESSED,
                             lambda e: self.on_fall_remove_btn_click())

        UILabel(pygame.Rect(262, 290, 120, 30),
                "Fall Settings",
                ui_manager,
                container=self)

        self.fall_settings_panel = UIPanel(pygame.Rect(270, 320, 250, 210),
                                           starting_layer_height=4,
                                           object_id="#thicker_panel",
                                           manager=ui_manager,
                                           container=self)

        # gold reward

        UILabel(pygame.Rect(5, 10, 100, 30),
                "Gold Reward",
                ui_manager,
                container=self.fall_settings_panel)

        self.fall_gold_reward = UITextEntryLine(
            pygame.Rect(105, 10, 60, 20),
            manager=ui_manager,
            container=self.fall_settings_panel,
        )

        register_ui_callback(self.fall_gold_reward,
                             pygame_gui.UI_TEXT_ENTRY_CHANGED,
                             lambda e: self.on_fall_gold_text_changed(e))

        # ---------------------------- groups

        UILabel(pygame.Rect(515, 0, 80, 30),
                "Groups",
                ui_manager,
                container=self)

        self.groups_list = []
        self.current_selected_group = 0
        self.groups_ui_list = UISelectionList(
            pygame.Rect(530, 30, 380, 220),
            item_list=self.groups_list,
            manager=ui_manager,
            container=self,
            object_id="#thicker_panel",
        )

        register_ui_callback(self.groups_ui_list,
                             pygame_gui.UI_SELECTION_LIST_NEW_SELECTION,
                             lambda e: self.on_group_list_item_select(e))

        self.group_add_btn = UIButton(pygame.Rect(530, 250, 380 * 0.5, 30),
                                      "Add Group",
                                      ui_manager,
                                      container=self)
        self.group_remove_btn = UIButton(pygame.Rect(530 + 380 * 0.5, 250,
                                                     380 * 0.5, 30),
                                         "Remove Group",
                                         ui_manager,
                                         container=self)

        register_ui_callback(self.group_add_btn, pygame_gui.UI_BUTTON_PRESSED,
                             lambda e: self.on_group_add_btn_click())
        register_ui_callback(self.group_remove_btn,
                             pygame_gui.UI_BUTTON_PRESSED,
                             lambda e: self.on_group_remove_btn_click())

        UILabel(pygame.Rect(530, 290, 120, 30),
                "Group Settings",
                ui_manager,
                container=self)

        group_settings_panel = UIPanel(pygame.Rect(530, 320, 380, 210),
                                       starting_layer_height=4,
                                       object_id="#thicker_panel",
                                       manager=ui_manager,
                                       container=self)

        UILabel(pygame.Rect(5, 10, 100, 30),
                "Spawn After",
                ui_manager,
                container=group_settings_panel)

        self.group_spawn_mode_dropdown = UIDropDownMenu(
            ["End Of Previous Group Spawn", "Previous Group Destruction"],
            "End Of Previous Group Spawn",
            pygame.Rect(105, 15, 250, 20),
            ui_manager,
            container=group_settings_panel)

        # spawn delay

        UILabel(pygame.Rect(5, 45, 100, 30),
                "Spawn Delay",
                ui_manager,
                container=group_settings_panel)
        self.spawn_delay_entry_line = UITextEntryLine(
            pygame.Rect(105, 45, 40, 20),
            manager=ui_manager,
            container=group_settings_panel)
        UILabel(pygame.Rect(150, 45, 60, 30),
                "seconds",
                ui_manager,
                container=group_settings_panel)

        register_ui_callback(self.spawn_delay_entry_line,
                             pygame_gui.UI_TEXT_ENTRY_CHANGED,
                             lambda e: self.on_group_spawn_delay_changed(e))

        # interval

        UILabel(pygame.Rect(-2, 80, 100, 30),
                "Interval:",
                ui_manager,
                container=group_settings_panel)
        UILabel(pygame.Rect(2, 115, 50, 30),
                "From",
                ui_manager,
                container=group_settings_panel)
        self.interval_from_entry_line = UITextEntryLine(
            pygame.Rect(50, 115, 40, 20),
            manager=ui_manager,
            container=group_settings_panel)
        UILabel(pygame.Rect(95, 115, 20, 30),
                "To",
                ui_manager,
                container=group_settings_panel)
        self.interval_to_entry_line = UITextEntryLine(
            pygame.Rect(120, 115, 40, 20),
            manager=ui_manager,
            container=group_settings_panel)
        UILabel(pygame.Rect(165, 115, 60, 30),
                "seconds",
                ui_manager,
                container=group_settings_panel)

        register_ui_callback(
            self.interval_from_entry_line, pygame_gui.UI_TEXT_ENTRY_CHANGED,
            lambda e: self.on_group_spawn_interval_left_changed(e))

        register_ui_callback(
            self.interval_to_entry_line, pygame_gui.UI_TEXT_ENTRY_CHANGED,
            lambda e: self.on_group_spawn_interval_right_changed(e))

        # ---------------------------- enemies

        self.enemies_label = UILabel(pygame.Rect(910, 0, 80, 30),
                                     "Enemies",
                                     ui_manager,
                                     container=self)

        self.enemies_view_panel = UIPanel(relative_rect=pygame.Rect(
            920, 30, 385, 505),
                                          starting_layer_height=4,
                                          object_id="#thicker_panel",
                                          manager=ui_manager,
                                          container=self)
        #self.enemies_view_panel.hide()
        #self.enemies_label.hide()

        #250, 600 - 100
        self.enemy_container = UIScrollingContainer(
            pygame.Rect(0, 0, 380, 500),
            ui_manager,
            container=self.enemies_view_panel,
            object_id="#enemy_scrolling_container",
            starting_height=4)

        item_height = 165
        self.enemy_container.set_scrollable_area_dimensions(
            (360, 5 + len(enemy.enemies_definitions) * item_height + 10))
        """
        for n in range(0, 24):
            UIButton(
                pygame.Rect(5, 5 + 50 * n, 370, 45),
                "hi",
                ui_manager,
                self.enemy_container
            )
        """

        self.enemies_counts_entry_lines = []
        for n in range(0, len(enemy.enemies_definitions)):
            enemy_panel = UIPanel(relative_rect=pygame.Rect(
                5, 5 + item_height * n, 350, item_height),
                                  starting_layer_height=4,
                                  manager=ui_manager,
                                  container=self.enemy_container,
                                  object_id="#thicker_panel")
            enemy_stats_panel = UIPanel(relative_rect=pygame.Rect(
                10, 35, 325, 80),
                                        starting_layer_height=4,
                                        manager=ui_manager,
                                        container=enemy_panel)

            UITextBox(
                "<b>" + enemy.enemies_definitions[n].name + "</b>",
                pygame.Rect(5, 5, 340, 30),
                ui_manager,
                container=enemy_panel,
                object_id="#no_border_textbox",
            )
            definition = enemy.enemies_definitions[n]
            preview_sprite_path = ENEMIES_PATH + definition.sprites_directory + "/" + definition.preview_sprite + ".png"
            image_size = (720 * 0.15, 480 * 0.15)
            UIImage(relative_rect=pygame.Rect(5, 5, image_size[0],
                                              image_size[1]),
                    image_surface=resource_cache.get_resource(
                        preview_sprite_path,
                        resource_cache.SurfaceType,
                        alpha=True),
                    manager=ui_manager,
                    container=enemy_stats_panel)
            UITextBox("<font color=#00FF00><b>Health: </b></font>" +
                      str(definition.health) + "<br><br>"
                      "<font color=#BB0000><b>Damage: </b></font>" +
                      str(definition.damages) + "</br></br>" +
                      "<font color=#4488FF><b>Speed: </b></font>" +
                      str(definition.speed),
                      pygame.Rect(5 + image_size[0] + 5, 5, 120, 140),
                      ui_manager,
                      container=enemy_stats_panel,
                      object_id="#no_border_textbox")
            UITextBox("Count: ",
                      pygame.Rect(5, item_height - 45, 80, 30),
                      ui_manager,
                      container=enemy_panel,
                      object_id="#no_border_textbox")
            self.enemies_counts_entry_lines.append(
                UITextEntryLine(
                    pygame.Rect(65, item_height - 45, 50, 25),
                    manager=ui_manager,
                    container=enemy_panel,
                ))

            register_ui_callback(
                self.enemies_counts_entry_lines[n],
                pygame_gui.UI_TEXT_ENTRY_CHANGED,
                lambda e, i=n: self.on_change_enemy_count(e, i))

        self.set_blocking(True)
        self.update_settings()

    def update_falls_list(self):
        self.falls_list = []
        for i in range(0, len(map_settings.settings.falls)):
            self.falls_list.append("Fall " + str(i + 1))
        self.falls_ui_list.set_item_list(self.falls_list)

        if len(self.falls_list) > 0:
            # self.falls_ui_list.item_list[self.current_selected_fall]['selected'] = True
            curr_fall = map_settings.settings.falls[self.current_selected_fall]
            self.fall_gold_reward.set_text(str(curr_fall.gold_reward))

    def update_groups_list(self):
        if len(self.falls_list) > 0:
            curr_fall = map_settings.settings.falls[self.current_selected_fall]

            # there is always at least 1 group per fall
            self.groups_list = []
            for i in range(0, len(curr_fall.groups)):
                self.groups_list.append("Group " + str(i + 1))
            self.groups_ui_list.set_item_list(self.groups_list)

    def update_group_panel(self):
        curr_fall = map_settings.settings.falls[self.current_selected_fall]
        if len(self.falls_list) > 0 and len(curr_fall.groups) > 0:
            curr_group = curr_fall.groups[self.current_selected_group]
            self.group_spawn_mode_dropdown.selected_option = curr_group.spawn_mode
            self.spawn_delay_entry_line.set_text(str(curr_group.spawn_delay))
            self.interval_from_entry_line.set_text(str(curr_group.interval[0]))
            self.interval_to_entry_line.set_text(str(curr_group.interval[1]))

    def update_fall_panel(self):
        self.fall_gold_reward.set_text(
            str(map_settings.settings.falls[
                self.current_selected_fall].gold_reward))

    def update_general_panel(self):
        self.start_gold_text_line.set_text(
            str(map_settings.settings.start_gold))
        self.start_mana_text_line.set_text(
            str(map_settings.settings.start_mana))
        self.max_tower_text_line.set_text(str(map_settings.settings.max_tower))
        self.max_spell_text_line.set_text(str(map_settings.settings.max_spell))

    def update_enemies_panel(self):
        curr_group = map_settings.settings.falls[
            self.current_selected_fall].groups[self.current_selected_group]
        for n in range(0, len(self.enemies_counts_entry_lines)):
            self.enemies_counts_entry_lines[n].set_text(
                str(curr_group.enemies_counts[n]))

    def update_settings(self):
        self.update_general_panel()
        self.update_falls_list()
        self.update_groups_list()
    def test_default_selection_exceptions(self):
        """
        Test that all exceptions throw appropriately:
        1. ValueError if a list of strings/string tuples is passed to a single-selection list.
        2. TypeError is a completely invalid type (like an object) is passed.
        3. ValueError if ANY of the requested default values are not actually present in the item
            list.
        """
        resolution = (400, 400)
        manager = UIManager(resolution)
        lst = [f'item {n}' for n in range(20)]

        # Test Case 1
        test_case_1_throws = False
        try:
            UISelectionList(relative_rect=pygame.Rect(100, 100, 400, 400),
                            item_list=lst,
                            default_selection=['item 1', 'item 2'],
                            manager=manager)
        except ValueError as e:
            assert 'Multiple default values' in str(e)
            test_case_1_throws = True

        assert test_case_1_throws is True

        # Test Case 2
        test_case_2_throws = False
        try:
            UISelectionList(relative_rect=pygame.Rect(100, 100, 400, 400),
                            item_list=lst,
                            default_selection=4,
                            manager=manager)
        except TypeError as e:
            assert 'is not a string or (str, str) tuple.' in str(e)
            test_case_2_throws = True

        assert test_case_2_throws is True

        # Test Case 3 for single-selection lists
        test_case_3_single_throws = False
        try:
            UISelectionList(relative_rect=pygame.Rect(100, 100, 400, 400),
                            item_list=lst,
                            default_selection='I am not in the list',
                            manager=manager)
        except ValueError as e:
            assert 'not found in selection list' in str(e)
            test_case_3_single_throws = True

        assert test_case_3_single_throws is True

        # Test Case 4 for multi-select lists.
        test_case_3_multiple_throws = False
        try:
            UISelectionList(
                relative_rect=pygame.Rect(100, 100, 400, 400),
                item_list=lst,
                default_selection=['item 1', 'I am not in the list'],
                allow_multi_select=True,
                manager=manager)
        except ValueError as e:
            assert 'not found in selection list' in str(e)
            test_case_3_multiple_throws = True

        assert test_case_3_multiple_throws is True
Exemple #17
0
    def start(self):
        """
        Called each time we enter the expanded state. It creates the necessary elements, the
        selected option, all the other available options and the close button.

        """
        self.should_transition = False

        self.selected_option_button = UIButton(pygame.Rect(self.base_position_rect.topleft,
                                                           (self.base_position_rect.width -
                                                            self.close_button_width,
                                                            self.base_position_rect.height)),
                                               self.selected_option,
                                               self.ui_manager,
                                               self.ui_container,
                                               starting_height=2,
                                               parent_element=self.drop_down_menu_ui,
                                               object_id=ObjectID('#selected_option', None))
        self.drop_down_menu_ui.join_focus_sets(self.selected_option_button)

        expand_button_symbol = '▼'

        list_object_id = '#drop_down_options_list'
        list_object_ids = self.drop_down_menu_ui.object_ids[:]
        list_object_ids.append(list_object_id)
        list_class_ids = self.drop_down_menu_ui.class_ids[:]
        list_class_ids.append(None)
        list_element_ids = self.drop_down_menu_ui.element_ids[:]
        list_element_ids.append('selection_list')

        final_ids = self.ui_manager.get_theme().build_all_combined_ids(list_element_ids,
                                                                       list_class_ids,
                                                                       list_object_ids)

        try:
            list_shadow_width = int(
                self.ui_manager.get_theme().get_misc_data('shadow_width', final_ids))
        except (LookupError, ValueError):
            list_shadow_width = 2

        try:
            list_border_width = int(
                self.ui_manager.get_theme().get_misc_data('border_width', final_ids))
        except (LookupError, ValueError):
            list_border_width = 1

        try:
            list_item_height = int(
                self.ui_manager.get_theme().get_misc_data('list_item_height', final_ids))
        except (LookupError, ValueError):
            list_item_height = 20

        options_list_border_and_shadow = list_shadow_width + list_border_width
        self.options_list_height = ((list_item_height * len(self.options_list)) +
                                    (2 * options_list_border_and_shadow))
        self.option_list_y_pos = 0
        if self.expand_direction is not None:
            if self.expand_direction == 'up':
                expand_button_symbol = '▲'

                if self.drop_down_menu_ui.expansion_height_limit is None:
                    self.drop_down_menu_ui.expansion_height_limit = self.base_position_rect.top

                self.options_list_height = min(self.options_list_height,
                                               self.drop_down_menu_ui.expansion_height_limit)

                self.option_list_y_pos = self.base_position_rect.top - self.options_list_height

            elif self.expand_direction == 'down':
                expand_button_symbol = '▼'

                if self.drop_down_menu_ui.expansion_height_limit is None:
                    height_limit = (self.drop_down_menu_ui.ui_container.relative_rect.height -
                                    self.base_position_rect.bottom)
                    self.drop_down_menu_ui.expansion_height_limit = height_limit

                self.options_list_height = min(self.options_list_height,
                                               self.drop_down_menu_ui.expansion_height_limit)

                self.option_list_y_pos = self.base_position_rect.bottom

        close_button_x = (self.base_position_rect.x +
                          self.base_position_rect.width -
                          self.close_button_width)

        self.close_button = UIButton(pygame.Rect((close_button_x,
                                                  self.base_position_rect.y),
                                                 (self.close_button_width,
                                                  self.base_position_rect.height)),
                                     expand_button_symbol,
                                     self.ui_manager,
                                     self.ui_container,
                                     starting_height=2,
                                     parent_element=self.drop_down_menu_ui,
                                     object_id='#expand_button')
        self.drop_down_menu_ui.join_focus_sets(self.close_button)

        list_rect = pygame.Rect(self.drop_down_menu_ui.relative_rect.left,
                                self.option_list_y_pos,
                                (self.drop_down_menu_ui.relative_rect.width -
                                 self.close_button_width),
                                self.options_list_height)
        self.options_selection_list = UISelectionList(list_rect,
                                                      starting_height=2,
                                                      item_list=self.options_list,
                                                      allow_double_clicks=False,
                                                      manager=self.ui_manager,
                                                      parent_element=self.drop_down_menu_ui,
                                                      container=self.ui_container,
                                                      object_id='#drop_down_options_list')
        self.drop_down_menu_ui.join_focus_sets(self.options_selection_list)

        self.rebuild()
Exemple #18
0
    def __init__(self, path, title, confirm_callback, save):
        super().__init__(
            pygame.Rect(SCREEN_WIDTH / 2 - 440 / 2, SCREEN_HEIGHT / 2 - 500 / 2, 440, 500),
            ui_manager,
            window_display_title=title,
            resizable=True
        )

        # set initial path
        self.path = path
        self.current_file_list = []
        self.confirm_callback = confirm_callback
        self.save = save

        # set minimum dimensions
        minimum_dimensions = (300, 300)
        self.set_minimum_dimensions(minimum_dimensions)

        # file browser panel
        file_selection_rect = pygame.Rect(
            10,
            20,
            self.get_container().get_size()[0] - 20,
            self.get_container().get_size()[1] - 70
        )

        self.update_file_list()
        self.file_selection_list = UISelectionList(
            relative_rect=file_selection_rect,
            item_list=self.current_file_list,
            manager=ui_manager,
            container=self,
            object_id='#file_display_list',
            anchors=
            {
                'left': 'left',
                'right': 'right',
                'top': 'top',
                'bottom': 'bottom'
            }
        )
        register_ui_callback(
            self.file_selection_list,
            pygame_gui.UI_SELECTION_LIST_NEW_SELECTION,
            lambda e: self.file_name_text_line.set_text(e.text)
        )

        # text entry line to write file name
        text_line_rect = pygame.Rect(10, -40, self.get_container().get_size()[0] - 110, 25)
        self.file_name_text_line = UITextEntryLine(
            relative_rect=text_line_rect,
            manager=self.ui_manager,
            container=self,
            object_id='#file_path_text_line',
            anchors=
            {
                'left': 'left',
                'right': 'right',
                'top': 'bottom',
                'bottom': 'bottom'
            }
        )
        if not save:
            self.file_name_text_line.disable()

        # confirm button
        confirm_btn_rect = pygame.Rect(-90, -40, 80, 30)
        self.confirm_btn = UIButton(
            relative_rect=confirm_btn_rect,
            text="OK",
            manager=self.ui_manager,
            container=self,
            anchors=
            {
                'left': 'right',
                'right': 'right',
                'top': 'bottom',
                'bottom': 'bottom'
            }
        )
        register_ui_callback(
            self.confirm_btn,
            pygame_gui.UI_BUTTON_PRESSED,
            lambda e: (
                self.on_confirm_btn_click()
            )
        )

        self.set_blocking(True)
 def test_creation(self, _init_pygame, default_ui_manager,
                   _display_surface_return_none):
     UISelectionList(relative_rect=pygame.Rect(50, 50, 150, 400),
                     item_list=['green', 'eggs', 'and', 'ham'],
                     manager=default_ui_manager)
    def test_process_event(self, _init_pygame, default_ui_manager,
                           _display_surface_return_none: None):
        selection_list = UISelectionList(
            relative_rect=pygame.Rect(50, 50, 150, 80),
            item_list=[
                'item 1', 'item 2', 'item 3', 'item 4', 'item 5', 'item 6',
                'item 7', 'item 8', 'item 9', 'item 10', 'item 11', 'item 12',
                'item 13', 'item 14', 'item 15', 'item 16'
            ],
            manager=default_ui_manager,
            allow_multi_select=True,
            allow_double_clicks=True)

        event_data = {
            'ui_element': selection_list.item_list_container.elements[0]
        }
        select_event = pygame.event.Event(pygame_gui.UI_BUTTON_PRESSED,
                                          event_data)

        selection_list.process_event(select_event)

        confirm_event_fired = False
        event_text = None
        for event in pygame.event.get():
            if (event.type == pygame_gui.UI_SELECTION_LIST_NEW_SELECTION
                    and event.ui_element == selection_list):
                confirm_event_fired = True
                event_text = event.text

        assert confirm_event_fired
        assert event_text == 'item 1'

        event_data = {
            'ui_element': selection_list.item_list_container.elements[0]
        }
        unselect_event = pygame.event.Event(pygame_gui.UI_BUTTON_PRESSED,
                                            event_data)

        selection_list.process_event(unselect_event)

        confirm_event_fired = False
        event_text = None
        for event in pygame.event.get():
            if (event.type == pygame_gui.UI_SELECTION_LIST_DROPPED_SELECTION
                    and event.ui_element == selection_list):
                confirm_event_fired = True
                event_text = event.text

        assert confirm_event_fired
        assert event_text == 'item 1'

        event_data = {
            'ui_element': selection_list.item_list_container.elements[0]
        }
        double_clicked_event = pygame.event.Event(
            pygame_gui.UI_BUTTON_DOUBLE_CLICKED, event_data)

        selection_list.process_event(double_clicked_event)

        confirm_event_fired = False
        event_text = None
        for event in pygame.event.get():
            if (event.type
                    == pygame_gui.UI_SELECTION_LIST_DOUBLE_CLICKED_SELECTION
                    and event.ui_element == selection_list):
                confirm_event_fired = True
                event_text = event.text

        assert confirm_event_fired
        assert event_text == 'item 1'

        single_selection_list = UISelectionList(
            relative_rect=pygame.Rect(50, 50, 150, 80),
            item_list=[
                'item 1', 'item 2', 'item 3', 'item 4', 'item 5', 'item 6',
                'item 7', 'item 8', 'item 9', 'item 10', 'item 11', 'item 12',
                'item 13', 'item 14', 'item 15', 'item 16'
            ],
            manager=default_ui_manager,
            allow_multi_select=False,
            allow_double_clicks=True)

        event_data = {
            'ui_element': single_selection_list.item_list_container.elements[0]
        }
        select_event = pygame.event.Event(pygame_gui.UI_BUTTON_PRESSED,
                                          event_data)

        single_selection_list.process_event(select_event)

        event_data = {
            'ui_element': single_selection_list.item_list_container.elements[1]
        }
        select_another_event = pygame.event.Event(pygame_gui.UI_BUTTON_PRESSED,
                                                  event_data)

        single_selection_list.process_event(select_another_event)

        dropped_event_text = None
        select_event_text = None
        for event in pygame.event.get():
            if (event.type == pygame_gui.UI_SELECTION_LIST_NEW_SELECTION
                    and event.ui_element == single_selection_list):
                select_event_text = event.text

            if (event.type == pygame_gui.UI_SELECTION_LIST_DROPPED_SELECTION
                    and event.ui_element == single_selection_list):
                dropped_event_text = event.text

        assert select_event_text == 'item 2' and dropped_event_text == 'item 1'
Exemple #21
0
chat_textBox = pygame_gui.elements.UITextBox(relative_rect=pygame.Rect(
    10, 60, 350, 400),
                                             html_text=html,
                                             manager=manager)

chat_entryText = pygame_gui.elements.UITextEntryLine(relative_rect=pygame.Rect(
    10, 460, 350, 200),
                                                     manager=manager)

button_online = pygame_gui.elements.UIButton(relative_rect=pygame.Rect(
    385, 100, 90, 30),
                                             text='Online',
                                             manager=manager)

lista = UISelectionList(relative_rect=pygame.Rect(405, 200, 150, 146),
                        item_list=agenda,
                        manager=manager)

screen.fill(grey)
clock = pygame.time.Clock()

manager.draw_ui(screen)
pygame.display.flip()

chat_context = None

running = True
while running:
    time_delta = clock.tick(60) / 1000.0

    screen.blit(text, textRect)
Exemple #22
0
    def start(self, should_rebuild: bool = True):
        """
        Called each time we enter the expanded state. It creates the necessary elements, the
        selected option, all the other available options and the close button.

        """
        self.should_transition = False

        border_and_shadow = (self.drop_down_menu_ui.shadow_width +
                             self.drop_down_menu_ui.border_width)
        self.active_buttons = []
        self.selected_option_button = UIButton(
            pygame.Rect(
                (border_and_shadow, border_and_shadow),
                (self.base_position_rect.width - self.close_button_width,
                 self.base_position_rect.height)),
            self.selected_option,
            self.ui_manager,
            self.ui_container,
            starting_height=2,
            parent_element=self.drop_down_menu_ui,
            object_id=ObjectID('#selected_option', None))
        self.drop_down_menu_ui.join_focus_sets(self.selected_option_button)
        self.active_buttons.append(self.selected_option_button)

        expand_button_symbol = '▼'

        list_object_id = '#drop_down_options_list'
        list_object_ids = self.drop_down_menu_ui.object_ids[:]
        list_object_ids.append(list_object_id)
        list_class_ids = self.drop_down_menu_ui.class_ids[:]
        list_class_ids.append(None)
        list_element_ids = self.drop_down_menu_ui.element_ids[:]
        list_element_ids.append('selection_list')

        final_ids = self.ui_manager.get_theme().build_all_combined_ids(
            list_element_ids, list_class_ids, list_object_ids)

        self._calculate_options_list_sizes(final_ids)
        if self.expand_direction is not None:
            if self.expand_direction == 'up':
                expand_button_symbol = '▲'

                if self.drop_down_menu_ui.expansion_height_limit is None:
                    self.drop_down_menu_ui.expansion_height_limit = self.base_position_rect.top

                self.options_list_height = min(
                    self.options_list_height,
                    self.drop_down_menu_ui.expansion_height_limit)

                self.option_list_y_pos = self.base_position_rect.top - self.options_list_height

            elif self.expand_direction == 'down':
                expand_button_symbol = '▼'

                if self.drop_down_menu_ui.expansion_height_limit is None:
                    height_limit = (self.drop_down_menu_ui.ui_container.
                                    relative_rect.height -
                                    self.base_position_rect.bottom)
                    self.drop_down_menu_ui.expansion_height_limit = height_limit

                self.options_list_height = min(
                    self.options_list_height,
                    self.drop_down_menu_ui.expansion_height_limit)

                self.option_list_y_pos = self.base_position_rect.bottom

        if self.close_button_width > 0:
            close_button_x = (border_and_shadow +
                              self.base_position_rect.width -
                              self.close_button_width)

            self.close_button = UIButton(pygame.Rect(
                (close_button_x, border_and_shadow),
                (self.close_button_width, self.base_position_rect.height)),
                                         expand_button_symbol,
                                         self.ui_manager,
                                         self.ui_container,
                                         starting_height=2,
                                         parent_element=self.drop_down_menu_ui,
                                         object_id='#expand_button')
            self.drop_down_menu_ui.join_focus_sets(self.close_button)
            self.active_buttons.append(self.close_button)
        list_rect = pygame.Rect(self.drop_down_menu_ui.relative_rect.left,
                                self.option_list_y_pos,
                                (self.drop_down_menu_ui.relative_rect.width -
                                 self.close_button_width),
                                self.options_list_height)
        self.options_selection_list = UISelectionList(
            list_rect,
            starting_height=3,
            item_list=self.options_list,
            allow_double_clicks=False,
            manager=self.ui_manager,
            parent_element=self.drop_down_menu_ui,
            container=self.drop_down_menu_ui.ui_container,
            anchors=self.drop_down_menu_ui.anchors,
            object_id='#drop_down_options_list')
        self.drop_down_menu_ui.join_focus_sets(self.options_selection_list)

        if should_rebuild:
            self.rebuild()
Exemple #23
0
    def start(self):
        """
        Called each time we enter the expanded state. It creates the necessary elements, the
        selected option, all the other available options and the close button.

        """
        self.should_transition = False

        self.selected_option_button = UIButton(
            pygame.Rect(
                self.base_position_rect.topleft,
                (self.base_position_rect.width - self.close_button_width,
                 self.base_position_rect.height)),
            self.selected_option,
            self.ui_manager,
            self.ui_container,
            starting_height=2,
            parent_element=self.drop_down_menu_ui,
            object_id='#selected_option')

        expand_button_symbol = '▼'

        options_list_object_id = '#drop_down_options_list'
        options_list_object_ids = self.drop_down_menu_ui.object_ids[:]
        options_list_object_ids.append(options_list_object_id)
        options_list_element_ids = self.drop_down_menu_ui.element_ids[:]
        options_list_element_ids.append('selection_list')
        list_shadow_width_str = self.ui_manager.get_theme().get_misc_data(
            options_list_object_ids, options_list_element_ids, 'shadow_width')
        list_border_width_str = self.ui_manager.get_theme().get_misc_data(
            options_list_object_ids, options_list_element_ids, 'border_width')
        if list_shadow_width_str is not None:
            try:
                options_list_shadow_width = int(list_shadow_width_str)
            except ValueError:
                options_list_shadow_width = 2
        else:
            options_list_shadow_width = 2

        if list_border_width_str is not None:
            try:
                options_list_border_width = int(list_border_width_str)
            except ValueError:
                options_list_border_width = 1
        else:
            options_list_border_width = 1

        options_list_border_and_shadow = options_list_shadow_width + options_list_border_width
        self.options_list_height = ((20 * len(self.options_list)) +
                                    (2 * options_list_border_and_shadow))
        self.option_list_y_pos = 0
        if self.expand_direction is not None:
            if self.expand_direction == 'up':
                expand_button_symbol = '▲'

                if self.drop_down_menu_ui.expansion_height_limit is None:
                    self.drop_down_menu_ui.expansion_height_limit = self.base_position_rect.top

                self.options_list_height = min(
                    self.options_list_height,
                    self.drop_down_menu_ui.expansion_height_limit)

                self.option_list_y_pos = self.base_position_rect.top - self.options_list_height

            elif self.expand_direction == 'down':
                expand_button_symbol = '▼'

                if self.drop_down_menu_ui.expansion_height_limit is None:
                    height_limit = (self.drop_down_menu_ui.ui_container.
                                    relative_rect.height -
                                    self.base_position_rect.bottom)
                    self.drop_down_menu_ui.expansion_height_limit = height_limit

                self.options_list_height = min(
                    self.options_list_height,
                    self.drop_down_menu_ui.expansion_height_limit)

                self.option_list_y_pos = self.base_position_rect.bottom

        close_button_x = (self.base_position_rect.x +
                          self.base_position_rect.width -
                          self.close_button_width)

        self.close_button = UIButton(pygame.Rect(
            (close_button_x, self.base_position_rect.y),
            (self.close_button_width, self.base_position_rect.height)),
                                     expand_button_symbol,
                                     self.ui_manager,
                                     self.ui_container,
                                     starting_height=2,
                                     parent_element=self.drop_down_menu_ui,
                                     object_id='#expand_button')
        list_rect = pygame.Rect(self.drop_down_menu_ui.relative_rect.left,
                                self.option_list_y_pos,
                                (self.drop_down_menu_ui.relative_rect.width -
                                 self.close_button_width),
                                self.options_list_height)
        self.options_selection_list = UISelectionList(
            list_rect,
            item_list=self.options_list,
            allow_double_clicks=False,
            manager=self.ui_manager,
            parent_element=self.drop_down_menu_ui,
            container=self.ui_container,
            object_id='#drop_down_options_list')

        self.rebuild()
    def test_set_position(self, _init_pygame, default_ui_manager,
                          _display_surface_return_none):
        test_container = UIContainer(relative_rect=pygame.Rect(
            10, 10, 300, 300),
                                     manager=default_ui_manager)

        selection_list = UISelectionList(
            relative_rect=pygame.Rect(0, 0, 50, 50),
            item_list=[
                'item 1', 'item 2', 'item 3', 'item 4', 'item 5', 'item 6',
                'item 7', 'item 8', 'item 9', 'item 10', 'item 11', 'item 12',
                'item 13', 'item 14', 'item 15', 'item 16'
            ],
            manager=default_ui_manager,
            container=test_container,
            allow_multi_select=True,
            anchors={
                'left': 'left',
                'right': 'left',
                'top': 'top',
                'bottom': 'top'
            })

        selection_list.set_position((20, 20))
        assert selection_list.relative_rect.topleft == (10, 10)
        assert selection_list.relative_rect.size == (50, 50)
        assert selection_list.relative_rect.bottomright == (60, 60)

        selection_list = UISelectionList(
            relative_rect=pygame.Rect(0, 0, 50, 50),
            item_list=[
                'item 1', 'item 2', 'item 3', 'item 4', 'item 5', 'item 6',
                'item 7', 'item 8', 'item 9', 'item 10', 'item 11', 'item 12',
                'item 13', 'item 14', 'item 15', 'item 16'
            ],
            manager=default_ui_manager,
            container=test_container,
            allow_multi_select=True,
            anchors={
                'left': 'right',
                'right': 'right',
                'top': 'top',
                'bottom': 'top'
            })

        selection_list.set_position((280, 120))
        assert selection_list.relative_rect.topleft == (-30, 110)
        assert selection_list.relative_rect.size == (50, 50)
        assert selection_list.relative_rect.bottomright == (20, 160)

        selection_list = UISelectionList(
            relative_rect=pygame.Rect(0, 0, 50, 50),
            item_list=[
                'item 1', 'item 2', 'item 3', 'item 4', 'item 5', 'item 6',
                'item 7', 'item 8', 'item 9', 'item 10', 'item 11', 'item 12',
                'item 13', 'item 14', 'item 15', 'item 16'
            ],
            manager=default_ui_manager,
            container=test_container,
            allow_multi_select=True,
            anchors={
                'left': 'right',
                'right': 'right',
                'top': 'bottom',
                'bottom': 'bottom'
            })

        selection_list.set_position((230, 230))
        assert selection_list.relative_rect.topleft == (-80, -80)
        assert selection_list.relative_rect.size == (50, 50)
        assert selection_list.relative_rect.bottomright == (-30, -30)

        selection_list = UISelectionList(
            relative_rect=pygame.Rect(0, 0, 50, 50),
            item_list=[
                'item 1', 'item 2', 'item 3', 'item 4', 'item 5', 'item 6',
                'item 7', 'item 8', 'item 9', 'item 10', 'item 11', 'item 12',
                'item 13', 'item 14', 'item 15', 'item 16'
            ],
            manager=default_ui_manager,
            container=test_container,
            allow_multi_select=True,
            anchors={
                'left': 'left',
                'right': 'left',
                'top': 'bottom',
                'bottom': 'bottom'
            })

        selection_list.set_position((130, 230))
        assert selection_list.relative_rect.topleft == (120, -80)
        assert selection_list.relative_rect.size == (50, 50)
        assert selection_list.relative_rect.bottomright == (170, -30)

        selection_list = UISelectionList(
            relative_rect=pygame.Rect(0, 0, 50, 50),
            item_list=[
                'item 1', 'item 2', 'item 3', 'item 4', 'item 5', 'item 6',
                'item 7', 'item 8', 'item 9', 'item 10', 'item 11', 'item 12',
                'item 13', 'item 14', 'item 15', 'item 16'
            ],
            manager=default_ui_manager,
            container=test_container,
            allow_multi_select=True,
            anchors={
                'left': 'left',
                'right': 'right',
                'top': 'top',
                'bottom': 'bottom'
            })

        assert selection_list.relative_right_margin == 250
        assert selection_list.relative_bottom_margin == 250

        selection_list.set_position((20, 20))
        assert selection_list.relative_rect.topleft == (10, 10)
        assert selection_list.relative_rect.size == (50, 50)
        assert selection_list.relative_rect.bottomright == (60, 60)
        assert selection_list.relative_right_margin == 240
        assert selection_list.relative_bottom_margin == 240
Exemple #25
0
class UIExpandedDropDownState:
    """
    The expanded state of the drop down  displays the currently chosen option, all the available
    options and a button to close the menu and return to the closed state.

    Picking an option will also close the menu.

    :param drop_down_menu_ui: The UIDropDownElement this state belongs to.
    :param options_list: The list of options in this drop down.
    :param selected_option: The currently selected option.
    :param base_position_rect: Position and dimensions rectangle.
    :param close_button_width: Width of close button.
    :param expand_direction: Direction of expansion, 'up' or 'down'.
    :param manager: The UI Manager for the whole UI.
    :param container: The container the element is within.
    :param object_ids: The object IDs for the drop down UI element.
    :param element_ids: The element IDs for the drop down UI element.
    """
    def __init__(self, drop_down_menu_ui: 'UIDropDownMenu',
                 options_list: List[str], selected_option: str,
                 base_position_rect: Union[pygame.Rect,
                                           None], close_button_width: int,
                 expand_direction: Union[str,
                                         None], manager: IUIManagerInterface,
                 container: IContainerLikeInterface,
                 object_ids: Union[List[Union[str, None]],
                                   None], element_ids: Union[List[str], None]):

        self.drop_down_menu_ui = drop_down_menu_ui
        self.options_list = options_list
        self.selected_option = selected_option
        self.base_position_rect = base_position_rect

        self.expand_direction = expand_direction
        self.ui_manager = manager
        self.ui_container = container
        self.element_ids = element_ids
        self.object_ids = object_ids

        # sizing variables
        self.options_list_height = 0
        self.option_list_y_pos = 0
        self.close_button_width = close_button_width

        # UI elements
        self.selected_option_button = None
        self.close_button = None
        self.options_selection_list = None

        # state transitioning
        self.should_transition = False
        self.target_state = 'closed'

        self.active_buttons = []

    def rebuild(self):
        """
        Rebuild the state from theming parameters and dimensions.

        """
        theming_parameters = {
            'normal_bg': self.drop_down_menu_ui.background_colour,
            'normal_border': self.drop_down_menu_ui.border_colour,
            'border_width': self.drop_down_menu_ui.border_width,
            'shadow_width': self.drop_down_menu_ui.shadow_width,
            'shape_corner_radius': self.drop_down_menu_ui.shape_corner_radius
        }

        shape_rect = self.drop_down_menu_ui.relative_rect
        if self.drop_down_menu_ui.shape == 'rectangle':
            self.drop_down_menu_ui.drawable_shape = RectDrawableShape(
                shape_rect, theming_parameters, ['normal'], self.ui_manager)

        elif self.drop_down_menu_ui.shape == 'rounded_rectangle':
            self.drop_down_menu_ui.drawable_shape = RoundedRectangleShape(
                shape_rect, theming_parameters, ['normal'], self.ui_manager)

        self.on_fresh_drawable_shape_ready()

        # extra
        if self.close_button is not None:
            expand_button_symbol = '▼'
            if self.expand_direction is not None:
                if self.expand_direction == 'up':
                    expand_button_symbol = '▲'
                elif self.expand_direction == 'down':
                    expand_button_symbol = '▼'
            self.close_button.set_text(expand_button_symbol)

    def start(self, should_rebuild: bool = True):
        """
        Called each time we enter the expanded state. It creates the necessary elements, the
        selected option, all the other available options and the close button.

        """
        self.should_transition = False

        border_and_shadow = (self.drop_down_menu_ui.shadow_width +
                             self.drop_down_menu_ui.border_width)
        self.active_buttons = []
        self.selected_option_button = UIButton(
            pygame.Rect(
                (border_and_shadow, border_and_shadow),
                (self.base_position_rect.width - self.close_button_width,
                 self.base_position_rect.height)),
            self.selected_option,
            self.ui_manager,
            self.ui_container,
            starting_height=2,
            parent_element=self.drop_down_menu_ui,
            object_id=ObjectID('#selected_option', None))
        self.drop_down_menu_ui.join_focus_sets(self.selected_option_button)
        self.active_buttons.append(self.selected_option_button)

        expand_button_symbol = '▼'

        list_object_id = '#drop_down_options_list'
        list_object_ids = self.drop_down_menu_ui.object_ids[:]
        list_object_ids.append(list_object_id)
        list_class_ids = self.drop_down_menu_ui.class_ids[:]
        list_class_ids.append(None)
        list_element_ids = self.drop_down_menu_ui.element_ids[:]
        list_element_ids.append('selection_list')

        final_ids = self.ui_manager.get_theme().build_all_combined_ids(
            list_element_ids, list_class_ids, list_object_ids)

        self._calculate_options_list_sizes(final_ids)
        if self.expand_direction is not None:
            if self.expand_direction == 'up':
                expand_button_symbol = '▲'

                if self.drop_down_menu_ui.expansion_height_limit is None:
                    self.drop_down_menu_ui.expansion_height_limit = self.base_position_rect.top

                self.options_list_height = min(
                    self.options_list_height,
                    self.drop_down_menu_ui.expansion_height_limit)

                self.option_list_y_pos = self.base_position_rect.top - self.options_list_height

            elif self.expand_direction == 'down':
                expand_button_symbol = '▼'

                if self.drop_down_menu_ui.expansion_height_limit is None:
                    height_limit = (self.drop_down_menu_ui.ui_container.
                                    relative_rect.height -
                                    self.base_position_rect.bottom)
                    self.drop_down_menu_ui.expansion_height_limit = height_limit

                self.options_list_height = min(
                    self.options_list_height,
                    self.drop_down_menu_ui.expansion_height_limit)

                self.option_list_y_pos = self.base_position_rect.bottom

        if self.close_button_width > 0:
            close_button_x = (border_and_shadow +
                              self.base_position_rect.width -
                              self.close_button_width)

            self.close_button = UIButton(pygame.Rect(
                (close_button_x, border_and_shadow),
                (self.close_button_width, self.base_position_rect.height)),
                                         expand_button_symbol,
                                         self.ui_manager,
                                         self.ui_container,
                                         starting_height=2,
                                         parent_element=self.drop_down_menu_ui,
                                         object_id='#expand_button')
            self.drop_down_menu_ui.join_focus_sets(self.close_button)
            self.active_buttons.append(self.close_button)
        list_rect = pygame.Rect(self.drop_down_menu_ui.relative_rect.left,
                                self.option_list_y_pos,
                                (self.drop_down_menu_ui.relative_rect.width -
                                 self.close_button_width),
                                self.options_list_height)
        self.options_selection_list = UISelectionList(
            list_rect,
            starting_height=3,
            item_list=self.options_list,
            allow_double_clicks=False,
            manager=self.ui_manager,
            parent_element=self.drop_down_menu_ui,
            container=self.drop_down_menu_ui.ui_container,
            anchors=self.drop_down_menu_ui.anchors,
            object_id='#drop_down_options_list')
        self.drop_down_menu_ui.join_focus_sets(self.options_selection_list)

        if should_rebuild:
            self.rebuild()

    def _calculate_options_list_sizes(self, final_ids):
        try:
            list_shadow_width = int(self.ui_manager.get_theme().get_misc_data(
                'shadow_width', final_ids))
        except (LookupError, ValueError):
            list_shadow_width = 2
        try:
            list_border_width = int(self.ui_manager.get_theme().get_misc_data(
                'border_width', final_ids))
        except (LookupError, ValueError):
            list_border_width = 1
        try:
            list_item_height = int(self.ui_manager.get_theme().get_misc_data(
                'list_item_height', final_ids))
        except (LookupError, ValueError):
            list_item_height = 20
        options_list_border_and_shadow = list_shadow_width + list_border_width
        self.options_list_height = (
            (list_item_height * len(self.options_list)) +
            (2 * options_list_border_and_shadow))
        self.option_list_y_pos = 0

    def finish(self):
        """
        cleans everything up upon exiting the expanded menu state.
        """
        self.options_selection_list.kill()
        self.selected_option_button.kill()
        if self.close_button is not None:
            self.close_button.kill()

    def process_event(self, event: pygame.event.Event) -> bool:
        """
        Processes events for the closed state of the drop down.

        :param event: The event to process.

        :return: Return True if we want to consume this event so it is not passed on to the
                 rest of the UI.

        """
        if event.type == UI_BUTTON_PRESSED and event.ui_element in self.active_buttons:
            self.should_transition = True

        if (event.type == UI_SELECTION_LIST_NEW_SELECTION
                and event.ui_element == self.options_selection_list):
            selection = self.options_selection_list.get_single_selection()
            self.drop_down_menu_ui.selected_option = selection
            self.should_transition = True

            # old event - to be removed in 0.8.0
            event_data = {
                'user_type': OldType(UI_DROP_DOWN_MENU_CHANGED),
                'text': self.drop_down_menu_ui.selected_option,
                'ui_element': self.drop_down_menu_ui,
                'ui_object_id':
                self.drop_down_menu_ui.most_specific_combined_id
            }
            pygame.event.post(pygame.event.Event(pygame.USEREVENT, event_data))

            # new event
            event_data = {
                'text': self.drop_down_menu_ui.selected_option,
                'ui_element': self.drop_down_menu_ui,
                'ui_object_id':
                self.drop_down_menu_ui.most_specific_combined_id
            }
            pygame.event.post(
                pygame.event.Event(UI_DROP_DOWN_MENU_CHANGED, event_data))

        return False  # don't consume any events

    def update_position(self):
        """
        Update the position of all the button elements in the open drop down state.

        Used when the position of the  drop down has been altered directly, rather than when it
        has been moved as a consequence of it's container being moved.
        """

        # update the base position rect
        border_and_shadow = (self.drop_down_menu_ui.shadow_width +
                             self.drop_down_menu_ui.border_width)
        self.base_position_rect.x = self.drop_down_menu_ui.relative_rect.x + border_and_shadow
        self.base_position_rect.y = self.drop_down_menu_ui.relative_rect.y + border_and_shadow

        # update all the ui elements that depend on the base position
        self.selected_option_button.set_relative_position(
            (border_and_shadow, border_and_shadow))
        list_post = (self.drop_down_menu_ui.relative_rect.left,
                     self.option_list_y_pos)
        self.options_selection_list.set_relative_position(list_post)

        if self.close_button is not None:
            close_button_x = (border_and_shadow +
                              self.base_position_rect.width -
                              self.close_button_width)
            self.close_button.set_relative_position(
                [close_button_x, border_and_shadow])

    def update_dimensions(self):
        """
        Update the dimensions of all the button elements in the closed drop down state.

        Used when the dimensions of the drop down have been altered.
        """

        # update the base position rect
        border_and_shadow = (self.drop_down_menu_ui.shadow_width +
                             self.drop_down_menu_ui.border_width)
        self.base_position_rect.width = (
            self.drop_down_menu_ui.relative_rect.width -
            (2 * border_and_shadow))
        self.base_position_rect.height = (
            self.drop_down_menu_ui.relative_rect.height -
            (2 * border_and_shadow))

        if self.expand_direction is not None:
            if self.expand_direction == 'up':
                self.options_list_height = min(
                    self.options_list_height,
                    self.drop_down_menu_ui.expansion_height_limit)
                self.option_list_y_pos = self.base_position_rect.top - self.options_list_height

            elif self.expand_direction == 'down':
                self.options_list_height = min(
                    self.options_list_height,
                    self.drop_down_menu_ui.expansion_height_limit)
                self.option_list_y_pos = self.base_position_rect.bottom

        # update all the ui elements that depend on the base position rect
        self.selected_option_button.set_dimensions(
            (self.base_position_rect.width - self.close_button_width,
             self.base_position_rect.height))

        self.options_selection_list.set_dimensions(
            ((self.drop_down_menu_ui.relative_rect.width -
              self.close_button_width), self.options_list_height))

        list_pos = (self.drop_down_menu_ui.relative_rect.left,
                    self.option_list_y_pos)
        self.options_selection_list.set_relative_position(list_pos)
        if self.close_button is not None:
            close_button_x = (border_and_shadow +
                              self.base_position_rect.width -
                              self.close_button_width)
            self.close_button.set_dimensions(
                (self.close_button_width, self.base_position_rect.height))
            self.close_button.set_relative_position(
                (close_button_x, border_and_shadow))

    def on_fresh_drawable_shape_ready(self):
        """
        Called by an element's drawable shape when it has a new image surface ready for use,
        normally after a rebuilding/redrawing of some kind.

        In this case the result is to set the UI element's image to the new surface.
        """
        self.drop_down_menu_ui.set_image(
            self.drop_down_menu_ui.drawable_shape.get_fresh_surface())

    def hide(self):
        """
        Transition from expanded state to closed state.
        """
        self.should_transition = True
    def test_set_dimensions(self, _init_pygame, default_ui_manager,
                            _display_surface_return_none):
        test_container = UIContainer(relative_rect=pygame.Rect(
            10, 10, 300, 300),
                                     manager=default_ui_manager)

        selection_list = UISelectionList(
            relative_rect=pygame.Rect(30, 30, 50, 50),
            item_list=[
                'item 1', 'item 2', 'item 3', 'item 4', 'item 5', 'item 6',
                'item 7', 'item 8', 'item 9', 'item 10', 'item 11', 'item 12',
                'item 13', 'item 14', 'item 15', 'item 16'
            ],
            manager=default_ui_manager,
            container=test_container,
            allow_multi_select=True,
            anchors={
                'left': 'left',
                'right': 'left',
                'top': 'top',
                'bottom': 'top'
            })
        assert selection_list.relative_right_margin is None
        assert selection_list.relative_bottom_margin is None

        selection_list.set_dimensions((20, 20))
        assert selection_list.relative_rect.topleft == (30, 30)
        assert selection_list.relative_rect.size == (20, 20)
        assert selection_list.relative_rect.bottomright == (50, 50)
        assert selection_list.rect.topleft == (40, 40)
        assert selection_list.rect.size == (20, 20)
        assert selection_list.rect.bottomright == (60, 60)
        assert selection_list.relative_right_margin is None
        assert selection_list.relative_bottom_margin is None

        selection_list = UISelectionList(
            relative_rect=pygame.Rect(-60, 10, 50, 50),
            item_list=[
                'item 1', 'item 2', 'item 3', 'item 4', 'item 5', 'item 6',
                'item 7', 'item 8', 'item 9', 'item 10', 'item 11', 'item 12',
                'item 13', 'item 14', 'item 15', 'item 16'
            ],
            manager=default_ui_manager,
            container=test_container,
            allow_multi_select=True,
            anchors={
                'left': 'right',
                'right': 'right',
                'top': 'top',
                'bottom': 'top'
            })

        assert selection_list.relative_right_margin == 10
        assert selection_list.relative_bottom_margin is None
        selection_list.set_dimensions((60, 60))
        assert selection_list.relative_rect.topleft == (-60, 10)
        assert selection_list.relative_rect.size == (60, 60)
        assert selection_list.relative_rect.bottomright == (0, 70)
        assert selection_list.rect.topleft == (250, 20)
        assert selection_list.rect.size == (60, 60)
        assert selection_list.rect.bottomright == (310, 80)
        assert selection_list.relative_right_margin == 0
        assert selection_list.relative_bottom_margin is None

        selection_list = UISelectionList(
            relative_rect=pygame.Rect(-70, -70, 50, 50),
            item_list=[
                'item 1', 'item 2', 'item 3', 'item 4', 'item 5', 'item 6',
                'item 7', 'item 8', 'item 9', 'item 10', 'item 11', 'item 12',
                'item 13', 'item 14', 'item 15', 'item 16'
            ],
            manager=default_ui_manager,
            container=test_container,
            allow_multi_select=True,
            anchors={
                'left': 'right',
                'right': 'right',
                'top': 'bottom',
                'bottom': 'bottom'
            })

        assert selection_list.relative_right_margin == 20
        assert selection_list.relative_bottom_margin == 20
        selection_list.set_dimensions((30, 30))
        assert selection_list.relative_rect.topleft == (-70, -70)
        assert selection_list.relative_rect.size == (30, 30)
        assert selection_list.relative_rect.bottomright == (-40, -40)
        assert selection_list.rect.topleft == (240, 240)
        assert selection_list.rect.size == (30, 30)
        assert selection_list.rect.bottomright == (270, 270)
        assert selection_list.relative_right_margin == 40
        assert selection_list.relative_bottom_margin == 40

        selection_list = UISelectionList(
            relative_rect=pygame.Rect(50, -50, 50, 50),
            item_list=[
                'item 1', 'item 2', 'item 3', 'item 4', 'item 5', 'item 6',
                'item 7', 'item 8', 'item 9', 'item 10', 'item 11', 'item 12',
                'item 13', 'item 14', 'item 15', 'item 16'
            ],
            manager=default_ui_manager,
            container=test_container,
            allow_multi_select=True,
            anchors={
                'left': 'left',
                'right': 'left',
                'top': 'bottom',
                'bottom': 'bottom'
            })

        assert selection_list.relative_right_margin is None
        assert selection_list.relative_bottom_margin == 0

        selection_list.set_dimensions((100, 100))
        assert selection_list.relative_rect.topleft == (50, -50)
        assert selection_list.relative_rect.size == (100, 100)
        assert selection_list.relative_rect.bottomright == (150, 50)
        assert selection_list.rect.topleft == (60, 260)
        assert selection_list.rect.size == (100, 100)
        assert selection_list.rect.bottomright == (160, 360)
        assert selection_list.relative_right_margin is None
        assert selection_list.relative_bottom_margin == -50

        selection_list = UISelectionList(
            relative_rect=pygame.Rect(10, 10, 50, 50),
            item_list=[
                'item 1', 'item 2', 'item 3', 'item 4', 'item 5', 'item 6',
                'item 7', 'item 8', 'item 9', 'item 10', 'item 11', 'item 12',
                'item 13', 'item 14', 'item 15', 'item 16'
            ],
            manager=default_ui_manager,
            container=test_container,
            allow_multi_select=True,
            anchors={
                'left': 'left',
                'right': 'right',
                'top': 'top',
                'bottom': 'bottom'
            })

        assert selection_list.relative_right_margin == 240
        assert selection_list.relative_bottom_margin == 240

        selection_list.set_dimensions((90, 90))
        assert selection_list.relative_rect.topleft == (10, 10)
        assert selection_list.relative_rect.size == (90, 90)
        assert selection_list.relative_rect.bottomright == (100, 100)
        assert selection_list.rect.topleft == (20, 20)
        assert selection_list.rect.size == (90, 90)
        assert selection_list.rect.bottomright == (110, 110)
        assert selection_list.relative_right_margin == 200
        assert selection_list.relative_bottom_margin == 200