window, image_view: Resize window based on image size
Allows us to have a more appropriate size for the window based on the content, instead of sticking with the small default window size.
This commit is contained in:
parent
f056c82ced
commit
fef57b242d
2 changed files with 96 additions and 3 deletions
|
|
@ -128,6 +128,26 @@ mod imp {
|
||||||
PROPERTIES.as_ref()
|
PROPERTIES.as_ref()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn signals() -> &'static [glib::subclass::Signal] {
|
||||||
|
static SIGNALS: Lazy<Vec<glib::subclass::Signal>> = Lazy::new(|| {
|
||||||
|
vec![subclass::Signal::builder(
|
||||||
|
// Called when the dimensions of the image
|
||||||
|
// have been found.
|
||||||
|
"dimensions-loaded",
|
||||||
|
&[
|
||||||
|
// The width of the image
|
||||||
|
i32::static_type().into(),
|
||||||
|
// The height of the image
|
||||||
|
i32::static_type().into(),
|
||||||
|
],
|
||||||
|
glib::Type::UNIT.into(),
|
||||||
|
)
|
||||||
|
.build()]
|
||||||
|
});
|
||||||
|
|
||||||
|
SIGNALS.as_ref()
|
||||||
|
}
|
||||||
|
|
||||||
fn get_property(
|
fn get_property(
|
||||||
&self,
|
&self,
|
||||||
_obj: &Self::Type,
|
_obj: &Self::Type,
|
||||||
|
|
@ -204,6 +224,21 @@ impl IvImageView {
|
||||||
let imp = imp::IvImageView::from_instance(&self);
|
let imp = imp::IvImageView::from_instance(&self);
|
||||||
|
|
||||||
imp.picture.set_file(Some(file));
|
imp.picture.set_file(Some(file));
|
||||||
|
|
||||||
|
if let Err(e) = self.load_dimensions_from_file(file) {
|
||||||
|
log::error!("Could not load image dimensions: {}", e);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn load_dimensions_from_file(&self, file: &gio::File) -> anyhow::Result<()> {
|
||||||
|
let pb = file.get_path().context("No path for current file")?;
|
||||||
|
let (_, width, height) =
|
||||||
|
gdk_pixbuf::Pixbuf::get_file_info(&pb.as_path()).context("Could not get file info")?;
|
||||||
|
|
||||||
|
log::debug!("Image dimensions: {} x {}", width, height);
|
||||||
|
let _ = self.emit_by_name("dimensions-loaded", &[&width, &height]);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_wallpaper(&self) -> anyhow::Result<()> {
|
pub fn set_wallpaper(&self) -> anyhow::Result<()> {
|
||||||
|
|
@ -220,7 +255,7 @@ impl IvImageView {
|
||||||
|
|
||||||
let request = RequestProxy::new(&imp.connection, &request_handle)?;
|
let request = RequestProxy::new(&imp.connection, &request_handle)?;
|
||||||
request.on_response(|response: Response<Basic>| {
|
request.on_response(|response: Response<Basic>| {
|
||||||
log::debug!("Response is OK: {}", response.is_ok());
|
log::debug!("Wallpaper set: {}", response.is_ok());
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
@ -281,4 +316,20 @@ impl IvImageView {
|
||||||
imp.popover.set_pointing_to(&rect);
|
imp.popover.set_pointing_to(&rect);
|
||||||
imp.popover.popup();
|
imp.popover.popup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn connect_dimensions_loaded<F: Fn(&Self, i32, i32) + 'static>(
|
||||||
|
&self,
|
||||||
|
f: F,
|
||||||
|
) -> glib::SignalHandlerId {
|
||||||
|
self.connect_local("dimensions-loaded", true, move |values| {
|
||||||
|
let view = values[0].get::<Self>().unwrap().unwrap();
|
||||||
|
let width = values[1].get::<i32>().unwrap().unwrap();
|
||||||
|
let height = values[2].get::<i32>().unwrap().unwrap();
|
||||||
|
|
||||||
|
f(&view, width, height);
|
||||||
|
|
||||||
|
None
|
||||||
|
})
|
||||||
|
.unwrap()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -115,6 +115,12 @@ mod imp {
|
||||||
.connect_released(clone!(@weak obj => move |_, _, _, _| {
|
.connect_released(clone!(@weak obj => move |_, _, _, _| {
|
||||||
obj.pick_file();
|
obj.pick_file();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
self.image_view.connect_dimensions_loaded(
|
||||||
|
clone!(@weak obj => move |_, width, height| {
|
||||||
|
obj.resize_from_dimensions(width, height);
|
||||||
|
}),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -243,11 +249,11 @@ impl IvWindow {
|
||||||
pub fn set_image_from_file(&self, file: &gio::File) {
|
pub fn set_image_from_file(&self, file: &gio::File) {
|
||||||
let imp = imp::IvWindow::from_instance(self);
|
let imp = imp::IvWindow::from_instance(self);
|
||||||
|
|
||||||
|
log::debug!("Loading file: {}", file.get_uri().to_string());
|
||||||
|
|
||||||
imp.image_view.set_image_from_file(file);
|
imp.image_view.set_image_from_file(file);
|
||||||
imp.stack.set_visible_child(&*imp.image_view);
|
imp.stack.set_visible_child(&*imp.image_view);
|
||||||
|
|
||||||
log::debug!("Loading file: {}", file.get_uri().to_string());
|
|
||||||
|
|
||||||
if let Some(name) = file.get_basename() {
|
if let Some(name) = file.get_basename() {
|
||||||
self.set_title(Some(
|
self.set_title(Some(
|
||||||
name.file_name().expect("Missing name").to_str().unwrap(),
|
name.file_name().expect("Missing name").to_str().unwrap(),
|
||||||
|
|
@ -281,4 +287,40 @@ impl IvWindow {
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.set_enabled(enabled);
|
.set_enabled(enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Adapted from https://gitlab.gnome.org/GNOME/eog/-/blob/master/src/eog-window.c:eog_window_obtain_desired_size
|
||||||
|
pub fn resize_from_dimensions(&self, img_width: i32, img_height: i32) {
|
||||||
|
let imp = imp::IvWindow::from_instance(self);
|
||||||
|
let mut final_width = img_width;
|
||||||
|
let mut final_height = img_height;
|
||||||
|
|
||||||
|
let header_height = imp.headerbar.get_height();
|
||||||
|
|
||||||
|
// Ensure the window surface exists
|
||||||
|
if !self.get_realized() {
|
||||||
|
self.realize();
|
||||||
|
}
|
||||||
|
|
||||||
|
let display = gdk::Display::get_default().unwrap();
|
||||||
|
let monitor = display
|
||||||
|
.get_monitor_at_surface(&self.get_native().unwrap().get_surface().unwrap())
|
||||||
|
.unwrap();
|
||||||
|
let monitor_geometry = monitor.get_geometry();
|
||||||
|
|
||||||
|
let monitor_width = monitor_geometry.width;
|
||||||
|
let monitor_height = monitor_geometry.height;
|
||||||
|
|
||||||
|
if img_width > monitor_width || img_height + header_height > monitor_height {
|
||||||
|
let width_factor = (monitor_width as f32 * 0.85) / img_width as f32;
|
||||||
|
let height_factor =
|
||||||
|
(monitor_height as f32 * 0.85 - header_height as f32) / img_height as f32;
|
||||||
|
let factor = width_factor.min(height_factor);
|
||||||
|
|
||||||
|
final_width = (final_width as f32 * factor).round() as i32;
|
||||||
|
final_height = (final_height as f32 * factor).round() as i32;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.set_default_size(final_width, final_height);
|
||||||
|
log::debug!("Window resized to {} x {}", final_width, final_height);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue