use jni::refs::Global;
use winio_handle::{AsContainer, AsWidget, BorrowedWidget};
use winio_primitive::{Point, Size};
use crate::{
BaseWidget, Result, current_activity,
java::android::widget::{
FrameLayout, HorizontalScrollView as AHorizontalScrollView, ScrollView as AScrollView,
},
vm_exec,
};
#[derive(Debug)]
pub struct ScrollView {
parent: Global<FrameLayout<'static>>,
vertical: BaseWidget<AScrollView<'static>>,
horizontal: BaseWidget<AHorizontalScrollView<'static>>,
inner_view: BaseWidget<FrameLayout<'static>>,
enable_vertical: bool,
enable_horizontal: bool,
}
impl ScrollView {
pub fn new(parent: impl AsContainer) -> Result<Self> {
vm_exec(|env| {
let context = current_activity(env)?;
let vertical = AScrollView::new(env, &context)?;
let horizontal = AHorizontalScrollView::new(env, &context)?;
let inner_view = FrameLayout::new(env, &context)?;
vertical.as_view_group().add_view(env, &horizontal)?;
horizontal.as_view_group().add_view(env, &inner_view)?;
let p = parent.as_container();
let parent = env.new_local_ref(p.to_android())?;
let parent =
env.new_global_ref(unsafe { FrameLayout::from_raw(env, parent.into_raw()) })?;
let vertical = BaseWidget::new_with_env(env, p, vertical)?;
let horizontal = env.new_global_ref(horizontal)?.into();
let inner_view = env.new_global_ref(inner_view)?.into();
Ok(Self {
parent,
vertical,
horizontal,
inner_view,
enable_vertical: true,
enable_horizontal: true,
})
})
}
pub fn is_visible(&self) -> Result<bool> {
self.inner_view.is_visible()
}
pub fn set_visible(&mut self, v: bool) -> Result<()> {
self.inner_view.set_visible(v)
}
pub fn is_enabled(&self) -> Result<bool> {
self.inner_view.is_enabled()
}
pub fn set_enabled(&mut self, v: bool) -> Result<()> {
self.inner_view.set_enabled(v)
}
pub fn loc(&self) -> Result<Point> {
if self.enable_vertical {
self.vertical.loc()
} else if self.enable_horizontal {
self.horizontal.loc()
} else {
self.inner_view.loc()
}
}
pub fn set_loc(&mut self, p: Point) -> Result<()> {
if self.enable_vertical {
self.vertical.set_loc(p)?;
self.horizontal.set_loc(Point::zero())?;
self.inner_view.set_loc(Point::zero())?;
} else if self.enable_horizontal {
self.horizontal.set_loc(p)?;
self.inner_view.set_loc(Point::zero())?;
} else {
self.inner_view.set_loc(p)?;
}
Ok(())
}
pub fn size(&self) -> Result<Size> {
if self.enable_vertical {
self.vertical.size()
} else if self.enable_horizontal {
self.horizontal.size()
} else {
self.inner_view.size()
}
}
pub fn set_size(&mut self, v: Size) -> Result<()> {
if self.enable_vertical {
self.vertical.set_size(v)?;
self.horizontal.set_wrap_content()?;
self.inner_view.set_wrap_content()?;
} else if self.enable_horizontal {
self.horizontal.set_size(v)?;
self.inner_view.set_wrap_content()?;
} else {
self.inner_view.set_size(v)?;
}
Ok(())
}
fn detach(&mut self) -> Result<()> {
vm_exec(|env| {
if self.enable_vertical {
self.parent
.as_view_group()
.remove_view(env, self.vertical.as_view())?;
if self.enable_horizontal {
self.vertical
.as_view_group()
.remove_view(env, self.horizontal.as_view())?;
self.horizontal
.as_view_group()
.remove_view(env, self.inner_view.as_view())?;
} else {
self.vertical
.as_view_group()
.remove_view(env, self.inner_view.as_view())?;
}
} else {
if self.enable_horizontal {
self.parent
.as_view_group()
.remove_view(env, self.horizontal.as_view())?;
self.horizontal
.as_view_group()
.remove_view(env, self.inner_view.as_view())?;
} else {
self.parent
.as_view_group()
.remove_view(env, self.inner_view.as_view())?;
}
}
Ok(())
})
}
fn attach(&mut self) -> Result<()> {
vm_exec(|env| {
if self.enable_vertical {
self.parent
.as_view_group()
.add_view(env, self.vertical.as_view())?;
if self.enable_horizontal {
self.vertical
.as_view_group()
.add_view(env, self.horizontal.as_view())?;
self.horizontal
.as_view_group()
.add_view(env, self.inner_view.as_view())?;
} else {
self.vertical
.as_view_group()
.add_view(env, self.inner_view.as_view())?;
}
} else {
if self.enable_horizontal {
self.parent
.as_view_group()
.add_view(env, self.horizontal.as_view())?;
self.horizontal
.as_view_group()
.add_view(env, self.inner_view.as_view())?;
} else {
self.parent
.as_view_group()
.add_view(env, self.inner_view.as_view())?;
}
}
Ok(())
})
}
pub fn hscroll(&self) -> Result<bool> {
Ok(self.enable_horizontal)
}
pub fn set_hscroll(&mut self, v: bool) -> Result<()> {
if self.enable_horizontal != v {
self.detach()?;
self.enable_horizontal = v;
self.attach()?;
}
Ok(())
}
pub fn vscroll(&self) -> Result<bool> {
Ok(self.enable_vertical)
}
pub fn set_vscroll(&mut self, v: bool) -> Result<()> {
if self.enable_vertical != v {
self.detach()?;
self.enable_vertical = v;
self.attach()?;
}
Ok(())
}
pub async fn start(&self) -> ! {
std::future::pending().await
}
}
winio_handle::impl_as_container!(ScrollView, inner_view);
impl AsWidget for ScrollView {
fn as_widget(&self) -> BorrowedWidget<'_> {
if self.enable_vertical {
self.vertical.as_widget()
} else if self.enable_horizontal {
self.horizontal.as_widget()
} else {
self.inner_view.as_widget()
}
}
}