widgets/image_dual: fix image size

parent ad03fe58
from gi.repository import Adw, Gtk, Gdk, Gio, GLib from gi.repository import Adw, Gtk, Gdk, Gio
import os import os
from .BaseWidget import BaseWidget from .BaseWidget import BaseWidget
class DualImageChooserWidget(BaseWidget): class DualImageChooserWidget(BaseWidget):
ORIENTATION_THRESHOLD = 750 """
IMAGE_WIDTH = 220 Widget for selecting two images (e.g., light/dark wallpapers).
PLACEHOLDER_HEIGHT = 120
YAML usage:
- name: Wallpaper
type: dual_image
backend: file
key: /path/to/config
default: ["/path/to/light.png", "/path/to/dark.png"]
map:
labels: ["Light", "Dark"]
extensions: [".png", ".jpg", ".webp"]
"""
ORIENTATION_THRESHOLD = 600
MIN_IMAGE_HEIGHT = 80
DEFAULT_ASPECT_RATIO = 16 / 10
def __init__(self, setting): def __init__(self, setting):
super().__init__(setting) super().__init__(setting)
self._aspect_ratios = [self.DEFAULT_ASPECT_RATIO, self.DEFAULT_ASPECT_RATIO]
self._surface_handler_id = None self._surface_handler_id = None
self._surface = None self._surface = None
...@@ -56,9 +71,8 @@ class DualImageChooserWidget(BaseWidget): ...@@ -56,9 +71,8 @@ class DualImageChooserWidget(BaseWidget):
self.images_box = Gtk.Box( self.images_box = Gtk.Box(
orientation=Gtk.Orientation.HORIZONTAL, orientation=Gtk.Orientation.HORIZONTAL,
spacing=12, spacing=12,
halign=Gtk.Align.CENTER,
valign=Gtk.Align.START,
homogeneous=True, homogeneous=True,
hexpand=True,
) )
labels = self.setting.map.get('labels', [_("Light"), _( labels = self.setting.map.get('labels', [_("Light"), _(
...@@ -66,7 +80,6 @@ class DualImageChooserWidget(BaseWidget): ...@@ -66,7 +80,6 @@ class DualImageChooserWidget(BaseWidget):
self.pictures = [] self.pictures = []
self.placeholders = [] self.placeholders = []
self.image_stacks = []
self.reset_revealers = [] self.reset_revealers = []
for i in range(2): for i in range(2):
...@@ -116,59 +129,44 @@ class DualImageChooserWidget(BaseWidget): ...@@ -116,59 +129,44 @@ class DualImageChooserWidget(BaseWidget):
container = Gtk.Box( container = Gtk.Box(
orientation=Gtk.Orientation.VERTICAL, orientation=Gtk.Orientation.VERTICAL,
spacing=6, spacing=6,
hexpand=True,
) )
image_frame = Gtk.Frame( image_frame = Gtk.Frame(
css_classes=["view"], css_classes=["view"],
halign=Gtk.Align.CENTER, hexpand=True,
) )
placeholder = Gtk.DrawingArea(hexpand=True)
placeholder.set_draw_func(self._draw_placeholder, index)
self.placeholders.append(placeholder)
picture = Gtk.Picture( picture = Gtk.Picture(
content_fit=Gtk.ContentFit.FILL, content_fit=Gtk.ContentFit.FILL,
can_shrink=True,
visible=False,
) )
self.pictures.append(picture) self.pictures.append(picture)
placeholder = Gtk.Box( overlay = Gtk.Overlay(hexpand=True)
orientation=Gtk.Orientation.VERTICAL, overlay.set_child(placeholder)
halign=Gtk.Align.CENTER, overlay.add_overlay(picture)
valign=Gtk.Align.CENTER,
width_request=self.IMAGE_WIDTH,
height_request=self.PLACEHOLDER_HEIGHT,
)
placeholder_icon = Gtk.Image(
icon_name="image-missing-symbolic",
pixel_size=48,
css_classes=["dim-label"],
)
placeholder.append(placeholder_icon)
self.placeholders.append(placeholder)
image_stack = Gtk.Stack(
transition_type=Gtk.StackTransitionType.CROSSFADE,
transition_duration=150,
)
image_stack.add_named(placeholder, "placeholder")
image_stack.add_named(picture, "picture")
self.image_stacks.append(image_stack)
overlay = Gtk.Overlay()
overlay.set_child(image_stack)
change_button = Gtk.Button( change_button = Gtk.Button(
icon_name="document-edit-symbolic", icon_name="document-edit-symbolic",
valign=Gtk.Align.END, valign=Gtk.Align.END,
halign=Gtk.Align.END, halign=Gtk.Align.END,
margin_bottom=5, margin_bottom=6,
margin_end=5, margin_end=6,
css_classes=["circular", "secondary"], css_classes=["circular", "osd"],
) )
change_button.connect("clicked", self._on_change_clicked, index) change_button.connect("clicked", self._on_change_clicked, index)
image_reset_button = Gtk.Button( image_reset_button = Gtk.Button(
icon_name="edit-undo-symbolic", icon_name="edit-undo-symbolic",
margin_top=5, margin_top=6,
margin_end=5, margin_end=6,
css_classes=["circular", "secondary"], css_classes=["circular", "osd"],
) )
image_reset_button.connect( image_reset_button.connect(
"clicked", self._on_image_reset_clicked, index) "clicked", self._on_image_reset_clicked, index)
...@@ -199,6 +197,30 @@ class DualImageChooserWidget(BaseWidget): ...@@ -199,6 +197,30 @@ class DualImageChooserWidget(BaseWidget):
return container return container
def _draw_placeholder(self, area, cr, width, height, index):
aspect = self._aspect_ratios[index]
target_height = max(int(width / aspect), self.MIN_IMAGE_HEIGHT)
if height != target_height:
area.set_size_request(-1, target_height)
return
cr.set_source_rgba(0.5, 0.5, 0.5, 0.15)
cr.rectangle(0, 0, width, height)
cr.fill()
icon_size = min(width, height) * 0.3
icon_size = max(24, min(icon_size, 48))
cr.set_source_rgba(0.5, 0.5, 0.5, 0.4)
cx, cy = width / 2, height / 2
cr.arc(cx, cy, icon_size / 2, 0, 2 * 3.14159)
cr.fill()
cr.set_source_rgba(1, 1, 1, 0.6)
cr.arc(cx, cy, icon_size / 4, 0, 2 * 3.14159)
cr.fill()
def _get_values(self): def _get_values(self):
values = self.setting._get_backend_value() values = self.setting._get_backend_value()
if isinstance(values, list) and len(values) >= 2: if isinstance(values, list) and len(values) >= 2:
...@@ -263,18 +285,21 @@ class DualImageChooserWidget(BaseWidget): ...@@ -263,18 +285,21 @@ class DualImageChooserWidget(BaseWidget):
width = texture.get_width() width = texture.get_width()
height = texture.get_height() height = texture.get_height()
if width > 0 and height > 0: if width > 0 and height > 0:
target_height = int(self.IMAGE_WIDTH * height / width) self._aspect_ratios[index] = width / height
self.pictures[index].set_size_request(
self.IMAGE_WIDTH, target_height)
self.image_stacks[index].set_visible_child_name("picture") self.placeholders[index].queue_draw()
self.pictures[index].set_visible(True)
except Exception as e: except Exception as e:
self.logger.error(f"Error loading image {index}: {e}") self.logger.error(f"Error loading image {index}: {e}")
self._aspect_ratios[index] = self.DEFAULT_ASPECT_RATIO
self.pictures[index].set_paintable(None) self.pictures[index].set_paintable(None)
self.image_stacks[index].set_visible_child_name("placeholder") self.pictures[index].set_visible(False)
self.placeholders[index].queue_draw()
else: else:
self._aspect_ratios[index] = self.DEFAULT_ASPECT_RATIO
self.pictures[index].set_paintable(None) self.pictures[index].set_paintable(None)
self.image_stacks[index].set_visible_child_name("placeholder") self.pictures[index].set_visible(False)
self.placeholders[index].queue_draw()
def _on_reset_clicked(self, button): def _on_reset_clicked(self, button):
default = self.setting.default default = self.setting.default
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment