mirror of
https://github.com/slint-ui/slint.git
synced 2025-10-02 22:54:36 +00:00

Removed the drop and create from the ComponentVTable: since we are not using VBox<ComponentVTable>, this simplifies a bit the code of the interpreter and everything else. But there is still a lot of changes everywhere to support that the Component is pinned. This is just for the component. Which would be required if later we want to access the properties as Pin<Property<_>>. But we have not yet ability to do projections
394 lines
12 KiB
Rust
394 lines
12 KiB
Rust
//! This module contains the basic datastructures that are exposed to the C API
|
|
|
|
use super::slice::Slice;
|
|
use crate::EvaluationContext;
|
|
use core::pin::Pin;
|
|
use std::cell::Cell;
|
|
use vtable::*;
|
|
|
|
/// 2D Rectangle
|
|
pub type Rect = euclid::default::Rect<f32>;
|
|
/// 2D Point
|
|
pub type Point = euclid::default::Point2D<f32>;
|
|
/// 2D Size
|
|
pub type Size = euclid::default::Size2D<f32>;
|
|
|
|
/// Expand Rect so that cbindgen can see it. ( is in fact euclid::default::Rect<f32>)
|
|
#[cfg(cbindgen)]
|
|
#[repr(C)]
|
|
struct Rect {
|
|
x: f32,
|
|
y: f32,
|
|
width: f32,
|
|
height: f32,
|
|
}
|
|
|
|
/// Expand Point so that cbindgen can see it. ( is in fact euclid::default::PointD2<f32>)
|
|
#[cfg(cbindgen)]
|
|
#[repr(C)]
|
|
struct Point {
|
|
x: f32,
|
|
y: f32,
|
|
}
|
|
|
|
/// A Component is representing an unit that is allocated together
|
|
#[vtable]
|
|
#[repr(C)]
|
|
pub struct ComponentVTable {
|
|
/// Visit the children of the item at index `index`.
|
|
/// Note that the root item is at index 0, so passing 0 would visit the item under root (the children of root).
|
|
/// If you want to visit the root item, you need to pass -1 as an index
|
|
pub visit_children_item: extern "C" fn(
|
|
core::pin::Pin<VRef<ComponentVTable>>,
|
|
index: isize,
|
|
visitor: VRefMut<ItemVisitorVTable>,
|
|
),
|
|
|
|
/// Returns the layout info for this component
|
|
pub layout_info: extern "C" fn(core::pin::Pin<VRef<ComponentVTable>>) -> LayoutInfo,
|
|
|
|
/// Will compute the layout of
|
|
pub compute_layout:
|
|
extern "C" fn(core::pin::Pin<VRef<ComponentVTable>>, eval_context: &EvaluationContext),
|
|
}
|
|
|
|
/// This structure must be present in items that are Rendered and contains information.
|
|
/// Used by the backend.
|
|
#[derive(Default)]
|
|
#[repr(C)]
|
|
pub struct CachedRenderingData {
|
|
/// Used and modified by the backend, should be initialized to 0 by the user code
|
|
pub(crate) cache_index: Cell<usize>,
|
|
/// Set to false initially and when changes happen that require updating the cache
|
|
pub(crate) cache_ok: Cell<bool>,
|
|
}
|
|
|
|
impl CachedRenderingData {
|
|
pub(crate) fn low_level_rendering_primitive<
|
|
'a,
|
|
GraphicsBackend: crate::graphics::GraphicsBackend,
|
|
>(
|
|
&self,
|
|
cache: &'a crate::graphics::RenderingCache<GraphicsBackend>,
|
|
) -> Option<&'a GraphicsBackend::LowLevelRenderingPrimitive> {
|
|
if !self.cache_ok.get() {
|
|
return None;
|
|
}
|
|
Some(cache.entry_at(self.cache_index.get()))
|
|
}
|
|
}
|
|
|
|
/// The item tree is an array of ItemTreeNode representing a static tree of items
|
|
/// within a component.
|
|
#[repr(u8)]
|
|
pub enum ItemTreeNode<T> {
|
|
/// Static item
|
|
Item {
|
|
/// byte offset where we can find the item (from the *ComponentImpl)
|
|
item: vtable::VOffset<T, ItemVTable>,
|
|
|
|
/// number of children
|
|
chilren_count: u32,
|
|
|
|
/// index of the first children within the item tree
|
|
children_index: u32,
|
|
},
|
|
/// A placeholder for many instance of item in their own component which
|
|
/// are instentiated according to a model.
|
|
DynamicTree {
|
|
/// the undex which is passed in the visit_dynamic callback.
|
|
index: usize,
|
|
},
|
|
}
|
|
|
|
/// Items are the nodes in the render tree.
|
|
#[vtable]
|
|
#[repr(C)]
|
|
pub struct ItemVTable {
|
|
/// Returns the geometry of this item (relative to its parent item)
|
|
pub geometry: extern "C" fn(VRef<'_, ItemVTable>, context: &crate::EvaluationContext) -> Rect,
|
|
|
|
/// offset in bytes fromthe *const ItemImpl.
|
|
/// isize::MAX means None
|
|
#[allow(non_upper_case_globals)]
|
|
#[offset(CachedRenderingData)]
|
|
pub cached_rendering_data_offset: usize,
|
|
|
|
/// Return the rendering primitive used to display this item.
|
|
pub rendering_primitive: extern "C" fn(
|
|
VRef<'_, ItemVTable>,
|
|
context: &crate::EvaluationContext,
|
|
) -> RenderingPrimitive,
|
|
|
|
/// We would need max/min/preferred size, and all layout info
|
|
pub layouting_info: extern "C" fn(VRef<'_, ItemVTable>) -> LayoutInfo,
|
|
|
|
/// input event
|
|
pub input_event: extern "C" fn(VRef<'_, ItemVTable>, MouseEvent, &crate::EvaluationContext),
|
|
}
|
|
|
|
/// The constraint that applies to an item
|
|
#[repr(C)]
|
|
#[derive(Clone)]
|
|
pub struct LayoutInfo {
|
|
min_width: f32,
|
|
max_width: f32,
|
|
min_height: f32,
|
|
max_height: f32,
|
|
}
|
|
|
|
impl Default for LayoutInfo {
|
|
fn default() -> Self {
|
|
LayoutInfo { min_width: 0., max_width: f32::MAX, min_height: 0., max_height: f32::MAX }
|
|
}
|
|
}
|
|
|
|
/// RGBA color
|
|
#[derive(Copy, Clone, PartialEq, Debug)]
|
|
#[repr(C)]
|
|
pub struct Color {
|
|
red: u8,
|
|
green: u8,
|
|
blue: u8,
|
|
alpha: u8,
|
|
}
|
|
|
|
impl Color {
|
|
/// Construct a color from an integer encoded as `0xAARRGGBB`
|
|
pub const fn from_argb_encoded(encoded: u32) -> Color {
|
|
Color {
|
|
red: (encoded >> 16) as u8,
|
|
green: (encoded >> 8) as u8,
|
|
blue: encoded as u8,
|
|
alpha: (encoded >> 24) as u8,
|
|
}
|
|
}
|
|
|
|
/// Construct a color from its RGBA components as u8
|
|
pub const fn from_rgba(red: u8, green: u8, blue: u8, alpha: u8) -> Color {
|
|
Color { red, green, blue, alpha }
|
|
}
|
|
/// Construct a color from its RGB components as u8
|
|
pub const fn from_rgb(red: u8, green: u8, blue: u8) -> Color {
|
|
Color::from_rgba(red, green, blue, 0xff)
|
|
}
|
|
|
|
/// Returns `(red, green, blue, alpha)` encoded as f32
|
|
pub fn as_rgba_f32(&self) -> (f32, f32, f32, f32) {
|
|
(
|
|
(self.red as f32) / 255.0,
|
|
(self.green as f32) / 255.0,
|
|
(self.blue as f32) / 255.0,
|
|
(self.alpha as f32) / 255.0,
|
|
)
|
|
}
|
|
|
|
/// Returns `(red, green, blue, alpha)` encoded as u8
|
|
pub fn as_rgba_u8(&self) -> (u8, u8, u8, u8) {
|
|
(self.red, self.green, self.blue, self.alpha)
|
|
}
|
|
|
|
/// A constant for the black color
|
|
pub const BLACK: Color = Color::from_rgb(0, 0, 0);
|
|
/// A constant for the white color
|
|
pub const WHITE: Color = Color::from_rgb(255, 255, 255);
|
|
}
|
|
|
|
/// A resource is a reference to binary data, for example images. They can be accessible on the file
|
|
/// system or embedded in the resulting binary. Or they might be URLs to a web server and a downloaded
|
|
/// is necessary before they can be used.
|
|
#[derive(Clone, PartialEq, Debug)]
|
|
#[repr(u8)]
|
|
pub enum Resource {
|
|
/// A resource that does not represent any data.
|
|
None,
|
|
/// A resource that points to a file in the file system
|
|
AbsoluteFilePath(crate::SharedString),
|
|
/// A resource that is embedded in the program and accessible via pointer
|
|
EmbeddedData(super::slice::Slice<'static, u8>),
|
|
}
|
|
|
|
impl Default for Resource {
|
|
fn default() -> Self {
|
|
Resource::None
|
|
}
|
|
}
|
|
|
|
/// Each item return a RenderingPrimitive to the backend with information about what to draw.
|
|
#[derive(PartialEq, Debug)]
|
|
#[repr(C)]
|
|
#[allow(missing_docs)]
|
|
pub enum RenderingPrimitive {
|
|
/// There is nothing to draw
|
|
NoContents,
|
|
Rectangle {
|
|
x: f32,
|
|
y: f32,
|
|
width: f32,
|
|
height: f32,
|
|
color: Color,
|
|
},
|
|
Image {
|
|
x: f32,
|
|
y: f32,
|
|
source: crate::Resource,
|
|
},
|
|
Text {
|
|
x: f32,
|
|
y: f32,
|
|
text: crate::SharedString,
|
|
font_family: crate::SharedString,
|
|
font_pixel_size: f32,
|
|
color: Color,
|
|
},
|
|
}
|
|
|
|
/// The type of a MouseEvent
|
|
#[repr(C)]
|
|
#[derive(Debug, Clone, Copy)]
|
|
pub enum MouseEventType {
|
|
/// The mouse was pressed
|
|
MousePressed,
|
|
/// The mouse was relased
|
|
MouseReleased,
|
|
/// The mouse position has changed
|
|
MouseMoved,
|
|
}
|
|
|
|
/// Structur representing a mouse event
|
|
#[repr(C)]
|
|
#[derive(Debug, Clone, Copy)]
|
|
pub struct MouseEvent {
|
|
/// The position of the cursor
|
|
pub pos: Point,
|
|
/// The action performed (pressed/released/moced)
|
|
pub what: MouseEventType,
|
|
}
|
|
|
|
/// The ComponentWindow is the (rust) facing public type that can render the items
|
|
/// of components to the screen.
|
|
#[repr(C)]
|
|
#[derive(Clone)]
|
|
pub struct ComponentWindow(std::rc::Rc<dyn crate::eventloop::GenericWindow>);
|
|
|
|
impl ComponentWindow {
|
|
/// Creates a new instance of a CompomentWindow based on the given window implementation. Only used
|
|
/// internally.
|
|
pub fn new(window_impl: std::rc::Rc<dyn crate::eventloop::GenericWindow>) -> Self {
|
|
Self(window_impl)
|
|
}
|
|
/// Spins an event loop and renders the items of the provided component in this window.
|
|
pub fn run(&self, component: Pin<VRef<ComponentVTable>>) {
|
|
let event_loop = crate::eventloop::EventLoop::new();
|
|
self.0.clone().map_window(&event_loop);
|
|
|
|
event_loop.run(component);
|
|
}
|
|
}
|
|
|
|
#[allow(non_camel_case_types)]
|
|
type c_void = ();
|
|
|
|
/// Same layout as ComponentWindow (fat pointer)
|
|
#[repr(C)]
|
|
pub struct ComponentWindowOpaque(*const c_void, *const c_void);
|
|
|
|
/// Releases the reference to the component window held by handle.
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn sixtyfps_component_window_drop(handle: *mut ComponentWindowOpaque) {
|
|
println!("sixtyfps_component_window_drop()");
|
|
assert_eq!(
|
|
core::mem::size_of::<ComponentWindow>(),
|
|
core::mem::size_of::<ComponentWindowOpaque>()
|
|
);
|
|
core::ptr::read(handle as *mut ComponentWindow);
|
|
}
|
|
|
|
/// Spins an event loop and renders the items of the provided component in this window.
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn sixtyfps_component_window_run(
|
|
handle: *mut ComponentWindowOpaque,
|
|
component: Pin<VRef<ComponentVTable>>,
|
|
) {
|
|
let window = &*(handle as *const ComponentWindow);
|
|
window.run(component);
|
|
}
|
|
|
|
#[repr(C)]
|
|
#[vtable]
|
|
/// Object to be passed in visit_item_children method of the Component.
|
|
pub struct ItemVisitorVTable {
|
|
/// Called for each children of the visited item
|
|
///
|
|
/// The `component` parameter is the component in which the item live which might not be the same
|
|
/// as the parent's component.
|
|
/// `index` is to be used again in the visit_item_children function of the Component (the one passed as parameter)
|
|
/// and `item` is a reference to the item itself
|
|
visit_item: fn(
|
|
VRefMut<ItemVisitorVTable>,
|
|
component: Pin<VRef<ComponentVTable>>,
|
|
index: isize,
|
|
item: VRef<ItemVTable>,
|
|
),
|
|
/// Destructor
|
|
drop: fn(VRefMut<ItemVisitorVTable>),
|
|
}
|
|
|
|
impl<T: FnMut(crate::ComponentRefPin, isize, VRef<ItemVTable>)> ItemVisitor for T {
|
|
fn visit_item(
|
|
&mut self,
|
|
component: crate::ComponentRefPin,
|
|
index: isize,
|
|
item: VRef<ItemVTable>,
|
|
) {
|
|
self(component, index, item)
|
|
}
|
|
}
|
|
|
|
/// Expose `crate::item_tree::visit_item_tree` to C++
|
|
///
|
|
/// Safety: Assume a correct implementation of the item_tree array
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn sixtyfps_visit_item_tree(
|
|
component: Pin<VRef<ComponentVTable>>,
|
|
item_tree: Slice<ItemTreeNode<u8>>,
|
|
index: isize,
|
|
visitor: VRefMut<ItemVisitorVTable>,
|
|
visit_dynamic: extern "C" fn(
|
|
base: &u8,
|
|
visitor: vtable::VRefMut<ItemVisitorVTable>,
|
|
dyn_index: usize,
|
|
),
|
|
) {
|
|
crate::item_tree::visit_item_tree(
|
|
&*(component.as_ptr() as *const u8),
|
|
component,
|
|
item_tree.as_slice(),
|
|
index,
|
|
visitor,
|
|
|a, b, c| visit_dynamic(a, b, c),
|
|
)
|
|
}
|
|
|
|
// This is here because for some reason (rust bug?) the ItemVTable_static is not accessible in the other modules
|
|
|
|
ItemVTable_static! {
|
|
/// The VTable for `Image`
|
|
#[no_mangle]
|
|
pub static ImageVTable for crate::abi::primitives::Image
|
|
}
|
|
ItemVTable_static! {
|
|
/// The VTable for `Rectangle`
|
|
#[no_mangle]
|
|
pub static RectangleVTable for crate::abi::primitives::Rectangle
|
|
}
|
|
ItemVTable_static! {
|
|
/// The VTable for `Text`
|
|
#[no_mangle]
|
|
pub static TextVTable for crate::abi::primitives::Text
|
|
}
|
|
ItemVTable_static! {
|
|
/// The VTable for `TouchArea`
|
|
#[no_mangle]
|
|
pub static TouchAreaVTable for crate::abi::primitives::TouchArea
|
|
}
|