diff options
Diffstat (limited to 'main/src/ui/widgets')
-rw-r--r-- | main/src/ui/widgets/fixed_ratio_picture.vala | 88 | ||||
-rw-r--r-- | main/src/ui/widgets/natural_size_increase.vala | 59 |
2 files changed, 147 insertions, 0 deletions
diff --git a/main/src/ui/widgets/fixed_ratio_picture.vala b/main/src/ui/widgets/fixed_ratio_picture.vala new file mode 100644 index 00000000..79c60141 --- /dev/null +++ b/main/src/ui/widgets/fixed_ratio_picture.vala @@ -0,0 +1,88 @@ +using Gdk; +using Gtk; + +class Dino.Ui.FixedRatioPicture : Gtk.Widget { + public int min_width { get; set; default = -1; } + public int max_width { get; set; default = int.MAX; } + public int min_height { get; set; default = -1; } + public int max_height { get; set; default = int.MAX; } + public File file { get { return inner.file; } set { inner.file = value; } } + public Gdk.Paintable paintable { get { return inner.paintable; } set { inner.paintable = value; } } +#if GTK_4_8 && VALA_0_58 + public Gtk.ContentFit content_fit { get { return inner.content_fit; } set { inner.content_fit = value; } } +#endif + private Gtk.Picture inner = new Gtk.Picture(); + + construct { + set_css_name("picture"); + add_css_class("fixed-ratio"); + inner.insert_after(this, null); + this.notify.connect(queue_resize); + } + + private void measure_target_size(out int width, out int height) { + if (width_request != -1 && height_request != -1) { + width = width_request; + height = height_request; + return; + } + width = min_width; + height = min_height; + + if (inner.should_layout()) { + int child_min = 0, child_nat = 0, child_min_baseline = -1, child_nat_baseline = -1; + inner.measure(Orientation.HORIZONTAL, -1, out child_min, out child_nat, out child_min_baseline, out child_nat_baseline); + width = int.max(child_nat, width); + } + width = int.min(width, max_width); + + if (inner.should_layout()) { + int child_min = 0, child_nat = 0, child_min_baseline = -1, child_nat_baseline = -1; + inner.measure(Orientation.VERTICAL, width, out child_min, out child_nat, out child_min_baseline, out child_nat_baseline); + height = int.max(child_nat, height); + } + + if (height > max_height) { + height = max_height; + width = min_width; + + if (inner.should_layout()) { + int child_min = 0, child_nat = 0, child_min_baseline = -1, child_nat_baseline = -1; + inner.measure(Orientation.HORIZONTAL, max_height, out child_min, out child_nat, out child_min_baseline, out child_nat_baseline); + width = int.max(child_nat, width); + } + width = int.min(width, max_width); + } + } + + public override void measure(Orientation orientation, int for_size, out int minimum, out int natural, out int minimum_baseline, out int natural_baseline) { + minimum_baseline = -1; + natural_baseline = -1; + int width, height; + measure_target_size(out width, out height); + if (orientation == Orientation.HORIZONTAL) { + minimum = min_width; + natural = width; + } else if (for_size == -1) { + minimum = min_height; + natural = height; + } else { + minimum = natural = height * for_size / width; + } + } + + public override void size_allocate(int width, int height, int baseline) { + if (inner.should_layout()) { + inner.allocate(width, height, baseline, null); + } + } + + public override SizeRequestMode get_request_mode() { + return SizeRequestMode.HEIGHT_FOR_WIDTH; + } + + public override void dispose() { + inner.unparent(); + base.dispose(); + } +}
\ No newline at end of file diff --git a/main/src/ui/widgets/natural_size_increase.vala b/main/src/ui/widgets/natural_size_increase.vala new file mode 100644 index 00000000..2b04d748 --- /dev/null +++ b/main/src/ui/widgets/natural_size_increase.vala @@ -0,0 +1,59 @@ +using Gtk; + +public class Dino.Ui.NaturalSizeIncrease : Gtk.Widget { + public int min_natural_height { get; set; default = -1; } + public int min_natural_width { get; set; default = -1; } + + construct { + this.notify.connect(queue_resize); + } + + public override void measure(Orientation orientation, int for_size, out int minimum, out int natural, out int minimum_baseline, out int natural_baseline) { + minimum = 0; + if (orientation == Orientation.HORIZONTAL) { + natural = min_natural_width; + } else { + natural = min_natural_height; + } + natural = int.max(0, natural); + minimum_baseline = -1; + natural_baseline = -1; + Widget child = get_first_child(); + while (child != null) { + if (child.should_layout()) { + int child_min = 0; + int child_nat = 0; + int child_min_baseline = -1; + int child_nat_baseline = -1; + child.measure(orientation, -1, out child_min, out child_nat, out child_min_baseline, out child_nat_baseline); + minimum = int.max(minimum, child_min); + natural = int.max(natural, child_nat); + if (child_min_baseline > 0) { + minimum_baseline = int.max(minimum_baseline, child_min_baseline); + } + if (child_nat_baseline > 0) { + natural_baseline = int.max(natural_baseline, child_nat_baseline); + } + } + child = child.get_next_sibling(); + } + } + + public override void size_allocate(int width, int height, int baseline) { + Widget child = get_first_child(); + while (child != null) { + if (child.should_layout()) { + child.allocate(width, height, baseline, null); + } + child = child.get_next_sibling(); + } + } + + public override SizeRequestMode get_request_mode() { + Widget child = get_first_child(); + if (child != null) { + return child.get_request_mode(); + } + return SizeRequestMode.CONSTANT_SIZE; + } +}
\ No newline at end of file |