alfrix d3281379ee gtk: change scaling of images
This reduces the amount of magic numbers used, some images will scale to bigger sizes, most of the icons and images in vertical mode will be bigger, thumbnails should be bigger in both modes.
2022-10-26 22:36:52 -03:00

267 lines
9.9 KiB
Python

# -*- coding: utf-8 -*-
import gi
import logging
import os
import pathlib
gi.require_version("Gtk", "3.0")
from gi.repository import Gdk, GdkPixbuf, Gio, Gtk, Pango
class KlippyGtk:
labels = {}
def __init__(self, screen, width, height, theme, cursor, fontsize_type):
self.screen = screen
self.width = width
self.height = height
self.themedir = os.path.join(pathlib.Path(__file__).parent.resolve().parent, "styles", theme, "images")
self.font_ratio = [33, 49] if self.screen.vertical_mode else [43, 29]
self.font_size = int(min(
self.width / self.font_ratio[0],
self.height / self.font_ratio[1]
))
if fontsize_type == "small":
self.font_size = round(self.font_size * 0.91)
elif fontsize_type == "large":
self.font_size = round(self.font_size * 1.09)
self.titlebar_height = self.font_size * 2
self.img_scale = self.font_size * 2.5
self.img_width = self.font_size * 3
self.img_height = self.font_size * 3
if self.screen.vertical_mode:
self.action_bar_width = int(self.width)
self.action_bar_height = int(self.height * .1)
else:
self.action_bar_width = int(self.width * .1)
self.action_bar_height = int(self.height)
self.cursor = cursor
self.color_list = {} # This is set by screen.py init_style()
for key in self.color_list:
if "base" in self.color_list[key]:
rgb = [int(self.color_list[key]['base'][i:i + 2], 16) for i in range(0, 6, 2)]
self.color_list[key]['rgb'] = rgb
logging.debug(f"img width: {self.img_width} height: {self.img_height}")
def get_action_bar_width(self):
return self.action_bar_width
def get_action_bar_height(self):
return self.action_bar_height
def get_content_width(self):
return self.width - self.action_bar_width
def get_content_height(self):
if self.screen.vertical_mode:
return self.height - self.titlebar_height - self.action_bar_height
else:
return self.height - self.titlebar_height
def get_font_size(self):
return self.font_size
def get_titlebar_height(self):
return self.titlebar_height
def get_keyboard_height(self):
if (self.height / self.width) >= 3:
# Ultra-tall
return self.get_content_height() * 0.25
else:
return self.get_content_height() * 0.5
def get_temp_color(self, device):
# logging.debug("Color list %s" % self.color_list)
if device not in self.color_list:
return False, False
if 'base' in self.color_list[device]:
rgb = self.color_list[device]['rgb'].copy()
if self.color_list[device]['state'] > 0:
rgb[1] = rgb[1] + self.color_list[device]['hsplit'] * self.color_list[device]['state']
self.color_list[device]['state'] += 1
rgb = [x / 255 for x in rgb]
# logging.debug(f"Assigning color: {device} {rgb}")
else:
colors = self.color_list[device]['colors']
if self.color_list[device]['state'] >= len(colors):
self.color_list[device]['state'] = 0
color = colors[self.color_list[device]['state'] % len(colors)]
rgb = [int(color[i:i + 2], 16) / 255 for i in range(0, 6, 2)]
self.color_list[device]['state'] += 1
# logging.debug(f"Assigning color: {device} {rgb} {color}")
return rgb
def reset_temp_color(self):
for key in self.color_list:
self.color_list[key]['state'] = 0
@staticmethod
def Label(label, style=None):
la = Gtk.Label(label)
if style is not None:
la.get_style_context().add_class(style)
return la
def Image(self, image_name, width=None, height=None):
width = width if width is not None else self.img_width
height = height if height is not None else self.img_height
filename = os.path.join(self.themedir, f"{image_name}.svg")
if os.path.exists(filename):
pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size(filename, int(width), int(height))
return Gtk.Image.new_from_pixbuf(pixbuf)
else:
logging.error(f"Unable to find image {filename}")
return Gtk.Image()
@staticmethod
def PixbufFromFile(filename, width=-1, height=-1):
return GdkPixbuf.Pixbuf.new_from_file_at_size(filename, int(width), int(height))
def PixbufFromHttp(self, resource, width=-1, height=-1):
response = self.screen.apiclient.get_thumbnail_stream(resource)
if response is False:
return None
stream = Gio.MemoryInputStream.new_from_data(response, None)
pixbuf = GdkPixbuf.Pixbuf.new_from_stream_at_scale(stream, int(width), int(height), True)
stream.close_async(2)
return pixbuf
def Button(self, label=None, style=None):
b = Gtk.Button(label=label)
b.set_hexpand(True)
b.set_vexpand(True)
b.set_can_focus(False)
b.props.relief = Gtk.ReliefStyle.NONE
if style is not None:
b.get_style_context().add_class(style)
b.connect("clicked", self.screen.reset_screensaver_timeout)
return b
def ButtonImage(self, image_name=None, label=None, style=None, scale=1.38, position=Gtk.PositionType.TOP, lines=2):
b = Gtk.Button()
if label is not None:
b.set_label(label.replace("\n", " "))
b.set_hexpand(True)
b.set_vexpand(True)
b.set_can_focus(False)
if image_name is not None:
width = height = self.img_scale * scale
b.set_image(self.Image(image_name, width, height))
b.set_image_position(position)
b.set_always_show_image(True)
if label is not None:
try:
# Get the label object
if image_name is not None:
if position == Gtk.PositionType.RIGHT:
child = b.get_children()[0].get_children()[0].get_children()[0]
else:
child = b.get_children()[0].get_children()[0].get_children()[1]
else:
child = b.get_children()[0]
child.set_line_wrap_mode(Pango.WrapMode.WORD_CHAR)
child.set_line_wrap(True)
child.set_ellipsize(True)
child.set_ellipsize(Pango.EllipsizeMode.END)
child.set_lines(lines)
except Exception as e:
logging.debug(f"Unable to wrap and ellipsize label: {label} image: {image_name} exception:{e}")
if style is not None:
b.get_style_context().add_class(style)
b.connect("clicked", self.screen.reset_screensaver_timeout)
return b
def Dialog(self, screen, buttons, content, callback=None, *args):
dialog = Gtk.Dialog()
dialog.set_default_size(screen.width, screen.height)
dialog.set_resizable(False)
dialog.set_transient_for(screen)
dialog.set_modal(True)
for i, button in enumerate(buttons):
dialog.add_button(button_text=button['name'], response_id=button['response'])
button = dialog.get_children()[0].get_children()[0].get_children()[0].get_children()[i]
button.get_child().set_line_wrap_mode(Pango.WrapMode.WORD_CHAR)
button.get_child().set_line_wrap(True)
button.set_size_request((screen.width - 30) / 3, screen.height / 5)
dialog.connect("response", self.screen.reset_screensaver_timeout)
dialog.connect("response", self.remove_dialog, dialog)
dialog.connect("response", callback, *args)
dialog.get_style_context().add_class("dialog")
content_area = dialog.get_content_area()
content_area.set_margin_start(15)
content_area.set_margin_end(15)
content_area.set_margin_top(15)
content_area.set_margin_bottom(15)
content_area.add(content)
dialog.show_all()
# Change cursor to blank
if self.cursor:
dialog.get_window().set_cursor(Gdk.Cursor.new(Gdk.CursorType.ARROW))
else:
dialog.get_window().set_cursor(Gdk.Cursor.new(Gdk.CursorType.BLANK_CURSOR))
self.screen.dialogs.append(dialog)
return dialog
def remove_dialog(self, widget, response_id, dialog):
logging.info("Removing Dialog")
self.screen.dialogs.remove(dialog)
def ToggleButtonImage(self, image_name, label, style=None, width=None, height=None):
b = Gtk.ToggleButton(label=label)
b.set_hexpand(True)
b.set_vexpand(True)
b.set_can_focus(False)
b.set_image(self.Image(image_name, width, height))
b.set_image_position(Gtk.PositionType.TOP)
b.set_always_show_image(True)
if style is not None:
ctx = b.get_style_context()
ctx.add_class(style)
b.connect("clicked", self.screen.reset_screensaver_timeout)
return b
@staticmethod
def HomogeneousGrid(width=None, height=None):
g = Gtk.Grid()
g.set_row_homogeneous(True)
g.set_column_homogeneous(True)
if width is not None and height is not None:
g.set_size_request(width, height)
return g
def ToggleButton(self, text):
b = Gtk.ToggleButton(text)
b.props.relief = Gtk.ReliefStyle.NONE
b.set_hexpand(True)
b.set_vexpand(True)
b.connect("clicked", self.screen.reset_screensaver_timeout)
return b
@staticmethod
def ScrolledWindow():
scroll = Gtk.ScrolledWindow()
scroll.set_property("overlay-scrolling", False)
scroll.set_vexpand(True)
scroll.add_events(Gdk.EventMask.BUTTON_PRESS_MASK |
Gdk.EventMask.TOUCH_MASK |
Gdk.EventMask.BUTTON_RELEASE_MASK)
scroll.set_kinetic_scrolling(True)
return scroll