def test_size(self) -> None: """ Test size. """ menu = MenuUtils.generic_menu(title='menu', theme=TEST_THEME.copy()) menu.render() self.assertEqual(menu.get_height(widget=True), 0) # Adds a button, hide it, then the height should be 0 as well btn = menu.add.button('hidden') btn.hide() self.assertEqual(menu.get_height(widget=True), 0) menu.render() # Get the size of the scrollarea sa = menu.get_scrollarea() sa_height = menu.get_height() - menu.get_menubar().get_height() sa_width = menu.get_width() self.assertEqual(sa.get_world_size()[0], sa_width) self.assertEqual(sa.get_world_size()[1], sa_height) rect = sa.get_view_rect() self.assertEqual(rect.x, 0) self.assertEqual(rect.y, 155) self.assertEqual(rect.width, sa_width) self.assertEqual(rect.height, sa_height) self.assertEqual(sa.get_hidden_width(), 0) self.assertEqual(sa.get_hidden_height(), 0) rect = sa.to_world_position(btn.get_rect()) self.assertEqual(rect.x, 0) self.assertEqual(rect.y, -155) self.assertEqual(rect.width, btn.get_width()) self.assertEqual(rect.height, btn.get_height()) pos_rect = sa.to_world_position((10, 10)) self.assertEqual(pos_rect, (10, -145)) self.assertFalse(sa.is_scrolling()) self.assertEqual(sa.get_menu(), menu) sa._on_vertical_scroll(50) sa._on_horizontal_scroll(50) # Remove the world of surface world = sa._world sa._world = None self.assertEqual(sa.get_world_size(), (0, 0)) sa._world = world # Test collide event = PygameEventUtils.mouse_click(100, 100, inlist=False) self.assertFalse(sa.collide(btn, event)) # Create virtual rect from button rect_virtual = sa.to_real_position(btn.get_rect()) event_click_widget = PygameEventUtils.middle_rect_click(rect_virtual, inlist=False) self.assertTrue(sa.collide(btn, event_click_widget))
def test_size(self) -> None: """ Test size. """ if SYS_PLATFORM_OSX: return menu = MenuUtils.generic_menu(title='menu', theme=TEST_THEME.copy()) menu.render() self.assertEqual(menu.get_height(widget=True), 0) # Adds a button, hide it, then the height should be 0 as well btn = menu.add.button('hidden') btn.hide() self.assertEqual(menu.get_height(widget=True), 0) menu.render() # Get the size of the scrollarea sa = menu.get_scrollarea() sa_height = menu.get_height() - menu.get_menubar().get_height() sa_width = menu.get_width() self.assertEqual(sa.get_world_size()[0], sa_width) self.assertEqual(sa.get_world_size()[1], sa_height) rect = sa.get_view_rect() self.assertEqual(rect.x, 0) self.assertEqual(rect.y, 155) self.assertEqual(rect.width, sa_width) self.assertEqual(rect.height, sa_height) self.assertEqual(sa.get_hidden_width(), 0) self.assertEqual(sa.get_hidden_height(), 0) rect = sa.to_world_position(btn.get_rect()) self.assertEqual(rect.x, 0) self.assertEqual(rect.y, -155) self.assertEqual(rect.width, btn.get_width()) self.assertEqual(rect.height, btn.get_height()) pos_rect = sa.to_world_position((10, 10)) self.assertEqual(pos_rect, (10, -145)) self.assertFalse(sa.is_scrolling()) self.assertEqual(sa.get_menu(), menu) sa._on_vertical_scroll(50) sa._on_horizontal_scroll(50) # Remove the world of surface world = sa._world sa._world = None self.assertEqual(sa.get_world_size(), (0, 0)) sa._world = world # Test collide event = PygameEventUtils.mouse_click(100, 100, inlist=False) self.assertFalse(sa.collide(btn, event)) # Create virtual rect from button rect_virtual = sa.to_real_position(btn.get_rect()) event_click_widget = PygameEventUtils.middle_rect_click(rect_virtual, inlist=False) self.assertTrue(sa.collide(btn, event_click_widget)) self.assertEqual(sa.get_world_rect(absolute=True), pygame.Rect(0, 0, 600, 345)) self.assertEqual(sa.get_size(), (600, 345)) self.assertIsInstance(sa.mouse_is_over(), bool) # Append many items within menu, thus, scrollbars will appear self.assertEqual(sa.get_scrollbar_thickness(ORIENTATION_VERTICAL), 0) self.assertEqual(sa.get_scrollbar_thickness(ORIENTATION_HORIZONTAL), 0) sa._scrollbar_positions = (POSITION_NORTH, POSITION_EAST, POSITION_WEST, POSITION_SOUTH) self.assertEqual(sa.get_view_rect(), pygame.Rect(0, 155, 600, 345)) for i in range(10): menu.add.button('b{0}'.format(i)).scale(20, 1) self.assertEqual(sa.get_scrollbar_thickness(ORIENTATION_VERTICAL), 20) self.assertEqual(sa.get_scrollbar_thickness(ORIENTATION_HORIZONTAL), 20) sa._on_vertical_scroll(0.5) sa._on_horizontal_scroll(0.5) self.assertEqual(sa.to_real_position((10, 10)), (10, 165)) sa.get_view_rect() # Test rect sa = pygame_menu._scrollarea.ScrollArea(100, 100) self.assertEqual(sa.get_rect(to_real_position=True), pygame.Rect(0, 0, 100, 100)) self.assertEqual(sa.get_scrollbar_thickness(ORIENTATION_VERTICAL, visible=False), 0) self.assertEqual(sa.get_scrollbar_thickness(ORIENTATION_HORIZONTAL, visible=False), 0) self.assertEqual(sa.get_scrollbar_thickness(ORIENTATION_VERTICAL, visible=False), 0) self.assertRaises(AssertionError, lambda: sa.get_scrollbar_thickness('fake', visible=False))
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_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_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_menubar(self) -> None: """ Test menubar widget. """ menu = MenuUtils.generic_menu() for mode in (MENUBAR_STYLE_ADAPTIVE, MENUBAR_STYLE_NONE, MENUBAR_STYLE_SIMPLE, MENUBAR_STYLE_UNDERLINE, MENUBAR_STYLE_UNDERLINE_TITLE, MENUBAR_STYLE_TITLE_ONLY, MENUBAR_STYLE_TITLE_ONLY_DIAGONAL): mb = MenuBar('Menu', 500, (0, 0, 0), back_box=True, mode=mode) menu.add.generic_widget(mb) mb = MenuBar('Menu', 500, (0, 0, 0), back_box=True) mb.set_backbox_border_width(2) self.assertRaises(AssertionError, lambda: mb.set_backbox_border_width(1.5)) self.assertRaises(AssertionError, lambda: mb.set_backbox_border_width(0)) self.assertRaises(AssertionError, lambda: mb.set_backbox_border_width(-1)) self.assertEqual(mb._backbox_border_width, 2) menu.draw(surface) menu.disable() # Test unknown mode mb = MenuBar('Menu', 500, (0, 0, 0), back_box=True, mode='unknown') mb.set_menu(menu) self.assertRaises(ValueError, lambda: mb._render()) # Check margins mb = MenuBar('Menu', 500, (0, 0, 0), back_box=True, mode=MENUBAR_STYLE_ADAPTIVE) self.assertEqual(mb.get_scrollbar_style_change(POSITION_SOUTH), (0, (0, 0))) self.assertEqual(mb.get_scrollbar_style_change(POSITION_EAST), (0, (0, 0))) self.assertEqual(mb.get_scrollbar_style_change(POSITION_WEST), (0, (0, 0))) self.assertEqual(mb.get_scrollbar_style_change(POSITION_NORTH), (0, (0, 0))) mb.set_menu(menu) mb._render() self.assertEqual(mb.get_scrollbar_style_change(POSITION_SOUTHWEST), (0, (0, 0))) # Test displacements theme = pygame_menu.themes.THEME_DEFAULT.copy() theme.title_bar_style = MENUBAR_STYLE_TITLE_ONLY menu = MenuUtils.generic_menu(theme=theme, title='my title') mb = menu.get_menubar() self.assertEqual(mb.get_scrollbar_style_change(POSITION_SOUTH), (0, (0, 0))) self.assertEqual(mb.get_scrollbar_style_change(POSITION_EAST), (0, (0, 0))) self.assertEqual(mb.get_scrollbar_style_change(POSITION_WEST), (-55, (0, 55))) self.assertEqual(mb.get_scrollbar_style_change(POSITION_NORTH), (0, (0, 55))) # Test with close button menu = MenuUtils.generic_menu(theme=theme, title='my title', onclose=pygame_menu.events.CLOSE, touchscreen=True) theme.widget_border_inflate = 0 mb = menu.get_menubar() self.assertEqual(mb.get_scrollbar_style_change(POSITION_SOUTH), (0, (0, 0))) self.assertEqual(mb.get_scrollbar_style_change(POSITION_EAST), (-33, (0, 33))) self.assertEqual(mb.get_scrollbar_style_change(POSITION_WEST), (-55, (0, 55))) self.assertEqual(mb.get_scrollbar_style_change(POSITION_NORTH), (0, (0, 55))) # Hide the title, and check mb.hide() self.assertEqual(mb.get_scrollbar_style_change(POSITION_SOUTH), (0, (0, 0))) self.assertEqual(mb.get_scrollbar_style_change(POSITION_EAST), (0, (0, 0))) self.assertEqual(mb.get_scrollbar_style_change(POSITION_WEST), (0, (0, 0))) self.assertEqual(mb.get_scrollbar_style_change(POSITION_NORTH), (0, (0, 0))) mb.show() self.assertEqual(mb.get_scrollbar_style_change(POSITION_SOUTH), (0, (0, 0))) self.assertEqual(mb.get_scrollbar_style_change(POSITION_EAST), (-33, (0, 33))) self.assertEqual(mb.get_scrollbar_style_change(POSITION_WEST), (-55, (0, 55))) self.assertEqual(mb.get_scrollbar_style_change(POSITION_NORTH), (0, (0, 55))) # Floating mb.set_float(True) self.assertEqual(mb.get_scrollbar_style_change(POSITION_SOUTH), (0, (0, 0))) self.assertEqual(mb.get_scrollbar_style_change(POSITION_EAST), (0, (0, 0))) self.assertEqual(mb.get_scrollbar_style_change(POSITION_WEST), (0, (0, 0))) self.assertEqual(mb.get_scrollbar_style_change(POSITION_NORTH), (0, (0, 0))) mb.set_float(False) self.assertEqual(mb.get_scrollbar_style_change(POSITION_SOUTH), (0, (0, 0))) self.assertEqual(mb.get_scrollbar_style_change(POSITION_EAST), (-33, (0, 33))) self.assertEqual(mb.get_scrollbar_style_change(POSITION_WEST), (-55, (0, 55))) self.assertEqual(mb.get_scrollbar_style_change(POSITION_NORTH), (0, (0, 55))) # Fixed mb.fixed = False self.assertEqual(mb.get_scrollbar_style_change(POSITION_SOUTH), (0, (0, 0))) self.assertEqual(mb.get_scrollbar_style_change(POSITION_EAST), (0, (0, 0))) self.assertEqual(mb.get_scrollbar_style_change(POSITION_WEST), (0, (0, 0))) self.assertEqual(mb.get_scrollbar_style_change(POSITION_NORTH), (0, (0, 0))) # Test menubar self.assertFalse( mb.update(PygameEventUtils.middle_rect_click(mb._rect))) self.assertTrue( mb.update(PygameEventUtils.middle_rect_click(mb._backbox_rect))) self.assertTrue( mb.update( PygameEventUtils.middle_rect_click(mb._backbox_rect, evtype=pygame.FINGERUP, menu=menu))) self.assertFalse( mb.update( PygameEventUtils.middle_rect_click( mb._backbox_rect, evtype=pygame.MOUSEBUTTONDOWN))) self.assertTrue( mb.update(PygameEventUtils.joy_button(ctrl.JOY_BUTTON_BACK))) mb.readonly = True self.assertFalse( mb.update(PygameEventUtils.joy_button(ctrl.JOY_BUTTON_BACK))) mb.readonly = False # Test none methods self.assertRaises(WidgetTransformationNotImplemented, lambda: mb.rotate(10)) self.assertEqual(mb._angle, 0) self.assertRaises(WidgetTransformationNotImplemented, lambda: mb.resize(10, 10)) self.assertFalse(mb._scale[0]) self.assertEqual(mb._scale[1], 1) self.assertEqual(mb._scale[2], 1) self.assertRaises(WidgetTransformationNotImplemented, lambda: mb.scale(100, 100)) self.assertFalse(mb._scale[0]) self.assertEqual(mb._scale[1], 1) self.assertEqual(mb._scale[2], 1) self.assertRaises(WidgetTransformationNotImplemented, lambda: mb.flip(True, True)) self.assertFalse(mb._flip[0]) self.assertFalse(mb._flip[1]) self.assertRaises(WidgetTransformationNotImplemented, lambda: mb.set_max_width(100)) self.assertIsNone(mb._max_width[0]) self.assertRaises(WidgetTransformationNotImplemented, lambda: mb.set_max_height(100)) self.assertIsNone(mb._max_height[0]) # Ignore others mb.set_padding() mb.set_border() mb.set_selection_effect() menu.add.button('nice')
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_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)))