def test_double_discrete(self) -> None: """ Test double range slider with discrete values. """ menu = MenuUtils.generic_menu() rv = [0, 1, 2, 3, 4, 5] # Double slider discrete slider = pygame_menu.widgets.RangeSlider( 'Range', range_text_value_tick_number=3, range_values=rv, default_value=(1, 4)) menu.add.generic_widget(slider, True) slider.draw(surface) # Test set values slider.set_value([1, 2]) self.assertEqual(slider.get_value(), (1, 2)) # Test invalid values self.assertRaises(AssertionError, lambda: slider.set_value((1.1, 2.2))) self.assertRaises(AssertionError, lambda: slider.set_value((1, 1))) self.assertRaises(AssertionError, lambda: slider.set_value((2, 1))) self.assertRaises(AssertionError, lambda: slider.set_value(1)) # Test left/right self.assertTrue( slider.update(PygameEventUtils.key(ctrl.KEY_LEFT, keydown=True))) self.assertEqual(slider.get_value(), (0, 2)) self.assertFalse( slider.update(PygameEventUtils.key(ctrl.KEY_LEFT, keydown=True))) self.assertEqual(slider.get_value(), (0, 2)) self.assertTrue( slider.update(PygameEventUtils.key(ctrl.KEY_RIGHT, keydown=True))) self.assertEqual(slider.get_value(), (1, 2)) self.assertFalse( slider.update(PygameEventUtils.key(ctrl.KEY_RIGHT, keydown=True))) self.assertEqual(slider.get_value(), (1, 2)) slider._update_value(0.99) self.assertEqual(slider.get_value(), (1, 2)) self.assertEqual( slider._get_slider_inflate_rect(0, to_absolute_position=True), pygame.Rect(301, 209, 15, 28))
def test_overflow_removal(self) -> None: """ Test text with max width and right overflow removal. """ if SYS_PLATFORM_OSX: return menu = MenuUtils.generic_menu() menu._copy_theme() menu._theme.widget_font_size = 20 textinput = menu.add.text_input('Some long text: ', maxwidth=19, textinput_id='long_text', input_underline='_') self.assertRaises(WidgetTransformationNotImplemented, lambda: textinput.resize()) self.assertRaises(WidgetTransformationNotImplemented, lambda: textinput.set_max_width()) self.assertRaises(WidgetTransformationNotImplemented, lambda: textinput.set_max_height()) self.assertRaises(WidgetTransformationNotImplemented, lambda: textinput.scale()) self.assertRaises(WidgetTransformationNotImplemented, lambda: textinput.rotate()) textinput.flip(True, True) self.assertEqual(textinput._flip, (False, True)) # noinspection SpellCheckingInspection textinput.set_value('aaaaaaaaaaaaaaaaaaaaaaaaaa') self.assertEqual(textinput._cursor_position, 26) self.assertEqual(textinput._renderbox, [1, 26, 25]) textinput.update(PygameEventUtils.key(pygame.K_BACKSPACE, keydown=True)) self.assertEqual(textinput._cursor_position, 25) self.assertEqual(textinput._renderbox, [0, 25, 25]) textinput.update( PygameEventUtils.key(pygame.K_a, keydown=True, char='a')) self.assertEqual(textinput._cursor_position, 26) self.assertEqual(textinput._renderbox, [1, 26, 25]) textinput.update(PygameEventUtils.key(pygame.K_BACKSPACE, keydown=True)) self.assertEqual(textinput._cursor_position, 25) self.assertEqual(textinput._renderbox, [0, 25, 25])
def test_config(self) -> None: """ Configure controls. """ self.assertEqual(ctrl.KEY_APPLY, K_RETURN) # Change apply to new key ctrl.KEY_APPLY = K_END self.assertEqual(ctrl.KEY_APPLY, K_END) # Create new button menu = MenuUtils.generic_menu() test = [False] def click_button() -> None: """ Button apply handler. """ test[0] = not test[0] print('new test value', test) button = menu.add.button('button', click_button) self.assertFalse(test[0]) button.apply() self.assertTrue(test[0]) button.apply() self.assertFalse(test[0]) # Now test new apply button button.update(PygameEventUtils.key(K_END, keydown=True)) self.assertTrue(test[0]) # Rollback change ctrl.KEY_APPLY = K_RETURN button.update(PygameEventUtils.key(K_END, keydown=True)) self.assertTrue(test[0]) button.update(PygameEventUtils.key(ctrl.KEY_APPLY, keydown=True)) self.assertFalse(test[0])
def test_invalid_range(self) -> None: """ Test invalid ranges. #356 """ menu = MenuUtils.generic_menu() r = menu.add.range_slider('Infection Rate', default=2, increment=0.5, range_values=(2, 10)) self.assertEqual(r.get_value(), 2) self.assertTrue( r.update(PygameEventUtils.key(ctrl.KEY_RIGHT, keydown=True))) self.assertEqual(r.get_value(), 2.5) self.assertTrue( r.update(PygameEventUtils.key(ctrl.KEY_LEFT, keydown=True))) self.assertEqual(r.get_value(), 2) self.assertFalse( r.update(PygameEventUtils.key(ctrl.KEY_LEFT, keydown=True))) self.assertEqual(r.get_value(), 2) for _ in range(20): r.update(PygameEventUtils.key(ctrl.KEY_RIGHT, keydown=True)) self.assertEqual(r.get_value(), 10)
def test_non_ascii(self) -> None: """ Test non-ascii. """ menu = MenuUtils.generic_menu() m = MenuUtils.generic_menu(title=u'Ménu') m.clear() menu.add.button('0', pygame_menu.events.NONE) menu.add.button('Test', pygame_menu.events.NONE) menu.add.button(u'Menú', pygame_menu.events.NONE) menu.add.color_input(u'Cólor', 'rgb') text = menu.add.text_input(u'Téxt') menu.add.label(u'Téxt') menu.add.selector(u'Sélect'.encode('latin1'), [('a', 'a')]) menu.enable() menu.draw(surface) # Text text input text.set_value('ą, ę, ś, ć, ż, ź, ó, ł, ń') self.assertEqual(text.get_value(), 'ą, ę, ś, ć, ż, ź, ó, ł, ń') text.set_value('') text.update(PygameEventUtils.key(pygame.K_l, char='ł', keydown=True)) self.assertEqual(text.get_value(), 'ł')
def test_textinput(self) -> None: """ Test TextInput widget. """ menu = MenuUtils.generic_menu() # Assert bad settings self.assertRaises( ValueError, lambda: menu.add.text_input('title', input_type=pygame_menu. locals.INPUT_FLOAT, default='bad')) self.assertRaises( ValueError, # Default and password cannot coexist lambda: menu.add.text_input('title', password=True, default='bad')) # Create text input widget textinput = menu.add.text_input('title', input_underline='_') textinput.set_value('new_value') # No error textinput._selected = False textinput.draw(surface) textinput.select(update_menu=True) textinput.draw(surface) self.assertEqual(textinput.get_value(), 'new_value') textinput.clear() self.assertEqual(textinput.get_value(), '') # Create selection box string = 'the text' textinput._cursor_render = True textinput.set_value(string) textinput._select_all() self.assertEqual(textinput._get_selected_text(), 'the text') textinput.draw(surface) textinput._unselect_text() textinput.draw(surface) # Assert events textinput.update(PygameEventUtils.key(0, keydown=True, testmode=False)) PygameEventUtils.test_widget_key_press(textinput) textinput.update(PygameEventUtils.key(ctrl.KEY_APPLY, keydown=True)) textinput.update(PygameEventUtils.key(pygame.K_LSHIFT, keydown=True)) textinput.clear() # Type textinput.update( PygameEventUtils.key(pygame.K_t, keydown=True, char='t')) textinput.update( PygameEventUtils.key(pygame.K_e, keydown=True, char='e')) textinput.update( PygameEventUtils.key(pygame.K_s, keydown=True, char='s')) textinput.update( PygameEventUtils.key(pygame.K_t, keydown=True, char='t')) # Keyup textinput.update(PygameEventUtils.key(pygame.K_a, keyup=True, char='a')) self.assertEqual(textinput.get_value(), 'test') # The text we typed # Ctrl events textinput.update(PygameEventUtils.keydown_mod_ctrl(pygame.K_c)) # copy textinput.update(PygameEventUtils.keydown_mod_ctrl( pygame.K_v)) # paste textinput.update(PygameEventUtils.keydown_mod_ctrl(pygame.K_z)) # undo self.assertEqual(textinput.get_value(), 'tes') textinput.update(PygameEventUtils.keydown_mod_ctrl(pygame.K_y)) # redo self.assertEqual(textinput.get_value(), 'test') textinput._select_all() textinput.update(PygameEventUtils.keydown_mod_ctrl(pygame.K_x)) # cut self.assertEqual(textinput.get_value(), '') textinput.update(PygameEventUtils.keydown_mod_ctrl(pygame.K_z)) # undo self.assertEqual(textinput.get_value(), 'test') textinput.update(PygameEventUtils.keydown_mod_ctrl(pygame.K_y)) # redo self.assertEqual(textinput.get_value(), '') textinput.update(PygameEventUtils.keydown_mod_ctrl(pygame.K_z)) # undo self.assertEqual(textinput.get_value(), 'test') # Test ignore ctrl events textinput._copy_paste_enabled = False self.assertFalse( textinput.update(PygameEventUtils.keydown_mod_ctrl(pygame.K_c))) self.assertFalse( textinput.update(PygameEventUtils.keydown_mod_ctrl(pygame.K_v))) max_history = textinput._max_history textinput._max_history = 0 self.assertFalse( textinput.update(PygameEventUtils.keydown_mod_ctrl(pygame.K_z))) self.assertFalse( textinput.update(PygameEventUtils.keydown_mod_ctrl(pygame.K_y))) self.assertFalse( textinput.update(PygameEventUtils.keydown_mod_ctrl(pygame.K_x))) textinput._selection_enabled = False self.assertFalse( textinput.update(PygameEventUtils.keydown_mod_ctrl(pygame.K_a))) self.assertFalse( textinput.update(PygameEventUtils.keydown_mod_ctrl( pygame.K_r))) # invalid # Reset textinput._copy_paste_enabled = True textinput._max_history = max_history textinput._selection_enabled = True # Test selection, if user selects all and types anything the selected # text must be destroyed textinput.update(PygameEventUtils.keydown_mod_ctrl( pygame.K_a)) # select all textinput._unselect_text() self.assertEqual(textinput._get_selected_text(), '') textinput._select_all() self.assertEqual(textinput._get_selected_text(), 'test') textinput._unselect_text() self.assertEqual(textinput._get_selected_text(), '') textinput.update(PygameEventUtils.keydown_mod_ctrl(pygame.K_a)) self.assertEqual(textinput._get_selected_text(), 'test') textinput.update( PygameEventUtils.key(pygame.K_t, keydown=True, char='t')) textinput._select_all() self.assertTrue( textinput.update( PygameEventUtils.key(pygame.K_ESCAPE, keydown=True))) textinput._select_all() self.assertTrue( textinput.update( PygameEventUtils.key(pygame.K_BACKSPACE, keydown=True))) self.assertEqual(textinput.get_value(), '') textinput.set_value('t') # Releasing shift disable selection textinput._selection_active = True textinput.update(PygameEventUtils.key(pygame.K_LSHIFT, keyup=True)) self.assertFalse(textinput._selection_active) # Arrows while selection textinput._select_all() self.assertIsNotNone(textinput._selection_surface) textinput.update(PygameEventUtils.key(pygame.K_LEFT, keydown=True)) self.assertIsNone(textinput._selection_surface) textinput._select_all() self.assertIsNotNone(textinput._selection_surface) textinput.update(PygameEventUtils.key(pygame.K_RIGHT, keydown=True)) self.assertIsNone(textinput._selection_surface) textinput._select_all() textinput._selection_active = True self.assertEqual(textinput._selection_box, [0, 1]) textinput.update(PygameEventUtils.key(pygame.K_LEFT, keydown=True)) self.assertEqual(textinput._selection_box, [0, 0]) textinput._select_all() textinput._selection_active = True textinput.update(PygameEventUtils.key(pygame.K_RIGHT, keydown=True)) self.assertEqual(textinput._selection_box, [0, 1]) # Remove while selection textinput._select_all() textinput.update(PygameEventUtils.key(pygame.K_DELETE, keydown=True)) self.assertEqual(textinput.get_value(), '') textinput.set_value('t') # Now the value must be t self.assertEqual(textinput._get_selected_text(), '') self.assertEqual(textinput.get_value(), 't') # Test readonly textinput.update( PygameEventUtils.key(pygame.K_t, keydown=True, char='k')) self.assertEqual(textinput.get_value(), 'tk') textinput.readonly = True textinput.update( PygameEventUtils.key(pygame.K_t, keydown=True, char='k')) self.assertEqual(textinput.get_value(), 'tk') textinput.readonly = False # Test keyup self.assertIn(pygame.K_t, textinput._keyrepeat_counters.keys()) self.assertFalse( textinput.update( PygameEventUtils.key(pygame.K_t, keyup=True, char='1'))) self.assertNotIn(pygame.K_t, textinput._keyrepeat_counters.keys()) # Test tab self.assertEqual(textinput._tab_size, 4) textinput.update(PygameEventUtils.key(pygame.K_TAB, keydown=True)) self.assertEqual(textinput.get_value(), 'tk ') # Test invalid unicode self.assertFalse( textinput.update(PygameEventUtils.key(pygame.K_1, keydown=True))) # Up/Down disable active status textinput.active = True textinput.update(PygameEventUtils.key(ctrl.KEY_MOVE_UP, keydown=True)) self.assertFalse(textinput.active) textinput.active = True textinput.update(PygameEventUtils.key(ctrl.KEY_MOVE_DOWN, keydown=True)) self.assertFalse(textinput.active) textinput.active = True self.assertTrue( textinput.update( PygameEventUtils.key(pygame.K_ESCAPE, keydown=True))) self.assertFalse(textinput.active) # Test mouse textinput._selected = True textinput._selection_time = 0 textinput.update(PygameEventUtils.middle_rect_click(textinput)) self.assertTrue(textinput._cursor_visible) textinput._select_all() textinput._selection_active = True self.assertEqual(textinput._cursor_position, 6) self.assertEqual(textinput._selection_box, [0, 6]) textinput.update( PygameEventUtils.middle_rect_click(textinput, evtype=pygame.MOUSEBUTTONDOWN)) self.assertEqual(textinput._selection_box, [0, 0]) # Check click pos textinput._check_mouse_collide_input( PygameEventUtils.middle_rect_click(textinput)[0].pos) self.assertEqual(textinput._cursor_position, 6) # Test touch textinput._cursor_position = 0 textinput._check_touch_collide_input( PygameEventUtils.middle_rect_click(textinput)[0].pos) self.assertEqual(textinput._cursor_position, 6) # Update mouse for i in range(50): textinput.update( PygameEventUtils.key(pygame.K_t, keydown=True, char='t')) textinput._update_cursor_mouse(50) textinput._cursor_render = True textinput._render_cursor() # Test multiple are selected menu.add.text_input('title', password=True, input_underline='_').select() self.assertRaises( pygame_menu.menu._MenuMultipleSelectedWidgetsException, lambda: menu.draw(surface)) textinput.clear() textinput.select(update_menu=True) menu.draw(surface) # Clear the menu self.assertEqual(menu._stats.removed_widgets, 0) self.assertEqual(textinput.get_menu(), menu) menu.clear() self.assertIsNone(textinput.get_menu()) self.assertEqual(menu._stats.removed_widgets, 3) menu.add.generic_widget(textinput) self.assertEqual(textinput.get_menu(), menu) menu.clear() self.assertEqual(menu._stats.removed_widgets, 4)
def test_toggleswitch(self) -> None: """ Test toggleswitch widget. """ menu = MenuUtils.generic_menu() value = [None] def onchange(val) -> None: """ Function executed by toggle. """ value[0] = val switch = menu.add.toggle_switch('toggle', False, onchange=onchange, infinite=False, single_click=False) self.assertFalse(switch.get_value()) self.assertIsNone(value[0]) switch.apply() self.assertFalse(value[0]) switch.update(PygameEventUtils.key(ctrl.KEY_LEFT, keydown=True)) # not infinite self.assertFalse(value[0]) # as this is false, dont change switch.update(PygameEventUtils.key(ctrl.KEY_RIGHT, keydown=True)) self.assertTrue(value[0]) switch.update(PygameEventUtils.key(ctrl.KEY_LEFT, keydown=True)) self.assertFalse(value[0]) switch.update(PygameEventUtils.key(ctrl.KEY_LEFT, keydown=True)) self.assertFalse(value[0]) self.assertFalse( switch.update( PygameEventUtils.key(ctrl.KEY_LEFT, keydown=True, testmode=False))) switch = menu.add.toggle_switch('toggle', False, onchange=onchange, infinite=True, single_click=False) switch.update(PygameEventUtils.key(ctrl.KEY_LEFT, keydown=True)) self.assertTrue(value[0]) switch.update(PygameEventUtils.key(ctrl.KEY_LEFT, keydown=True)) self.assertFalse(value[0]) # As there's only 2 states, return should change too switch.update(PygameEventUtils.key(ctrl.KEY_APPLY, keydown=True)) self.assertTrue(value[0]) switch.update(PygameEventUtils.key(ctrl.KEY_APPLY, keydown=True)) self.assertFalse(value[0]) # Check left/right clicks click_pos = switch.get_rect(to_real_position=True, apply_padding=False).midleft switch.update( PygameEventUtils.mouse_click(click_pos[0] + 150, click_pos[1])) self.assertFalse(value[0]) switch.update( PygameEventUtils.mouse_click(click_pos[0] + 250, click_pos[1])) self.assertTrue(value[0]) switch.update( PygameEventUtils.mouse_click(click_pos[0] + 150, click_pos[1])) self.assertFalse(value[0]) # Test left/right touch switch._touchscreen_enabled = True switch.update( PygameEventUtils.touch_click(click_pos[0] + 250, click_pos[1], menu=switch.get_menu())) self.assertTrue(value[0]) switch.update( PygameEventUtils.touch_click(click_pos[0] + 250, click_pos[1], menu=switch.get_menu())) self.assertTrue(value[0]) switch.update( PygameEventUtils.touch_click(click_pos[0] + 150, click_pos[1], menu=switch.get_menu())) self.assertFalse(value[0]) # Test readonly switch.readonly = True switch.update(PygameEventUtils.key(ctrl.KEY_APPLY, keydown=True)) self.assertFalse(value[0]) switch.update(PygameEventUtils.key(ctrl.KEY_APPLY, keydown=True)) self.assertFalse(value[0]) switch.update(PygameEventUtils.key(ctrl.KEY_APPLY, keydown=True)) self.assertFalse(value[0]) switch._left() self.assertFalse(value[0]) switch._right() self.assertFalse(value[0]) switch.readonly = False switch.update(PygameEventUtils.key(ctrl.KEY_RIGHT, keydown=True)) self.assertTrue(value[0]) switch.update(PygameEventUtils.key(ctrl.KEY_RIGHT, keydown=True)) self.assertFalse(value[0]) switch.draw(surface) # Test transforms switch.set_position(1, 1) self.assertEqual(switch.get_position(), (1, 1)) switch.translate(1, 1) self.assertEqual(switch.get_translate(), (1, 1)) self.assertRaises(WidgetTransformationNotImplemented, lambda: switch.rotate(10)) self.assertEqual(switch._angle, 0) self.assertRaises(WidgetTransformationNotImplemented, lambda: switch.scale(100, 100)) self.assertFalse(switch._scale[0]) self.assertEqual(switch._scale[1], 1) self.assertEqual(switch._scale[2], 1) self.assertRaises(WidgetTransformationNotImplemented, lambda: switch.resize(100, 100)) self.assertFalse(switch._scale[0]) self.assertEqual(switch._scale[1], 1) self.assertEqual(switch._scale[2], 1) self.assertRaises(WidgetTransformationNotImplemented, lambda: switch.flip(True, True)) self.assertFalse(switch._flip[0]) self.assertFalse(switch._flip[1]) self.assertRaises(WidgetTransformationNotImplemented, lambda: switch.set_max_width(100)) self.assertIsNone(switch._max_width[0]) self.assertRaises(WidgetTransformationNotImplemented, lambda: switch.set_max_height(100)) self.assertIsNone(switch._max_height[0]) # Assert switch values self.assertRaises( ValueError, lambda: menu.add.toggle_switch( 'toggle', 'false', onchange=onchange, infinite=False)) # Test single click toggle switch_single = menu.add.toggle_switch('toggle', False, onchange=onchange) self.assertTrue(switch_single._infinite ) # Infinite sets to True if using single click self.assertFalse(switch_single.get_value()) switch_single._left() self.assertTrue(switch_single.get_value()) click_pos = switch_single.get_rect(to_real_position=True, apply_padding=False).midleft # Test single click toggle between two states switch_single.update( PygameEventUtils.mouse_click(click_pos[0] + 150, click_pos[1])) self.assertFalse( switch_single.get_value()) # single_click_dir=True, move to left switch_single.update( PygameEventUtils.mouse_click(click_pos[0] + 250, click_pos[1])) self.assertTrue(switch_single.get_value()) switch_single.update( PygameEventUtils.mouse_click(click_pos[0] + 250, click_pos[1])) self.assertFalse(switch_single.get_value()) switch_single._single_click_dir = False switch_single.update( PygameEventUtils.mouse_click(click_pos[0] + 250, click_pos[1])) self.assertTrue(switch_single.get_value()) # Create invalid single click params self.assertRaises( AssertionError, lambda: menu.add.toggle_switch( 'toggle', False, single_click='true')) self.assertRaises( AssertionError, lambda: menu.add.toggle_switch( 'toggle', False, single_click_dir='true')) # Test other constructor params pygame_menu.widgets.ToggleSwitch( 'Epic', state_text_font=menu._theme.widget_font) self.assertRaises( AssertionError, lambda: pygame_menu.widgets.ToggleSwitch('Epic', state_text_font_size=-1))
def test_scrollbar(self) -> None: """ Test ScrollBar widget. """ screen_size = surface.get_size() world = pygame.Surface((WINDOW_SIZE[0] * 2, WINDOW_SIZE[1] * 3)) world.fill((200, 200, 200)) for x in range(100, world.get_width(), 200): for y in range(100, world.get_height(), 200): pygame.draw.circle(world, (225, 34, 43), (x, y), 100, 10) # Vertical right scrollbar thick = 80 length = screen_size[1] world_range = (50, world.get_height()) x, y = screen_size[0] - thick, 0 sb = ScrollBar( length, world_range, 'sb2', ORIENTATION_VERTICAL, slider_pad=2, slider_color=(210, 120, 200), page_ctrl_thick=thick, page_ctrl_color=(235, 235, 230) ) self.assertEqual(sb.get_thickness(), 80) self.assertIsNone(sb.get_scrollarea()) sb.set_shadow(color=(245, 245, 245), position=POSITION_SOUTHEAST) self.assertFalse(sb._font_shadow) sb.set_position(x, y) self.assertEqual(sb._orientation, 1) self.assertEqual(sb.get_orientation(), ORIENTATION_VERTICAL) self.assertEqual(sb.get_minimum(), world_range[0]) self.assertEqual(sb.get_maximum(), world_range[1]) sb.set_value(80) self.assertAlmostEqual(sb.get_value(), 80, delta=2) # Scaling delta sb.update(PygameEventUtils.mouse_click(x + thick / 2, y + 2, evtype=pygame.MOUSEBUTTONDOWN)) self.assertEqual(sb.get_value(), 50) self.assertEqual(sb.get_value_percentage(), 0) sb.set_page_step(length) self.assertAlmostEqual(sb.get_page_step(), length, delta=2) # Scaling delta sb.draw(surface) # Test events sb.update(PygameEventUtils.key(pygame.K_PAGEDOWN, keydown=True)) self.assertEqual(sb.get_value(), 964) sb.update(PygameEventUtils.key(pygame.K_PAGEUP, keydown=True)) self.assertEqual(sb.get_value(), 50) self.assertEqual(sb._last_mouse_pos, (-1, -1)) sb.update(PygameEventUtils.enter_window()) self.assertEqual(sb._last_mouse_pos, (-1, -1)) sb.update(PygameEventUtils.leave_window()) self.assertEqual(sb._last_mouse_pos, pygame.mouse.get_pos()) self.assertFalse(sb.scrolling) sb.update(PygameEventUtils.middle_rect_click(sb.get_slider_rect(), evtype=pygame.MOUSEBUTTONDOWN)) self.assertTrue(sb.scrolling) sb.update(PygameEventUtils.mouse_click(1, 1)) self.assertFalse(sb.scrolling) self.assertEqual(sb.get_value(), 50) sb.update(PygameEventUtils.middle_rect_click(sb.get_rect(to_absolute_position=True), evtype=pygame.MOUSEBUTTONDOWN)) self.assertEqual(sb.get_value(), 964) sb.update(PygameEventUtils.middle_rect_click(sb.get_slider_rect(), evtype=pygame.MOUSEBUTTONDOWN)) self.assertTrue(sb.scrolling) sb.update(PygameEventUtils.middle_rect_click(sb.get_slider_rect(), button=4, evtype=pygame.MOUSEBUTTONDOWN)) self.assertEqual(sb.get_value(), 875) sb.update(PygameEventUtils.middle_rect_click(sb.get_slider_rect(), button=5, evtype=pygame.MOUSEBUTTONDOWN)) self.assertEqual(sb.get_value(), 964) self.assertEqual(sb.get_value_percentage(), 0.522) # Test mouse motion while scrolling sb.update(PygameEventUtils.middle_rect_click(sb.get_slider_rect(), button=5, delta=(0, 50), rel=(0, 10), evtype=pygame.MOUSEMOTION)) self.assertEqual(sb.get_value_percentage(), 0.547) sb.update(PygameEventUtils.middle_rect_click(sb.get_slider_rect(), button=5, delta=(0, 50), rel=(0, -10), evtype=pygame.MOUSEMOTION)) self.assertEqual(sb.get_value_percentage(), 0.522) sb.update(PygameEventUtils.middle_rect_click(sb.get_slider_rect(), button=5, delta=(0, 50), rel=(0, 999), evtype=pygame.MOUSEMOTION)) self.assertEqual(sb.get_value_percentage(), 1) sb.readonly = True self.assertFalse(sb.update([])) # Ignore events if mouse outside the region sb.update(PygameEventUtils.middle_rect_click(sb.get_slider_rect(), button=5, delta=(0, 999), rel=(0, -10), evtype=pygame.MOUSEMOTION)) self.assertIn(sb.get_value_percentage(), (0.976, 1)) # Test remove onreturn sb = ScrollBar(length, world_range, 'sb', ORIENTATION_VERTICAL, onreturn=-1) self.assertIsNone(sb._onreturn) self.assertTrue(sb._kwargs.get('onreturn', 0)) # Scrollbar ignores scaling self.assertRaises(WidgetTransformationNotImplemented, lambda: sb.scale(2, 2)) self.assertFalse(sb._scale[0]) self.assertRaises(WidgetTransformationNotImplemented, lambda: sb.resize(2, 2)) self.assertFalse(sb._scale[0]) self.assertRaises(WidgetTransformationNotImplemented, lambda: sb.set_max_width(10)) self.assertIsNone(sb._max_width[0]) self.assertRaises(WidgetTransformationNotImplemented, lambda: sb.set_max_height(10)) self.assertIsNone(sb._max_height[0]) sb._apply_font() sb.set_padding(10) self.assertEqual(sb._padding[0], 0) self.assertRaises(WidgetTransformationNotImplemented, lambda: sb.rotate(10)) self.assertEqual(sb._angle, 0) self.assertRaises(WidgetTransformationNotImplemented, lambda: sb.flip(True, True)) self.assertFalse(sb._flip[0]) self.assertFalse(sb._flip[1]) # Set minimum sb.set_minimum(0.5 * sb._values_range[1]) # Test hide sb._mouseover = True sb.hide()
def test_selector(self) -> None: """ Test selector widget. """ menu = MenuUtils.generic_menu() selector = menu.add.selector('selector', [('1 - Easy', 'EASY'), ('2 - Medium', 'MEDIUM'), ('3 - Hard', 'HARD')], default=1) menu.enable() menu.draw(surface) selector.draw(surface) selector._selected = False selector.draw(surface) # Test events selector.update(PygameEventUtils.key(0, keydown=True, testmode=False)) selector.update(PygameEventUtils.key(ctrl.KEY_LEFT, keydown=True)) selector.update(PygameEventUtils.key(ctrl.KEY_RIGHT, keydown=True)) selector.update(PygameEventUtils.key(ctrl.KEY_APPLY, keydown=True)) selector.update(PygameEventUtils.joy_hat_motion(ctrl.JOY_LEFT)) selector.update(PygameEventUtils.joy_hat_motion(ctrl.JOY_RIGHT)) selector.update(PygameEventUtils.joy_motion(1, 0)) selector.update(PygameEventUtils.joy_motion(-1, 0)) click_pos = selector.get_rect(to_real_position=True, apply_padding=False).center selector.update( PygameEventUtils.mouse_click(click_pos[0], click_pos[1])) # Check left/right clicks self.assertEqual(selector.get_index(), 0) click_pos = selector.get_rect(to_real_position=True, apply_padding=False).midleft selector.update( PygameEventUtils.mouse_click(click_pos[0] + 150, click_pos[1])) self.assertEqual(selector.get_index(), 2) selector.update( PygameEventUtils.mouse_click(click_pos[0] + 150, click_pos[1])) self.assertEqual(selector.get_index(), 1) selector.update( PygameEventUtils.mouse_click(click_pos[0] + 150, click_pos[1])) self.assertEqual(selector.get_index(), 0) selector.update( PygameEventUtils.mouse_click(click_pos[0] + 250, click_pos[1])) self.assertEqual(selector.get_index(), 1) selector.update( PygameEventUtils.mouse_click(click_pos[0] + 250, click_pos[1])) self.assertEqual(selector.get_index(), 2) selector.update( PygameEventUtils.mouse_click(click_pos[0] + 250, click_pos[1])) self.assertEqual(selector.get_index(), 0) # Test left/right touch click_pos = selector.get_rect(to_real_position=True, apply_padding=False).midleft selector._touchscreen_enabled = True selector.update( PygameEventUtils.touch_click(click_pos[0] + 150, click_pos[1], menu=selector.get_menu())) self.assertEqual(selector.get_index(), 2) selector.update( PygameEventUtils.touch_click(click_pos[0] + 250, click_pos[1], menu=selector.get_menu())) self.assertEqual(selector.get_index(), 0) selector.update( PygameEventUtils.touch_click(click_pos[0] + 250, click_pos[1], menu=selector.get_menu())) self.assertEqual(selector.get_index(), 1) # Update elements new_elements = [('4 - Easy', 'EASY'), ('5 - Medium', 'MEDIUM'), ('6 - Hard', 'HARD')] selector.update_items(new_elements) selector.set_value('6 - Hard') self.assertEqual(selector.get_value()[1], 2) self.assertRaises(AssertionError, lambda: selector.set_value(bool)) self.assertRaises(AssertionError, lambda: selector.set_value(200)) selector.set_value(1) self.assertEqual(selector.get_value()[1], 1) self.assertEqual(selector.get_value()[0][0], '5 - Medium') selector.update(PygameEventUtils.key(ctrl.KEY_LEFT, keydown=True)) self.assertEqual(selector.get_value()[0][0], '4 - Easy') selector.readonly = True selector.update(PygameEventUtils.key(ctrl.KEY_LEFT, keydown=True)) self.assertEqual(selector.get_value()[0][0], '4 - Easy') selector._left() self.assertEqual(selector.get_value()[0][0], '4 - Easy') selector._right() self.assertEqual(selector.get_value()[0][0], '4 - Easy') # Test fancy selector sel_fancy = menu.add.selector( 'Fancy ', [('1 - Easy', 'EASY'), ('2 - Medium', 'MEDIUM'), ('3 - Hard', 'HARD')], default=1, style=pygame_menu.widgets.widget.selector.SELECTOR_STYLE_FANCY) self.assertEqual(sel_fancy.get_items(), [('1 - Easy', 'EASY'), ('2 - Medium', 'MEDIUM'), ('3 - Hard', 'HARD')]) self.assertRaises( AssertionError, lambda: menu.add.selector('title', [('a', 'a'), ('b', 'b')], default=2))
def test_dropselect_multiple(self) -> None: """ Test dropselect multiple widget. """ theme = pygame_menu.themes.THEME_DEFAULT.copy() theme.widget_font_size = 25 menu = MenuUtils.generic_menu(mouse_motion_selection=True, theme=theme) items = [('This is a really long selection item', 1), ('epic', 2)] for i in range(10): items.append(('item{}'.format(i + 1), i + 1)) # noinspection SpellCheckingInspection drop = pygame_menu.widgets.DropSelectMultiple('dropsel', items, open_middle=True, selection_box_height=5) self.assertNotEqual(id(items), id(drop._items)) menu.add.generic_widget(drop, configure_defaults=True) self.assertEqual(drop._selection_box_width, 225 if not SYS_PLATFORM_OSX else 226) # Check drop is empty self.assertEqual(drop.get_value(), ([], [])) self.assertEqual(drop.get_index(), []) self.assertEqual(drop._get_current_selected_text(), 'Select an option') # Check events self.assertFalse(drop.active) drop.update(PygameEventUtils.key(ctrl.KEY_APPLY, keydown=True)) self.assertTrue(drop.active) self.assertEqual(drop._index, -1) drop.update(PygameEventUtils.key(ctrl.KEY_APPLY, keydown=True)) # Index is -1 self.assertFalse(drop.active) drop.update(PygameEventUtils.key(ctrl.KEY_APPLY, keydown=True)) self.assertTrue(drop.active) drop.update(PygameEventUtils.key(ctrl.KEY_MOVE_UP, keydown=True)) self.assertEqual(drop._index, 0) drop.update(PygameEventUtils.key(ctrl.KEY_MOVE_UP, keydown=True)) self.assertEqual(drop._index, 1) # Apply on current drop.update(PygameEventUtils.key(ctrl.KEY_APPLY, keydown=True)) self.assertEqual(drop.get_value(), ([('epic', 2)], [1])) self.assertEqual(drop.get_index(), [1]) self.assertEqual(drop._get_current_selected_text(), '1 selected') drop.update(PygameEventUtils.key(ctrl.KEY_MOVE_UP, keydown=True)) drop.update(PygameEventUtils.key(ctrl.KEY_MOVE_UP, keydown=True)) drop.update(PygameEventUtils.key(ctrl.KEY_APPLY, keydown=True)) self.assertEqual(drop.get_value(), ([('epic', 2), ('item2', 2)], [1, 3])) self.assertEqual(drop._get_current_selected_text(), '2 selected') # Change selection type drop._selection_placeholder_format = DROPSELECT_MULTIPLE_SFORMAT_LIST_COMMA self.assertEqual(drop._get_current_selected_text(), 'epic,item2 selected') drop._selection_placeholder_format = DROPSELECT_MULTIPLE_SFORMAT_LIST_HYPHEN self.assertEqual(drop._get_current_selected_text(), 'epic-item2 selected') drop._selection_placeholder_format = '+' self.assertEqual(drop._get_current_selected_text(), 'epic+item2 selected') def format_string_list(items_list) -> str: """ Receives the items list string and returns a function. :param items_list: Items list :return: Join string """ if len(items_list) == 1: return items_list[0] elif len(items_list) == 2: return items_list[0] + ' and ' + items_list[1] return 'overflow' drop._selection_placeholder_format = format_string_list self.assertEqual(drop._get_current_selected_text(), 'epic and item2 selected') # Invalid format drop._selection_placeholder_format = 1 self.assertRaises(ValueError, lambda: drop._get_current_selected_text()) drop._selection_placeholder_format = lambda: print('nice') self.assertRaises(ValueError, lambda: drop._get_current_selected_text()) drop._selection_placeholder_format = lambda x: 1 self.assertRaises(AssertionError, lambda: drop._get_current_selected_text()) # Back to default drop._selection_placeholder_format = DROPSELECT_MULTIPLE_SFORMAT_TOTAL # Click item 2, this should unselect self.assertTrue(drop.active) drop.update(PygameEventUtils.middle_rect_click( drop._option_buttons[3])) self.assertEqual(drop.get_value(), ([('epic', 2)], [1])) self.assertEqual(drop._get_current_selected_text(), '1 selected') drop.update(PygameEventUtils.key(ctrl.KEY_MOVE_UP, keydown=True)) self.assertEqual(drop._index, 4) drop.update(PygameEventUtils.key(ctrl.KEY_APPLY, keydown=True)) self.assertEqual(drop.get_value(), ([('epic', 2), ('item3', 3)], [1, 4])) self.assertEqual(drop._get_current_selected_text(), '2 selected') # Close drop.update(PygameEventUtils.key(pygame.K_ESCAPE, keydown=True)) self.assertFalse(drop.active) self.assertEqual(drop.get_value(), ([('epic', 2), ('item3', 3)], [1, 4])) self.assertEqual(drop._get_current_selected_text(), '2 selected') # Change drop selected text method # Set max limit drop._max_selected = 3 self.assertEqual(drop.get_total_selected(), 2) drop.update(PygameEventUtils.key(ctrl.KEY_APPLY, keydown=True)) drop.update(PygameEventUtils.key(ctrl.KEY_MOVE_UP, keydown=True)) drop.update(PygameEventUtils.key(ctrl.KEY_APPLY, keydown=True)) self.assertEqual(drop.get_total_selected(), 3) self.assertTrue(drop.active) drop.update(PygameEventUtils.key(ctrl.KEY_MOVE_UP, keydown=True)) drop.update(PygameEventUtils.key(ctrl.KEY_APPLY, keydown=True)) self.assertEqual(drop.get_total_selected(), 3) # Limit reached self.assertEqual(drop.get_value(), ([('epic', 2), ('item3', 3), ('item4', 4)], [1, 4, 5])) drop.update(PygameEventUtils.key(ctrl.KEY_MOVE_DOWN, keydown=True)) drop.update(PygameEventUtils.key(ctrl.KEY_APPLY, keydown=True)) # Unselect previous self.assertEqual(drop.get_total_selected(), 2) # Limit reached self.assertEqual(drop.get_value(), ([('epic', 2), ('item3', 3)], [1, 4])) # Update elements drop.update_items([('This is a really long selection item', 1), ('epic', 2)]) self.assertEqual(drop.get_value(), ([], [])) self.assertEqual(drop._get_current_selected_text(), 'Select an option') drop.set_value(1, process_index=True) self.assertEqual(drop.get_value(), ([('epic', 2)], [1])) drop.set_value('This is a really long selection item', process_index=True) self.assertEqual(drop.get_value(), ([('This is a really long selection item', 1), ('epic', 2)], [0, 1])) self.assertEqual(drop._get_current_selected_text(), '2 selected') drop.set_default_value(1) self.assertEqual(drop.get_value(), ([('epic', 2)], [1])) self.assertEqual(drop._get_current_selected_text(), '1 selected') # Use manager drop2 = menu.add.dropselect_multiple( 'nice', [('This is a really long selection item', 1), ('epic', 2)], placeholder_selected='nice {0}', placeholder='epic', max_selected=1) self.assertEqual(drop2._selection_box_width, 134 if not SYS_PLATFORM_OSX else 135) self.assertEqual(drop2._get_current_selected_text(), 'epic') drop2.set_value('epic', process_index=True) self.assertEqual(drop2.get_index(), [1]) self.assertEqual(drop2._get_current_selected_text(), 'nice 1') drop2.set_value(0, process_index=True) self.assertEqual(drop2.get_index(), [1]) self.assertEqual(drop2._get_current_selected_text(), 'nice 1') self.assertEqual(drop2._default_value, []) self.assertEqual(drop2._index, 0) self.assertRaises(ValueError, lambda: drop2.set_value('not epic')) # Reset drop2.reset_value() self.assertEqual(drop2._get_current_selected_text(), 'epic') self.assertEqual(drop2._default_value, []) self.assertEqual(drop2._index, -1) self.assertEqual(drop2.get_index(), []) self.assertNotEqual(id(drop2._default_value), id(drop2._selected_indices)) menu.select_widget(drop2) self.assertTrue( drop2.update(PygameEventUtils.key(pygame.K_TAB, keydown=True))) # Test hide self.assertTrue(drop2._drop_frame.is_visible()) self.assertTrue(drop2.active) drop2.hide() # Hiding selects the other widget self.assertEqual(menu.get_selected_widget(), drop) self.assertFalse(drop2._drop_frame.is_visible()) self.assertFalse(drop2.active) drop2.show() self.assertFalse(drop2._drop_frame.is_visible()) self.assertFalse(drop2.active) self.assertEqual(menu.get_selected_widget(), drop) menu.select_widget(drop2) drop2._toggle_drop() self.assertTrue(drop2.active) self.assertTrue(drop2._drop_frame.is_visible()) # Test change test = [-1] def onchange(value) -> None: """ Test onchange. """ test[0] = value[1] drop2.set_onchange(onchange) # Pick any option menu.render() self.assertEqual(test, [-1]) drop2._option_buttons[0].apply() self.assertEqual(test[0], [0]) drop2._option_buttons[0].apply() self.assertEqual(test[0], []) drop2._option_buttons[0].apply() drop2._option_buttons[1].apply() self.assertEqual(test[0], [0]) # As max selected is only 1 drop2._max_selected = 2 drop2._option_buttons[1].apply() self.assertEqual(test[0], [0, 1]) # Test none drop frame drop2._drop_frame = None self.assertEqual(drop2.get_scroll_value_percentage('any'), -1) # Test format option from manager menu._theme.widget_background_inflate_to_selection = True menu._theme.widget_background_inflate = 0 # menu._theme.widget_border_inflate = 0 menu._theme.widget_margin = 0 drop2 = menu.add.dropselect_multiple( 'nice', [('This is a really long selection item', 1), ('epic', 2)], placeholder_selected='nice {0}', placeholder='epic', max_selected=1, selection_placeholder_format=lambda x: 'not EPIC') self.assertEqual(drop2._get_current_selected_text(), 'epic') drop2.set_value('epic', process_index=True) self.assertEqual(drop2._get_current_selected_text(), 'nice not EPIC') self.assertEqual(drop2.get_margin(), (0, 0)) self.assertEqual(drop2._background_inflate, (0, 0)) self.assertEqual(drop2._border_inflate, (0, 0)) menu._theme.widget_background_inflate_to_selection = False # Process index drop2._index = -1 drop2._process_index()
def test_double(self) -> None: """ Test double range slider. """ menu = MenuUtils.generic_menu() # Double slider slider = pygame_menu.widgets.RangeSlider( 'Range', range_text_value_tick_number=3, default_value=(0.2, 1.0), slider_text_value_font=pygame_menu.font.FONT_BEBAS, range_text_value_font=pygame_menu.font.FONT_8BIT, slider_text_value_triangle=False) slider._slider_text_value_vmargin = -2 menu.add.generic_widget(slider, True) slider.draw(surface) slider.draw_after_if_selected(surface) self.assertEqual(slider.get_value(), (0.2, 1.0)) self.assertRaises(AssertionError, lambda: slider.set_value(0.2)) self.assertRaises(AssertionError, lambda: slider.set_value((0.2, 0.2))) self.assertRaises(AssertionError, lambda: slider.set_value((1.0, 0.2))) self.assertRaises(AssertionError, lambda: slider.set_value( (0.2, 0.5, 1.0))) # Test slider selection self.assertTrue(slider._slider_selected[0]) self.assertTrue( slider.update(PygameEventUtils.key(ctrl.KEY_TAB, keydown=True))) self.assertFalse(slider._slider_selected[0]) slider.draw(surface) slider.draw_after_if_selected(surface) # Test click sliders slider_rect = slider._get_slider_inflate_rect(0, to_real_position=True) self.assertTrue( slider.update( PygameEventUtils.middle_rect_click( slider_rect, evtype=pygame.MOUSEBUTTONDOWN))) self.assertTrue(slider._slider_selected[0]) self.assertFalse( slider.update( # Slider already selected PygameEventUtils.middle_rect_click( slider_rect, evtype=pygame.MOUSEBUTTONDOWN))) # Click if sliders are colliding slider.set_value((0.5, 0.50000001)) slider_rect = slider._get_slider_inflate_rect(1, to_real_position=True) self.assertFalse( slider.update( PygameEventUtils.middle_rect_click( slider_rect, evtype=pygame.MOUSEBUTTONDOWN))) self.assertTrue(slider._slider_selected[0]) slider.set_value((0.5, 0.7)) slider_rect = slider._get_slider_inflate_rect(1, to_real_position=True) self.assertTrue( slider.update( PygameEventUtils.middle_rect_click( slider_rect, evtype=pygame.MOUSEBUTTONDOWN))) self.assertTrue(slider._slider_selected[1]) # Test left slider pos = slider._test_get_pos_value(0.5) pos2 = slider._test_get_pos_value(0.6) slider_rect = slider._get_slider_inflate_rect(0, to_real_position=True) self.assertEqual(slider_rect, pygame.Rect(344, 311, 15, 28)) slider.update( PygameEventUtils.middle_rect_click(slider_rect, evtype=pygame.MOUSEBUTTONDOWN)) self.assertTrue(slider._slider_selected[0]) self.assertTrue(slider._scrolling) self.assertTrue(slider._selected_mouse) dx = pos[0] - pos2[0] slider.update( PygameEventUtils.mouse_motion(slider_rect, rel=(-dx, pos[1]), update_mouse=True)) self.assertEqual(slider.get_value(), (0.6, 0.7)) # As slider moved, ignore this slider.update( PygameEventUtils.mouse_motion(slider_rect, rel=(-dx, pos[1]), update_mouse=True)) self.assertEqual(slider.get_value(), (0.6, 0.7)) self.assertTrue(slider._scrolling) self.assertTrue(slider._slider_selected[0]) # Move to 0 self.assertTrue(slider._selected_mouse) pos = slider._test_get_pos_value(0) pos2 = slider._test_get_pos_value(0.6) dx = pos[0] - pos2[0] slider.update( PygameEventUtils.mouse_motion(slider_rect, rel=(dx, pos[1]), update_mouse=True)) self.assertEqual(slider.get_value(), (0, 0.7)) # Move more than 0.7 pos = slider._test_get_pos_value(0) pos2 = slider._test_get_pos_value(0.75) slider_rect = slider._get_slider_inflate_rect(0, to_real_position=True) dx = pos[0] - pos2[0] slider.update( PygameEventUtils.mouse_motion(slider_rect, rel=(-dx, pos[1]), update_mouse=True)) self.assertEqual(slider.get_value(), (0, 0.7)) # Move to 0.7 - eps pos = slider._test_get_pos_value(0) pos2 = slider._test_get_pos_value(0.7 - 1e-6) slider_rect = slider._get_slider_inflate_rect(0, to_real_position=True) dx = pos[0] - pos2[0] slider.update( PygameEventUtils.mouse_motion(slider_rect, rel=(-dx, pos[1]), update_mouse=True)) self.assertAlmostEqual(slider.get_value()[0], 0.7 - 1e-7, places=1) # Ignore if move 0.7 + eps self.assertFalse( slider.update( PygameEventUtils.mouse_motion(slider_rect, rel=(1, pos[1]), update_mouse=True))) # Change to right slider_rect = slider._get_slider_inflate_rect(1, to_real_position=True) self.assertTrue( slider.update(PygameEventUtils.key(ctrl.KEY_TAB, keydown=True))) pos = slider._test_get_pos_value(0.7) pos2 = slider._test_get_pos_value(0.8) dx = pos[0] - pos2[0] self.assertFalse( slider.update( PygameEventUtils.mouse_motion(slider_rect, rel=(-1, pos[1]), update_mouse=True))) self.assertTrue( slider.update( PygameEventUtils.mouse_motion(slider_rect, rel=(-dx, pos[1]), update_mouse=True))) self.assertAlmostEqual(slider.get_value()[1], 0.8) # Test left/right slider.set_value((0.7, 0.8)) slider.update(PygameEventUtils.key(ctrl.KEY_LEFT, keydown=True)) slider.set_value((0.7, 0.8)) # Ignored slider.update(PygameEventUtils.key(ctrl.KEY_RIGHT, keydown=True)) slider.set_value((0.7, 0.9)) slider.update(PygameEventUtils.key(ctrl.KEY_RIGHT, keydown=True)) slider.set_value((0.7, 1.0)) slider.update(PygameEventUtils.key(ctrl.KEY_RIGHT, keydown=True)) slider.set_value((0.7, 1.0)) slider.set_value((0.7, 0.8)) slider.update(PygameEventUtils.key(ctrl.KEY_TAB, keydown=True)) slider.update(PygameEventUtils.key(ctrl.KEY_RIGHT, keydown=True)) slider.set_value((0.7, 0.8)) slider.update(PygameEventUtils.key(ctrl.KEY_LEFT, keydown=True)) slider.set_value((0.6, 0.8)) # Reset value slider.reset_value() self.assertEqual(slider.get_value(), (0.2, 1.0))
def test_single_rangeslider(self) -> None: """ Test single range slider. """ menu = MenuUtils.generic_menu() # Single slider slider = pygame_menu.widgets.RangeSlider('Range S') test = [0, 0] def onchange(x: float) -> None: """ Change slider. """ # noinspection PyTypeChecker test[0] = x def onreturn(x: float) -> None: """ Return slider. """ # noinspection PyTypeChecker test[1] = x slider.set_onchange(onchange) slider.set_onreturn(onreturn) menu.add.generic_widget(slider, True) self.assertEqual(slider.get_value(), 0) slider.set_value(0.5) self.assertEqual(slider.get_value(), 0.5) self.assertEqual(slider._value, [0.5, 0]) self.assertEqual(test[0], 0) slider.update(PygameEventUtils.key(ctrl.KEY_LEFT, keydown=True)) self.assertEqual(test[0], 0.4) self.assertEqual(slider.get_value(), 0.4) slider.update(PygameEventUtils.key(ctrl.KEY_LEFT, keydown=True)) self.assertAlmostEqual(slider.get_value(), 0.3) for _ in range(10): slider.update(PygameEventUtils.key(ctrl.KEY_LEFT, keydown=True)) self.assertEqual(slider.get_value(), 0) self.assertTrue( slider.update(PygameEventUtils.key(ctrl.KEY_RIGHT, keydown=True))) self.assertEqual(slider.get_value(), 0.1) self.assertEqual(test[1], 0) slider.update(PygameEventUtils.key(ctrl.KEY_APPLY, keydown=True)) self.assertEqual(test[1], 0.1) # Ignore invalid key self.assertFalse( slider.update( PygameEventUtils.key(ctrl.KEY_LEFT, keydown=True, testmode=False))) # Ignore for readonly slider.draw(surface) slider.draw_after_if_selected(surface) slider.readonly = True self.assertFalse( slider.update(PygameEventUtils.key(ctrl.KEY_RIGHT, keydown=True))) self.assertEqual(slider.get_value(), 0.1) slider._update_value(0) self.assertEqual(slider.get_value(), 0.1) slider.readonly = False # Test invalid values self.assertRaises(AssertionError, lambda: slider.set_value(-1)) self.assertRaises(AssertionError, lambda: slider.set_value([0.4, 0.5])) # Test invalid transforms self.assertRaises(WidgetTransformationNotImplemented, lambda: slider.rotate()) self.assertRaises(WidgetTransformationNotImplemented, lambda: slider.flip()) self.assertRaises(WidgetTransformationNotImplemented, lambda: slider.scale()) self.assertRaises(WidgetTransformationNotImplemented, lambda: slider.resize()) self.assertRaises(WidgetTransformationNotImplemented, lambda: slider.set_max_width()) self.assertRaises(WidgetTransformationNotImplemented, lambda: slider.set_max_height()) # Test mouse click self.assertFalse(slider._selected_mouse) pos = slider._test_get_pos_value(0.5) slider.update( PygameEventUtils.middle_rect_click(pos, evtype=pygame.MOUSEBUTTONDOWN)) self.assertEqual(slider.get_value(), 0.1) self.assertTrue(slider._selected_mouse) self.assertFalse(slider._scrolling) slider.update(PygameEventUtils.middle_rect_click(pos)) self.assertFalse(slider._scrolling) self.assertEqual(slider.get_value(), 0.5) self.assertFalse(slider._selected_mouse) # Mouse click out of range slider._selected_mouse = True pos = slider._test_get_pos_value(1, dx=100) slider.update(PygameEventUtils.middle_rect_click(pos)) self.assertEqual(slider.get_value(), 0.5) self.assertFalse(slider._selected_mouse) slider._selected_mouse = True pos = slider._test_get_pos_value(0, dx=-100) slider.update(PygameEventUtils.middle_rect_click(pos)) self.assertEqual(slider.get_value(), 0.5) self.assertFalse(slider._selected_mouse) # Test extremes slider._selected_mouse = True pos = slider._test_get_pos_value(0) slider.update(PygameEventUtils.middle_rect_click(pos)) self.assertEqual(slider.get_value(), 0) slider._selected_mouse = True pos = slider._test_get_pos_value(1) slider.update(PygameEventUtils.middle_rect_click(pos)) self.assertEqual(slider.get_value(), 1) # Scroll to 0.5 pos2 = slider._test_get_pos_value(0.5) self.assertFalse(slider._scrolling) slider_rect = slider._get_slider_inflate_rect(0, to_real_position=True) slider.update( PygameEventUtils.middle_rect_click(slider_rect, evtype=pygame.MOUSEBUTTONDOWN)) self.assertTrue(slider._scrolling) self.assertTrue(slider._selected_mouse) dx = pos[0] - pos2[0] slider.update( PygameEventUtils.mouse_motion(slider_rect, rel=(-dx, pos[1]), update_mouse=True)) self.assertEqual(slider.get_value(), 0.5) self.assertTrue(slider._scrolling) slider.update(PygameEventUtils.middle_rect_click(pos)) self.assertFalse(slider._scrolling) # Check invalid constructor for single slider self.assertRaises( AssertionError, lambda: pygame_menu.widgets.RangeSlider( 'Range S', default_value=2)) self.assertRaises( AssertionError, lambda: pygame_menu.widgets.RangeSlider( 'Range S', default_value=1, range_values=[1, 0])) self.assertRaises( AssertionError, lambda: pygame_menu.widgets.RangeSlider( 'Range S', default_value=1, range_values=[1, 1])) self.assertRaises( AssertionError, lambda: pygame_menu.widgets.RangeSlider('Range S', default_value='a')) # Ignore tabs self.assertFalse( slider.update(PygameEventUtils.key(ctrl.KEY_TAB, keydown=True))) # Check LEFT key in repeat self.assertIn(ctrl.KEY_RIGHT, slider._keyrepeat_counters.keys()) self.assertEqual(slider.get_value(), 0.5) # Make left repeat slider._keyrepeat_counters[ctrl.KEY_RIGHT] += 1e4 self.assertEqual(len(slider._events), 0) self.assertFalse(slider.update([])) self.assertEqual(len(slider._events), 1) self.assertFalse(slider.update( [])) # As key is not pressed, event continues self.assertEqual(len(slider._events), 0) # Keyup, removes counters slider.update(PygameEventUtils.key(ctrl.KEY_RIGHT, keyup=True)) self.assertNotIn(ctrl.KEY_RIGHT, slider._keyrepeat_counters.keys()) self.assertFalse(hasattr(slider, '_range_box')) # Single slider with range box slider_rb = pygame_menu.widgets.RangeSlider( 'Range', range_box_single_slider=True) menu.add.generic_widget(slider_rb, True) slider_rb.draw(surface) self.assertTrue(hasattr(slider_rb, '_range_box')) self.assertEqual(slider_rb._range_box.get_width(), 0) slider_rb.set_value(1) self.assertEqual(slider_rb._range_box.get_width(), 150)
def test_single_discrete(self) -> None: """ Test single range slider with discrete values. """ menu = MenuUtils.generic_menu() # Single slider with discrete values rv = [0, 1, 2, 3, 4, 5] slider = pygame_menu.widgets.RangeSlider('Range', range_values=rv) menu.add.generic_widget(slider, True) self.assertRaises( AssertionError, lambda: pygame_menu.widgets.RangeSlider( 'Range', default_value=0.5, range_values=rv)) self.assertRaises( AssertionError, lambda: pygame_menu.widgets.RangeSlider( 'Range', default_value=-1, range_values=rv)) self.assertRaises(AssertionError, lambda: slider.set_value(-1)) self.assertRaises(AssertionError, lambda: slider.set_value([0, 1])) self.assertRaises(AssertionError, lambda: slider.set_value((0, 1))) # Test key events self.assertFalse( slider.update(PygameEventUtils.key(ctrl.KEY_TAB, keydown=True))) slider.update(PygameEventUtils.key(ctrl.KEY_RIGHT, keydown=True)) self.assertEqual(slider.get_value(), 1) slider.update(PygameEventUtils.key(ctrl.KEY_RIGHT, keydown=True)) self.assertEqual(slider.get_value(), 2) slider._increment = 0 slider.update(PygameEventUtils.key(ctrl.KEY_RIGHT, keydown=True)) self.assertEqual(slider.get_value(), 3) slider.update(PygameEventUtils.key(ctrl.KEY_LEFT, keydown=True)) self.assertEqual(slider.get_value(), 2) slider.update(PygameEventUtils.key(ctrl.KEY_LEFT, keydown=True)) self.assertEqual(slider.get_value(), 1) slider.update(PygameEventUtils.key(ctrl.KEY_LEFT, keydown=True)) self.assertEqual(slider.get_value(), 0) slider.update(PygameEventUtils.key(ctrl.KEY_LEFT, keydown=True)) self.assertEqual(slider.get_value(), 0) # Test click mouse slider._selected_mouse = True pos = slider._test_get_pos_value(2) slider.update(PygameEventUtils.middle_rect_click(pos)) self.assertEqual(slider.get_value(), 2) self.assertFalse(slider._selected_mouse) # Test invalid click slider._selected_mouse = True pos = slider._test_get_pos_value(2, dx=1000) slider.update(PygameEventUtils.middle_rect_click(pos)) self.assertEqual(slider.get_value(), 2) self.assertFalse(slider._selected_mouse) # Scroll to 4 pos = slider._test_get_pos_value(2) pos2 = slider._test_get_pos_value(4) self.assertFalse(slider._scrolling) slider_rect = slider._get_slider_inflate_rect(0, to_real_position=True) slider.update( PygameEventUtils.middle_rect_click(slider_rect, evtype=pygame.MOUSEBUTTONDOWN)) self.assertTrue(slider._scrolling) self.assertTrue(slider._selected_mouse) dx = pos[0] - pos2[0] slider.update( PygameEventUtils.mouse_motion(slider_rect, rel=(-dx, pos[1]), update_mouse=True)) self.assertEqual(slider.get_value(), 4) self.assertTrue(slider._scrolling) slider.update(PygameEventUtils.middle_rect_click(pos)) self.assertFalse(slider._scrolling) # Back to 2 slider.set_value(2) # Invalid scrolling if clicked outside the slider slider.update( PygameEventUtils.middle_rect_click(slider._test_get_pos_value(0), evtype=pygame.MOUSEBUTTONDOWN)) self.assertFalse(slider._scrolling)
def test_config(self) -> None: """ Configure controls. """ self.assertEqual(ctrl.KEY_APPLY, pygame.K_RETURN) # Change apply to new key ctrl.KEY_APPLY = pygame.K_END self.assertEqual(ctrl.KEY_APPLY, pygame.K_END) # Create new button menu = MenuUtils.generic_menu() test = [False] def click_button() -> None: """ Button apply handler. """ test[0] = not test[0] print('new test value', test) button = menu.add.button('button', click_button) self.assertFalse(test[0]) button.apply() self.assertTrue(test[0]) button.apply() self.assertFalse(test[0]) # Now test new apply button button.update(PygameEventUtils.key(pygame.K_END, keydown=True)) self.assertTrue(test[0]) button.update(PygameEventUtils.key(pygame.K_END, keydown=True)) self.assertFalse(test[0]) # Rollback change ctrl.KEY_APPLY = pygame.K_RETURN # Create new controller object new_ctrl = ctrl.Controller() test_apply = [0] def new_apply(event, _) -> bool: """ Updates apply. """ test_apply[0] += 1 return event.key == pygame.K_a new_ctrl.apply = new_apply button.set_controller(new_ctrl) # Now test new apply button button.update(PygameEventUtils.key(pygame.K_a, keydown=True)) self.assertTrue(test[0]) button.update(PygameEventUtils.key(pygame.K_a, keydown=True)) self.assertFalse(test[0]) self.assertEqual(test_apply[0], 2) button.update(PygameEventUtils.key(pygame.K_END, keydown=True)) self.assertFalse(test[0]) button.update(PygameEventUtils.key(ctrl.KEY_APPLY, keydown=True)) self.assertFalse( test[0]) # It should do nothing as object has new controller # The same can be done with menu menu.set_controller(new_ctrl)
def test_menu_link(self) -> None: """ Test menu link. """ menu = MenuUtils.generic_menu() menu1 = MenuUtils.generic_menu(title='Menu1', theme=pygame_menu.themes.THEME_BLUE) menu1.add.button('Back', pygame_menu.events.BACK) menu2 = MenuUtils.generic_menu(title='Menu2', theme=pygame_menu.themes.THEME_ORANGE) menu2.add.button('Back', pygame_menu.events.BACK) menu3 = MenuUtils.generic_menu(title='Menu3', theme=pygame_menu.themes.THEME_GREEN) menu3.add.button('Back', pygame_menu.events.BACK) btn1 = menu.add.button('menu1', menu1) btn2 = menu.add.button('menu2', menu2) btn3 = menu.add.button('menu3', menu3) # Hide the buttons btn1.hide() btn2.hide() btn3.hide() # Now open menu with the button, this should open Menu1 by default self.assertEqual(menu.get_current(), menu) btn1.apply() self.assertEqual(menu.get_current(), menu1) menu.full_reset() self.assertEqual(menu.get_current(), menu) # Add menu link link_test = menu.add.menu_link(menu2) link_test.open() self.assertEqual(menu.get_current(), menu2) menu.full_reset() self.assertEqual(menu.get_current(), menu) self.assertFalse(link_test.is_visible()) link_test.hide() self.assertFalse(link_test.is_visible()) link_test.show() self.assertFalse(link_test.is_visible()) self.assertRaises(ValueError, lambda: menu.add.menu_link(menu)) # Invalid objects self.assertRaises(ValueError, lambda: menu.add.menu_link(True)) # noinspection PyMissingTypeHints,PyMissingOrEmptyDocstring def open_link(*args) -> None: link: 'pygame_menu.widgets.MenuLink' = args[-1] self.assertIsInstance(link, pygame_menu.widgets.MenuLink) link.open() # Add a selection object, which opens the links sel = menu.add.selector('Change menu ', [('Menu 1', menu.add.menu_link(menu1)), ('Menu 2', menu.add.menu_link(menu2)), ('Menu 3', menu.add.menu_link(menu3))], onreturn=open_link, style=pygame_menu.widgets.SELECTOR_STYLE_FANCY) sel.update(PygameEventUtils.key(ctrl.KEY_APPLY, keydown=True))
def test_unicode(self) -> None: """ Test unicode support. """ menu = MenuUtils.generic_menu() textinput = menu.add.text_input('title', input_underline='_') textinput.set_value('tk') # Test alt+x textinput.update(PygameEventUtils.key(pygame.K_SPACE, keydown=True)) textinput.update( PygameEventUtils.key(pygame.K_2, keydown=True, char='2')) textinput.update( PygameEventUtils.key(pygame.K_1, keydown=True, char='1')) textinput.update( PygameEventUtils.key(pygame.K_1, keydown=True, char='5')) self.assertEqual(textinput.get_value(), 'tk 215') textinput.update(PygameEventUtils.keydown_mod_alt( pygame.K_x)) # convert 215 to unicode self.assertEqual(textinput.get_value(), 'tkȕ') textinput.update(PygameEventUtils.key(pygame.K_SPACE, keydown=True)) textinput.update(PygameEventUtils.key(pygame.K_SPACE, keydown=True)) textinput.update( PygameEventUtils.key(pygame.K_b, keydown=True, char='B')) textinput.update( PygameEventUtils.key(pygame.K_1, keydown=True, char='1')) textinput.update(PygameEventUtils.keydown_mod_alt( pygame.K_x)) # convert 215 to unicode self.assertEqual(textinput.get_value(), 'tkȕ ±') # Remove all textinput.clear() textinput.update( PygameEventUtils.key(pygame.K_b, keydown=True, char='B')) textinput.update( PygameEventUtils.key(pygame.K_1, keydown=True, char='1')) textinput.update(PygameEventUtils.keydown_mod_alt( pygame.K_x)) # convert 215 to unicode self.assertEqual(textinput.get_value(), '±') textinput.update(PygameEventUtils.keydown_mod_alt( pygame.K_x)) # convert same to unicode, do nothing self.assertEqual(textinput.get_value(), '±') # Test consecutive textinput.update( PygameEventUtils.key(pygame.K_2, keydown=True, char='2')) textinput.update( PygameEventUtils.key(pygame.K_0, keydown=True, char='0')) textinput.update( PygameEventUtils.key(pygame.K_1, keydown=True, char='1')) textinput.update( PygameEventUtils.key(pygame.K_3, keydown=True, char='3')) textinput.update(PygameEventUtils.keydown_mod_alt( pygame.K_x)) # convert 215 to unicode self.assertEqual(textinput.get_value(), '±–') # Test 0x textinput.clear() PygameEventUtils.release_key_mod() textinput.update( PygameEventUtils.key(pygame.K_0, keydown=True, char='0')) self.assertEqual(textinput.get_value(), '0') textinput.update( PygameEventUtils.key(pygame.K_x, keydown=True, char='x')) self.assertEqual(textinput.get_value(), '0x') textinput.update(PygameEventUtils.keydown_mod_alt(pygame.K_x)) self.assertEqual(textinput.get_value(), '0x') textinput.update( PygameEventUtils.key(pygame.K_b, keydown=True, char='B')) textinput.update( PygameEventUtils.key(pygame.K_1, keydown=True, char='1')) self.assertEqual(textinput.get_value(), '0xB1') textinput.update(PygameEventUtils.keydown_mod_alt(pygame.K_x)) self.assertEqual(textinput.get_value(), '±') PygameEventUtils.release_key_mod() textinput.update( PygameEventUtils.key(pygame.K_0, keydown=True, char='0')) textinput.update( PygameEventUtils.key(pygame.K_x, keydown=True, char='x')) textinput.update( PygameEventUtils.key(pygame.K_b, keydown=True, char='B')) textinput.update( PygameEventUtils.key(pygame.K_1, keydown=True, char='1')) textinput.update(PygameEventUtils.keydown_mod_alt(pygame.K_x)) self.assertEqual(textinput.get_value(), '±±') # Test keyup self.assertIn(pygame.K_1, textinput._keyrepeat_counters.keys()) self.assertFalse( textinput.update( PygameEventUtils.key(pygame.K_1, keyup=True, char='1'))) self.assertNotIn(pygame.K_1, textinput._keyrepeat_counters.keys()) # Test tab self.assertEqual(textinput._tab_size, 4) textinput.update(PygameEventUtils.key(pygame.K_TAB, keydown=True)) self.assertEqual(textinput.get_value(), '±± ') # Test invalid unicode self.assertFalse( textinput.update(PygameEventUtils.key(pygame.K_1, keydown=True))) # Test others textinput._input_type = 'other' self.assertTrue(textinput._check_input_type('-')) self.assertFalse(textinput._check_input_type('x')) textinput._maxwidth_update = None self.assertIsNone(textinput._update_maxlimit_renderbox())
def test_colorinput(self) -> None: """ Test ColorInput widget. """ def _assert_invalid_color(widg) -> None: """ Assert that the widget color is invalid. :param widg: Widget object """ r, g, b = widg.get_value() self.assertEqual(r, -1) self.assertEqual(g, -1) self.assertEqual(b, -1) def _assert_color(widg, cr, cg, cb) -> None: """ Assert that the widget color is invalid. :param widg: Widget object :param cr: Red channel, number between 0 and 255 :param cg: Green channel, number between 0 and 255 :param cb: Blue channel, number between 0 and 255 """ r, g, b = widg.get_value() self.assertEqual(r, cr) self.assertEqual(g, cg) self.assertEqual(b, cb) menu = MenuUtils.generic_menu(theme=TEST_THEME.copy()) # Base rgb widget = menu.add.color_input('title', color_type='rgb', input_separator=',') widget.set_value((123, 234, 55)) self.assertRaises(AssertionError, lambda: widget.set_value('0,0,0')) self.assertRaises(AssertionError, lambda: widget.set_value(( 255, 0, ))) self.assertRaises(AssertionError, lambda: widget.set_value( (255, 255, -255))) _assert_color(widget, 123, 234, 55) # Test separator widget = menu.add.color_input('color', color_type='rgb', input_separator='+') widget.set_value((34, 12, 12)) self.assertEqual(widget._input_string, '34+12+12') self.assertRaises( AssertionError, lambda: menu.add.color_input( 'title', color_type='rgb', input_separator='')) self.assertRaises( AssertionError, lambda: menu.add.color_input( 'title', color_type='rgb', input_separator=' ')) self.assertRaises( AssertionError, lambda: menu.add.color_input('title', color_type='unknown')) for i in range(10): self.assertRaises( AssertionError, lambda: menu.add.color_input( 'title', color_type='rgb', input_separator=str(i))) # Empty rgb widget = menu.add.color_input('color', color_type='rgb', input_separator=',') PygameEventUtils.test_widget_key_press(widget) self.assertEqual(widget._cursor_position, 0) widget.update(PygameEventUtils.key(pygame.K_RIGHT, keydown=True)) self.assertEqual(widget._cursor_position, 0) _assert_invalid_color(widget) # Write sequence: 2 -> 25 -> 25, -> 25,0, # The comma after the zero must be automatically set self.assertFalse( widget.update(PygameEventUtils.key(0, keydown=True, testmode=False))) widget.update(PygameEventUtils.key(pygame.K_2, keydown=True, char='2')) widget.update(PygameEventUtils.key(pygame.K_5, keydown=True, char='5')) widget.update( PygameEventUtils.key(pygame.K_COMMA, keydown=True, char=',')) self.assertEqual(widget._input_string, '25,') widget.update(PygameEventUtils.key(pygame.K_0, keydown=True, char='0')) self.assertEqual(widget._input_string, '25,0,') _assert_invalid_color(widget) # Now, sequence: 25,0,c -> 25c,0, with cursor c widget.update(PygameEventUtils.key(pygame.K_LEFT, keydown=True)) widget.update(PygameEventUtils.key(pygame.K_LEFT, keydown=True)) widget.update(PygameEventUtils.key(pygame.K_LEFT, keydown=True)) self.assertEqual(widget._cursor_position, 2) # Sequence. 25,0, -> 255,0, -> 255,0, trying to write another 5 in the same position # That should be cancelled because 2555 > 255 widget.update(PygameEventUtils.key(pygame.K_5, keydown=True, char='5')) self.assertEqual(widget._input_string, '255,0,') widget.update(PygameEventUtils.key(pygame.K_5, keydown=True, char='5')) self.assertEqual(widget._input_string, '255,0,') # Invalid left zeros, try to write 255,0, -> 255,00, but that should be disabled widget.update(PygameEventUtils.key(pygame.K_RIGHT, keydown=True)) widget.update(PygameEventUtils.key(pygame.K_0, keydown=True, char='0')) self.assertEqual(widget._input_string, '255,0,') # Second comma cannot be deleted because there's a number between ,0, widget.update(PygameEventUtils.key(pygame.K_BACKSPACE, keydown=True)) self.assertEqual(widget._input_string, '255,0,') widget.update(PygameEventUtils.key(pygame.K_LEFT, keydown=True)) widget.update(PygameEventUtils.key(pygame.K_DELETE, keydown=True)) self.assertEqual(widget._input_string, '255,0,') # Current cursor is at 255c,0, # Now right comma and 0 can be deleted widget.update(PygameEventUtils.key(pygame.K_END, keydown=True)) widget.update(PygameEventUtils.key(pygame.K_BACKSPACE, keydown=True)) widget.update(PygameEventUtils.key(pygame.K_BACKSPACE, keydown=True)) self.assertEqual(widget._input_string, '255,') # Fill with zeros, then number with 2 consecutive 0 types must be 255,0,0 # Commas should be inserted automatically widget.readonly = True widget.update(PygameEventUtils.key(pygame.K_0, keydown=True, char='0')) self.assertEqual(widget._input_string, '255,') widget.readonly = False widget.update(PygameEventUtils.key(pygame.K_0, keydown=True, char='0')) widget.update(PygameEventUtils.key(pygame.K_0, keydown=True, char='0')) self.assertEqual(widget._input_string, '255,0,0') _assert_color(widget, 255, 0, 0) # At this state, user cannot add more zeros at right for i in range(5): widget.update( PygameEventUtils.key(pygame.K_0, keydown=True, char='0')) self.assertEqual(widget._input_string, '255,0,0') widget.get_rect() widget.clear() self.assertEqual(widget._input_string, '') # Assert invalid defaults rgb self.assertRaises( AssertionError, lambda: menu.add.color_input( 'title', color_type='rgb', default=( 255, 255, ))) self.assertRaises( AssertionError, lambda: menu.add.color_input( 'title', color_type='rgb', default=(255, 255))) self.assertRaises( AssertionError, lambda: menu.add.color_input( 'title', color_type='rgb', default=(255, 255, 255, 255))) # Assert hex widget widget = menu.add.color_input('title', color_type='hex') self.assertEqual(widget._input_string, '#') self.assertEqual(widget._cursor_position, 1) _assert_invalid_color(widget) self.assertRaises(AssertionError, lambda: widget.set_value('#FF')) self.assertRaises(AssertionError, lambda: widget.set_value('#FFFFF<')) self.assertRaises(AssertionError, lambda: widget.set_value('#FFFFF')) self.assertRaises(AssertionError, lambda: widget.set_value('#F')) # noinspection SpellCheckingInspection self.assertRaises(AssertionError, lambda: widget.set_value('FFFFF')) self.assertRaises(AssertionError, lambda: widget.set_value('F')) widget.set_value('FF00FF') _assert_color(widget, 255, 0, 255) widget.set_value('#12FfAa') _assert_color(widget, 18, 255, 170) widget.set_value(' 59C1e5') _assert_color(widget, 89, 193, 229) widget.render() widget.draw(surface) widget.clear() self.assertEqual(widget._input_string, '#') # This cannot be empty self.assertEqual(widget._cursor_position, 1) # In hex widget # cannot be deleted widget.update(PygameEventUtils.key(pygame.K_BACKSPACE, keydown=True)) self.assertEqual(widget._cursor_position, 1) widget.update(PygameEventUtils.key(pygame.K_LEFT, keydown=True)) widget.update(PygameEventUtils.key(pygame.K_DELETE, keydown=True)) self.assertEqual(widget._input_string, '#') widget.update(PygameEventUtils.key(pygame.K_END, keydown=True)) for i in range(10): widget.update( PygameEventUtils.key(pygame.K_f, keydown=True, char='f')) self.assertEqual(widget._input_string, '#ffffff') _assert_color(widget, 255, 255, 255) # Test hex formats widget = menu.add.color_input('title', color_type='hex', hex_format='none') widget.set_value('#ff00ff') self.assertFalse( widget.update(PygameEventUtils.key(0, keydown=True, testmode=False))) self.assertEqual(widget.get_value(as_string=True), '#ff00ff') widget.set_value('#FF00ff') self.assertEqual(widget.get_value(as_string=True), '#FF00ff') widget = menu.add.color_input('title', color_type='hex', hex_format='lower') widget.set_value('#FF00ff') self.assertEqual(widget.get_value(as_string=True), '#ff00ff') widget.set_value('AABBcc') self.assertEqual(widget.get_value(as_string=True), '#aabbcc') widget = menu.add.color_input('title', color_type='hex', hex_format='upper') widget.set_value('#FF00ff') self.assertEqual(widget.get_value(as_string=True), '#FF00FF') widget.set_value('AABBcc') self.assertEqual(widget.get_value(as_string=True), '#AABBCC') # Test dynamic sizing widget = menu.add.color_input('title', color_type='hex', hex_format='upper', dynamic_width=True) self.assertEqual(widget.get_width(), 200) widget.set_value('#ffffff') width = 342 if PYGAME_V2 else 345 self.assertEqual(widget.get_width(), width) widget.set_value(None) self.assertEqual(widget.get_width(), 200) self.assertEqual(widget.get_value(as_string=True), '#') widget.set_value('#ffffff') self.assertEqual(widget.get_width(), width) widget.update(PygameEventUtils.key( pygame.K_BACKSPACE, keydown=True)) # remove the last character, now color is invalid self.assertEqual(widget.get_value(as_string=True), '#FFFFF') # is upper widget.render() self.assertEqual(widget.get_width(), 200) widget = menu.add.color_input('title', color_type='hex', hex_format='upper', dynamic_width=False) self.assertEqual(widget.get_width(), width) widget.set_value('#ffffff') self.assertEqual(widget.get_width(), width)
def test_dropselect(self) -> None: """ Test dropselect widget. """ menu = MenuUtils.generic_menu(mouse_motion_selection=True, theme=THEME_NON_FIXED_TITLE) items = [('This is a really long selection item', 1), ('epic', 2)] for i in range(10): items.append(('item{}'.format(i + 1), i + 1)) # noinspection SpellCheckingInspection drop = pygame_menu.widgets.DropSelect( 'dropsel', items, selection_option_font_size=int(0.75 * menu._theme.widget_font_size), placeholder_add_to_selection_box=False, selection_option_font=menu._theme.widget_font) menu.add.generic_widget(drop, configure_defaults=True) self.assertEqual( drop._selection_box_width, (207 if PYGAME_V2 else 208) if not SYS_PLATFORM_OSX else 209) self.assertEqual(drop.get_frame_depth(), 0) drop.render() self.assertTrue(drop._drop_frame.is_scrollable) drop_frame = drop._drop_frame self.assertIn(drop_frame, menu._update_frames) if PYGAME_V2: # noinspection SpellCheckingInspection self.assertEqual( menu._test_widgets_status(), ((('DropSelect-dropsel', (0, 0, 0, 123, 149, 354, 49, 123, 304, 123, 149), (1, 0, 1, 1, 0, 0, 0), ('Frame', (-1, -1, -1, 261, 193, 207, 136, 261, 348, 261, 193), (0, 0, 0, 0, 1, 0, 0), (-1, -1)), ('Button-This is a really long selection item', (-1, -1, -1, 0, -1, 356, 40, 261, 348, 0, 154), (1, 0, 0, 0, 0, 1, 1)), ('Button-epic', (-1, -1, -1, 0, 38, 356, 40, 261, 386, 0, 193), (1, 0, 0, 0, 0, 1, 1)), ('Button-item1', (-1, -1, -1, 0, 77, 356, 40, 261, 425, 0, 232), (1, 0, 0, 0, 0, 1, 1)), ('Button-item2', (-1, -1, -1, 0, 116, 356, 40, 261, 348, 0, 271), (1, 0, 0, 0, 0, 1, 1)), ('Button-item3', (-1, -1, -1, 0, 155, 356, 40, 261, 348, 0, 310), (1, 0, 0, 0, 0, 1, 1)), ('Button-item4', (-1, -1, -1, 0, 194, 356, 40, 261, 348, 0, 349), (1, 0, 0, 0, 0, 1, 1)), ('Button-item5', (-1, -1, -1, 0, 233, 356, 40, 261, 348, 0, 388), (1, 0, 0, 0, 0, 1, 1)), ('Button-item6', (-1, -1, -1, 0, 272, 356, 40, 261, 348, 0, 427), (1, 0, 0, 0, 0, 1, 1)), ('Button-item7', (-1, -1, -1, 0, 311, 356, 40, 261, 348, 0, 466), (1, 0, 0, 0, 0, 1, 1)), ('Button-item8', (-1, -1, -1, 0, 350, 356, 40, 261, 348, 0, 505), (1, 0, 0, 0, 0, 1, 1)), ('Button-item9', (-1, -1, -1, 0, 389, 356, 40, 261, 348, 0, 544), (1, 0, 0, 0, 0, 1, 1)), ('Button-item10', (-1, -1, -1, 0, 428, 356, 40, 261, 348, 0, 583), (1, 0, 0, 0, 0, 1, 1))), ))) self.assertEqual( drop._drop_frame.get_attribute('height'), (135 if PYGAME_V2 else 138) if not SYS_PLATFORM_OSX else 141) self.assertEqual( drop._drop_frame.get_attribute('width'), (187 if PYGAME_V2 else 188) if not SYS_PLATFORM_OSX else 189) # Test events self.assertFalse(drop.active) self.assertFalse(drop._drop_frame.is_visible()) drop.update(PygameEventUtils.key(ctrl.KEY_APPLY, keydown=True)) self.assertTrue(drop.active) self.assertTrue(drop._drop_frame.is_visible()) self.assertEqual(drop.get_index(), -1) drop.update(PygameEventUtils.key(ctrl.KEY_MOVE_UP, keydown=True)) self.assertEqual(drop.get_index(), 0) self.assertTrue(drop.active) drop.update(PygameEventUtils.key(ctrl.KEY_APPLY, keydown=True)) self.assertFalse( drop.update( PygameEventUtils.key(ctrl.KEY_APPLY, keydown=True, testmode=False))) self.assertFalse(drop.active) self.assertFalse(drop._drop_frame.is_visible()) drop.update(PygameEventUtils.key(ctrl.KEY_MOVE_DOWN, keydown=True)) self.assertEqual(drop.get_index(), 0) self.assertFalse(drop.active) drop.update(PygameEventUtils.key(pygame.K_TAB, keydown=True)) # Enable self.assertTrue(drop.active) drop.update(PygameEventUtils.key(pygame.K_TAB, keydown=True)) self.assertFalse(drop.active) drop.update(PygameEventUtils.key(pygame.K_TAB, keydown=True)) # Enable self.assertTrue(drop.active) drop.update(PygameEventUtils.key(ctrl.KEY_MOVE_DOWN, keydown=True)) # Not infinite self.assertEqual(drop.get_index(), 0) scroll_values = [ -1, 0, 0, 0.114, 0.228, 0.33, 0.447, 0.561, 0.664, 0.778, 0.895, 0.997 ] for i in range(1, 12): drop.update(PygameEventUtils.key(ctrl.KEY_MOVE_UP, keydown=True)) self.assertEqual(drop.get_index(), i) if PYGAME_V2: self.assertEqual( drop.get_scroll_value_percentage(ORIENTATION_VERTICAL), scroll_values[i]) drop.update(PygameEventUtils.key(ctrl.KEY_MOVE_UP, keydown=True)) # Not infinite self.assertEqual(drop.get_index(), 11) # Not infinite if PYGAME_V2: self.assertEqual( drop.get_scroll_value_percentage(ORIENTATION_VERTICAL), 0.997) # Mouseup over rect returns True updated status self.assertTrue(drop.active) self.assertTrue( drop.update( PygameEventUtils.middle_rect_click( drop.get_focus_rect(), evtype=pygame.MOUSEBUTTONDOWN))) self.assertTrue(drop.active) # Touch also does the same trick if PYGAME_V2: drop._touchscreen_enabled = True self.assertTrue( drop.update( PygameEventUtils.middle_rect_click(drop.get_focus_rect(), menu=menu, evtype=FINGERDOWN))) self.assertTrue(drop.active) # Scroll to bottom and close, then open again, this should scroll to current selected drop.scrollh(0) drop.scrollv(0) self.assertEqual( drop._drop_frame.get_scroll_value_percentage(ORIENTATION_VERTICAL), 0) drop._toggle_drop() drop._toggle_drop() if PYGAME_V2: self.assertEqual( drop._drop_frame.get_scroll_value_percentage( ORIENTATION_VERTICAL), 0.997) # Click drop box should toggle it self.assertTrue(drop.active) drop.update(PygameEventUtils.middle_rect_click(drop)) self.assertFalse(drop.active) drop.update(PygameEventUtils.middle_rect_click(drop)) self.assertTrue(drop.active) # Click middle option drop.update(PygameEventUtils.middle_rect_click(drop.get_focus_rect())) self.assertEqual(drop.get_index(), 10) self.assertFalse(drop.active) # Touch middle if not SYS_PLATFORM_OSX: self.assertTrue(drop._touchscreen_enabled) drop.update( PygameEventUtils.middle_rect_click(drop.get_focus_rect(), evtype=pygame.FINGERUP, menu=drop.get_menu())) self.assertTrue(drop.active) # Test focus if not drop.active: drop.update(PygameEventUtils.key(ctrl.KEY_APPLY, keydown=True)) if PYGAME_V2: self.assertEqual( menu._draw_focus_widget(surface, drop), { 1: ((0, 0), (600, 0), (600, 307), (0, 307)), 2: ((0, 308), (260, 308), (260, 483), (0, 483)), 3: ((468, 308), (600, 308), (600, 483), (468, 483)), 4: ((0, 484), (600, 484), (600, 600), (0, 600)) }) else: if not SYS_PLATFORM_OSX: self.assertEqual( menu._draw_focus_widget(surface, drop), { 1: ((0, 0), (600, 0), (600, 306), (0, 306)), 2: ((0, 307), (259, 307), (259, 486), (0, 486)), 3: ((468, 307), (600, 307), (600, 486), (468, 486)), 4: ((0, 487), (600, 487), (600, 600), (0, 600)) }) else: self.assertEqual( menu._draw_focus_widget(surface, drop), { 1: ((0, 0), (600, 0), (600, 305), (0, 305)), 2: ((0, 306), (259, 306), (259, 489), (0, 489)), 3: ((469, 306), (600, 306), (600, 489), (469, 489)), 4: ((0, 490), (600, 490), (600, 600), (0, 600)) }) # Test change items drop_frame = drop._drop_frame drop._drop_frame = None self.assertEqual(drop.get_scroll_value_percentage('any'), -1) self.assertRaises( pygame_menu.widgets.widget.dropselect. _SelectionDropNotMadeException, lambda: drop._check_drop_made()) drop._drop_frame = drop_frame drop.update_items([]) drop._make_selection_drop() self.assertEqual(drop._drop_frame.get_attribute('height'), 0) self.assertEqual(drop._drop_frame.get_attribute('width'), 0) self.assertFalse(drop.active) drop._toggle_drop() self.assertFalse(drop.active) fr = drop.get_focus_rect() r = drop.get_rect(apply_padding=False, to_real_position=True) self.assertEqual(fr.x, r.x) self.assertEqual(fr.y, r.y) self.assertEqual(fr.width + drop._selection_box_border_width, r.width) self.assertEqual(fr.height, r.height) self.assertEqual(drop.get_index(), -1) self.assertRaises(ValueError, lambda: drop.get_value()) drop._up() self.assertEqual(drop.get_index(), -1) drop._down() self.assertEqual(drop.get_index(), -1) # Check previous frame not in scrollable frames self.assertFalse(drop._drop_frame.is_scrollable) self.assertNotIn(drop_frame, menu._update_frames) # Restore previous values drop.update_items(items) self.assertEqual(drop.get_index(), -1) # Apply transforms drop.translate(1, 1) self.assertEqual(drop.get_translate(), (1, 1)) drop.translate(0, 0) self.assertRaises(WidgetTransformationNotImplemented, lambda: drop.rotate(10)) self.assertEqual(drop._angle, 0) self.assertRaises(WidgetTransformationNotImplemented, lambda: drop.resize(10, 10)) self.assertFalse(drop._scale[0]) self.assertEqual(drop._scale[1], 1) self.assertEqual(drop._scale[2], 1) self.assertRaises(WidgetTransformationNotImplemented, lambda: drop.scale(100, 100)) self.assertFalse(drop._scale[0]) self.assertEqual(drop._scale[1], 1) self.assertEqual(drop._scale[2], 1) self.assertRaises(WidgetTransformationNotImplemented, lambda: drop.flip(True, True)) self.assertFalse(drop._flip[0]) self.assertFalse(drop._flip[1]) self.assertRaises(WidgetTransformationNotImplemented, lambda: drop.set_max_width(100)) self.assertIsNone(drop._max_width[0]) self.assertRaises(WidgetTransformationNotImplemented, lambda: drop.set_max_height(100)) self.assertIsNone(drop._max_height[0]) self.assertFalse(drop.active) # Add margin vm = menu.add.vertical_margin(500) self.assertEqual(vm.get_height(), 500) # Add drop from widget manager, this has the placeholder button drop2 = menu.add.dropselect('drop2', items, dropselect_id='2', selection_infinite=True, selection_option_font_size=int( 0.75 * menu._theme.widget_font_size)) self.assertEqual(drop2._tab_size, menu._theme.widget_tab_size) for btn in drop2._option_buttons: self.assertEqual(btn._tab_size, menu._theme.widget_tab_size) self.assertEqual(drop2._drop_frame._tab_size, 4) self.assertEqual(drop2.get_id(), '2') self.assertEqual( menu.get_scrollarea().get_scroll_value_percentage( ORIENTATION_VERTICAL), 0) self.assertTrue(drop._open_bottom) self.assertFalse(drop2._open_bottom) # Move to bottom menu.get_scrollarea().scroll_to(ORIENTATION_VERTICAL, 1) menu.render() self.assertTrue(drop._open_bottom) self.assertFalse(drop2._open_bottom) menu.select_widget(drop2) drop2._toggle_drop() self.assertEqual(drop2.get_position(), ((132, 554) if PYGAME_V2 else (131, 555)) if not SYS_PLATFORM_OSX else (131, 556)) self.assertEqual( drop2._drop_frame.get_attribute('height'), (117 if PYGAME_V2 else 120) if not SYS_PLATFORM_OSX else 123) self.assertEqual( drop2._drop_frame.get_attribute('width'), (187 if PYGAME_V2 else 188) if not SYS_PLATFORM_OSX else 189) # Test infinite self.assertTrue(drop2.active) self.assertEqual(drop2.get_index(), -1) drop2._down() self.assertEqual(drop2.get_index(), 11) drop2.draw(surface) drop._index = -1 drop2._up() self.assertEqual(drop2.get_index(), 0) drop2._up() self.assertEqual(drop2.get_index(), 1) drop2._down() self.assertEqual(drop2.get_index(), 0) drop2._down() self.assertEqual(drop2.get_index(), 11) drop2._up() self.assertEqual(drop2.get_index(), 0) drop2.set_value('item6') self.assertEqual(drop2.get_index(), 7) drop2.readonly = True drop2._up() self.assertEqual(drop2.get_index(), 7) drop2._down() self.assertEqual(drop2.get_index(), 7) drop2.readonly = False menu.render() self.assertEqual( drop2.get_scroll_value_percentage(ORIENTATION_VERTICAL), (0.606 if PYGAME_V2 else 0.603) if not SYS_PLATFORM_OSX else 0.609) drop2.reset_value() self.assertTrue(drop2.active) self.assertEqual(drop2.get_index(), -1) drop2.set_scrollarea(drop2.get_scrollarea()) if PYGAME_V2: self.assertEqual( menu._draw_focus_widget(surface, drop2), { 1: ((0, 0), (600, 0), (600, 338), (0, 338)), 2: ((0, 339), (239, 339), (239, 496), (0, 496)), 3: ((447, 339), (600, 339), (600, 496), (447, 496)), 4: ((0, 497), (600, 497), (600, 600), (0, 600)) }) menu.draw(surface) self.assertIsNone(drop2.get_frame()) self.assertEqual(drop2.last_surface, menu._widgets_surface ) # Outside frame, must be the widgets surface # Add drop inside frame f = menu.add.frame_v(400, 500, max_height=200, background_color=(0, 0, 255)) f.pack(drop2) self.assertEqual(drop2.get_scrollarea(), f.get_scrollarea(inner=True)) self.assertEqual(drop2._drop_frame.get_scrollarea(), f.get_scrollarea(inner=True)) self.assertEqual(drop2.get_scrollarea().get_parent(), menu.get_scrollarea()) self.assertEqual(drop2._drop_frame.get_scrollarea().get_parent(), menu.get_scrollarea()) drop2.update_items([('optionA', 1), ('optionB', 2)]) if PYGAME_V2: self.assertEqual( drop2._get_status(), (('DropSelect-drop2', (0, 2, 3, 0, 0, 332, 49, 88, 308, 0, -242), (1, 0, 1, 1, 0, 1, 1), ('Frame', (-1, -1, -1, 116, 44, 207, 100, 204, 352, 116, -198), (0, 0, 0, 0, 0, 1, 1), (-1, -1)), ('Button-optionA', (-1, -1, -1, 116, 77, 207, 34, 204, 385, 116, -165), (1, 0, 0, 0, 0, 1, 2)), ('Button-optionB', (-1, -1, -1, 116, 110, 207, 34, 204, 418, 116, -132), (1, 0, 0, 0, 0, 1, 2))))) self.assertEqual( drop2._drop_frame.get_attribute('height'), (100 if PYGAME_V2 else 103) if not SYS_PLATFORM_OSX else 106) self.assertEqual( drop2._drop_frame.get_attribute('width'), (207 if PYGAME_V2 else 208) if not SYS_PLATFORM_OSX else 209) self.assertEqual( drop2.get_scrollarea().get_parent_scroll_value_percentage( ORIENTATION_VERTICAL), (0, 1) if not SYS_PLATFORM_OSX else (0, 0.997)) self.assertTrue(drop2._open_bottom) # Test onchange test = [-1, False] drop2.set_default_value(0) def test_change(item, v) -> None: """ Test change. """ assert item[0][1] == v test[0] = item[0][0] def test_apply(item, v) -> None: """ Test apply. """ assert item[0][1] == v test[1] = not test[1] drop2.set_onchange(test_change) drop2.set_onreturn(test_apply) drop2._toggle_drop() self.assertEqual(drop2.get_index(), -1) self.assertEqual(test[0], -1) drop2._up() self.assertEqual(test[0], 'optionA') drop2._up() self.assertEqual(test[0], 'optionB') drop2._up() self.assertEqual(test[0], 'optionA') self.assertFalse(test[1]) drop2.update(PygameEventUtils.key(ctrl.KEY_APPLY, keydown=True)) # Now it's closed self.assertTrue(test[1]) self.assertFalse(drop2.active) drop2.update(PygameEventUtils.key( ctrl.KEY_APPLY, keydown=True)) # This only opens but not apply self.assertTrue(test[1]) self.assertTrue(drop2.active) menu.draw(surface) self.assertEqual(drop2.get_frame(), f) self.assertEqual( drop2.last_surface, f.get_surface()) # Frame surface as drop is not in middle drop2.update(PygameEventUtils.key(ctrl.KEY_APPLY, keydown=True)) # Now applies self.assertFalse(test[1]) self.assertFalse(drop2.active) # Unpack from frame f.unpack(drop2) self.assertTrue(drop2.is_floating()) drop2.set_float(False) self.assertEqual( drop2._drop_frame.get_attribute('height'), (100 if PYGAME_V2 else 103) if not SYS_PLATFORM_OSX else 106) self.assertEqual( drop2._drop_frame.get_attribute('width'), (207 if PYGAME_V2 else 208) if not SYS_PLATFORM_OSX else 209) # Test close if mouse clicks outside menu.select_widget(drop) drop._toggle_drop() self.assertTrue(drop.active) drop.update(PygameEventUtils.mouse_click(0, 0)) self.assertFalse(drop.active) # Set drop in middle if PYGAME_V2: self.assertEqual(drop._drop_frame.get_position(), (251, 45)) self.assertEqual(drop.get_focus_rect(), pygame.Rect(121, 160, 337, 41)) drop._open_middle = True menu.render() # For this test, hide all widgets except drop # for w in menu.get_widgets(): # w.hide() # drop.show() if PYGAME_V2: self.assertEqual(drop._drop_frame.get_position(), (196, 105)) self.assertEqual(drop.get_focus_rect(), pygame.Rect(121, 160, 337, 41)) scr = drop._drop_frame.get_scrollarea() sfr = drop._drop_frame.get_frame() # Add drop to frame f.pack(drop) menu.render() self.assertEqual(drop._drop_frame.get_scrollarea(), scr) self.assertEqual(drop._drop_frame.get_frame(), sfr) if PYGAME_V2: self.assertEqual(drop._drop_frame.get_position(), (196, 453)) self.assertEqual(drop.get_focus_rect(), pygame.Rect(96, 312, 337, 41)) self.assertFalse(drop.active) drop._toggle_drop() menu.render() menu.draw(surface) self.assertEqual( drop.last_surface, menu._widgets_surface) # Menu surface as drop is in middle if PYGAME_V2: self.assertEqual( menu._draw_focus_widget(surface, drop), { 1: ((0, 0), (600, 0), (600, 259), (0, 259)), 2: ((0, 260), (195, 260), (195, 394), (0, 394)), 3: ((403, 260), (600, 260), (600, 394), (403, 394)), 4: ((0, 395), (600, 395), (600, 600), (0, 600)) }) drop._toggle_drop() drop2._open_middle = True menu.render() menu.select_widget(drop2) drop2._toggle_drop() menu.draw(surface) self.assertEqual(drop2.last_surface, menu._widgets_surface) if PYGAME_V2: self.assertEqual(drop2._drop_frame.get_position(), (196, 519)) self.assertEqual(drop2.get_focus_rect(), pygame.Rect(196, 277, 207, 99)) # Disable focus menu._mouse_motion_selection = False # As drop1 is scrollable, remove from menu, this should remove the widget too drop_frame = drop._drop_frame self.assertIn(drop_frame, menu._update_frames) menu.remove_widget(drop) self.assertNotIn(drop_frame, menu._update_frames) def draw_rect() -> None: """ Draw absolute rect on surface for testing purposes. """ # surface.fill((255, 0, 0), drop2.get_focus_rect()) # surface.fill((0, 0, 255), drop2.get_scrollarea().get_absolute_view_rect()) # surface.fill((255, 255, 0), drop2.get_scrollarea().get_absolute_view_rect().clip(drop.get_focus_rect())) return menu.get_decorator().add_callable(draw_rect, prev=False, pass_args=False) # Test active with different menu settings menu_theme = pygame_menu.themes.THEME_ORANGE.copy() menu_theme.title_fixed = False menu_theme.title_offset = (5, -2) menu_theme.widget_alignment = pygame_menu.locals.ALIGN_LEFT menu_theme.widget_font = pygame_menu.font.FONT_OPEN_SANS_LIGHT menu_theme.widget_font_size = 20 menu2 = MenuUtils.generic_menu(theme=menu_theme, width=400) menu2.add.vertical_margin(1000) drop3 = menu2.add.dropselect_multiple( title='Pick 3 colors', items=[('Black', (0, 0, 0)), ('Blue', (0, 0, 255)), ('Cyan', (0, 255, 255)), ('Fuchsia', (255, 0, 255)), ('Green', (0, 255, 0)), ('Red', (255, 0, 0)), ('White', (255, 255, 255)), ('Yellow', (255, 255, 0))], dropselect_multiple_id='pickcolors', open_middle=True, max_selected=3) rh = 28 if not SYS_PLATFORM_OSX else 29 self.assertEqual(drop3.get_focus_rect(), pygame.Rect(108, 468, 320, rh)) # Translate the menu, this should also modify focus menu2.translate(100, 50) self.assertEqual(drop3.get_focus_rect(), pygame.Rect(108 + 100, 468 + 50, 320, rh)) menu2.translate(100, 150) self.assertEqual(drop3.get_focus_rect(), pygame.Rect(108 + 100, 468 + 150, 320, rh)) menu2.translate(0, 0) self.assertEqual(drop3.get_focus_rect(), pygame.Rect(108, 468, 320, rh)) # Test update list def remove_selection_item(select: 'pygame_menu.widgets.DropSelect'): """ Update list event. """ if select.get_index() == -1: return s_val = select.get_value() _items = select.get_items() _items.pop(_items.index(s_val[0])) select.update_items(_items) print('removed {} left'.format(len(_items))) menu = MenuUtils.generic_menu() select1 = menu.add.dropselect('Subject Id', items=[('a', ), ('b', ), ('c', ), ('d', ), ('e', ), ('f', )], dropselect_id='s0') b_sel = menu.add.button('One', remove_selection_item, select1) b_sel.apply() select1.set_value(0) self.assertEqual(select1.get_value(), (('a', ), 0)) b_sel.apply() self.assertEqual(select1.get_index(), -1) self.assertEqual(select1.get_items(), [('b', ), ('c', ), ('d', ), ('e', ), ('f', )]) b_sel.apply() # Update by value select1.set_value('b') self.assertEqual(select1.get_index(), 0) select1.set_value('e') self.assertEqual(select1.get_index(), 3) self.assertRaises(ValueError, lambda: select1.set_value('unknown')) b_sel.apply() # to -1 select1.active = True select1.show() # Test configured select1.configured = False self.assertRaises(RuntimeError, lambda: select1._make_selection_drop()) select1.configured = True select1.readonly = True self.assertFalse(select1.update([])) # Test touchscreen support if not PYGAME_V2: return menu = MenuUtils.generic_menu(touchscreen=True) sel = menu.add.dropselect('Subject Id', items=[('a', ), ('b', ), ('c', ), ('d', ), ('e', ), ('f', )], dropselect_id='s0') menu.add.button('One', remove_selection_item, sel) # Select by touch touch_sel = sel.get_rect(to_real_position=True).center self.assertEqual(sel.get_index(), -1) self.assertFalse(sel.active) sel.update( PygameEventUtils.touch_click(touch_sel[0], touch_sel[1], menu=menu)) self.assertTrue(sel.active) # Touch null option sel.update( PygameEventUtils.touch_click(touch_sel[0], touch_sel[1] + 40, menu=menu)) self.assertTrue(sel.active) # Select option a sel.update( PygameEventUtils.touch_click(touch_sel[0], touch_sel[1] + 80, menu=menu)) self.assertEqual(sel.get_index(), 0) self.assertFalse(sel.active) # Touch outside sel.update( PygameEventUtils.touch_click(touch_sel[0], touch_sel[1] + 400, menu=menu)) self.assertFalse(sel.active) # Touch button menu.update( PygameEventUtils.touch_click(touch_sel[0], touch_sel[1] + 40, menu=menu, evtype=FINGERDOWN)) menu.update( PygameEventUtils.touch_click(touch_sel[0], touch_sel[1] + 40, menu=menu)) # Touch again outside sel.update( PygameEventUtils.touch_click(touch_sel[0], touch_sel[1] + 400, menu=menu)) self.assertFalse(sel.active) # Select sel.select(update_menu=True) sel.update( PygameEventUtils.touch_click(touch_sel[0], touch_sel[1], menu=menu)) self.assertTrue(sel.active) # Touch but by menu events, unselect current and force selection sel.active = False menu._widget_selected_update = False menu.update( PygameEventUtils.touch_click(touch_sel[0], touch_sel[1], menu=menu)) self.assertTrue(sel.active) menu.update( PygameEventUtils.touch_click(touch_sel[0], touch_sel[1], menu=menu)) self.assertFalse(sel.active) # Mouse click menu.update(PygameEventUtils.mouse_click(touch_sel[0], touch_sel[1])) self.assertTrue(sel.active) menu.update(PygameEventUtils.mouse_click(touch_sel[0], touch_sel[1])) self.assertFalse(sel.active) menu._widget_selected_update = True # Update the number of items sel.update_items([('a', ), ('b', )]) self.assertFalse(sel.active) sel.update( PygameEventUtils.touch_click(touch_sel[0], touch_sel[1], menu=menu)) self.assertTrue(sel.active) self.assertEqual(sel.get_index(), -1) sel.update( PygameEventUtils.touch_click(touch_sel[0], touch_sel[1] + 80, menu=menu)) self.assertEqual(sel.get_index(), 0) self.assertFalse(sel.active) sel.update( PygameEventUtils.touch_click(touch_sel[0], touch_sel[1], menu=menu)) self.assertTrue(sel.active) sel.update( PygameEventUtils.touch_click(touch_sel[0], touch_sel[1] + 80, menu=menu, evtype=pygame.FINGERDOWN)) sel.update( PygameEventUtils.touch_click(touch_sel[0], touch_sel[1], menu=menu)) self.assertFalse(sel.active) # Ignore buttons if not active self.assertFalse( sel.update( PygameEventUtils.key(pygame_menu.controls.KEY_MOVE_UP, keydown=True)))