@effindomv2/fui-rs 0.1.14 → 0.1.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/Cargo.toml CHANGED
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "fui-rs"
3
- version = "0.1.14"
3
+ version = "0.1.16"
4
4
  edition = "2021"
5
5
  license = "AGPL-3.0-only OR LicenseRef-EffinDom-Commercial"
6
6
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@effindomv2/fui-rs",
3
- "version": "0.1.14",
3
+ "version": "0.1.16",
4
4
  "private": false,
5
5
  "license": "AGPL-3.0-only OR LicenseRef-EffinDom-Commercial",
6
6
  "description": "EffinDom v2 Rust frontend framework SDK and host generators",
package/src/drawing.rs CHANGED
@@ -63,36 +63,45 @@ impl Paint {
63
63
  }
64
64
  }
65
65
 
66
- pub struct Path {
66
+ struct PathResource {
67
67
  id: u32,
68
- disposed: bool,
68
+ }
69
+
70
+ impl Drop for PathResource {
71
+ fn drop(&mut self) {
72
+ unsafe { ffi::fui_path_destroy(self.id) };
73
+ }
74
+ }
75
+
76
+ #[derive(Clone)]
77
+ pub struct Path {
78
+ resource: Rc<PathResource>,
69
79
  }
70
80
 
71
81
  impl Path {
72
82
  pub fn new() -> Self {
73
83
  let id = unsafe { ffi::fui_path_create() };
74
84
  Self {
75
- id,
76
- disposed: false,
85
+ resource: Rc::new(PathResource { id }),
77
86
  }
78
87
  }
79
88
 
80
89
  pub fn id(&self) -> u32 {
81
- self.id
90
+ self.resource.id
82
91
  }
83
92
 
84
93
  pub fn move_to(&mut self, x: f32, y: f32) -> &mut Self {
85
- unsafe { ffi::fui_path_move_to(self.id, x, y) };
94
+ unsafe { ffi::fui_path_move_to(self.id(), x, y) };
86
95
  self
87
96
  }
88
97
 
89
98
  pub fn line_to(&mut self, x: f32, y: f32) -> &mut Self {
90
- unsafe { ffi::fui_path_line_to(self.id, x, y) };
99
+ unsafe { ffi::fui_path_line_to(self.id(), x, y) };
91
100
  self
92
101
  }
93
102
 
94
103
  pub fn quad_to(&mut self, cx: f32, cy: f32, x: f32, y: f32) -> &mut Self {
95
- unsafe { ffi::fui_path_quad_to(self.id, cx, cy, x, y) };
104
+ unsafe { ffi::fui_path_quad_to(self.id(), cx, cy, x, y) };
96
105
  self
97
106
  }
98
107
 
@@ -105,39 +114,31 @@ impl Path {
105
114
  x: f32,
106
115
  y: f32,
107
116
  ) -> &mut Self {
108
- unsafe { ffi::fui_path_cubic_to(self.id, cx1, cy1, cx2, cy2, x, y) };
117
+ unsafe { ffi::fui_path_cubic_to(self.id(), cx1, cy1, cx2, cy2, x, y) };
109
118
  self
110
119
  }
111
120
 
112
121
  pub fn close(&mut self) -> &mut Self {
113
- unsafe { ffi::fui_path_close(self.id) };
122
+ unsafe { ffi::fui_path_close(self.id()) };
114
123
  self
115
124
  }
116
125
 
117
126
  pub fn add_rect(&mut self, x: f32, y: f32, w: f32, h: f32) -> &mut Self {
118
- unsafe { ffi::fui_path_add_rect(self.id, x, y, w, h) };
127
+ unsafe { ffi::fui_path_add_rect(self.id(), x, y, w, h) };
119
128
  self
120
129
  }
121
130
 
122
131
  pub fn add_circle(&mut self, cx: f32, cy: f32, r: f32) -> &mut Self {
123
- unsafe { ffi::fui_path_add_circle(self.id, cx, cy, r) };
132
+ unsafe { ffi::fui_path_add_circle(self.id(), cx, cy, r) };
124
133
  self
125
134
  }
126
135
  }
127
136
 
128
- impl Drop for Path {
129
- fn drop(&mut self) {
130
- if !self.disposed {
131
- unsafe { ffi::fui_path_destroy(self.id) };
132
- self.disposed = true;
133
- }
134
- }
135
- }
136
-
137
137
  #[derive(Default)]
138
138
  struct DrawContextState {
139
139
  canvas_ptr: usize,
140
140
  words: Vec<u32>,
141
+ retained_paths: Vec<Path>,
141
142
  }
142
143
 
143
144
  #[derive(Clone, Default)]
@@ -151,6 +152,7 @@ impl DrawContext {
151
152
  inner: Rc::new(RefCell::new(DrawContextState {
152
153
  canvas_ptr,
153
154
  words: Vec::new(),
155
+ retained_paths: Vec::new(),
154
156
  })),
155
157
  }
156
158
  }
