mirror of
https://github.com/ilya-zlobintsev/LACT.git
synced 2026-11-03 20:56:39 -06:00
implement MasonryLayout via LayoutManager
This commit is contained in:
1 parent
76afd1ba33
commit
f46cc07007
2 files changed
+123
-59
No files matched your search
@@ -1,4 +1,5 @@
|
||||
mod clocks_frame;
|
||||
mod masonry_layout;
|
||||
mod performance_frame;
|
||||
mod power_frame;
|
||||
mod power_states;
|
||||
@@ -80,47 +81,25 @@ impl relm4::Component for OcPage {
|
||||
|
||||
model.stats_section.widget(),
|
||||
|
||||
gtk::FlowBox {
|
||||
set_orientation: gtk::Orientation::Horizontal,
|
||||
set_selection_mode: gtk::SelectionMode::None,
|
||||
set_min_children_per_line: 1,
|
||||
set_max_children_per_line: 2,
|
||||
set_column_spacing: 10,
|
||||
set_row_spacing: 10,
|
||||
set_homogeneous: false,
|
||||
gtk::Box {
|
||||
set_layout_manager: Some(masonry_layout::MasonryLayout::default()),
|
||||
set_valign: gtk::Align::Start,
|
||||
set_hexpand: true,
|
||||
|
||||
append: gpu_clocks_child = >k::FlowBoxChild {
|
||||
model.gpu_clocks_frame.widget() {
|
||||
add_css_class: "oc-page-section",
|
||||
set_valign: gtk::Align::Start,
|
||||
set_hexpand: true,
|
||||
|
||||
model.gpu_clocks_frame.widget(),
|
||||
},
|
||||
|
||||
append: vram_clocks_child = >k::FlowBoxChild {
|
||||
model.vram_clocks_frame.widget() {
|
||||
add_css_class: "oc-page-section",
|
||||
set_valign: gtk::Align::Start,
|
||||
set_hexpand: true,
|
||||
|
||||
model.vram_clocks_frame.widget(),
|
||||
},
|
||||
|
||||
append: power_child = >k::FlowBoxChild {
|
||||
model.power_frame.widget() {
|
||||
add_css_class: "oc-page-section",
|
||||
set_valign: gtk::Align::Start,
|
||||
set_hexpand: true,
|
||||
|
||||
model.power_frame.widget(),
|
||||
},
|
||||
|
||||
append: power_states_child = >k::FlowBoxChild {
|
||||
model.power_states_frame.widget() {
|
||||
add_css_class: "oc-page-section",
|
||||
set_valign: gtk::Align::Start,
|
||||
set_hexpand: true,
|
||||
|
||||
model.power_states_frame.widget(),
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -181,37 +160,6 @@ impl relm4::Component for OcPage {
|
||||
|
||||
let widgets = view_output!();
|
||||
|
||||
let section_size_group = gtk::SizeGroup::new(gtk::SizeGroupMode::Horizontal);
|
||||
section_size_group.add_widget(&widgets.gpu_clocks_child);
|
||||
section_size_group.add_widget(&widgets.vram_clocks_child);
|
||||
section_size_group.add_widget(&widgets.power_child);
|
||||
section_size_group.add_widget(&widgets.power_states_child);
|
||||
|
||||
model
|
||||
.gpu_clocks_frame
|
||||
.widget()
|
||||
.bind_property("visible", &widgets.gpu_clocks_child, "visible")
|
||||
.sync_create()
|
||||
.build();
|
||||
model
|
||||
.vram_clocks_frame
|
||||
.widget()
|
||||
.bind_property("visible", &widgets.vram_clocks_child, "visible")
|
||||
.sync_create()
|
||||
.build();
|
||||
model
|
||||
.power_frame
|
||||
.widget()
|
||||
.bind_property("visible", &widgets.power_child, "visible")
|
||||
.sync_create()
|
||||
.build();
|
||||
model
|
||||
.power_states_frame
|
||||
.widget()
|
||||
.bind_property("visible", &widgets.power_states_child, "visible")
|
||||
.sync_create()
|
||||
.build();
|
||||
|
||||
ComponentParts { model, widgets }
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
use gtk::{glib, prelude::*};
|
||||
|
||||
glib::wrapper! {
|
||||
pub struct MasonryLayout(ObjectSubclass<imp::MasonryLayout>)
|
||||
@extends gtk::LayoutManager;
|
||||
}
|
||||
|
||||
impl Default for MasonryLayout {
|
||||
fn default() -> Self {
|
||||
glib::Object::new()
|
||||
}
|
||||
}
|
||||
|
||||
mod imp {
|
||||
use super::*;
|
||||
use gtk::subclass::prelude::*;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct MasonryLayout;
|
||||
|
||||
#[glib::object_subclass]
|
||||
impl ObjectSubclass for MasonryLayout {
|
||||
const NAME: &'static str = "MasonryLayout";
|
||||
type Type = super::MasonryLayout;
|
||||
type ParentType = gtk::LayoutManager;
|
||||
}
|
||||
|
||||
impl ObjectImpl for MasonryLayout {}
|
||||
|
||||
impl LayoutManagerImpl for MasonryLayout {
|
||||
fn request_mode(&self, _widget: >k::Widget) -> gtk::SizeRequestMode {
|
||||
gtk::SizeRequestMode::HeightForWidth
|
||||
}
|
||||
|
||||
// returns minimum, natural, minimum_baseline, natural_baseline
|
||||
fn measure(
|
||||
&self,
|
||||
widget: >k::Widget,
|
||||
orientation: gtk::Orientation,
|
||||
for_size: i32,
|
||||
) -> (i32, i32, i32, i32) {
|
||||
let (minimum, natural) = measure_width(widget);
|
||||
if orientation == gtk::Orientation::Horizontal {
|
||||
(minimum, natural, -1, -1)
|
||||
} else {
|
||||
let width = if for_size < 0 { natural } else { for_size };
|
||||
let height = layout(widget, width, |_, _| {});
|
||||
(height, height, -1, -1)
|
||||
}
|
||||
}
|
||||
|
||||
fn allocate(&self, widget: >k::Widget, width: i32, _height: i32, _baseline: i32) {
|
||||
layout(widget, width, |child, allocation| {
|
||||
child.size_allocate(allocation, -1);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const SPACING: i32 = 10;
|
||||
|
||||
fn children(widget: >k::Widget) -> impl Iterator<Item = gtk::Widget> {
|
||||
std::iter::successors(widget.first_child(), |child| child.next_sibling())
|
||||
.filter(|child| child.should_layout())
|
||||
}
|
||||
|
||||
fn measure_width(widget: >k::Widget) -> (i32, i32) {
|
||||
let mut minimum = 0;
|
||||
let mut natural = 0;
|
||||
let mut count = 0;
|
||||
for child in children(widget) {
|
||||
let (child_minimum, child_natural, _, _) = child.measure(gtk::Orientation::Horizontal, -1);
|
||||
minimum = minimum.max(child_minimum);
|
||||
natural = natural.max(child_natural);
|
||||
count += 1;
|
||||
}
|
||||
if count > 1 {
|
||||
natural = natural * 2 + SPACING;
|
||||
}
|
||||
(minimum, natural)
|
||||
}
|
||||
|
||||
// Measurement and allocation use the same packing so the scroller gets the full height.
|
||||
fn layout(
|
||||
widget: >k::Widget,
|
||||
width: i32,
|
||||
mut place: impl FnMut(>k::Widget, >k::Allocation),
|
||||
) -> i32 {
|
||||
let (minimum, _) = measure_width(widget);
|
||||
let columns = if children(widget).count() > 1 && width >= minimum * 2 + SPACING {
|
||||
2
|
||||
} else {
|
||||
1
|
||||
};
|
||||
let column_width = ((width - SPACING * (columns as i32 - 1)) / columns as i32).max(0);
|
||||
let mut heights = [0, 0];
|
||||
for child in children(widget) {
|
||||
let column = usize::from(columns == 2 && heights[1] < heights[0]);
|
||||
let x = column as i32 * (column_width + SPACING);
|
||||
let child_width = if column == columns - 1 {
|
||||
width - x
|
||||
} else {
|
||||
column_width
|
||||
};
|
||||
let (_, height, _, _) = child.measure(gtk::Orientation::Vertical, child_width);
|
||||
let y = heights[column];
|
||||
let x = if widget.direction() == gtk::TextDirection::Rtl {
|
||||
width - x - child_width
|
||||
} else {
|
||||
x
|
||||
};
|
||||
place(&child, >k::Allocation::new(x, y, child_width, height));
|
||||
heights[column] = y + height + SPACING;
|
||||
}
|
||||
(heights[0].max(heights[1]) - SPACING).max(0)
|
||||
}
|
||||
Reference in new issue
Block a user