82 lines
2.3 KiB
Python
82 lines
2.3 KiB
Python
from typing import Optional
|
|
|
|
from gi.repository import Gdk, GdkPixbuf, Gtk
|
|
|
|
|
|
class SpinnerPicture(Gtk.Bin):
|
|
def __init__(
|
|
self,
|
|
loading: bool = True,
|
|
spinner_name: str = None,
|
|
**kwargs,
|
|
):
|
|
"""An picture with a loading overlay."""
|
|
super().__init__()
|
|
self.filename: Optional[str] = None
|
|
self.pixbuf = None
|
|
|
|
self.offset = (0, 0)
|
|
self.sized_pixbuf = None
|
|
|
|
self.spinner = Gtk.Spinner(
|
|
name=spinner_name,
|
|
active=loading,
|
|
halign=Gtk.Align.CENTER,
|
|
valign=Gtk.Align.CENTER,
|
|
)
|
|
self.add(self.spinner)
|
|
|
|
def set_from_file(self, filename: Optional[str]):
|
|
"""Set the picture to the given filename."""
|
|
filename = filename or None
|
|
if self.filename == filename:
|
|
return
|
|
|
|
self.filename = filename
|
|
|
|
if self.filename:
|
|
self.pixbuf = GdkPixbuf.Pixbuf.new_from_file(self.filename)
|
|
else:
|
|
self.pixbuf = None
|
|
self._update_sized_pixbuf()
|
|
|
|
def set_loading(self, loading_status: bool):
|
|
if loading_status:
|
|
self.spinner.start()
|
|
self.spinner.show()
|
|
else:
|
|
self.spinner.stop()
|
|
self.spinner.hide()
|
|
|
|
def do_size_allocate(self, allocation):
|
|
Gtk.Bin.do_size_allocate(self, allocation)
|
|
|
|
self._update_sized_pixbuf()
|
|
|
|
def do_draw(self, cr):
|
|
if self.sized_pixbuf:
|
|
Gdk.cairo_set_source_pixbuf(cr, self.sized_pixbuf, self.offset[0], self.offset[1])
|
|
cr.paint()
|
|
|
|
Gtk.Bin.do_draw(self, cr)
|
|
|
|
def _update_sized_pixbuf(self):
|
|
if self.pixbuf is None:
|
|
self.sized_pixbuf = None
|
|
return
|
|
|
|
pix_width = self.pixbuf.get_width()
|
|
pix_height = self.pixbuf.get_height()
|
|
alloc_width = self.get_allocated_width()
|
|
alloc_height = self.get_allocated_height()
|
|
|
|
scale = max(alloc_width / pix_width, alloc_height / pix_height)
|
|
scaled_width = pix_width * scale
|
|
scaled_height = pix_height * scale
|
|
self.sized_pixbuf = self.pixbuf.scale_simple(scaled_width, scaled_height, GdkPixbuf.InterpType.BILINEAR)
|
|
|
|
self.offset = (
|
|
(alloc_width - scaled_width) / 2,
|
|
(alloc_height - scaled_height) / 2,
|
|
)
|