%PDF- %PDF-
Direktori : /lib/python3/dist-packages/orca/ |
Current File : //lib/python3/dist-packages/orca/highlighter.py |
# Orca # # Copyright 2023 Igalia, S.L. # Author: Joanmarie Diggs <jdiggs@igalia.com> # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the # Free Software Foundation, Inc., Franklin Street, Fifth Floor, # Boston MA 02110-1301 USA. """Module for drawing highlights over an area of interest.""" __id__ = "$Id$" __version__ = "$Revision$" __date__ = "$Date$" __copyright__ = "Copyright (c) 2023 Igalia, S.L." __license__ = "LGPL" from . import debug try: import cairo import gi gi.require_version('Gtk', '3.0') from gi.repository import Gtk CAIRO_AVAILABLE = True except Exception as error: tokens = ["HIGHLIGHTER: GtkHighlighter unavailable:", error] debug.printTokens(debug.LEVEL_INFO, tokens, True) CAIRO_AVAILABLE = False class Highlighter: """Base class of all highlighters supported by Orca.""" HIGHLIGHT = "highlight" RECTANGLE = "rectangle" UNDERLINE = "underline" RED = (1, 0, 0) BLUE = (0, 0, 1) GREEN = (0, 1, 0) YELLOW = (1, 1, 0) PURPLE = (0.5, 0, 0.5) ORANGE = (1, 0.5, 0) PINK = (1, 0.75, 0.8) CYAN = (0, 1, 1) MAGENTA = (1, 0, 1) LIME = (0.5, 1, 0) NAVY = (0, 0, 0.5) TEAL = (0, 0.5, 0.5) BLACK = (0, 0, 0) WHITE = (1, 1, 1) def __init__(self, highlight_type, color, alpha, thickness, padding, fill_color, fill_alpha): self._highlight_type = highlight_type self._color = color self._alpha = alpha self._thickness = thickness self._padding = padding self._fill_color = fill_color self._fill_alpha = fill_alpha self._gui = self._create_gui() def _create_gui(self): """Creates the gui for the overlay.""" return None def _draw_highlight(self, painter): """Called by highlight to draw a highlight over the item.""" pass def _draw_rectangle(self, painter): """Called by highlight to draw a rectangle around the item.""" pass def _draw_underline(self, painter): """Called by highlight to draw an underline under the item.""" pass def highlight(self, x, y, width, height): """Draws the desired indicator over the specified box.""" pass def quit(self): """Quits the highlighter.""" pass class GtkHighlighter(Highlighter): """Highlighter that uses a GtkWindow to highlight items.""" def __init__(self, highlight_type=Highlighter.UNDERLINE, color=Highlighter.GREEN, alpha=1.0, thickness=5, padding=5, fill_color=None, fill_alpha=None): if not CAIRO_AVAILABLE: msg = "GTK HIGHLIGHTER: Unavailable. Is Cairo installed?" debug.printMessage(debug.LEVEL_INFO, msg, True) return super().__init__(highlight_type, color, alpha, thickness, padding, fill_color, fill_alpha) self._drawing_area = None def _create_gui(self): """Creates the gui for the overlay.""" gui = Gtk.Window() gui.set_decorated(False) gui.set_accept_focus(False) gui.set_app_paintable(True) gui.set_skip_taskbar_hint(True) gui.set_skip_pager_hint(True) screen = gui.get_screen() visual = screen.get_rgba_visual() if visual and screen.is_composited(): gui.set_visual(visual) self._drawing_area = Gtk.DrawingArea() self._drawing_area.connect("draw", self._on_draw) gui.add(self._drawing_area) return gui def _on_draw(self, widget, painter): """Signal handler for the 'draw' event.""" if self._highlight_type == self.HIGHLIGHT: self._draw_highlight(painter) elif self._highlight_type == self.RECTANGLE: self._draw_rectangle(painter) elif self._highlight_type == self.UNDERLINE: self._draw_underline(painter) def _draw_highlight(self, painter): """Called by highlight to draw a highlight over the item.""" if self._fill_color is None: self._fill_color = self.YELLOW if self._fill_alpha is None: self._fill_alpha = 0.3 fill = (*self._fill_color, self._fill_alpha) painter.set_source_rgba(*fill) painter.set_operator(cairo.OPERATOR_SOURCE) painter.paint() painter.set_operator(cairo.OPERATOR_OVER) def _draw_rectangle(self, painter): """Called by highlight to draw a rectangle around the item.""" x = self._padding y = self._padding width = self._gui.get_allocated_width() - 2 * self._padding height = self._gui.get_allocated_height() - 2 * self._padding if self._fill_color is not None and self._fill_alpha is not None: fill = (*self._fill_color, self._fill_alpha * 255) painter.set_source_rgba(*fill) painter.rectangle(x, y, width, height) painter.fill() line = (*self._color, self._alpha) painter.set_source_rgba(*line) painter.set_line_width(self._thickness) painter.rectangle(x, y, width, height) painter.stroke() def _draw_underline(self, painter): """Called by highlight to draw an underline under the item.""" line = (*self._color, self._alpha) painter.set_source_rgba(*line) painter.set_line_width(self._thickness) painter.move_to(0, self._gui.get_allocated_height() - 5) painter.line_to(self._gui.get_allocated_width(), self._gui.get_allocated_height() - 5) painter.stroke() def highlight(self, x, y, width, height): """Draws the desired indicator over the specified box.""" msg = f"GTK HIGHLIGHTER: x:{x}, y:{y}, width:{width}, height:{height}" debug.printMessage(debug.LEVEL_INFO, msg, True) try: self._gui.move(x - self._padding, y - self._padding) self._gui.resize(width + 2 * self._padding, height + 2 * self._padding) except Exception as exc: error_tokens = ["GTK HIGHLIGHTER: Exception:", exc] debug.printTokens(debug.LEVEL_INFO, error_tokens, True) else: self._gui.show_all() def quit(self): """Quits the highlighter.""" msg = "GTK HIGHLIGHTER: Quitting." debug.printMessage(debug.LEVEL_INFO, msg, True) self._gui.destroy() self._drawing_area = None self._gui = None