use std::any::Any;
use std::cell::UnsafeCell;
use std::marker::PhantomPinned;
use std::pin::Pin;
use std::sync::Arc;
use crate::co;
use crate::decl::*;
use crate::gui::{collections::*, privs::*};
use crate::macros::*;
use crate::msg;
use crate::prelude::*;
#[derive(Clone, Copy, PartialEq, Eq)]
pub enum SbPart {
Fixed(i32),
Proportional(u8),
}
struct StatusBarObj {
base: BaseCtrl,
events: BaseCtrlEvents,
parts_info: UnsafeCell<Vec<SbPart>>,
right_edges: UnsafeCell<Vec<i32>>, _pin: PhantomPinned,
}
native_ctrl! { StatusBar: StatusBarObj => GuiEventsStatusBar;
}
impl StatusBar {
#[must_use]
pub fn new(parent: &(impl GuiParent + 'static), parts: &[SbPart]) -> Self {
let ctrl_id = auto_id::next();
let new_self = Self(Arc::pin(StatusBarObj {
base: BaseCtrl::new(ctrl_id),
events: BaseCtrlEvents::new(parent, ctrl_id),
parts_info: UnsafeCell::new(parts.to_vec()),
right_edges: UnsafeCell::new(vec![0; parts.len()]),
_pin: PhantomPinned,
}));
let self2 = new_self.clone();
let parent2 = parent.clone();
parent
.as_ref()
.before_on()
.wm(parent.as_ref().wnd_ty().creation_msg(), move |_| {
let parent_style = parent2.hwnd().style();
let is_parent_resizable =
parent_style.has(co::WS::MAXIMIZEBOX) || parent_style.has(co::WS::SIZEBOX);
self2.0.base.create_window(
co::WS_EX::LEFT,
"msctls_statusbar32",
None,
co::WS::CHILD
| co::WS::VISIBLE | co::SBARS::TOOLTIPS.into()
| if is_parent_resizable {
co::SBARS::SIZEGRIP
} else {
co::SBARS::NoValue
}
.into(),
POINT::default(),
SIZE::default(),
&parent2,
);
let parent_rc = parent2.hwnd().GetClientRect().expect(DONTFAIL);
self2.resize(&mut msg::WmSize {
client_area: SIZE::with(parent_rc.right, parent_rc.bottom),
request: co::SIZE_R::RESTORED,
});
Ok(0) });
let self2 = new_self.clone();
parent.as_ref().before_on().wm_size(move |mut p| {
self2.resize(&mut p);
Ok(())
});
new_self
}
fn resize(&self, p: &mut msg::WmSize) {
if p.request == co::SIZE_R::MINIMIZED || *self.hwnd() == HWND::NULL {
return; }
unsafe {
self.hwnd().SendMessage(p.as_generic_wm()); }
let mut total_proportions = 0u8;
let mut cx_available = p.client_area.cx as i32;
let parts_info = unsafe { &mut *self.0.parts_info.get() };
for part_info in parts_info.iter() {
match part_info {
SbPart::Fixed(pixels) => {
cx_available -= if *pixels > cx_available { 0 } else { *pixels }; },
SbPart::Proportional(prop) => total_proportions += prop,
}
}
let right_edges = unsafe { &mut *self.0.right_edges.get() };
let mut total_cx = p.client_area.cx;
for (idx, part_info) in parts_info.iter().rev().enumerate() {
right_edges[parts_info.len() - idx - 1] = total_cx as _;
let minus = match part_info {
SbPart::Fixed(pixels) => *pixels,
SbPart::Proportional(pp) => {
(cx_available / total_proportions as i32) * (*pp as i32)
},
};
total_cx -= if minus > total_cx { 0 } else { minus }; }
*right_edges.last_mut().unwrap() = -1;
unsafe {
self.hwnd()
.SendMessage(msg::SbSetParts { right_edges: &right_edges })
}
.expect(DONTFAIL);
}
#[must_use]
pub const fn parts(&self) -> StatusBarParts<'_> {
StatusBarParts::new(self)
}
}