def align_region_canvas_rect(self, region): if region.rect: horizontal_margin = self.theme.get_int_value( "screen_overlay_region_horizontal_margin", 10) vertical_margin = self.theme.get_int_value( "screen_overlay_region_vertical_margin", 2) y = region.rect.y if self.expand_direction == "up": y += region.rect.height - self.height - vertical_margin else: y += vertical_margin x = region.rect.x if self.alignment == "right": x = region.rect.x + region.rect.width - self.limit_width - horizontal_margin elif self.alignment == "center": x = region.rect.x + (region.rect.width - self.limit_width) / 2 else: x += horizontal_margin if region.vertical_centered: y = region.rect.y + (region.rect.height - self.height) / 2 return ui.Rect(x, y, self.limit_width, self.limit_height) else: return ui.Rect(x, y, 0, 0)
def draw_header_buttons(self, canvas, paint, dimensions): header_height = dimensions["header_height"] dimensions = dimensions["rect"] # Header button tray x = dimensions.x for index, icon in enumerate(self.icons): # Minimize / maximize icon icon_position = Point2d(x + dimensions.width - (self.icon_radius * 1.5 + ( index * self.icon_radius * 2.2 )), dimensions.y + self.icon_radius + self.padding[0] / 2) self.icons[index].pos = icon_position paint.style = paint.Style.FILL if icon.id == "minimize": hover_colour = self.theme.get_colour("button_hover_background", "999999") if self.icon_hovered == index \ else self.theme.get_colour("button_background", "CCCCCC") paint.shader = linear_gradient(self.x, self.y, self.x, self.y + header_height, (hover_colour, hover_colour)) canvas.draw_circle(icon_position.x, icon_position.y, self.icon_radius, paint) text_colour = self.theme.get_colour("icon_colour", "000000") paint.shader = linear_gradient(self.x, self.y, self.x, self.y + header_height, (text_colour, text_colour)) if not self.minimized: canvas.draw_rect(ui.Rect(icon_position.x - self.icon_radius / 2, icon_position.y - 1, self.icon_radius, 2)) else: paint.style = paint.Style.STROKE canvas.draw_rect(ui.Rect( 1 + icon_position.x - self.icon_radius / 2, icon_position.y - self.icon_radius / 2, self.icon_radius - 2, self.icon_radius - 2)) elif icon.id == "close": close_colour = self.theme.get_colour("close_icon_hover_colour") if self.icon_hovered == index else self.theme.get_colour("close_icon_accent_colour") paint.shader = linear_gradient(self.x, self.y, self.x, self.y + header_height, (self.theme.get_colour("close_icon_colour"), close_colour)) canvas.draw_circle(icon_position.x, icon_position.y, self.icon_radius, paint)
def start_setup(self, setup_type, mouse_position=None): if not self.canvas: return self.mark_layout_invalid = True # Make sure the canvas is still the right size after canceling resizing if setup_type == "cancel": self.drag_position = [] if (self.setup_type != ""): self.load({}, False) self.setup_type = "" if self.canvas: self.canvas.rect = ui.Rect(self.limit_x, self.limit_y, self.limit_width, self.limit_height) self.canvas.resume() elif setup_type == "reload": self.drag_position = [] self.setup_type = "" if self.canvas: # Only do a rect change if it has actually changed to prevent costly operations if self.canvas.rect.x != self.limit_x or self.canvas.rect.y != self.limit_y or \ self.canvas.rect.width != self.limit_width or self.canvas.rect.height != self.limit_height: self.canvas.rect = ui.Rect(self.limit_x, self.limit_y, self.limit_width, self.limit_height) self.canvas.resume() else: super().start_setup(setup_type, mouse_position)
def on_ready(): actions.user.hud_add_poller("mode", PartialModePoller("mode", mode_poller), True) # This poller needs to be kept alive so that the sleep state is properly sent to all widgets actions.user.hud_add_poller("mode_toggle", PartialModePoller("mode_toggle", mode_poller)) add_mode_option = HudButton("command_icon", "Add mode indicator", ui.Rect(0,0,0,0), lambda widget: add_mode_toggle()) remove_mode_option = HudButton("command_icon", "Remove mode indicator", ui.Rect(0,0,0,0), lambda widget: remove_mode_toggle()) mode_option = HudStatusOption("mode_toggle", add_mode_option, remove_mode_option) actions.user.hud_publish_status_option("mode_option", mode_option)
def draw_animation(self, canvas, animation_tick): if self.enabled: paint = canvas.paint if self.mark_layout_invalid and animation_tick == self.animation_max_duration - 1: self.layout = self.layout_content(canvas, paint) if self.page_index > len(self.layout) - 1: self.page_index = len(self.layout) -1 dimensions = self.layout[self.page_index]["rect"] # Determine colour of the animation animation_progress = ( animation_tick - self.animation_max_duration ) / self.animation_max_duration red = self.intro_animation_start_colour[0] - int( self.blink_difference[0] * animation_progress ) green = self.intro_animation_start_colour[1] - int( self.blink_difference[1] * animation_progress ) blue = self.intro_animation_start_colour[2] - int( self.blink_difference[2] * animation_progress ) red_hex = "0" + format(red, "x") if red <= 15 else format(red, "x") green_hex = "0" + format(green, "x") if green <= 15 else format(green, "x") blue_hex = "0" + format(blue, "x") if blue <= 15 else format(blue, "x") paint.color = red_hex + green_hex + blue_hex if self.minimized: self.draw_background(canvas, paint, dimensions) else: header_height = self.layout[self.page_index]["header_height"] growth = (self.animation_max_duration - animation_tick ) / self.animation_max_duration easeInOutQuint = 16 * growth ** 5 if growth < 0.5 else 1 - pow(-2 * growth + 2, 5) / 2 rect = ui.Rect(dimensions.x, dimensions.y, dimensions.width, max(header_height, dimensions.height * easeInOutQuint)) self.draw_background(canvas, paint, rect) if animation_tick == 1: return self.draw(canvas) return True else: return False
def get_url_rect(canvas): rect = canvas.paint.measure_text(instructions_text)[1] width = rect.width + 2 * line_height height = line_height + padding cr = canvas.rect return ui.Rect(cr.x + cr.width - width, cr.y + cr.height - height, width, height)
def draw(self, canvas) -> bool: if not self.mark_position_invalid: return super().draw(canvas) else: # Reposition the canvas to fit the contents in the screen screen = determine_screen_for_pos(Point2d(self.x, self.y)) layout = self.layout_content(canvas, canvas.paint) dimensions = layout[self.page_index]["rect"] if dimensions is not None and screen is not None: should_go_left = dimensions.x + dimensions.width >= screen.x + screen.width should_go_up = dimensions.y + dimensions.height >= screen.y + screen.height can_go_middle_hor = dimensions.x + dimensions.width / 2 < screen.x + screen.width can_go_middle_ver = dimensions.y + dimensions.height / 2 < screen.y + screen.height if can_go_middle_hor: self.limit_x = int(dimensions.x - dimensions.width / 2) elif should_go_left: self.limit_x = int(dimensions.x - dimensions.width) self.x = self.limit_x if can_go_middle_ver: self.limit_y = int(dimensions.y - dimensions.height / 2 if not can_go_middle_hor else self.limit_y) if should_go_up: self.limit_y = int(dimensions.y - dimensions.height) self.y = self.limit_y if self.canvas: self.canvas.move(self.x, self.y) self.mouse_capture_canvas.rect = ui.Rect( self.x, self.y, dimensions.width, dimensions.height) self.mark_position_invalid = False return True
def move_screen(off): win = ui.active_window() src_screen = win.screen screens = sorted_screens() dst_screen = screens[(screens.index(src_screen) + off) % len(screens)] if src_screen == dst_screen: return src = src_screen.visible_rect dst = dst_screen.visible_rect old = win.rect change_screen_mode = config.get("window_management.change_screen_mode", "same") if change_screen_mode == "same": new_rectangle = ui.Rect( dst.left + (old.left - src.left) / src.width * dst.width, dst.top + (old.top - src.top) / src.height * dst.height, old.width / src.width * dst.width, old.height / src.height * dst.height, ) elif change_screen_mode == "full": new_rectangle = dst else: raise ValueError("{} screen mode not understood." (change_screen_mode)) win.rect = new_rectangle time.sleep(0.25) win.rect = new_rectangle time.sleep(0.25) win.rect = new_rectangle
def layout_content(self, canvas, paint): # Determine the dimensions and positions of the content return [{ "rect": ui.Rect(self.limit_x, self.limit_y, self.limit_width, self.limit_height) }]
def draw_content_text(self, canvas, paint, layout): """Draws the text, choices and confirm button""" super().draw_content_text(canvas, paint, layout) if self.minimized: return self.draw_choices(canvas, paint, layout) # Draw multiple choice confirm button if self.panel_content.choices and self.panel_content.choices.multiple: base_button_x = layout["rect"].x self.confirm_button.rect = ui.Rect( layout["confirm"]["rect"].x, layout["confirm"]["rect"].y, layout["confirm"]["rect"].width, layout["confirm"]["rect"].height) paint.color = self.theme.get_colour( "button_hover_background", "AAAAAA") if self.confirm_hovered else self.theme.get_colour( "button_background", "CCCCCC") button_rect = ui.Rect(base_button_x, self.confirm_button.rect.y, layout["rect"].width, self.confirm_button.rect.height) canvas.draw_rrect(skia.RoundRect.from_rect(button_rect, x=10, y=10)) confirm_icon = self.confirm_button.image if confirm_icon: image = self.theme.get_image(confirm_icon) canvas.draw_image( image, base_button_x + self.padding[3], self.confirm_button.rect.y + self.confirm_button.rect.height / 2 - image.height / 2) paint.color = self.theme.get_colour( "button_hover_text_colour", "000000") if self.confirm_hovered else self.theme.get_colour( "button_text_colour", "000000") line_height = (self.confirm_button.rect.height - self.padding[0] - self.padding[2]) / layout["confirm"]["line_count"] self.draw_rich_text( canvas, paint, layout["confirm"]["rich_text"], base_button_x + self.padding[3] * 2 if not confirm_icon else base_button_x + self.padding[3] * 2 + self.image_size, self.confirm_button.rect.y + self.padding[0], line_height)
def draw_choices(self, canvas, paint, layout): """Draws the choice buttons""" paint.textsize = self.font_size content_dimensions = layout["rect"] self.visible_indecis = [] base_button_x = content_dimensions.x + self.padding[3] / 2 icon_button_x = base_button_x + self.image_size + self.padding[3] / 2 for index, choice_layout in enumerate(layout["choice_layouts"]): paint.color = self.theme.get_colour("button_hover_background", "AAAAAA") if self.choice_hovered == choice_layout["choice_index"] \ else self.theme.get_colour("button_background", "CCCCCC") self.visible_indecis.append(choice_layout["choice_index"]) button_height = self.padding[0] / 2 + choice_layout[ "text_height"] + self.padding[2] / 2 rect = ui.Rect( base_button_x, choice_layout["choice_y"], content_dimensions.width - (self.padding[3] + self.padding[1]) / 2, button_height) self.choices[choice_layout["choice_index"]].rect = rect canvas.draw_rrect(skia.RoundRect.from_rect(rect, x=10, y=10)) # Selected style applied if choice_layout["choice"].selected: selected_colour = self.theme.get_colour( "success_colour", "00CC00") if len(selected_colour) == 6: selected_colour = selected_colour + "33" paint.color = selected_colour canvas.draw_rrect(skia.RoundRect.from_rect(rect, x=10, y=10)) paint.color = "000000" image = self.theme.get_image("check_icon") canvas.draw_image( image, content_dimensions.x + content_dimensions.width - self.padding[1] - image.width, choice_layout["choice_y"] + button_height / 2 - image.height / 2) # Draw choice icon on the left in the middle choice_icon = choice_layout["choice"].image if choice_icon: image = self.theme.get_image(choice_icon) canvas.draw_image( image, content_dimensions.x + self.padding[3], choice_layout["choice_y"] + button_height / 2 - image.height / 2) paint.color = self.theme.get_colour("button_hover_text_colour", "000000") if self.choice_hovered == choice_layout["choice_index"] \ else self.theme.get_colour("button_text_colour", "000000") self.draw_rich_text( canvas, paint, choice_layout["rich_text"], base_button_x + self.padding[3] if not choice_icon else base_button_x + self.padding[3] + self.image_size, choice_layout["choice_y"] - self.padding[0] / 2, self.line_padding)
def update_buttons(self): buttons = [] buttons.append( HudButton("", "Keep alive", ui.Rect(0, 0, 0, 0), lambda widget: widget.set_log_ttl(-1))) if self.ttl_duration_seconds == self.infinite_ttl: buttons[0].text = "Timed live" buttons[0].callback = lambda widget: widget.set_log_ttl( self.theme.get_float_value("event_log_ttl_duration_seconds", 9) ) buttons.append( HudButton("", "Unlock entries" if self.locked else "Lock entries", ui.Rect(0, 0, 0, 0), lambda widget: widget.set_lock(not widget.locked))) buttons.append( HudButton("", "Clear logs", ui.Rect(0, 0, 0, 0), lambda widget: widget.clear_logs())) self.buttons = buttons
def _set_window_pos(window, x, y, width, height): """Helper to set the window position.""" # TODO: Special case for full screen move - use os-native maximize, rather # than setting the position? # 2020/10/01: While the upstream Talon implementation for MS Windows is # settling, this may be buggy on full screen windows. Aegis doesn't want a # hacky solution merged, so for now just repeat the command. # # TODO: Audit once upstream Talon is bug-free on MS Windows window.rect = ui.Rect(round(x), round(y), round(width), round(height))
def resize(self, width: int, height: int): if not self.need_resize: return self.need_resize = False screen = ui.main_screen() rect = ui.Rect( screen.x + (screen.width - width) / 2, screen.y + (screen.height - height) / 2, width, height, ) self.canvas.rect = rect
def layout_content(self, canvas, paint): paint.textsize = self.font_size horizontal_alignment = "right" if self.limit_x < self.x else "left" vertical_alignment = "bottom" if self.limit_y < self.y else "top" total_width = 0 button_layout = [] total_text_width = 0 total_button_height = self.padding[0] + self.padding[2] for index, button in enumerate(self.buttons): icon_offset = 0 if button.image: icon_offset = self.image_size + self.padding[3] * 3 button_rich_text = layout_rich_text(paint, button.text, \ self.limit_width - icon_offset - self.padding[3] * 2 - self.padding[1] * 2, self.limit_height) line_count = 0 button_text_height = self.font_size for index, text in enumerate(button_rich_text): line_count = line_count + 1 if text.x == 0 else line_count current_line_length = current_line_length + text.width if text.x != 0 else text.width + icon_offset total_text_width = max(total_text_width, current_line_length) button_text_height = button_text_height + self.font_size + self.line_padding if text.x == 0 and index != 0 else button_text_height if button.image != None: total_button_height += max( self.image_size + self.padding[0] + self.padding[2], button_text_height + self.padding[0] + self.padding[2]) else: total_button_height += button_text_height + self.padding[ 0] + self.padding[2] button_layout.append({ "button": button, "rich_text": button_rich_text, "line_count": line_count, "text_height": button_text_height }) # Add the padding between the buttons total_button_height += (len(button_layout) - 1) * self.padding[0] content_width = min( self.limit_width, max(self.width, total_text_width + self.padding[1] * 2 + self.padding[3] * 2)) content_height = min(self.limit_height, max(self.height, total_button_height)) return [{ "rect": ui.Rect(self.x, self.y, content_width, content_height), "button_layouts": button_layout }]
def draw_footer(self, canvas, paint, dimensions): footer_height = dimensions["header_height"] dimensions = dimensions["rect"] # Small divider between the content and the header x = dimensions.x + self.padding[3] start_y = dimensions.y + dimensions.height - self.padding[0] - self.padding[2] / 2 paint.color = self.theme.get_colour("text_colour") canvas.draw_text(str(self.page_index + 1 ) + " of " + str(len(self.layout)), x, start_y) paint.color = self.theme.get_colour("text_box_line", "000000") canvas.draw_rect(ui.Rect(x - self.padding[3], start_y - footer_height, dimensions.width, 1))
def resize_mouse_canvas(self, content_dimensions): rect = content_dimensions["rect"] if self.confirm_button.rect.height > 0: rect = ui.Rect( rect.x, rect.y, rect.width, rect.height + self.confirm_button.rect.height + self.padding[0] + self.padding[2]) self.capture_rect = rect self.mouse_capture_canvas.rect = rect self.mouse_capture_canvas.freeze() self.mark_layout_invalid = False
def hud_create_choices(choices_list: list[Any], callback: Callable[[Any], None], multiple: Union[bool, int] = False) -> HudChoices: """Creates a list of choices with a single list of dictionaries""" choices = [] for index, choice_data in enumerate(choices_list): image = choice_data["image"] if "image" in choice_data else "" choices.append( HudChoice( image, choice_data["text"], choice_data, "selected" in choice_data and choice_data["selected"], ui.Rect(0, 0, 0, 0))) return HudChoices(choices, callback, multiple)
def load_widgets(self): """Load the user defined widgets""" # TODO - Make the widgets properly user-definable # By making them addable and removable # With subscribed content, topics etc for specific widgets # For now, we will just use the default widgets taken from the display widgets array self.widgets = self.get_default_widgets() self.previous_screen_rects = [] for screen in ui.screens(): self.previous_screen_rects.append( ui.Rect(screen.x, screen.y, screen.width, screen.height))
def draw_header(self, canvas, paint, dimensions): header_height = dimensions["header_height"] dimensions = dimensions["rect"] paint.color = self.theme.get_colour("text_colour") paint.font.embolden = True x = dimensions.x + self.padding[3] canvas.draw_text(self.panel_content.title if self.panel_content.title else self.id, x, dimensions.y + self.font_size) # Small divider between the content and the header if not self.minimized: paint.color = self.theme.get_colour("text_box_line", "000000") canvas.draw_rect(ui.Rect(x - self.padding[3], dimensions.y + header_height + self.padding[0] * 2, dimensions.width, 1))
def update_buttons(self): buttons = [] buttons.append( HudButton("", "Content toolkit", ui.Rect(0, 0, 0, 0), lambda widget: actions.user.hud_toolkit_options())) status_options = self.content.get_topic("status_options") for status_option in status_options: if status_option.icon_topic in self.current_topics: if status_option.activated_option: buttons.append(status_option.activated_option) else: if status_option.default_option: buttons.append(status_option.default_option) self.buttons = buttons
def __init__(self, preferences: HeadUpDisplayUserPreferences, theme: HeadUpDisplayTheme, event_dispatch: HeadUpEventDispatch): self.default_screen_rect = ui.Rect(0, 0, 1920, 1080) self.default_screen_mm_size = [527.0, 296.0] self.previous_talon_hud_environment = "" self.previous_screen_rects = [] self.preferences = preferences self.theme = theme self.event_dispatch = event_dispatch self.initial_load_preferences() self.load_widgets() # Reload the preferences according to the monitor sizes if the given file does not exist if not os.path.exists( self.preferences.get_screen_preferences_filepath( ui.screens())): self.previous_screen_rects = [ ui.Rect(self.default_screen_rect.x, self.default_screen_rect.y, self.default_screen_rect.width, self.default_screen_rect.height) ] self.reload_preferences(True, self.previous_talon_hud_environment)
def hud_create_screen_region(topic: str, colour: str = None, icon: str = None, title: str = None, hover_visibility: Union[bool, int] = False, x: int = 0, y: int = 0, width: int = 0, height: int = 0, relative_x: int = 0, relative_y: int = 0): """Create a HUD screen region, where by default it is active all over the available space and it is visible only on a hover""" rect = ui.Rect(x, y, width, height) if width * height > 0 else None point = Point2d(x + relative_x, y + relative_y) return HudScreenRegion(topic, title, icon, colour, rect, point, hover_visibility)
def draw_key(self, canvas, text): canvas.paint.typeface = command_font rect = canvas.paint.measure_text(text)[1] canvas.paint.color = command_background_color radius = 4 rrect = ui.Rect(self.x, self.y, rect.width + 2 * padding, text_size + 2 * padding) rrect = skia.RoundRect.from_rect(rrect, x=radius, y=radius) canvas.draw_rrect(rrect) canvas.paint.color = command_text_color draw_text(canvas, text, self.x + padding, self.y) self.y += line_height self.w = max(self.w, rect.width)
def draw_content_buttons(self, canvas, paint, dimensions): """Draws the content buttons""" paint.textsize = self.font_size content_dimensions = dimensions["rect"] base_button_x = content_dimensions.x + self.padding[3] icon_button_x = base_button_x + self.image_size + self.padding[3] button_y = content_dimensions.y + self.padding[0] for index, button_layout in enumerate(dimensions["button_layouts"]): paint.color = self.theme.get_colour("button_hover_background", "AAAAAA") if self.button_hovered == index \ else self.theme.get_colour("button_background", "CCCCCC") button_height = self.padding[0] + button_layout[ "text_height"] + self.padding[2] button_icon = button_layout["button"].image if button_icon: button_height = max( self.image_size + self.padding[0] + self.padding[2], button_height) rect = ui.Rect( base_button_x, button_y, content_dimensions.width - self.padding[3] - self.padding[1], button_height) self.buttons[index].rect = rect canvas.draw_rrect(skia.RoundRect.from_rect(rect, x=10, y=10)) button_text_y = button_y + self.padding[0] / 2 # Draw button icon on the left in the middle if button_icon: image = self.theme.get_image(button_icon) canvas.draw_image( image, base_button_x + self.padding[3], button_y + button_height / 2 - image.height / 2) if button_layout["text_height"] < self.image_size: button_text_y += (self.image_size - button_layout["text_height"]) / 2 paint.color = self.theme.get_colour("button_hover_text_colour", "000000") if self.button_hovered == index \ else self.theme.get_colour("button_text_colour", "000000") self.draw_rich_text( canvas, paint, button_layout["rich_text"], base_button_x + self.padding[3] if not button_icon else icon_button_x + self.padding[3] / 2, button_text_y, self.line_padding) button_y += button_height + self.padding[0]
def move_screen(off): win = ui.active_window() src_screen = win.screen screens = ui.screens() dst_screen = screens[(screens.index(src_screen) + off) % len(screens)] if src_screen == dst_screen: return src = src_screen.visible_rect dst = dst_screen.visible_rect old = win.rect win.rect = ui.Rect( dst.left + (old.left - src.left) / src.width * dst.width, dst.top + (old.top - src.top) / src.height * dst.height, old.width / src.width * dst.width, old.height / src.height * dst.height, )
def draw_animation(self, canvas, animation_tick): if self.enabled and self.should_enable(): paint = canvas.paint if self.mark_layout_invalid and animation_tick == self.animation_max_duration - 1: self.layout = self.layout_content(canvas, paint) if self.page_index > len(self.layout) - 1: self.page_index = len(self.layout) -1 dimensions = self.layout[self.page_index]["rect"] # Determine colour of the animation animation_progress = ( animation_tick - self.animation_max_duration ) / self.animation_max_duration red = self.intro_animation_start_colour[0] - int( self.blink_difference[0] * animation_progress ) green = self.intro_animation_start_colour[1] - int( self.blink_difference[1] * animation_progress ) blue = self.intro_animation_start_colour[2] - int( self.blink_difference[2] * animation_progress ) red_hex = "0" + format(red, "x") if red <= 15 else format(red, "x") green_hex = "0" + format(green, "x") if green <= 15 else format(green, "x") blue_hex = "0" + format(blue, "x") if blue <= 15 else format(blue, "x") paint.color = red_hex + green_hex + blue_hex horizontal_alignment = "right" if self.limit_x < self.x else "left" if self.alignment == "center" or \ ( self.x + self.width < self.limit_x + self.limit_width and self.limit_x < self.x ): horizontal_alignment = "center" growth = (self.animation_max_duration - animation_tick ) / self.animation_max_duration easeInOutQuint = 16 * growth ** 5 if growth < 0.5 else 1 - pow(-2 * growth + 2, 5) / 2 width = dimensions.width * easeInOutQuint if horizontal_alignment == "left": x = dimensions.x elif horizontal_alignment == "right": x = self.limit_x + self.limit_width - width elif horizontal_alignment == "center": x = self.limit_x + ( self.limit_width / 2 ) - ( width / 2 ) rect = ui.Rect(x, dimensions.y, width, dimensions.height - self.layout[self.page_index]["footer_height"]) if animation_tick == 1: return self.draw(canvas) else: self.draw_background(canvas, paint, rect) return True else: return False
def move_screen(direction: int): """Moves a window between screens""" win = ui.active_window() src_screen = win.screen screens = ui.screens() dst_screen = screens[(screens.index(src_screen) + direction) % len(screens)] if src_screen == dst_screen: return src = src_screen.rect dst = dst_screen.rect old = win.rect win.rect = ui.Rect( dst.left + (old.left - src.left) / src.width * dst.width, dst.top + (old.top - src.top) / src.height * dst.height, old.width / src.width * dst.width, old.height / src.height * dst.height, )
def draw(self, canvas): text = self.history[:] if not text: return paint = canvas.paint paint.filter_quality = paint.FilterQuality.LOW paint.textsize = 15 paint.antialias = True # canvas.draw_res is a long testct(ui.Rect(x - 50, y - 50, 100, 100)) x = canvas.x + 1595 y = canvas.y + 50 text_pad = 0 rect_pad = 6 # measure text width = 0 text_top = y text_bot = y line_spacing = 0 for line in text: _, trect = paint.measure_text(line) width = max(width, trect.width) line_spacing = max(line_spacing, trect.height) text_top = min(text_top, y - trect.height) line_spacing += text_pad text_bot = y + (len(text) - 1) * line_spacing height = text_bot - text_top rect = ui.Rect(x - rect_pad, text_top - 2, -width - rect_pad * 2, height + rect_pad + 2) paint.color = 'ffffffaa' paint.style = paint.Style.FILL canvas.draw_round_rect(rect, 3, 3) paint.color = '000000' paint.style = paint.Style.FILL for line in text: _, trect = paint.measure_text(line) canvas.draw_text(line, x - trect.width - rect_pad * 2, y) y += line_spacing
def draw(self, canvas): text = self.history[:] if not text or not self.enabled: return paint = canvas.paint paint.filter_quality = paint.FilterQuality.LOW paint.textsize = 15 paint.antialias = True # canvas.draw_rect(ui.Rect(x - 50, y - 50, 100, 100)) x = canvas.x + 20 y = canvas.y + 50 text_pad = 0 rect_pad = 10 # measure text width = 0 text_top = y text_bot = y line_spacing = 0 for line in text: _, trect = paint.measure_text(line) width = max(width, trect.width) line_spacing = max(line_spacing, trect.height) text_top = min(text_top, y - trect.height) x = canvas.x + ui.main_screen().width - 2 * rect_pad - width line_spacing += text_pad text_bot = y + (len(text) - 1) * line_spacing height = text_bot - text_top rect = ui.Rect(x - rect_pad, text_top - 2, width + rect_pad * 2, height + rect_pad + 2) paint.color = 'ffffffbb' paint.style = paint.Style.FILL canvas.draw_round_rect(rect, 10, 10) paint.color = '000000' paint.style = paint.Style.FILL for line in text: canvas.draw_text(line, x, y) y += line_spacing