mirror of
https://github.com/darkrenaissance/darkfi.git
synced 2026-04-28 03:00:18 -04:00
wallet: add Property wrapper types, and begin prelim selection code
This commit is contained in:
@@ -507,6 +507,15 @@ def draw():
|
||||
|
||||
node_id = api.add_node("editz", SceneNodeType.EDIT_BOX)
|
||||
|
||||
prop = Property(
|
||||
"is_active", PropertyType.BOOL, PropertySubType.NULL,
|
||||
None,
|
||||
"Is Active", "Whether the editbox is active",
|
||||
False, True, 1, None, None, []
|
||||
)
|
||||
api.add_property(node_id, prop)
|
||||
api.set_property_bool(node_id, "is_active", 0, True)
|
||||
|
||||
prop = Property(
|
||||
"rect", PropertyType.FLOAT32, PropertySubType.PIXEL,
|
||||
None,
|
||||
@@ -563,16 +572,38 @@ def draw():
|
||||
api.set_property_str(node_id, "text", 0, "hello king!😁🍆jelly 🍆1234")
|
||||
|
||||
prop = Property(
|
||||
"color", PropertyType.FLOAT32, PropertySubType.COLOR,
|
||||
"text_color", PropertyType.FLOAT32, PropertySubType.COLOR,
|
||||
None,
|
||||
"Color", "Color of the text",
|
||||
"Text Color", "Color of the text",
|
||||
False, False, 4, 0, 1, []
|
||||
)
|
||||
api.add_property(node_id, prop)
|
||||
api.set_property_f32(node_id, "color", 0, 1)
|
||||
api.set_property_f32(node_id, "color", 1, 1)
|
||||
api.set_property_f32(node_id, "color", 2, 1)
|
||||
api.set_property_f32(node_id, "color", 3, 1)
|
||||
api.set_property_f32(node_id, "text_color", 0, 1)
|
||||
api.set_property_f32(node_id, "text_color", 1, 1)
|
||||
api.set_property_f32(node_id, "text_color", 2, 1)
|
||||
api.set_property_f32(node_id, "text_color", 3, 1)
|
||||
|
||||
prop = Property(
|
||||
"hi_bg_color", PropertyType.FLOAT32, PropertySubType.COLOR,
|
||||
None,
|
||||
"Highlight Bg Color", "Background color for highlighted text",
|
||||
False, False, 4, 0, 1, []
|
||||
)
|
||||
api.add_property(node_id, prop)
|
||||
api.set_property_f32(node_id, "hi_bg_color", 0, 1)
|
||||
api.set_property_f32(node_id, "hi_bg_color", 1, 1)
|
||||
api.set_property_f32(node_id, "hi_bg_color", 2, 1)
|
||||
api.set_property_f32(node_id, "hi_bg_color", 3, 0.5)
|
||||
|
||||
prop = Property(
|
||||
"selected", PropertyType.UINT32, PropertySubType.NULL,
|
||||
None,
|
||||
"Selected", "Selected range",
|
||||
True, False, 2, 0, None, []
|
||||
)
|
||||
api.add_property(node_id, prop)
|
||||
api.set_property_u32(node_id, "selected", 0, 1)
|
||||
api.set_property_u32(node_id, "selected", 1, 4)
|
||||
|
||||
prop = Property(
|
||||
"z_index", PropertyType.UINT32, PropertySubType.NULL,
|
||||
|
||||
@@ -1,20 +1,29 @@
|
||||
use miniquad::{KeyMods, UniformType};
|
||||
use miniquad::{KeyMods, UniformType, MouseButton};
|
||||
use std::{io::Cursor, sync::{Arc, Mutex}};
|
||||
use darkfi_serial::Decodable;
|
||||
use freetype as ft;
|
||||
|
||||
use crate::{error::{Error, Result}, prop::Property, scene::{SceneGraph, SceneNodeId, Pimpl, Slot}, gfx::{Rectangle, RenderContext, COLOR_WHITE, COLOR_BLUE, COLOR_RED, COLOR_GREEN, FreetypeFace}, text::{Glyph, TextShaper}};
|
||||
use crate::{error::{Error, Result}, prop::{
|
||||
PropertyBool, PropertyFloat32, PropertyUint32, PropertyStr, PropertyColor,
|
||||
Property}, scene::{SceneGraph, SceneNode, SceneNodeId, Pimpl, Slot}, gfx::{Rectangle, RenderContext, COLOR_WHITE, COLOR_BLUE, COLOR_RED, COLOR_GREEN, FreetypeFace, Point}, text::{Glyph, TextShaper}, keysym::{MouseButtonAsU8, KeyCodeAsU16}};
|
||||
|
||||
const CURSOR_WIDTH: f32 = 4.;
|
||||
|
||||
pub type EditBoxPtr = Arc<EditBox>;
|
||||
|
||||
pub struct EditBox {
|
||||
scroll: Arc<Property>,
|
||||
cursor_pos: Arc<Property>,
|
||||
text: Arc<Property>,
|
||||
font_size: Arc<Property>,
|
||||
color: Arc<Property>,
|
||||
is_active: PropertyBool,
|
||||
debug: PropertyBool,
|
||||
baseline: PropertyFloat32,
|
||||
scroll: PropertyFloat32,
|
||||
cursor_pos: PropertyUint32,
|
||||
selected: Arc<Property>,
|
||||
text: PropertyStr,
|
||||
font_size: PropertyFloat32,
|
||||
text_color: PropertyColor,
|
||||
hi_bg_color: PropertyColor,
|
||||
// Used for mouse clicks
|
||||
world_rect: Mutex<Rectangle<f32>>,
|
||||
glyphs: Mutex<Vec<Glyph>>,
|
||||
text_shaper: TextShaper,
|
||||
}
|
||||
@@ -22,32 +31,40 @@ pub struct EditBox {
|
||||
impl EditBox {
|
||||
pub fn new(scene_graph: &mut SceneGraph, node_id: SceneNodeId, font_faces: Vec<FreetypeFace>) -> Result<Pimpl> {
|
||||
let node = scene_graph.get_node(node_id).unwrap();
|
||||
let scroll = node.get_property("scroll").ok_or(Error::PropertyNotFound)?;
|
||||
let cursor_pos = node.get_property("cursor_pos").ok_or(Error::PropertyNotFound)?;
|
||||
let text = node.get_property("text").ok_or(Error::PropertyNotFound)?;
|
||||
let font_size = node.get_property("font_size").ok_or(Error::PropertyNotFound)?;
|
||||
let color = node.get_property("color").ok_or(Error::PropertyNotFound)?;
|
||||
let is_active = PropertyBool::wrap(node, "is_active", 0)?;
|
||||
let debug = PropertyBool::wrap(node, "debug", 0)?;
|
||||
let baseline = PropertyFloat32::wrap(node, "baseline", 0)?;
|
||||
let scroll = PropertyFloat32::wrap(node, "scroll", 0)?;
|
||||
let cursor_pos = PropertyUint32::wrap(node, "cursor_pos", 0)?;
|
||||
let selected = node.get_property("selected").ok_or(Error::PropertyNotFound)?;
|
||||
let text = PropertyStr::wrap(node, "text", 0)?;
|
||||
let font_size = PropertyFloat32::wrap(node, "font_size", 0)?;
|
||||
let text_color = PropertyColor::wrap(node, "text_color")?;
|
||||
let hi_bg_color = PropertyColor::wrap(node, "hi_bg_color")?;
|
||||
|
||||
let text_shaper = TextShaper {
|
||||
font_faces
|
||||
};
|
||||
|
||||
let glyphs = text_shaper.shape(text.get_str(0)?, font_size.get_f32(0)?,
|
||||
[color.get_f32(0)?, color.get_f32(1)?,
|
||||
color.get_f32(2)?, color.get_f32(3)?]);
|
||||
|
||||
println!("EditBox::new()");
|
||||
let self_ = Arc::new(Self{
|
||||
is_active,
|
||||
debug,
|
||||
baseline,
|
||||
scroll,
|
||||
cursor_pos,
|
||||
selected,
|
||||
text,
|
||||
font_size,
|
||||
color,
|
||||
glyphs: Mutex::new(glyphs),
|
||||
text_color,
|
||||
hi_bg_color,
|
||||
world_rect: Mutex::new(Rectangle { x: 0., y: 0., w: 0., h: 0. }),
|
||||
glyphs: Mutex::new(vec![]),
|
||||
text_shaper,
|
||||
});
|
||||
let weak_self = Arc::downgrade(&self_);
|
||||
self_.regen_glyphs().unwrap();
|
||||
|
||||
let weak_self = Arc::downgrade(&self_);
|
||||
let slot = Slot {
|
||||
name: "editbox::key_down".to_string(),
|
||||
func: Box::new(move |data| {
|
||||
@@ -74,15 +91,76 @@ impl EditBox {
|
||||
.expect("no keyboard attached!");
|
||||
keyb_node.register("key_down", slot);
|
||||
|
||||
let weak_self = Arc::downgrade(&self_);
|
||||
let slot_btn_down = Slot {
|
||||
name: "editbox::mouse_button_down".to_string(),
|
||||
func: Box::new(move |data| {
|
||||
let mut cur = Cursor::new(&data);
|
||||
let button = MouseButton::from_u8(u8::decode(&mut cur).unwrap());
|
||||
let x = f32::decode(&mut cur).unwrap();
|
||||
let y = f32::decode(&mut cur).unwrap();
|
||||
|
||||
let self_ = weak_self.upgrade();
|
||||
if let Some(self_) = self_ {
|
||||
self_.mouse_button_down(button, x, y);
|
||||
}
|
||||
}),
|
||||
};
|
||||
|
||||
let weak_self = Arc::downgrade(&self_);
|
||||
let slot_btn_up = Slot {
|
||||
name: "editbox::mouse_button_up".to_string(),
|
||||
func: Box::new(move |data| {
|
||||
let mut cur = Cursor::new(&data);
|
||||
let button = MouseButton::from_u8(u8::decode(&mut cur).unwrap());
|
||||
let x = f32::decode(&mut cur).unwrap();
|
||||
let y = f32::decode(&mut cur).unwrap();
|
||||
|
||||
let self_ = weak_self.upgrade();
|
||||
if let Some(self_) = self_ {
|
||||
self_.mouse_button_up(button, x, y);
|
||||
}
|
||||
}),
|
||||
};
|
||||
|
||||
let weak_self = Arc::downgrade(&self_);
|
||||
let slot_move = Slot {
|
||||
name: "editbox::mouse_move".to_string(),
|
||||
func: Box::new(move |data| {
|
||||
let mut cur = Cursor::new(&data);
|
||||
let x = f32::decode(&mut cur).unwrap();
|
||||
let y = f32::decode(&mut cur).unwrap();
|
||||
|
||||
let self_ = weak_self.upgrade();
|
||||
if let Some(self_) = self_ {
|
||||
self_.mouse_move(x, y);
|
||||
}
|
||||
}),
|
||||
};
|
||||
|
||||
let mouse_node =
|
||||
scene_graph
|
||||
.lookup_node_mut("/window/input/mouse")
|
||||
.expect("no mouse attached!");
|
||||
mouse_node.register("button_down", slot_btn_down);
|
||||
mouse_node.register("button_up", slot_btn_up);
|
||||
mouse_node.register("move", slot_move);
|
||||
|
||||
// Save any properties we use
|
||||
Ok(Pimpl::EditBox(self_))
|
||||
}
|
||||
|
||||
pub fn render<'a>(&self, render: &mut RenderContext<'a>, node_id: SceneNodeId, layer_rect: &Rectangle<i32>) -> Result<()> {
|
||||
pub fn render<'a>(&self, render: &mut RenderContext<'a>, node_id: SceneNodeId, layer_rect: &Rectangle<f32>) -> Result<()> {
|
||||
let node = render.scene_graph.get_node(node_id).unwrap();
|
||||
|
||||
let rect = RenderContext::get_dim(node, layer_rect)?;
|
||||
|
||||
// Used for detecting mouse clicks
|
||||
let mut world_rect = rect.clone();
|
||||
world_rect.x += layer_rect.x as f32;
|
||||
world_rect.y += layer_rect.y as f32;
|
||||
*self.world_rect.lock().unwrap() = world_rect;
|
||||
|
||||
let layer_w = layer_rect.w as f32;
|
||||
let layer_h = layer_rect.h as f32;
|
||||
let off_x = rect.x / layer_w;
|
||||
@@ -106,24 +184,20 @@ impl EditBox {
|
||||
self.apply_cursor_scrolling(&rect);
|
||||
|
||||
let node = render.scene_graph.get_node(node_id).unwrap();
|
||||
let text = node.get_property_str("text")?;
|
||||
let font_size = node.get_property_f32("font_size")?;
|
||||
let debug = node.get_property_bool("debug")?;
|
||||
let baseline = node.get_property_f32("baseline")?;
|
||||
let scroll = node.get_property_f32("scroll")?;
|
||||
let cursor_pos = node.get_property_u32("cursor_pos")?;
|
||||
let debug = self.debug.get();
|
||||
let baseline = self.baseline.get();
|
||||
let scroll = self.scroll.get();
|
||||
let cursor_pos = self.cursor_pos.get() as usize;
|
||||
|
||||
let color_prop = node.get_property("color").ok_or(Error::PropertyNotFound)?;
|
||||
let color_r = color_prop.get_f32(0)?;
|
||||
let color_g = color_prop.get_f32(1)?;
|
||||
let color_b = color_prop.get_f32(2)?;
|
||||
let color_a = color_prop.get_f32(3)?;
|
||||
let text_color = [color_r, color_g, color_b, color_a];
|
||||
let color = node.get_property("text_color").ok_or(Error::PropertyNotFound)?;
|
||||
let text_color = self.text_color.get();
|
||||
|
||||
if !self.selected.is_null(0)? && !self.selected.is_null(1)? {
|
||||
self.render_selected(render, &rect)?;
|
||||
}
|
||||
|
||||
let mut glyph_idx = 0;
|
||||
let mut rhs = 0.;
|
||||
|
||||
for glyph in &*self.glyphs.lock().unwrap() {
|
||||
for (glyph_idx, glyph) in self.glyphs.lock().unwrap().iter().enumerate() {
|
||||
let texture = render.ctx.new_texture_from_rgba8(glyph.bmp_width, glyph.bmp_height, &glyph.bmp);
|
||||
|
||||
let x1 = glyph.pos.x + scroll;
|
||||
@@ -150,8 +224,6 @@ impl EditBox {
|
||||
render.render_box(x2, 0., x2 + CURSOR_WIDTH, rect.h, cursor_color);
|
||||
}
|
||||
|
||||
glyph_idx += 1;
|
||||
|
||||
rhs = x2;
|
||||
}
|
||||
|
||||
@@ -168,9 +240,35 @@ impl EditBox {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn apply_cursor_scrolling(&self, rect: &Rectangle<f32>) -> Result<()> {
|
||||
let cursor_pos = self.cursor_pos.get_u32(0)? as usize;
|
||||
let mut scroll = self.scroll.get_f32(0)?;
|
||||
pub fn render_selected<'a>(&self, render: &mut RenderContext<'a>, rect: &Rectangle<f32>) -> Result<()> {
|
||||
let sel_start = self.selected.get_u32(0)? as usize;
|
||||
let sel_end = self.selected.get_u32(1)? as usize;
|
||||
assert!(sel_start <= sel_end);
|
||||
let scroll = self.scroll.get();
|
||||
let hi_bg_color = self.hi_bg_color.get();
|
||||
|
||||
let mut start_x = 0.;
|
||||
let mut end_x = 0.;
|
||||
|
||||
for (glyph_idx, glyph) in self.glyphs.lock().unwrap().iter().enumerate() {
|
||||
let x1 = glyph.pos.x + scroll;
|
||||
let x2 = x1 + glyph.pos.w;
|
||||
|
||||
if glyph_idx == sel_start {
|
||||
start_x = x1;
|
||||
}
|
||||
if glyph_idx == sel_end {
|
||||
end_x = x2;
|
||||
}
|
||||
}
|
||||
|
||||
render.render_box(start_x, 0., end_x, rect.h, hi_bg_color);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn apply_cursor_scrolling(&self, rect: &Rectangle<f32>) {
|
||||
let cursor_pos = self.cursor_pos.get() as usize;
|
||||
let mut scroll = self.scroll.get();
|
||||
|
||||
let cursor_x = {
|
||||
let glyphs = &*self.glyphs.lock().unwrap();
|
||||
@@ -189,13 +287,12 @@ impl EditBox {
|
||||
scroll = -cursor_x;
|
||||
}
|
||||
|
||||
self.scroll.set_f32(0, scroll)
|
||||
self.scroll.set(scroll);
|
||||
}
|
||||
|
||||
fn regen_glyphs(&self) -> Result<()> {
|
||||
let glyphs = self.text_shaper.shape(self.text.get_str(0)?, self.font_size.get_f32(0)?,
|
||||
[self.color.get_f32(0)?, self.color.get_f32(1)?,
|
||||
self.color.get_f32(2)?, self.color.get_f32(3)?]);
|
||||
let glyphs = self.text_shaper.shape(self.text.get(), self.font_size.get(),
|
||||
self.text_color.get());
|
||||
*self.glyphs.lock().unwrap() = glyphs;
|
||||
Ok(())
|
||||
}
|
||||
@@ -204,6 +301,9 @@ impl EditBox {
|
||||
if repeat {
|
||||
return;
|
||||
}
|
||||
if !self.is_active.get() {
|
||||
return
|
||||
}
|
||||
match key.as_str() {
|
||||
"PageUp" => {
|
||||
println!("pageup!");
|
||||
@@ -212,20 +312,44 @@ impl EditBox {
|
||||
println!("pagedown!");
|
||||
}
|
||||
"Left" => {
|
||||
let cursor_pos = self.cursor_pos.get_u32(0).unwrap();
|
||||
let mut cursor_pos = self.cursor_pos.get();
|
||||
if cursor_pos > 0 {
|
||||
self.cursor_pos.set_u32(0, cursor_pos - 1).unwrap();
|
||||
cursor_pos -= 1;
|
||||
self.cursor_pos.set(cursor_pos);
|
||||
}
|
||||
|
||||
if !mods.shift {
|
||||
self.selected.set_null(0).unwrap();
|
||||
self.selected.set_null(1).unwrap();
|
||||
} else {
|
||||
if self.selected.is_null(0).unwrap() {
|
||||
assert!(self.selected.is_null(1).unwrap());
|
||||
self.selected.set_u32(0, cursor_pos).unwrap();
|
||||
}
|
||||
self.selected.set_u32(1, cursor_pos).unwrap();
|
||||
}
|
||||
}
|
||||
"Right" => {
|
||||
let cursor_pos = self.cursor_pos.get_u32(0).unwrap();
|
||||
let mut cursor_pos = self.cursor_pos.get();
|
||||
let glyphs_len = self.glyphs.lock().unwrap().len() as u32;
|
||||
if cursor_pos < glyphs_len {
|
||||
self.cursor_pos.set_u32(0, cursor_pos + 1).unwrap();
|
||||
cursor_pos += 1;
|
||||
self.cursor_pos.set(cursor_pos);
|
||||
}
|
||||
|
||||
if !mods.shift {
|
||||
self.selected.set_null(0).unwrap();
|
||||
self.selected.set_null(1).unwrap();
|
||||
} else {
|
||||
if self.selected.is_null(0).unwrap() {
|
||||
assert!(self.selected.is_null(1).unwrap());
|
||||
self.selected.set_u32(1, cursor_pos).unwrap();
|
||||
}
|
||||
self.selected.set_u32(1, cursor_pos).unwrap();
|
||||
}
|
||||
}
|
||||
"Delete" => {
|
||||
let cursor_pos = self.cursor_pos.get_u32(0).unwrap();
|
||||
let cursor_pos = self.cursor_pos.get();
|
||||
if cursor_pos == 0 {
|
||||
return;
|
||||
}
|
||||
@@ -240,11 +364,11 @@ impl EditBox {
|
||||
}
|
||||
text.push_str(&substr);
|
||||
}
|
||||
self.text.set_str(0, text).unwrap();
|
||||
self.text.set(text);
|
||||
self.regen_glyphs().unwrap();
|
||||
}
|
||||
"Backspace" => {
|
||||
let cursor_pos = self.cursor_pos.get_u32(0).unwrap();
|
||||
let cursor_pos = self.cursor_pos.get();
|
||||
if cursor_pos == 0 {
|
||||
return;
|
||||
}
|
||||
@@ -256,12 +380,49 @@ impl EditBox {
|
||||
}
|
||||
text.push_str(&substr);
|
||||
}
|
||||
self.cursor_pos.set_u32(0, cursor_pos - 1).unwrap();
|
||||
self.text.set_str(0, text).unwrap();
|
||||
self.cursor_pos.set(cursor_pos - 1);
|
||||
self.text.set(text);
|
||||
self.regen_glyphs().unwrap();
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn mouse_button_down(self: Arc<Self>, button: MouseButton, x: f32, y: f32) {
|
||||
let mouse_pos = Point { x, y };
|
||||
let rect = self.world_rect.lock().unwrap();
|
||||
|
||||
// clicking inside box will:
|
||||
// 1. make it active
|
||||
// 2. begin selection
|
||||
if rect.contains(&mouse_pos) {
|
||||
if !self.is_active.get() {
|
||||
self.is_active.set(true);
|
||||
println!("inside!");
|
||||
// Send signal
|
||||
}
|
||||
|
||||
// set cursor pos
|
||||
// begin selection
|
||||
}
|
||||
// click outside the box will:
|
||||
// 1. make it inactive
|
||||
else {
|
||||
if self.is_active.get() {
|
||||
self.is_active.set(false);
|
||||
// Send signal
|
||||
}
|
||||
}
|
||||
}
|
||||
fn mouse_button_up(self: Arc<Self>, button: MouseButton, x: f32, y: f32) {
|
||||
// releasing mouse button will:
|
||||
// 1. end selection
|
||||
}
|
||||
fn mouse_move(self: Arc<Self>, x: f32, y: f32) {
|
||||
// if active and selection_active, then use x to modify the selection.
|
||||
// also implement scrolling when cursor is to the left or right
|
||||
// just scroll to the end
|
||||
// also set cursor_pos too
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ use crate::{
|
||||
error::{Error, Result},
|
||||
editbox,
|
||||
expr::{SExprMachine, SExprVal},
|
||||
keysym::MouseButtonAsU8,
|
||||
prop::{Property, PropertySubType, PropertyType},
|
||||
res::{ResourceId, ResourceManager},
|
||||
scene::{
|
||||
@@ -27,21 +28,6 @@ use crate::{
|
||||
shader,
|
||||
};
|
||||
|
||||
trait MouseButtonAsU8 {
|
||||
fn to_u8(&self) -> u8;
|
||||
}
|
||||
|
||||
impl MouseButtonAsU8 for MouseButton {
|
||||
fn to_u8(&self) -> u8 {
|
||||
match self {
|
||||
MouseButton::Left => 0,
|
||||
MouseButton::Middle => 1,
|
||||
MouseButton::Right => 2,
|
||||
MouseButton::Unknown => 3,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type Color = [f32; 4];
|
||||
|
||||
pub const COLOR_RED: Color = [1., 0., 0., 1.];
|
||||
@@ -76,6 +62,11 @@ struct Mesh {
|
||||
pub index_buffer: BufferId,
|
||||
}
|
||||
|
||||
pub struct Point<T> {
|
||||
pub x: T,
|
||||
pub y: T,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Rectangle<T: Copy + std::ops::Add<Output=T> + std::ops::Sub<Output=T> + std::cmp::PartialOrd> {
|
||||
pub x: T,
|
||||
@@ -84,7 +75,7 @@ pub struct Rectangle<T: Copy + std::ops::Add<Output=T> + std::ops::Sub<Output=T>
|
||||
pub h: T,
|
||||
}
|
||||
|
||||
impl<T: Copy + std::ops::Add<Output=T> + std::ops::Sub<Output=T> + std::cmp::PartialOrd> Rectangle<T> {
|
||||
impl<T: Copy + std::ops::Add<Output=T> + std::ops::Sub<Output=T> + std::ops::AddAssign + std::cmp::PartialOrd> Rectangle<T> {
|
||||
fn from_array(arr: [T; 4]) -> Self {
|
||||
let mut iter = IntoIter::new(arr);
|
||||
Self {
|
||||
@@ -95,7 +86,7 @@ impl<T: Copy + std::ops::Add<Output=T> + std::ops::Sub<Output=T> + std::cmp::Par
|
||||
}
|
||||
}
|
||||
|
||||
fn clip(&self, other: &Rectangle<T>) -> Option<Rectangle<T>> {
|
||||
pub fn clip(&self, other: &Self) -> Option<Self> {
|
||||
if other.x + other.w < self.x ||
|
||||
other.x > self.x + self.w ||
|
||||
other.y + other.h < self.y ||
|
||||
@@ -119,6 +110,11 @@ impl<T: Copy + std::ops::Add<Output=T> + std::ops::Sub<Output=T> + std::cmp::Par
|
||||
}
|
||||
Some(clipped)
|
||||
}
|
||||
|
||||
pub fn contains(&self, point: &Point<T>) -> bool {
|
||||
self.x < point.x && point.x < self.x + self.w &&
|
||||
self.y < point.y && point.y < self.y + self.h
|
||||
}
|
||||
}
|
||||
|
||||
pub type FreetypeFace = ft::Face<&'static [u8]>;
|
||||
@@ -472,11 +468,19 @@ impl<'a> RenderContext<'a> {
|
||||
|
||||
let (_, screen_height) = window::screen_size();
|
||||
|
||||
let mut rect = Self::get_rect(&layer)?;
|
||||
rect.y = screen_height as i32 - (rect.y + rect.h);
|
||||
let rect = Self::get_rect(&layer)?;
|
||||
|
||||
self.ctx.apply_viewport(rect.x, rect.y, rect.w, rect.h);
|
||||
self.ctx.apply_scissor_rect(rect.x, rect.y, rect.w, rect.h);
|
||||
let mut view = rect.clone();
|
||||
view.y = screen_height as i32 - (rect.y + rect.h);
|
||||
self.ctx.apply_viewport(view.x, view.y, view.w, view.h);
|
||||
self.ctx.apply_scissor_rect(view.x, view.y, view.w, view.h);
|
||||
|
||||
let rect = Rectangle {
|
||||
x: rect.x as f32,
|
||||
y: rect.y as f32,
|
||||
w: rect.w as f32,
|
||||
h: rect.h as f32,
|
||||
};
|
||||
|
||||
let layer_children =
|
||||
layer.get_children(&[SceneNodeType::RenderMesh, SceneNodeType::RenderText, SceneNodeType::EditBox]);
|
||||
@@ -536,7 +540,7 @@ impl<'a> RenderContext<'a> {
|
||||
nodes.into_iter().map(|(z_index, node_inf)| node_inf).collect()
|
||||
}
|
||||
|
||||
pub fn get_dim(mesh: &SceneNode, layer_rect: &Rectangle<i32>) -> Result<Rectangle<f32>> {
|
||||
pub fn get_dim(mesh: &SceneNode, layer_rect: &Rectangle<f32>) -> Result<Rectangle<f32>> {
|
||||
let prop = mesh.get_property("rect").ok_or(Error::PropertyNotFound)?;
|
||||
if prop.array_len != 4 {
|
||||
return Err(Error::PropertyWrongLen)
|
||||
@@ -563,7 +567,7 @@ impl<'a> RenderContext<'a> {
|
||||
Ok(Rectangle::from_array(rect))
|
||||
}
|
||||
|
||||
fn render_mesh(&mut self, node_id: SceneNodeId, layer_rect: &Rectangle<i32>) -> Result<()> {
|
||||
fn render_mesh(&mut self, node_id: SceneNodeId, layer_rect: &Rectangle<f32>) -> Result<()> {
|
||||
let mesh = self.scene_graph.get_node(node_id).unwrap();
|
||||
|
||||
let z_index = mesh.get_property_u32("z_index")?;
|
||||
@@ -754,7 +758,7 @@ impl<'a> RenderContext<'a> {
|
||||
self.render_box(x1, y2 - w, x2, y2, color);
|
||||
}
|
||||
|
||||
fn render_text(&mut self, node_id: SceneNodeId, layer_rect: &Rectangle<i32>) -> Result<()> {
|
||||
fn render_text(&mut self, node_id: SceneNodeId, layer_rect: &Rectangle<f32>) -> Result<()> {
|
||||
let node = self.scene_graph.get_node(node_id).unwrap();
|
||||
|
||||
let text = node.get_property_str("text")?;
|
||||
|
||||
@@ -14,6 +14,8 @@ mod expr;
|
||||
mod gfx;
|
||||
use gfx::run_gui;
|
||||
|
||||
mod keysym;
|
||||
|
||||
mod net;
|
||||
use net::ZeroMQAdapter;
|
||||
|
||||
|
||||
@@ -13,6 +13,11 @@ use std::{
|
||||
|
||||
use crate::{expr::SExprCode, scene::SceneNodeId};
|
||||
|
||||
mod wrap;
|
||||
pub use wrap::{
|
||||
PropertyBool, PropertyFloat32, PropertyUint32, PropertyStr, PropertyColor,
|
||||
};
|
||||
|
||||
type Buffer = Arc<Vec<u8>>;
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, SerialEncodable, SerialDecodable)]
|
||||
@@ -437,7 +442,7 @@ impl Property {
|
||||
|
||||
// Get
|
||||
|
||||
fn is_bounded(&self) -> bool {
|
||||
pub fn is_bounded(&self) -> bool {
|
||||
self.array_len != 0
|
||||
}
|
||||
|
||||
@@ -454,6 +459,10 @@ impl Property {
|
||||
let val = self.get_raw_value(i)?;
|
||||
Ok(val.is_unset())
|
||||
}
|
||||
pub fn is_null(&self, i: usize) -> Result<bool> {
|
||||
let val = self.get_raw_value(i)?;
|
||||
Ok(val.is_null())
|
||||
}
|
||||
|
||||
pub fn is_expr(&self, i: usize) -> Result<bool> {
|
||||
if !self.is_expr_allowed {
|
||||
134
bin/darkwallet/src/prop/wrap.rs
Normal file
134
bin/darkwallet/src/prop/wrap.rs
Normal file
@@ -0,0 +1,134 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::{scene::SceneNode, error::{Error, Result}};
|
||||
use super::Property;
|
||||
|
||||
pub struct PropertyBool {
|
||||
prop: Arc<Property>,
|
||||
idx: usize,
|
||||
}
|
||||
|
||||
impl PropertyBool {
|
||||
pub fn wrap(node: &SceneNode, prop_name: &str, idx: usize) -> Result<Self> {
|
||||
let prop = node.get_property(prop_name).ok_or(Error::PropertyNotFound)?;
|
||||
|
||||
// Test if it works
|
||||
let _ = prop.get_bool(idx)?;
|
||||
|
||||
Ok(Self { prop, idx })
|
||||
}
|
||||
|
||||
pub fn get(&self) -> bool {
|
||||
self.prop.get_bool(self.idx).unwrap()
|
||||
}
|
||||
|
||||
pub fn set(&self, val: bool) {
|
||||
self.prop.set_bool(self.idx, val).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct PropertyUint32 {
|
||||
prop: Arc<Property>,
|
||||
idx: usize,
|
||||
}
|
||||
|
||||
impl PropertyUint32 {
|
||||
pub fn wrap(node: &SceneNode, prop_name: &str, idx: usize) -> Result<Self> {
|
||||
let prop = node.get_property(prop_name).ok_or(Error::PropertyNotFound)?;
|
||||
|
||||
// Test if it works
|
||||
let _ = prop.get_u32(idx)?;
|
||||
|
||||
Ok(Self { prop, idx })
|
||||
}
|
||||
|
||||
pub fn get(&self) -> u32 {
|
||||
self.prop.get_u32(self.idx).unwrap()
|
||||
}
|
||||
|
||||
pub fn set(&self, val: u32) {
|
||||
self.prop.set_u32(self.idx, val).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct PropertyFloat32 {
|
||||
prop: Arc<Property>,
|
||||
idx: usize,
|
||||
}
|
||||
|
||||
impl PropertyFloat32 {
|
||||
pub fn wrap(node: &SceneNode, prop_name: &str, idx: usize) -> Result<Self> {
|
||||
let prop = node.get_property(prop_name).ok_or(Error::PropertyNotFound)?;
|
||||
|
||||
// Test if it works
|
||||
let _ = prop.get_f32(idx)?;
|
||||
|
||||
Ok(Self { prop, idx })
|
||||
}
|
||||
|
||||
pub fn get(&self) -> f32 {
|
||||
self.prop.get_f32(self.idx).unwrap()
|
||||
}
|
||||
|
||||
pub fn set(&self, val: f32) {
|
||||
self.prop.set_f32(self.idx, val).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct PropertyStr {
|
||||
prop: Arc<Property>,
|
||||
idx: usize,
|
||||
}
|
||||
|
||||
impl PropertyStr {
|
||||
pub fn wrap(node: &SceneNode, prop_name: &str, idx: usize) -> Result<Self> {
|
||||
let prop = node.get_property(prop_name).ok_or(Error::PropertyNotFound)?;
|
||||
|
||||
// Test if it works
|
||||
let _ = prop.get_str(idx)?;
|
||||
|
||||
Ok(Self { prop, idx })
|
||||
}
|
||||
|
||||
pub fn get(&self) -> String {
|
||||
self.prop.get_str(self.idx).unwrap()
|
||||
}
|
||||
|
||||
pub fn set<S: Into<String>>(&self, val: S) {
|
||||
self.prop.set_str(self.idx, val.into()).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct PropertyColor {
|
||||
prop: Arc<Property>,
|
||||
}
|
||||
|
||||
impl PropertyColor {
|
||||
pub fn wrap(node: &SceneNode, prop_name: &str) -> Result<Self> {
|
||||
let prop = node.get_property(prop_name).ok_or(Error::PropertyNotFound)?;
|
||||
|
||||
if !prop.is_bounded() || prop.get_len() != 4 {
|
||||
return Err(Error::PropertyWrongLen)
|
||||
}
|
||||
|
||||
// Test if it works
|
||||
let _ = prop.get_f32(0)?;
|
||||
|
||||
Ok(Self { prop })
|
||||
}
|
||||
|
||||
pub fn get(&self) -> [f32; 4] {
|
||||
[self.prop.get_f32(0).unwrap(),
|
||||
self.prop.get_f32(1).unwrap(),
|
||||
self.prop.get_f32(2).unwrap(),
|
||||
self.prop.get_f32(3).unwrap()]
|
||||
}
|
||||
|
||||
pub fn set(&self, val: [f32; 4]) {
|
||||
self.prop.set_f32(0, val[0]).unwrap();
|
||||
self.prop.set_f32(1, val[1]).unwrap();
|
||||
self.prop.set_f32(2, val[2]).unwrap();
|
||||
self.prop.set_f32(3, val[3]).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user