mirror of
https://github.com/slint-ui/slint.git
synced 2025-10-03 23:24:34 +00:00
216 lines
4.7 KiB
Rust
216 lines
4.7 KiB
Rust
/// The opaque component type
|
|
type ComponentImpl = ();
|
|
|
|
#[repr(C)]
|
|
pub struct ComponentType {
|
|
/// Allocate an instance of this component
|
|
create: fn(*const ComponentType) -> *mut ComponentImpl,
|
|
|
|
/// destruct this component
|
|
destroy: fn(*const ComponentType, *mut ComponentImpl),
|
|
|
|
/// Returns an array that represent the item tree
|
|
/// FIXME: dynamic items
|
|
item_tree: fn(*const ComponentType) -> *const ItemTreeNode,
|
|
}
|
|
|
|
/// From the ItemTreeNode and a ComponentImpl, you can get a pointer to the instance data
|
|
/// ItemImpl via the offset field.
|
|
type ItemImpl = ();
|
|
// Example memory representation:
|
|
// offset| type | value
|
|
// 0 | f32 | x
|
|
// 4 | f32 | y
|
|
// ...
|
|
// 64 | RenderNode | render node index
|
|
|
|
#[repr(C)]
|
|
pub struct RenderNode {
|
|
/// Used and modified by the backend, should be initialized to 0 by the user code
|
|
cache_index: core::cell::Cell<usize>,
|
|
/// Set to true by the user code, and reset to false by the backend
|
|
dirty_bit: core::cell::Cell<bool>,
|
|
}
|
|
|
|
#[repr(C)]
|
|
pub struct ItemTreeNode {
|
|
/// byte offset where we can find the item (from the *ComponentImpl)
|
|
offset: isize,
|
|
/// virtual table of the item
|
|
vtable: *const ItemVTable,
|
|
|
|
/// number of children
|
|
chilren_count: u32,
|
|
|
|
/// index of the first children
|
|
children_index: u32,
|
|
}
|
|
|
|
#[repr(C)]
|
|
#[derive(Default)]
|
|
pub struct ItemVTable {
|
|
// Rectangle: x/y/width/height ==> (path -> vertices/indicies(triangle))
|
|
pub geometry: Option<fn(*const ItemImpl) -> ()>, // like kurbo::Rect
|
|
|
|
// offset in bytes fromthe *const ItemImpl
|
|
pub render_node_index_offset: Option<usize>,
|
|
// fn(*const ItemImpl) -> usize,
|
|
|
|
// ???
|
|
pub rendering_info: Option<fn(*const ItemImpl) -> RenderingInfo>,
|
|
|
|
/// We would need max/min/preferred size, and all layout info
|
|
pub layouting_info: Option<fn(*const ItemImpl) -> LayoutInfo>,
|
|
|
|
/// input event
|
|
pub input_event: Option<fn(*const ItemImpl, MouseEvent)>,
|
|
}
|
|
|
|
// given an ItemImpl & ItemVTable
|
|
// (1) Identify that the item *is* a rectangle or has everything a rectangle would have
|
|
// (2) change the width
|
|
|
|
#[repr(C)]
|
|
pub struct LayoutInfo {
|
|
min_size: f32,
|
|
//...
|
|
width_offset: isize,
|
|
}
|
|
|
|
#[repr(C)]
|
|
pub enum RenderingInfo {
|
|
NoContents,
|
|
/*Path(Vec<PathElement>),
|
|
Image(OpaqueImageHandle, AspectRatio),
|
|
Text(String)*/
|
|
}
|
|
|
|
type MouseEvent = ();
|
|
/*
|
|
|
|
/*
|
|
Button { visible: false; text: "foo"}
|
|
|
|
-> ProxyWithVisibility<NativeItem>
|
|
|
|
// Qt style selected:
|
|
fn render_button(item: *const ItemImpl) -> RenderingInfo {
|
|
let button = reinterpret_cast<&Button>(button)
|
|
let text = b.text();
|
|
let isPressed = b.isPressed();
|
|
// ...
|
|
let image = qt_render_button(width, height, isPressed, text)
|
|
|
|
return RenderingInfo::Image(image)
|
|
}
|
|
|
|
// Basic style selected:
|
|
|
|
-> Rectangle / Text
|
|
|
|
fn render_rectangle(item: *const ItemImpl) -> RenderingInfo {
|
|
let rect = reinterpret_cast<&Rectangle>(item)
|
|
...
|
|
return RenderingInfo::Path(rect_path)
|
|
}
|
|
|
|
fn render_text(item: *const ItemImpl) -> RenderInfo {
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
// in corelib/primitives.rs
|
|
|
|
bitflags! {
|
|
enum ItemExtensions {
|
|
HasVisibility,
|
|
HasOpacity
|
|
}
|
|
}
|
|
|
|
struct ItemBase {
|
|
extensions: ItemExtensions,
|
|
x: Property<f32>,
|
|
y: Property<f32>,
|
|
// visible, opacity, ?
|
|
extraData: Vec<...>
|
|
}
|
|
|
|
impl ItemBase {
|
|
pub fn is_visible(&self) -> bool {
|
|
if self.extensions & HasVisibility {
|
|
return self.extraData
|
|
} else {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(SixtyFpsItem)]
|
|
/// ```
|
|
/// width: f32
|
|
/// height: f32
|
|
/// ```
|
|
fn render_rectangle(item: *const ItemImpl) -> RenderingInfo {
|
|
//let width = property_at_offset(item, 1);
|
|
let rect : &Rectnalge = unsafe { std::mem::transmute(item) };
|
|
let width = rect.width.get()
|
|
}
|
|
|
|
//#[derive(SixtyFpsItem)]
|
|
struct Rectangle {
|
|
base: ItemBase,
|
|
width: Property<f32>,
|
|
height: Property<f32>,
|
|
radius: Property<f32>,
|
|
}
|
|
|
|
/// fn rect_from_item(item: *const ItemImpl) -> *const Rectangle {
|
|
/// reinterpet_cast<const Rectangle *>(reinterpret_cast<char *>(item) + ... some offset))
|
|
///}
|
|
|
|
pub static RECTANGLE_VTABLE: ItemVTable = ItemVTable {
|
|
rendering_info: render_rectangle,
|
|
}
|
|
|
|
// in styles/qt.rs
|
|
|
|
//#[derive(SixtyFpsItem)]
|
|
struct QtButton {
|
|
text: String,
|
|
is_pressed: bool,
|
|
}
|
|
|
|
|
|
pub static QT_BUTTON_VTABLE: ItemVTable = ItemVTable {
|
|
rendering_info: render_qt_button,
|
|
};
|
|
|
|
// Button { text: "hello "}
|
|
const GENERATED : &str = r#"
|
|
#include <qtstyle.h>
|
|
/*
|
|
// generated with cbindgen
|
|
struct QtButton { String text; bool is_pressed };
|
|
*/
|
|
|
|
struct MyGeneratedComponent {
|
|
QtButton button;
|
|
|
|
MyGeneratedComponent() {
|
|
button.text = "hello"
|
|
}
|
|
};
|
|
|
|
ItemTreeNode array[] = {
|
|
{ 0, &QT_BUTTON_VTABLE, 0, 0 }
|
|
}
|
|
|
|
main() {
|
|
MyGeneratedComponent foo;
|
|
sixtyfps_runtime::run(&foo, ComponentType{ nullptr, nullptr, []{return array} })
|
|
}
|
|
|
|
"#
|
|
*/
|