def __stack_windows(self) -> ndarray: final = self.__windows[0].current_matrix.copy() for k in range(1, len(self.__windows)): window_coords = self.__windows[k].relative_coordinates MatrixUtils.blit_image_inplace(final, self.__windows[k].current_matrix, window_coords[0], window_coords[1]) return final
def test_blit_image_inplace(self): MatrixUtils.blit_image_inplace(self.destination_image, self.source_image, 1, 1) result_single_channel = np.array([[0, 0, 0, 0], [0, 1, 1, 0], [0, 1, 1, 0], [0, 0, 0, 0]]) result = np.dstack((result_single_channel, result_single_channel, result_single_channel)) self.assertTrue(np.array_equal(result, self.destination_image))
def test_get_blank_image_as_numpy_array_image_color(self): image = MatrixUtils.get_blank_image_as_numpy_array((25, 85, 172), width=2, height=2) result_red = np.array([[25, 25], [25, 25]]) result_green = np.array([[85, 85], [85, 85]]) result_blue = np.array([[172, 172], [172, 172]]) result = np.dstack((result_red, result_green, result_blue)) self.assertTrue(np.array_equal(image, result))
def click(self, click_coordinates: ndarray, parent_coordinates: ndarray = None ) -> (int, bool, ndarray, ndarray): click_on_window = False if self.visible: if MatrixUtils.includes_point(click_coordinates, self.relative_coordinates, self.width, self.height): click_on_window = True for child in self.children: reward, click_on_child, matrix, coords = child.click( click_coordinates, self.relative_coordinates) if click_on_child: MatrixUtils.blit_image_inplace(self.__current_matrix, matrix, coords[0], coords[1]) return reward, click_on_window, matrix, coords + self.relative_coordinates return 0, click_on_window, None, None
def step(self, action: ndarray) -> (ndarray, int, bool): reward = 0 number_of_windows_to_be_removed = 0 # Click on windows starting with the topmost window down to the window at the bottom # Continue clicking only while the current window was not clicked AND # the current window is not modal for i in range(-1, -len(self.__windows) - 1, -1): index = i + number_of_windows_to_be_removed reward, window_includes_point, clicked_child_component_matrix, clicked_child_component_coords = \ self.__windows[index].click(action) if window_includes_point: if clicked_child_component_matrix is not None: # Blit the changed component directly on the frame buffer, only if the clicked component is # in the topmost window if not self.__should_re_stack: MatrixUtils.blit_image_inplace(self.__frame_buffer, clicked_child_component_matrix, clicked_child_component_coords[0], clicked_child_component_coords[1]) break else: if self.__windows[index].modal: break elif self.__windows[index].auto_close: # Save the removed window for future reference and continue with the loop removed_window = self.__remove_window() self.__windows_to_be_removed.append(removed_window) number_of_windows_to_be_removed += 1 # Redraw all windows by stacking them up from the bottom to the top, if needed if self.__should_re_stack: self.__frame_buffer = self.__stack_windows() # Reset internal state self.__should_re_stack = False self.__windows_to_be_removed.clear() return self.__frame_buffer, reward, self.__done, None
class Checkbox(Button): ARRAY_CLICKED = MatrixUtils.get_numpy_array_of_image('chk_clicked.png') ARRAY_UNCLICKED = MatrixUtils.get_numpy_array_of_image('chk_unclicked.png') ARRAY_CLICKED_DISABLED = MatrixUtils.get_numpy_array_of_image('chk_clicked_dis.png') ARRAY_UNCLICKED_DISABLED = MatrixUtils.get_numpy_array_of_image('chk_unclicked_dis.png') def __init__(self, relative_coordinates: ndarray, reward: int, on_click_listener: Callable[[Button], None] = lambda b: None): """ A :class:`Button` with checkbox appearance :param relative_coordinates: Coordinates of the button relative to its parent Drawable :param reward: The amount of reward this button generates when clicked for the first time :param on_click_listener: Function which is called when the button is clicked """ super().__init__(Checkbox.ARRAY_UNCLICKED, relative_coordinates, Checkbox.ARRAY_CLICKED, Checkbox.ARRAY_CLICKED_DISABLED, reward, on_click_listener, False)
def click(self, click_coordinates: ndarray, parent_coordinates: ndarray) -> (int, bool, ndarray, ndarray): if self.visible: if MatrixUtils.includes_point( click_coordinates, self.relative_coordinates + parent_coordinates, self.width, self.height): self.__clicked = not self.__clicked if self.__reward_given: reward = 0 else: self.__reward_given = True reward = self.__reward self.__on_click_listener(self) return reward, True, self._select_matrix( ), self.relative_coordinates return 0, False, None, None
def __init__(self, matrix_unclicked: ndarray, relative_coordinates: ndarray, menu_buttons: List[MenuButton], matrix_clicked: ndarray = None, matrix_disabled: ndarray = None, reward: int = 0, on_click_listener: Callable[[Button], None] = lambda b: None): """ A :class:`Button` which opens a dropdown menu when clicked. The dropdown menu consists of :class:`MenuButton`'s :param matrix_unclicked: Image matrix of the button in unclicked state :param relative_coordinates: Coordinates of the button relative to its parent Drawable :param menu_buttons: A List of MenuButton's to be shown on the dropdown menu :param matrix_clicked: Image matrix of the button in clicked state :param matrix_disabled: Image matrix of the button in disabled state :param reward: The amount of reward this button generates when clicked for the first time """ super().__init__(matrix_unclicked, relative_coordinates, matrix_clicked, matrix_disabled, reward, on_click_listener) # Lazy init in click self.__parent_coords = None # Lazy init in click listener self.__menu = None dropdown_menu_width, dropdown_menu_height = DropdownButton.__calculate_menu_dimensions( menu_buttons) dropdown_menu_width += DropdownButton.DROPDOWN_MENU_BORDER_WIDTH dropdown_menu_height += DropdownButton.DROPDOWN_MENU_BORDER_WIDTH self.__background_matrix = MatrixUtils.get_blank_image_as_numpy_array( DropdownButton.DROPDOWN_MENU_BORDER_COLOR, dropdown_menu_width, dropdown_menu_height) self.__menu_buttons = menu_buttons # Set relative positions of menu buttons menu_button_pos = np.array([1, 1]) for button in menu_buttons: button.relative_coordinates = menu_button_pos menu_button_pos = menu_button_pos + np.array([0, button.height])
def __init_components(self) -> Window: # Load drawable images # -------------------------------------------------------------------------------------------------- main_window_array = MatrixUtils.get_numpy_array_of_image('main_window.png') close_button_large_array = MatrixUtils.get_numpy_array_of_image('close_window_button_large_unclicked.png') uber_window_array = MatrixUtils.get_numpy_array_of_image('window_über.png') close_uber_window_button_array = MatrixUtils.get_numpy_array_of_image('close_über_window_button.png') close_button_array = MatrixUtils.get_numpy_array_of_image('close_window_button_unclicked.png') preferences_window_array = MatrixUtils.get_numpy_array_of_image('window_preferences.png') preferences_window_abbrechen_button_array = MatrixUtils.get_numpy_array_of_image('button_abbrechen_unclicked.png') preferences_window_speichern_button_array = MatrixUtils.get_numpy_array_of_image('button_speichern_unclicked.png') preferences_window_zuruecksetzen_unclicked_array = MatrixUtils.get_numpy_array_of_image('button_zuruecksetzen_unclicked.png') preferences_window_zuruecksetzen_clicked_array = MatrixUtils.get_numpy_array_of_image('button_zuruecksetzen_clicked.png') preferences_window_clipboard_unclicked_array = MatrixUtils.get_numpy_array_of_image('button_clipboard_unclicked.png') preferences_window_clipboard_clicked_array = MatrixUtils.get_numpy_array_of_image('button_clipboard_clicked.png') preferences_window_aendern_unclicked_array = MatrixUtils.get_numpy_array_of_image('button_aendern_unclicked.png') preferences_window_aendern_clicked_array = MatrixUtils.get_numpy_array_of_image('button_aendern_clicked.png') preferences_window_bearbeiten_unclicked_array = MatrixUtils.get_numpy_array_of_image('button_bearbeiten_unclicked.png') preferences_window_bearbeiten_clicked_array = MatrixUtils.get_numpy_array_of_image('button_bearbeiten_clicked.png') preferences_window_close_array = MatrixUtils.get_numpy_array_of_image('close_pref_button.png') dropdown_datei_unclicked_array = MatrixUtils.get_numpy_array_of_image('drpdwn_datei_unclicked.png') dropdown_datei_clicked_array = MatrixUtils.get_numpy_array_of_image('drpdwn_datei_clicked.png') dropdown_anzeigen_unclicked_array = MatrixUtils.get_numpy_array_of_image('drpdwn_anzeigen_unclicked.png') dropdown_anzeigen_clicked_array = MatrixUtils.get_numpy_array_of_image('drpdwn_anzeigen.png') dropdown_hilfe_unclicked_array = MatrixUtils.get_numpy_array_of_image('drpdwn_hilfe_unclicked.png') dropdown_hilfe_clicked_array = MatrixUtils.get_numpy_array_of_image('drpdwn_hilfe_clicked.png') dropdown_navigation_unclicked_array = MatrixUtils.get_numpy_array_of_image('drpdwn_navigation_unclicked.png') dropdown_navigation_clicked_array = MatrixUtils.get_numpy_array_of_image('drpdwn_navigation_clicked.png') dropdown_tools_unclicked_array = MatrixUtils.get_numpy_array_of_image('drpdwn_tools_unclicked.png') dropdown_tools_clicked_array = MatrixUtils.get_numpy_array_of_image('drpdwn_tools_clicked.png') small_button_arrays = [] for i in range(1, 14): small_button_arrays.append(MatrixUtils.get_numpy_array_of_image('small_button_' + str(i) + '_unclicked.png')) small_button_arrays.append(MatrixUtils.get_numpy_array_of_image('small_button_' + str(i) + '_clicked.png')) menu_button_uber_unclicked_array = MatrixUtils.get_numpy_array_of_image('menu_über_unclicked.png') menu_button_other_unclicked_array = MatrixUtils.get_numpy_array_of_image('menu_button_1.png') menu_button_other_clicked_array = MatrixUtils.get_numpy_array_of_image('menu_button_1_clicked.png') menu_button_preferences_unclicked_array = MatrixUtils.get_numpy_array_of_image('menu_button_preferences_unclicked.png') # -------------------------------------------------------------------------------------------------- # Define click listeners # -------------------------------------------------------------------------------------------------- def open_uber(_): # Close dropdown menu first self.__remove_window() self.__add_window(uber_window) def open_preferences(_): # Close dropdown menu first self.__remove_window() self.__add_window(preferences_window) def open_dropdown_menu(btn: DropdownButton): # Button is clicked while its dropdown menu was active -> Make button unclicked instead of opening the menu if self.__is_window_going_to_be_removed(btn.menu): btn.clicked = False else: btn.menu = Window(btn.background_matrix, btn.menu_buttons, btn.parent_coords + btn.relative_coordinates + np.array([0, btn.height]), False, True) self.__add_window(btn.menu) """ def hide_button(btn: Button): self.change_visibility(btn, not btn.visible) """ def close_window(_): self.__remove_window() def close_application(_): self.__done = True # -------------------------------------------------------------------------------------------------- # Initialize components # -------------------------------------------------------------------------------------------------- # Init dropdown buttons in main window # -------------------------------------------------------------------------------------------------- next_pos = 0 main_window_children = [] app_close_button = Button(close_button_large_array, np.array([380, 0]), reward=2, on_click_listener=close_application) self.__all_buttons.append(app_close_button) main_window_children.append(app_close_button) dropdown_button_datei_children = [] for i in range(0, 10): button = MenuButton(menu_button_other_unclicked_array, menu_button_other_clicked_array, reward=2) dropdown_button_datei_children.append(button) self.__all_buttons.append(button) preferences_button = MenuButton(menu_button_preferences_unclicked_array, reward=2, on_click_listener=open_preferences) dropdown_button_datei_children.append(preferences_button) self.__all_buttons.append(preferences_button) dropdown_button_datei = DropdownButton(dropdown_datei_unclicked_array, np.array([next_pos, 12]), dropdown_button_datei_children, dropdown_datei_clicked_array, reward=2, on_click_listener=open_dropdown_menu) self.__all_buttons.append(dropdown_button_datei) next_pos += dropdown_button_datei.width main_window_children.append(dropdown_button_datei) dropdown_button_anzeigen_children = [] for i in range(0, 3): button = MenuButton(menu_button_other_unclicked_array, menu_button_other_clicked_array, reward=2) dropdown_button_anzeigen_children.append(button) self.__all_buttons.append(button) dropdown_button_anzeigen = DropdownButton(dropdown_anzeigen_unclicked_array, np.array([next_pos, 12]), dropdown_button_anzeigen_children, dropdown_anzeigen_clicked_array, reward=2, on_click_listener=open_dropdown_menu) self.__all_buttons.append(dropdown_button_anzeigen) next_pos += dropdown_button_anzeigen.width main_window_children.append(dropdown_button_anzeigen) dropdown_button_navigation_children = [] for i in range(0, 4): button = MenuButton(menu_button_other_unclicked_array, menu_button_other_clicked_array, reward=2) dropdown_button_navigation_children.append(button) self.__all_buttons.append(button) dropdown_button_navigation = DropdownButton(dropdown_navigation_unclicked_array, np.array([next_pos, 12]), dropdown_button_navigation_children, dropdown_navigation_clicked_array, reward=2, on_click_listener=open_dropdown_menu) self.__all_buttons.append(dropdown_button_navigation) next_pos += dropdown_button_navigation.width main_window_children.append(dropdown_button_navigation) dropdown_button_tools_children = [] for i in range(0, 2): button = MenuButton(menu_button_other_unclicked_array, menu_button_other_clicked_array, reward=2) dropdown_button_tools_children.append(button) self.__all_buttons.append(button) dropdown_button_tools = DropdownButton(dropdown_tools_unclicked_array, np.array([next_pos, 12]), dropdown_button_tools_children, dropdown_tools_clicked_array, reward=2, on_click_listener=open_dropdown_menu) self.__all_buttons.append(dropdown_button_tools) next_pos += dropdown_button_tools.width main_window_children.append(dropdown_button_tools) menu_button_uber = MenuButton(menu_button_uber_unclicked_array, reward=2, on_click_listener=open_uber) self.__all_buttons.append(menu_button_uber) dropdown_button_hilfe = DropdownButton(dropdown_hilfe_unclicked_array, np.array([next_pos, 12]), [menu_button_uber], dropdown_hilfe_clicked_array, reward=2, on_click_listener=open_dropdown_menu) self.__all_buttons.append(dropdown_button_hilfe) main_window_children.append(dropdown_button_hilfe) # -------------------------------------------------------------------------------------------------- # Init small buttons in main window # -------------------------------------------------------------------------------------------------- k = 0 for i in range(1, 86, 7): small_button = Button(small_button_arrays[k], np.array([i, 22]), small_button_arrays[k + 1], reward=2, resettable=False) self.__all_buttons.append(small_button) main_window_children.append(small_button) k += 2 # -------------------------------------------------------------------------------------------------- # Init preferences window # -------------------------------------------------------------------------------------------------- preferences_window_children = [] preferences_window_checkbox_coords = [[136, 25], [169, 102], [169, 113], [169, 125], [155, 145], [148, 206], [148, 218], [148, 230], [312, 64], [312, 82], [312, 100], [312, 118], [312, 136], [312, 154], [312, 172], [312, 190], [312, 208], [312, 226]] for coord in preferences_window_checkbox_coords: preferences_window_checkbox = Checkbox(np.array(coord), reward=2) preferences_window_children.append(preferences_window_checkbox) self.__all_buttons.append(preferences_window_checkbox) preferences_window_bearbeiten_button = Button(preferences_window_bearbeiten_unclicked_array, np.array([310, 45]), preferences_window_bearbeiten_clicked_array, reward=2) self.__all_buttons.append(preferences_window_bearbeiten_button) preferences_window_children.append(preferences_window_bearbeiten_button) preferences_window_aendern_button = Button(preferences_window_aendern_unclicked_array, np.array([146, 164]), preferences_window_aendern_clicked_array, reward=2) self.__all_buttons.append(preferences_window_aendern_button) preferences_window_children.append(preferences_window_aendern_button) preferences_window_abbrechen_button = Button(preferences_window_abbrechen_button_array, np.array([315, 248]), reward=2, on_click_listener=close_window) self.__all_buttons.append(preferences_window_abbrechen_button) preferences_window_children.append(preferences_window_abbrechen_button) preferences_window_speichern_button = Button(preferences_window_speichern_button_array, np.array([282, 248]), reward=2, on_click_listener=close_window) self.__all_buttons.append(preferences_window_speichern_button) preferences_window_children.append(preferences_window_speichern_button) preferences_window_zuruecksetzen_button = Button(preferences_window_zuruecksetzen_unclicked_array, np.array([4, 248]), preferences_window_zuruecksetzen_clicked_array, reward=2) self.__all_buttons.append(preferences_window_zuruecksetzen_button) preferences_window_children.append(preferences_window_zuruecksetzen_button) preferences_window_clipboard_button = Button(preferences_window_clipboard_unclicked_array, np.array([38, 248]), preferences_window_clipboard_clicked_array, reward=2) self.__all_buttons.append(preferences_window_clipboard_button) preferences_window_children.append(preferences_window_clipboard_button) close_preferences_button = Button(preferences_window_close_array, np.array([335, 1]), reward=2, on_click_listener=close_window) self.__all_buttons.append(close_preferences_button) preferences_window_children.append(close_preferences_button) preferences_window = Window(preferences_window_array, preferences_window_children, np.array([2, 2])) # -------------------------------------------------------------------------------------------------- # Init über window # -------------------------------------------------------------------------------------------------- close_uber_button_1 = Button(close_button_array, np.array([80, 1]), reward=2, on_click_listener=close_window) self.__all_buttons.append(close_uber_button_1) close_uber_button_2 = Button(close_uber_window_button_array, np.array([1, 87]), reward=2, on_click_listener=close_window) self.__all_buttons.append(close_uber_button_2) uber_window = Window(uber_window_array, [close_uber_button_1, close_uber_button_2], np.array([273, 123])) # -------------------------------------------------------------------------------------------------- # -------------------------------------------------------------------------------------------------- # Return main window return Window(main_window_array, main_window_children, np.array([0, 0]))
def __add_window(self, window: Window): self.__windows.append(window) MatrixUtils.blit_image_inplace(self.__frame_buffer, window.current_matrix, window.relative_coordinates[0], window.relative_coordinates[1])
def draw_self(self, parent_matrix: ndarray): if self.visible: return MatrixUtils.blit_image_inplace(parent_matrix, self._select_matrix(), self.relative_coordinates[0], self.relative_coordinates[1])
def test_get_numpy_array_of_image_shape(self): image = MatrixUtils.get_numpy_array_of_image('window_über.png') self.assertEqual(image.shape, (95, 95, 3))
def test_get_numpy_array_of_image_type(self): image = MatrixUtils.get_numpy_array_of_image('window_über.png') self.assertIsInstance(image, np.ndarray)
def test_get_blank_image_as_numpy_array_image_shape(self): image = MatrixUtils.get_blank_image_as_numpy_array((25, 85, 172), width=30, height=80) self.assertEqual(image.shape, (30, 80, 3))
def test_includes_point_click_outside(self): click = np.array([-2, 8]) self.assertFalse(MatrixUtils.includes_point(click, self.rectangle_origin, self.rectangle_width, self.rectangle_height))
def test_includes_point_click_border(self): click = np.array([3, 6]) self.assertTrue(MatrixUtils.includes_point(click, self.rectangle_origin, self.rectangle_width, self.rectangle_height))