pub use crate::register_widget;
use {
crate::makepad_draw::*,
crate::designer_data::DesignerDataToWidget,
std::any::TypeId,
std::cell::RefCell,
std::collections::BTreeMap,
std::fmt,
std::sync::Arc,
std::fmt::{Debug, Error, Formatter},
std::rc::Rc,
};
#[derive(Clone, Copy)]
pub enum WidgetCache {
Yes,
No,
Clear,
}
#[derive(Clone, Debug, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct WidgetUid(pub u64);
pub trait WidgetDesign: WidgetNode {}
#[derive(Clone, Debug, DefaultNone)]
pub enum WidgetDesignAction {
PickedBody,
None,
}
pub trait WidgetNode: LiveApply {
fn widget_design(&mut self) -> Option<&mut dyn WidgetDesign> {
return None;
}
fn uid_to_widget(&self, _uid: WidgetUid) -> WidgetRef;
fn find_widgets(&self, _path: &[LiveId], _cached: WidgetCache, _results: &mut WidgetSet);
fn walk(&mut self, _cx: &mut Cx) -> Walk;
fn area(&self) -> Area; fn redraw(&mut self, _cx: &mut Cx);
fn set_action_data(&mut self, _data:Arc<dyn ActionTrait>){}
fn action_data(&self)->Option<Arc<dyn ActionTrait>>{None}
fn set_visible(&mut self, _cx:&mut Cx, _visible:bool){}
fn visible(&self) -> bool {true}
}
pub trait Widget: WidgetNode {
fn handle_event_with(
&mut self,
cx: &mut Cx,
event: &Event,
scope: &mut Scope,
_sweep_area: Area,
) {
self.handle_event(cx, event, scope)
}
fn handle_event(&mut self, _cx: &mut Cx, _event: &Event, _scope: &mut Scope) {}
fn widget(&self, path: &[LiveId]) -> WidgetRef {
let mut results = WidgetSet::default();
self.find_widgets(path, WidgetCache::Yes, &mut results);
return results.into_first();
}
fn widgets(&self, paths: &[&[LiveId]]) -> WidgetSet {
let mut results = WidgetSet::default();
for path in paths {
self.find_widgets(path, WidgetCache::Yes, &mut results);
}
results
}
fn widget_uid(&self) -> WidgetUid {
return WidgetUid(self as *const _ as *const () as u64);
}
fn widget_to_data(
&self,
_cx: &mut Cx,
_actions: &Actions,
_nodes: &mut LiveNodeVec,
_path: &[LiveId],
) -> bool {
false
}
fn data_to_widget(&mut self, _cx: &mut Cx, _nodes: &[LiveNode], _path: &[LiveId]) {}
fn draw_3d(&mut self, _cx:&mut Cx3d, _scope: &mut Scope)->DrawStep{
DrawStep::done()
}
fn draw_3d_all(&mut self, cx:&mut Cx3d, scope: &mut Scope){
while self.draw_3d(cx, scope).is_step() {}
}
fn draw_walk(&mut self, _cx: &mut Cx2d, _scope: &mut Scope, _walk: Walk) -> DrawStep{
DrawStep::done()
}
fn draw(&mut self, cx: &mut Cx2d, scope: &mut Scope) -> DrawStep {
let walk = self.walk(cx);
self.draw_walk(cx, scope, walk)
}
fn draw_walk_all(&mut self, cx: &mut Cx2d, scope: &mut Scope, walk: Walk) {
while self.draw_walk(cx, scope, walk).is_step() {}
}
fn draw_all(&mut self, cx: &mut Cx2d, scope: &mut Scope) {
while self.draw(cx, scope).is_step() {}
}
fn draw_unscoped(&mut self, cx: &mut Cx2d) -> DrawStep {
self.draw(cx, &mut Scope::empty())
}
fn draw_all_unscoped(&mut self, cx: &mut Cx2d) {
self.draw_all(cx, &mut Scope::empty());
}
fn text(&self) -> String {
String::new()
}
fn set_text(&mut self, _cx:&mut Cx, _v: &str) {}
fn set_key_focus(&self, cx:&mut Cx){
cx.set_key_focus(self.area())
}
fn key_focus(&self, cx:&Cx)->bool{
cx.has_key_focus(self.area())
}
fn set_disabled(&mut self, _cx:&mut Cx, _disabled:bool){
}
fn disabled(&self, _cx:&Cx) -> bool {
false
}
fn ref_cast_type_id(&self) -> LiveType
where
Self: 'static,
{
LiveType::of::<Self>()
}
fn ui_runner(&self) -> UiRunner<Self> where Self: Sized + 'static {
UiRunner::new(self.widget_uid().0 as usize)
}
}
#[derive(Clone, Copy)]
pub enum CreateAt {
Template,
Begin,
After(LiveId),
Before(LiveId),
End,
}
pub trait DrawStepApi {
fn done() -> DrawStep {
Result::Ok(())
}
fn make_step_here(arg: WidgetRef) -> DrawStep {
Result::Err(arg)
}
fn make_step() -> DrawStep {
Result::Err(WidgetRef::empty())
}
fn is_done(&self) -> bool;
fn is_step(&self) -> bool;
fn step(self) -> Option<WidgetRef>;
}
impl DrawStepApi for DrawStep {
fn is_done(&self) -> bool {
match *self {
Result::Ok(_) => true,
Result::Err(_) => false,
}
}
fn is_step(&self) -> bool {
match *self {
Result::Ok(_) => false,
Result::Err(_) => true,
}
}
fn step(self) -> Option<WidgetRef> {
match self {
Result::Ok(_) => None,
Result::Err(nd) => Some(nd),
}
}
}
pub type DrawStep = Result<(), WidgetRef>;
generate_any_trait_api!(Widget);
pub trait WidgetFactory {
fn new(&self, cx: &mut Cx) -> Box<dyn Widget>;
}
#[derive(Default, LiveComponentRegistry)]
pub struct WidgetRegistry {
pub map: BTreeMap<LiveType, (LiveComponentInfo, Box<dyn WidgetFactory>)>,
}
pub struct WidgetRefInner {
pub widget: Box<dyn Widget>,
}
#[derive(Clone, Default)]
pub struct WidgetRef(Rc<RefCell<Option<WidgetRefInner>>>);
impl Debug for WidgetRef {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
write!(f, "WidgetRef {}", self.widget_uid().0)
}
}
#[derive(Default, Clone, Debug)]
pub struct WidgetSet(pub SmallVec<[WidgetRef;2]>);
impl WidgetSet {
pub fn is_empty(&mut self) -> bool {
self.0.len() == 0
}
pub fn push(&mut self, item: WidgetRef) {
self.0.push(item);
}
pub fn extend_from_set(&mut self, other: &WidgetSet) {
for item in other.iter(){
self.0.push(item.clone())
}
}
pub fn into_first(self) -> WidgetRef {
for item in self.0{
return item
}
WidgetRef::empty()
}
pub fn widgets(&self, paths: &[&[LiveId]]) -> WidgetSet {
let mut results = WidgetSet::default();
for widget in &self.0 {
if let Some(inner) = widget.0.borrow().as_ref() {
for path in paths {
inner
.widget
.find_widgets(path, WidgetCache::Yes, &mut results);
}
}
}
results
}
pub fn contains(&self, widget: &WidgetRef) -> bool {
for item in &self.0 {
if *item == *widget {
return true;
}
}
false
}
}
impl LiveHook for WidgetSet {}
impl LiveApply for WidgetSet {
fn apply(&mut self, cx: &mut Cx, apply: &mut Apply, index: usize, nodes: &[LiveNode]) -> usize {
for inner in &self.0 {
let mut inner = inner.0.borrow_mut();
if let Some(component) = &mut *inner {
return component.widget.apply(cx, apply, index, nodes);
}
}
nodes.skip_node(index)
}
}
impl WidgetSet {
pub fn empty() -> Self {
Self::default()
}
pub fn set_text(&self, cx: &mut Cx, v: &str) {
for item in &self.0 {
item.set_text(cx, v)
}
}
pub fn iter(&self)->WidgetSetIterator{
return WidgetSetIterator{
widget_set: self,
index: 0
}
}
pub fn filter_actions<'a>(&'a self, actions:&'a Actions)-> impl Iterator<Item = &'a WidgetAction>{
actions.filter_widget_actions_set(self)
}
}
pub struct WidgetSetIterator<'a> {
widget_set: &'a WidgetSet,
index: usize,
}
impl<'a> Iterator for WidgetSetIterator<'a> {
type Item = &'a WidgetRef;
fn next(&mut self) -> Option<Self::Item> {
if self.index < self.widget_set.0.len(){
let idx = self.index;
self.index += 1;
return Some(&self.widget_set.0[idx])
}
None
}
}
impl PartialEq for WidgetRef {
fn eq(&self, other: &WidgetRef) -> bool {
Rc::ptr_eq(&self.0, &other.0)
}
fn ne(&self, other: &WidgetRef) -> bool {
!Rc::ptr_eq(&self.0, &other.0)
}
}
pub trait OptionWidgetRefExt{
fn into_ref(self) -> WidgetRef;
}
impl OptionWidgetRefExt for Option<WidgetRef>{
fn into_ref(self) -> WidgetRef{
if let Some(v) = self{
return v
}
else{
WidgetRef::empty()
}
}
}
impl WidgetRef {
pub fn into_option(self)->Option<WidgetRef>{
if self.is_empty(){
None
}
else{
Some(self)
}
}
pub fn empty() -> Self {
Self(Rc::new(RefCell::new(None)))
}
pub fn is_empty(&self) -> bool {
self.0.borrow().as_ref().is_none()
}
pub fn new_with_inner(widget: Box<dyn Widget>) -> Self {
Self(Rc::new(RefCell::new(Some(WidgetRefInner { widget }))))
}
pub fn handle_event_with(
&self,
cx: &mut Cx,
event: &Event,
scope: &mut Scope,
sweep_area: Area,
) {
if let Some(inner) = self.0.borrow_mut().as_mut() {
inner.widget.handle_event_with(cx, event, scope, sweep_area)
}
}
pub fn handle_event(&self, cx: &mut Cx, event: &Event, scope: &mut Scope) {
let start = cx.new_actions.len();
if let Some(inner) = self.0.borrow_mut().as_mut() {
inner.widget.handle_event(cx, event, scope);
}
let end = cx.new_actions.len();
if start != end{
for action in &mut cx.new_actions[start..end]{
if let Some(action) = action.downcast_mut::<WidgetAction>() {
action.widgets.push(self.clone());
}
}
}
}
pub fn widget_uid(&self) -> WidgetUid {
self.0
.try_borrow()
.ok()
.and_then(|r| r.as_ref().map(|w| w.widget.widget_uid()))
.unwrap_or(WidgetUid(0))
}
pub fn area(&self) -> Area {
if let Some(inner) = self.0.borrow().as_ref() {
return inner.widget.area();
}
Area::Empty
}
pub fn widget_to_data(
&self,
cx: &mut Cx,
actions: &Actions,
nodes: &mut LiveNodeVec,
path: &[LiveId],
) -> bool {
if let Some(inner) = self.0.borrow_mut().as_mut() {
return inner.widget.widget_to_data(cx, actions, nodes, path);
}
false
}
pub fn set_action_data<T:ActionTrait + PartialEq>(&self, data:T){
if let Some(inner) = self.0.borrow_mut().as_mut() {
if let Some(v) = inner.widget.action_data(){
if let Some(v) = v.downcast_ref::<T>(){
if v.ne(&data){
inner.widget.set_action_data(Arc::new(data));
}
}
}
else{
inner.widget.set_action_data(Arc::new(data));
}
}
}
pub fn set_action_data_always<T:ActionTrait>(&self, data:T){
if let Some(inner) = self.0.borrow_mut().as_mut() {
inner.widget.set_action_data(Arc::new(data));
}
}
pub fn data_to_widget(&self, cx: &mut Cx, nodes: &[LiveNode], path: &[LiveId]) {
if let Some(inner) = self.0.borrow_mut().as_mut() {
inner.widget.data_to_widget(cx, nodes, path);
}
}
pub fn uid_to_widget(&self, uid: WidgetUid) -> WidgetRef {
if self.widget_uid() == uid {
return self.clone();
}
if let Some(inner) = self.0.borrow().as_ref() {
return inner.widget.uid_to_widget(uid);
}
WidgetRef::empty()
}
pub fn clear_query_cache(&self){
if let Some(inner) = self.0.borrow_mut().as_ref() {
let mut res = WidgetSet::empty();
inner.widget.find_widgets(&[], WidgetCache::Clear, &mut res);
}
}
pub fn find_widgets(&self, path: &[LiveId], cached: WidgetCache, results: &mut WidgetSet) {
if let Some(inner) = self.0.borrow().as_ref() {
inner.widget.find_widgets(path, cached, results)
}
}
pub fn widget(&self, path: &[LiveId]) -> WidgetRef {
if let Some(inner) = self.0.borrow_mut().as_mut() {
return inner.widget.widget(path);
}
WidgetRef::empty()
}
pub fn widgets(&self, paths: &[&[LiveId]]) -> WidgetSet {
if let Some(inner) = self.0.borrow_mut().as_mut() {
return inner.widget.widgets(paths);
}
WidgetSet::default()
}
pub fn widget_set(&self, paths: &[&[LiveId]]) -> WidgetSet {
if let Some(inner) = self.0.borrow_mut().as_mut() {
return inner.widget.widgets(paths);
}
WidgetSet::default()
}
pub fn draw_walk(&self, cx: &mut Cx2d, scope: &mut Scope, walk: Walk) -> DrawStep {
if let Some(inner) = self.0.borrow_mut().as_mut() {
if let Some(nd) = inner.widget.draw_walk(cx, scope, walk).step() {
if nd.is_empty() {
return DrawStep::make_step_here(self.clone());
}
return DrawStep::make_step_here(nd);
}
}
DrawStep::done()
}
pub fn draw_walk_all(&self, cx: &mut Cx2d, scope: &mut Scope, walk: Walk) {
if let Some(inner) = self.0.borrow_mut().as_mut() {
inner.widget.draw_walk_all(cx, scope, walk)
}
}
pub fn draw_3d_all(&self, cx: &mut Cx3d, scope: &mut Scope) {
if let Some(inner) = self.0.borrow_mut().as_mut() {
inner.widget.draw_3d_all(cx, scope)
}
}
pub fn draw_3d(&mut self, cx: &mut Cx3d, scope: &mut Scope) -> DrawStep {
if let Some(inner) = self.0.borrow_mut().as_mut() {
if let Some(nd) = inner.widget.draw_3d(cx, scope).step() {
if nd.is_empty() {
return DrawStep::make_step_here(self.clone());
}
return DrawStep::make_step_here(nd);
}
}
DrawStep::done()
}
pub fn draw(&mut self, cx: &mut Cx2d, scope: &mut Scope) -> DrawStep {
if let Some(inner) = self.0.borrow_mut().as_mut() {
if let Some(nd) = inner.widget.draw(cx, scope).step() {
if nd.is_empty() {
return DrawStep::make_step_here(self.clone());
}
return DrawStep::make_step_here(nd);
}
}
DrawStep::done()
}
pub fn draw_unscoped(&mut self, cx: &mut Cx2d) -> DrawStep {
if let Some(inner) = self.0.borrow_mut().as_mut() {
if let Some(nd) = inner.widget.draw(cx, &mut Scope::empty()).step() {
if nd.is_empty() {
return DrawStep::make_step_here(self.clone());
}
return DrawStep::make_step_here(nd);
}
}
DrawStep::done()
}
pub fn walk(&self, cx: &mut Cx) -> Walk {
if let Some(inner) = self.0.borrow_mut().as_mut() {
return inner.widget.walk(cx);
}
Walk::default()
}
pub fn redraw(&self, cx: &mut Cx) {
if let Some(inner) = self.0.borrow_mut().as_mut() {
return inner.widget.redraw(cx);
}
}
pub fn set_visible(&self, cx:&mut Cx, visible:bool) {
if let Some(inner) = self.0.borrow_mut().as_mut() {
return inner.widget.set_visible(cx, visible);
}
}
pub fn visible(&self) -> bool {
if let Some(inner) = self.0.borrow().as_ref() {
return inner.widget.visible();
}
true
}
pub fn text(&self) -> String {
if let Some(inner) = self.0.borrow_mut().as_mut() {
inner.widget.text()
} else {
String::new()
}
}
pub fn set_text(&self, cx: &mut Cx, v: &str) {
if let Some(inner) = self.0.borrow_mut().as_mut() {
inner.widget.set_text(cx, v)
}
}
pub fn key_focus(&self, cx:&Cx) -> bool {
if let Some(inner) = self.0.borrow().as_ref() {
inner.widget.key_focus(cx)
} else {
false
}
}
pub fn set_key_focus(&self, cx: &mut Cx) {
if let Some(inner) = self.0.borrow_mut().as_mut() {
inner.widget.set_key_focus(cx)
}
}
pub fn set_disabled(&self, cx:&mut Cx, disabled:bool) {
if let Some(inner) = self.0.borrow_mut().as_mut() {
return inner.widget.set_disabled(cx, disabled);
}
}
pub fn disabled(&self, cx:&Cx) -> bool {
if let Some(inner) = self.0.borrow().as_ref() {
return inner.widget.disabled(cx);
}
true
}
pub fn draw_all(&self, cx: &mut Cx2d, scope: &mut Scope) {
if let Some(inner) = self.0.borrow_mut().as_mut() {
return inner.widget.draw_all(cx, scope);
}
}
pub fn action_data(&self)->Option<Arc<dyn ActionTrait>>{
if let Some(inner) = self.0.borrow().as_ref() {
return inner.widget.action_data()
}
None
}
pub fn filter_actions<'a>(&'a self, actions:&'a Actions)-> impl Iterator<Item = &'a WidgetAction>{
actions.filter_widget_actions(self.widget_uid())
}
pub fn draw_all_unscoped(&self, cx: &mut Cx2d) {
if let Some(inner) = self.0.borrow_mut().as_mut() {
return inner.widget.draw_all_unscoped(cx);
}
}
pub fn borrow_mut<T: 'static + Widget>(&self) -> Option<std::cell::RefMut<'_, T>> {
if let Ok(ret) = std::cell::RefMut::filter_map(self.0.borrow_mut(), |inner| {
if let Some(inner) = inner.as_mut() {
inner.widget.downcast_mut::<T>()
} else {
None
}
}) {
Some(ret)
} else {
None
}
}
pub fn borrow<T: 'static + Widget>(&self) -> Option<std::cell::Ref<'_, T>> {
if let Ok(ret) = std::cell::Ref::filter_map(self.0.borrow(), |inner| {
if let Some(inner) = inner.as_ref() {
inner.widget.downcast_ref::<T>()
} else {
None
}
}) {
Some(ret)
} else {
None
}
}
pub fn apply_over(&self, cx: &mut Cx, nodes: &[LiveNode]) {
self.apply(cx, &mut ApplyFrom::Over.into(), 0, nodes);
}
fn store_designer_backref(&self, cx:&mut Cx, apply:&mut Apply, index:usize){
if let Some(scope) = &mut apply.scope{
if let Some(file_id) = apply.from.file_id(){
if let Some(dd) = scope.data.get_mut::<DesignerDataToWidget>(){
let ptr = cx.live_registry.borrow().file_id_index_to_live_ptr(file_id, index);
dd.live_ptr_to_widget.insert(ptr, self.clone());
}
}
}
}
fn apply(&self, cx: &mut Cx, apply: &mut Apply, index: usize, nodes: &[LiveNode]) -> usize {
let mut inner = self.0.borrow_mut();
if let LiveValue::Class { live_type, .. } = nodes[index].value {
if let Some(component) = &mut *inner {
if component.widget.ref_cast_type_id() != live_type {
*inner = None; log!("TYPECHANGE {:?}", nodes[index]);
} else {
self.store_designer_backref(cx, apply, index);
let idx = component.widget.apply(cx, apply, index, nodes);
component.widget.redraw(cx);
return idx;
}
}
if let Some(component) = cx
.live_registry
.clone()
.borrow()
.components
.get::<WidgetRegistry>()
.new(cx, live_type)
{
if cx.debug.marker() == 1 {
panic!()
}
*inner = Some(WidgetRefInner { widget: component });
self.store_designer_backref(cx, apply, index);
if let Some(component) = &mut *inner {
let idx = component.widget.apply(cx, apply, index, nodes);
component.widget.redraw(cx);
return idx;
}
} else {
cx.apply_error_cant_find_target(
live_error_origin!(),
index,
nodes,
nodes[index].id,
);
}
} else if let Some(component) = &mut *inner {
self.store_designer_backref(cx, apply, index);
let idx = component.widget.apply(cx, apply, index, nodes);
component.widget.redraw(cx);
return idx;
}
cx.apply_error_cant_find_target(live_error_origin!(), index, nodes, nodes[index].id);
nodes.skip_node(index)
}
}
impl LiveHook for WidgetRef {}
impl LiveApply for WidgetRef {
fn apply(&mut self, cx: &mut Cx, apply: &mut Apply, index: usize, nodes: &[LiveNode]) -> usize {
<WidgetRef>::apply(self, cx, apply, index, nodes)
}
}
impl LiveNew for WidgetRef {
fn new(_cx: &mut Cx) -> Self {
Self(Rc::new(RefCell::new(None)))
}
fn live_type_info(_cx: &mut Cx) -> LiveTypeInfo {
LiveTypeInfo {
module_id: LiveModuleId::from_str(&module_path!()).unwrap(),
live_type: LiveType::of::<dyn Widget>(),
fields: Vec::new(),
live_ignore: true,
type_name: LiveId(0),
}
}
}
pub trait WidgetActionTrait: 'static + Send+ Sync {
fn ref_cast_type_id(&self) -> TypeId;
fn debug_fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result;
fn box_clone(&self) -> Box<dyn WidgetActionTrait>;
}
pub trait ActionDefault{
fn default_ref(&self) -> Box<dyn WidgetActionTrait>;
}
impl<T: 'static + ?Sized + Clone + Debug + Send+ Sync> WidgetActionTrait for T {
fn ref_cast_type_id(&self) -> TypeId {
TypeId::of::<T>()
}
fn box_clone(&self) -> Box<dyn WidgetActionTrait> {
Box::new((*self).clone())
}
fn debug_fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.fmt(f)
}
}
impl Debug for dyn WidgetActionTrait {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.debug_fmt(f)
}
}
generate_any_trait_api!(WidgetActionTrait);
impl Clone for Box<dyn WidgetActionTrait> {
fn clone(&self) -> Box<dyn WidgetActionTrait> {
self.as_ref().box_clone()
}
}
#[derive(Default)]
pub struct WidgetActionData{
data: Option<Arc<dyn ActionTrait>>
}
impl WidgetActionData{
pub fn set(&mut self, data:impl ActionTrait){
self.data = Some(Arc::new(data));
}
pub fn set_box(&mut self, data:Arc<dyn ActionTrait>){
self.data = Some(data);
}
pub fn clone_data(&self)->Option<Arc<dyn ActionTrait>>{
self.data.clone()
}
}
#[derive(Clone, Debug)]
pub struct WidgetAction {
pub data: Option< Arc<dyn ActionTrait>>,
pub action: Box<dyn WidgetActionTrait>,
pub widgets: SmallVec<[WidgetRef;4]>,
pub widget_uid: WidgetUid,
pub path: HeapLiveIdPath,
pub group: Option<WidgetActionGroup>,
}
#[derive(Clone, Debug)]
pub struct WidgetActionGroup {
pub group_uid: WidgetUid,
pub item_uid: WidgetUid,
}
pub trait WidgetActionCxExt {
fn widget_action(&mut self, uid: WidgetUid, path: &HeapLiveIdPath, t: impl WidgetActionTrait);
fn widget_action_with_data(
&mut self,
action_data: &WidgetActionData,
widget_uid: WidgetUid,
path: &HeapLiveIdPath,
t: impl WidgetActionTrait,
);
fn group_widget_actions<F, R>(&mut self, group_id: WidgetUid, item_id: WidgetUid, f: F) -> R
where
F: FnOnce(&mut Cx) -> R;
}
pub trait WidgetActionsApi {
fn widget(&self, path:&[LiveId])->WidgetRef;
fn widget_action(&self, path:&[LiveId])->Option<&WidgetAction>;
fn find_widget_action_cast<T: WidgetActionTrait>(
&self,
widget_uid: WidgetUid,
) -> T
where
T: Default + Clone;
fn find_widget_action(&self, widget_uid: WidgetUid) -> Option<&WidgetAction>;
fn filter_widget_actions(&self, widget_uid: WidgetUid) -> impl Iterator<Item = &WidgetAction>;
fn filter_widget_actions_cast<T: WidgetActionTrait>(
&self,
widget_uid: WidgetUid,
) -> impl Iterator<Item = T>
where
T: Default + Clone;
fn filter_actions_data<T: ActionTrait>(
&self,
) -> impl Iterator<Item = &T>
where
T: Clone;
fn filter_widget_actions_set(&self, set: &WidgetSet) -> impl Iterator<Item = &WidgetAction>;
}
pub trait WidgetActionOptionApi {
fn widget_uid_eq(&self, widget_uid: WidgetUid) -> Option<&WidgetAction>;
fn cast<T: WidgetActionTrait>(&self) -> T
where
T: Default + Clone;
fn cast_ref<T: WidgetActionTrait+ ActionDefaultRef>(&self) -> &T;
}
impl WidgetActionOptionApi for Option<&WidgetAction> {
fn widget_uid_eq(&self, widget_uid: WidgetUid) -> Option<&WidgetAction> {
if let Some(item) = self {
if item.widget_uid == widget_uid {
return Some(item);
}
}
None
}
fn cast<T: WidgetActionTrait>(&self) -> T
where
T: Default + Clone,
{
if let Some(item) = self {
if let Some(item) = item.action.downcast_ref::<T>() {
return item.clone();
}
}
T::default()
}
fn cast_ref<T: WidgetActionTrait+ ActionDefaultRef>(&self) -> &T
{
if let Some(item) = self {
if let Some(item) = item.action.downcast_ref::<T>() {
return item;
}
}
T::default_ref()
}
}
pub trait WidgetActionCast {
fn as_widget_action(&self) -> Option<&WidgetAction>;
}
impl WidgetActionCast for Action {
fn as_widget_action(&self) -> Option<&WidgetAction> {
self.downcast_ref::<WidgetAction>()
}
}
impl WidgetActionsApi for Actions {
fn widget_action(&self, path:&[LiveId])->Option<&WidgetAction>{
for action in self {
if let Some(action) = action.downcast_ref::<WidgetAction>() {
let mut ap = action.path.data.iter().rev();
if path.iter().rev().all(|p| ap.find(|&ap| p == ap).is_some()){
return Some(action)
}
}
}
None
}
fn widget(&self, path:&[LiveId])->WidgetRef{
self.iter().find_map(|action| {
action.downcast_ref::<WidgetAction>().and_then(|action| {
let mut ret = None;
let mut ap = action.path.data.iter().rev();
path.iter().enumerate().rev().all(|(i, p)| {
let found = ap.find(|&ap| p == ap).is_some();
if found && ret.is_none() {
ret = action.widgets.get(i);
}
found
}).then_some(ret).flatten()
})
}).map_or_else(|| WidgetRef::empty(), |ret| ret.clone())
}
fn find_widget_action(&self, widget_uid: WidgetUid) -> Option<&WidgetAction> {
for action in self {
if let Some(action) = action.downcast_ref::<WidgetAction>() {
if action.widget_uid == widget_uid {
return Some(action);
}
}
}
None
}
fn find_widget_action_cast<T: WidgetActionTrait + 'static + Send>(
&self,
widget_uid: WidgetUid,
) -> T
where
T: Default + Clone,
{
if let Some(item) = self.find_widget_action(widget_uid) {
if let Some(item) = item.action.downcast_ref::<T>() {
return item.clone();
}
}
T::default()
}
fn filter_widget_actions(&self, widget_uid: WidgetUid) -> impl Iterator<Item = &WidgetAction> {
self.iter().filter_map(move |action| {
action
.downcast_ref::<WidgetAction>()
.and_then(|action| (action.widget_uid == widget_uid).then_some(action))
})
}
fn filter_widget_actions_cast<T: WidgetActionTrait >(
&self,
widget_uid: WidgetUid,
) -> impl Iterator<Item = T>
where
T: Default + Clone,
{
self.filter_widget_actions(widget_uid).map(|action| {
if let Some(a) = action.action.downcast_ref::<T>() {
a.clone()
}else {
T::default()
}
})
}
fn filter_actions_data<T: ActionTrait>(
&self,
) -> impl Iterator<Item = &T>
{
self.iter().filter_map(move |action| {
action
.downcast_ref::<WidgetAction>()
.and_then(|action|{
if let Some(a) = &action.data{
if let Some(a) = a.downcast_ref::<T>() {
Some(a)
}else {
None
}
}else {
None
}
})
})
}
fn filter_widget_actions_set(&self, set:&WidgetSet) -> impl Iterator<Item = &WidgetAction> {
self.iter().filter_map(move |action| {
action
.downcast_ref::<WidgetAction>()
.and_then(|action| (
set.iter().any(|w| action.widget_uid == w.widget_uid())
).then_some(action))
})
}
}
impl WidgetActionCxExt for Cx {
fn widget_action(
&mut self,
widget_uid: WidgetUid,
path: &HeapLiveIdPath,
t: impl WidgetActionTrait,
) {
self.action(WidgetAction {
widget_uid,
data: None,
path: path.clone(),
widgets: Default::default(),
action: Box::new(t),
group: None,
})
}
fn widget_action_with_data(
&mut self,
action_data: &WidgetActionData,
widget_uid: WidgetUid,
path: &HeapLiveIdPath,
t: impl WidgetActionTrait,
) {
self.action(WidgetAction {
widget_uid,
data: action_data.clone_data(),
path: path.clone(),
widgets: Default::default(),
action: Box::new(t),
group: None,
})
}
fn group_widget_actions<F, R>(&mut self, group_uid: WidgetUid, item_uid: WidgetUid, f: F) -> R
where
F: FnOnce(&mut Cx) -> R,
{
self.mutate_actions(
|cx| f(cx),
|actions| {
for action in actions {
if let Some(action) = action.downcast_mut::<WidgetAction>() {
if action.group.is_none() {
action.group = Some(WidgetActionGroup {
group_uid,
item_uid,
})
}
}
}
},
)
}
}
impl WidgetAction {
pub fn widget(&self)->&WidgetRef{
self.widgets.first().unwrap()
}
pub fn widget_nth(&self, n:usize)->&WidgetRef{
self.widgets.iter().nth(n).unwrap()
}
pub fn cast<T: WidgetActionTrait + 'static + Send>(&self) -> T
where
T: Default + Clone,
{
if let Some(item) = self.action.downcast_ref::<T>() {
return item.clone();
}
T::default()
}
pub fn cast_ref<T: WidgetActionTrait + 'static + Send + ActionDefaultRef>(&self) -> &T
{
if let Some(item) = self.action.downcast_ref::<T>() {
return item
}
T::default_ref()
}
pub fn downcast_ref<T: WidgetActionTrait + Send + ActionDefaultRef>(&self) -> Option<&T>
{
self.action.downcast_ref::<T>()
}
}
pub struct DrawStateWrap<T: Clone> {
state: Option<T>,
redraw_id: u64,
}
impl<T: Clone> Default for DrawStateWrap<T> {
fn default() -> Self {
Self {
state: None,
redraw_id: 0,
}
}
}
impl<T: Clone> DrawStateWrap<T> {
pub fn begin(&mut self, cx: &mut CxDraw, init: T) -> bool {
if self.redraw_id != cx.redraw_id() {
self.redraw_id = cx.redraw_id();
self.state = Some(init);
true
} else {
false
}
}
pub fn begin_with<F, S>(&mut self, cx: &mut CxDraw, v: &S, init: F) -> bool
where
F: FnOnce(&mut CxDraw, &S) -> T,
{
if self.redraw_id != cx.redraw_id() {
self.redraw_id = cx.redraw_id();
self.state = Some(init(cx, v));
true
} else {
false
}
}
pub fn begin_state(&mut self, cx: &mut Cx) -> Option<&mut Option<T>>
{
if self.redraw_id != cx.redraw_id() {
self.redraw_id = cx.redraw_id();
Some(&mut self.state)
} else {
None
}
}
pub fn get(&self) -> Option<T> {
self.state.clone()
}
pub fn as_ref(&self) -> Option<&T> {
self.state.as_ref()
}
pub fn as_mut(&mut self) -> Option<&mut T> {
self.state.as_mut()
}
pub fn set(&mut self, value: T) {
self.state = Some(value);
}
pub fn end(&mut self) {
self.state = None;
}
}
#[macro_export]
macro_rules! register_widget {
( $ cx: ident, $ ty: ty) => {{
struct Factory();
impl WidgetFactory for Factory {
fn new(&self, cx: &mut Cx) -> Box<dyn Widget> {
Box::new(<$ty>::new(cx))
}
}
register_component_factory!($cx, WidgetRegistry, $ty, Factory);
}};
}