@@ -172,6 +174,7 @@ impl DrawContext {
172
174
  )
173
175
  };
174
176
  state.words.clear();
177
+ state.retained_paths.clear();
175
178
  }
176
179
 
177
180
  pub fn save(&self) {
@@ -289,6 +292,7 @@ impl DrawContext {
289
292
  state.words.push(paint.fill_color);
290
293
  state.words.push(paint.stroke_color);
291
294
  Self::push_float(&mut state.words, paint.stroke_width);
295
+ state.retained_paths.push(path.clone());
292
296
  }
293
297
 
294
298
  pub fn draw_text_node<T: Node>(&self, node: &T, x: f32, y: f32) {
package/src/lib.rs CHANGED
@@ -433,6 +433,7 @@ pub mod prelude {
433
433
  FileWorkerProcessResult, FileWriteProgress,
434
434
  };
435
435
  pub use crate::focus_visibility::show_keyboard_focus_for_key_event;
436
+ pub use crate::frame_scheduler::{mark_needs_commit, on_loaded, LoadedEventArgs};
436
437
  pub use crate::fui_component;
437
438
  pub use crate::image_sampling::{ImageSampling, ImageSamplingMode};
438
439
  pub use crate::logger;
@@ -440,8 +441,8 @@ pub mod prelude {
440
441
  pub use crate::node::{
441
442
  auto, column, custom_drawable, fill, flex_box, grid, image, pct, portal, px, row,
442
443
  scroll_box, scroll_view, svg, text, viewport_height, viewport_width, virtual_list, Border,
443
- Child, ContextMenuEventArgs, Corners, CustomDrawable, EdgeInsets, FlexBox, FlexBoxSurface,
444
- GradientStop, Grid, GridTrack, HasFlexBoxRoot, Image, ImageNode, Length, Node,
444
+ Child, ContextMenuEventArgs, Corners, CustomDrawable, DrawableInvalidator, EdgeInsets,
445
+ FlexBox, FlexBoxSurface, GradientStop, Grid, GridTrack, HasFlexBoxRoot, Image, ImageNode, Length, Node,
445
446
  PresenterHostStyle, ScrollBar, ScrollBarVisibility, ScrollBox, ScrollState, ScrollView,
446
447
  Shadow, Svg, SvgNode, Text, TextCore, TextNode, ThemeBindable, VirtualList,
447
448
  };
@@ -558,8 +559,8 @@ pub use navigation::*;
558
559
  pub use node::{
559
560
  auto, column, custom_drawable, fill, flex_box, grid, image, pct, portal, px, row, scroll_box,
560
561
  scroll_view, svg, text, viewport_height, viewport_width, virtual_list, Border, Child,
561
- ContextMenuEventArgs, Corners, CustomDrawable, EdgeInsets, FlexBox, FlexBoxSurface,
562
- GradientStop, Grid, GridTrack, HasFlexBoxRoot, Image, ImageNode, Length, Node,
562
+ ContextMenuEventArgs, Corners, CustomDrawable, DrawableInvalidator, EdgeInsets, FlexBox,
563
+ FlexBoxSurface, GradientStop, Grid, GridTrack, HasFlexBoxRoot, Image, ImageNode, Length, Node,
563
564
  PresenterHostStyle, ScrollBar, ScrollBarVisibility, ScrollBox, ScrollState, ScrollView, Shadow,
564
565
  Svg, SvgNode, Text, TextCore, TextNode, ThemeBindable, VirtualList,
565
566
  };
@@ -7,6 +7,19 @@ pub struct CustomDrawable {
7
7
  draw_callback: DrawCallback,
8
8
  }
9
9
 
10
+ #[derive(Clone)]
11
+ pub struct DrawableInvalidator {
12
+ base: WeakFlexBox,
13
+ }
14
+
15
+ impl DrawableInvalidator {
16
+ pub fn mark_dirty(&self) {
17
+ if let Some(base) = self.base.upgrade() {
18
+ mark_base_dirty(&base);
19
+ }
20
+ }
21
+ }
22
+
10
23
  impl CustomDrawable {
11
24
  pub fn new(handler: impl Fn(&mut DrawContext) + 'static) -> Self {
12
25
  let base = FlexBox::default();
@@ -17,94 +30,28 @@ impl CustomDrawable {
17
30
  }
18
31
  }
19
32
 
20
- pub fn width(&self, width: f32, unit: Unit) -> &Self {
21
- self.base.width(width, unit);
22
- self
23
- }
24
-
25
- pub fn width_len(&self, length: Length) -> &Self {
26
- self.base.width_len(length);
27
- self
28
- }
29
-
30
- pub fn height(&self, height: f32, unit: Unit) -> &Self {
31
- self.base.height(height, unit);
32
- self
33
- }
34
-
35
- pub fn height_len(&self, length: Length) -> &Self {
36
- self.base.height_len(length);
37
- self
38
- }
39
-
40
- pub fn bg_color(&self, color: u32) -> &Self {
41
- self.base.bg_color(color);
42
- self
43
- }
44
-
45
- pub fn corner_radius(&self, radius: f32) -> &Self {
46
- self.base.corner_radius(radius);
47
- self
48
- }
49
-
50
- pub fn border(&self, width: f32, color: u32) -> &Self {
51
- self.base.border(width, color);
52
- self
53
- }
54
-
55
- pub fn border_config(&self, border: Border) -> &Self {
56
- self.base.border_config(border);
57
- self
58
- }
59
-
60
- pub fn opacity(&self, value: f32) -> &Self {
61
- self.base.opacity(value);
62
- self
63
- }
64
-
65
- pub fn drop_shadow(
66
- &self,
67
- color: u32,
68
- offset_x: f32,
69
- offset_y: f32,
70
- blur_sigma: f32,
71
- spread: f32,
72
- ) -> &Self {
73
- self.base
74
- .drop_shadow(color, offset_x, offset_y, blur_sigma, spread);
75
- self
76
- }
77
-
78
- pub fn linear_gradient(
79
- &self,
80
- sx: f32,
81
- sy: f32,
82
- ex: f32,
83
- ey: f32,
84
- offsets: Vec<f32>,
85
- colors: Vec<u32>,
86
- ) -> &Self {
87
- self.base.linear_gradient(sx, sy, ex, ey, offsets, colors);
88
- self
33
+ pub fn mark_dirty(&self) {
34
+ mark_base_dirty(&self.base);
89
35
  }
90
36
 
91
- pub fn child<T: Node>(&self, child: &T) -> &Self {
92
- self.base.child(child);
93
- self
37
+ pub fn invalidator(&self) -> DrawableInvalidator {
38
+ DrawableInvalidator {
39
+ base: self.base.downgrade(),
40
+ }
94
41
  }
42
+ }
95
43
 
96
- pub fn mark_dirty(&self) {
97
- let handle = self.handle();
98
- if handle != NodeHandle::INVALID {
99
- let Some(bounds) = ui::get_visible_bounds(handle.raw()) else {
100
- return;
101
- };
102
- if bounds[2] <= 0.0 || bounds[3] <= 0.0 {
103
- return;
104
- }
44
+ fn mark_base_dirty(base: &FlexBox) {
45
+ let handle = base.handle();
46
+ if handle != NodeHandle::INVALID {
47
+ let Some(bounds) = ui::get_visible_bounds(handle.raw()) else {
48
+ return;
49
+ };
50
+ if bounds[2] <= 0.0 || bounds[3] <= 0.0 {
51
+ return;
105
52
  }
106
- crate::frame_scheduler::mark_needs_commit();
107
53
  }
54
+ crate::frame_scheduler::mark_needs_commit();
108
55
  }
109
56
 
110
57
  impl Node for CustomDrawable {
@@ -147,3 +94,55 @@ impl Node for CustomDrawable {
147
94
  }));
148
95
  }
149
96
  }
97
+
98
+ impl HasFlexBoxRoot for CustomDrawable {
99
+ fn flex_box_root(&self) -> &FlexBox {
100
+ &self.base
101
+ }
102
+ }
103
+
104
+ impl ThemeBindable for CustomDrawable {
105
+ fn theme_binding_node(&self) -> NodeRef {
106
+ self.base.retained_node_ref()
107
+ }
108
+
109
+ fn weak_theme_target(&self) -> Box<dyn Fn() -> Option<Self>> {
110
+ let weak_base = self.base.downgrade();
111
+ let draw_callback = self.draw_callback.clone();
112
+ Box::new(move || {
113
+ weak_base.upgrade().map(|base| Self {
114
+ base,
115
+ draw_callback: draw_callback.clone(),
116
+ })
117
+ })
118
+ }
119
+ }
120
+
121
+ #[cfg(test)]
122
+ mod tests {
123
+ use super::*;
124
+
125
+ fn assert_flex_box_surface<T: FlexBoxSurface>() {}
126
+ fn assert_theme_bindable<T: ThemeBindable>() {}
127
+
128
+ #[test]
129
+ fn custom_drawable_exposes_generic_retained_visual_surfaces() {
130
+ assert_flex_box_surface::<CustomDrawable>();
131
+ assert_theme_bindable::<CustomDrawable>();
132
+
133
+ let drawable = CustomDrawable::new(|_| {});
134
+ drawable
135
+ .width(300.0, Unit::Pixel)
136
+ .height(200.0, Unit::Pixel)
137
+ .min_width(120.0, Unit::Pixel)
138
+ .margin(1.0, 2.0, 3.0, 4.0)
139
+ .padding(5.0, 6.0, 7.0, 8.0)
140
+ .corner_radius(12.0)
141
+ .bg_color(0x112233FF)
142
+ .clip_to_bounds(true);
143
+
144
+ let invalidator = drawable.invalidator();
145
+ drop(drawable);
146
+ invalidator.mark_dirty();
147
+ }
148
+ }
package/src/node/mod.rs CHANGED
@@ -37,7 +37,7 @@ mod virtual_list;
37
37
  pub use core::NodeRef;
38
38
  pub use core::{ContextMenuEventArgs, Node, NodeHandle};
39
39
  pub(crate) use core::{WeakFlexBox, WeakNodeRef};
40
- pub use custom_drawable::CustomDrawable;
40
+ pub use custom_drawable::{CustomDrawable, DrawableInvalidator};
41
41
  pub use flex_box::{Border, FlexBox, GradientStop};
42
42
  pub use grid::{Grid, GridTrack};
43
43
  pub(crate) use helpers::*;