use crate::geom::Coord;
use crate::{Id, Layout, LayoutExt};
use std::fmt;
pub struct IdentifyWidget<'a>(pub(crate) &'static str, pub(crate) &'a Id);
impl<'a> fmt::Display for IdentifyWidget<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
write!(f, "{}{}", self.0, self.1)
}
}
pub struct WidgetHierarchy<'a> {
widget: &'a dyn Layout,
indent: usize,
}
impl<'a> WidgetHierarchy<'a> {
pub fn new(widget: &'a dyn Layout) -> Self {
WidgetHierarchy { widget, indent: 0 }
}
}
impl<'a> fmt::Display for WidgetHierarchy<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
let len = 43 - 2 * self.indent;
let trail = "| ".repeat(self.indent);
let identify = format!("{}", self.widget.identify());
let r = self.widget.rect();
let Coord(x1, y1) = r.pos;
let Coord(x2, y2) = r.pos + r.size;
let xr = format!("x={x1}..{x2}");
let xrlen = xr.len().max(12);
write!(f, "\n{trail}{identify:<len$} {xr:<xrlen$} y={y1}..{y2}")?;
let indent = self.indent + 1;
self.widget
.for_children_try(|w| write!(f, "{}", WidgetHierarchy { widget: w, indent }))?;
Ok(())
}
}
pub struct TryFormat<'a, T: ?Sized>(pub &'a T);
#[cfg(not(feature = "spec"))]
impl<'a, T: ?Sized> fmt::Debug for TryFormat<'a, T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{{{}}}", std::any::type_name::<T>())
}
}
#[cfg(feature = "spec")]
impl<'a, T: ?Sized> fmt::Debug for TryFormat<'a, T> {
default fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{{{}}}", std::any::type_name::<T>())
}
}
#[cfg(feature = "spec")]
impl<'a, T: fmt::Debug + ?Sized> fmt::Debug for TryFormat<'a, T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{:?}", self.0)
}
}
pub fn nav_next(reverse: bool, from: Option<usize>, len: usize) -> Option<usize> {
let last = len.wrapping_sub(1);
if last == usize::MAX {
return None;
}
if let Some(index) = from {
match reverse {
false if index < last => Some(index + 1),
true if 0 < index => Some(index - 1),
_ => None,
}
} else {
match reverse {
false => Some(0),
true => Some(last),
}
}
}
#[cfg(feature = "image")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "image")))]
pub fn load_icon_from_path<P: AsRef<std::path::Path>>(
path: P,
) -> Result<Icon, Box<dyn std::error::Error>> {
let im = image::io::Reader::open(path)?
.with_guessed_format()?
.decode()?
.into_rgba8();
let (w, h) = im.dimensions();
Ok(Icon::from_rgba(im.into_vec(), w, h)?)
}
#[cfg_attr(not(feature = "internal_doc"), doc(hidden))]
#[cfg_attr(doc_cfg, doc(cfg(internal_doc)))]
pub fn warn_about_error(msg: &str, mut error: &dyn std::error::Error) {
log::warn!("{msg}: {error}");
while let Some(source) = error.source() {
log::warn!("Source: {source}");
error = source;
}
}