wallet/chatedit: resize with wrapped text

This commit is contained in:
darkfi
2024-12-22 15:07:30 +01:00
parent f62f3179ad
commit a41dfb9611
4 changed files with 71 additions and 103 deletions

View File

@@ -268,6 +268,9 @@ pub fn create_chatedit(name: &str) -> SceneNode {
let prop = Property::new("baseline", PropertyType::Float32, PropertySubType::Pixel); let prop = Property::new("baseline", PropertyType::Float32, PropertySubType::Pixel);
node.add_property(prop).unwrap(); node.add_property(prop).unwrap();
let prop = Property::new("descent", PropertyType::Float32, PropertySubType::Pixel);
node.add_property(prop).unwrap();
let mut prop = Property::new("scroll", PropertyType::Float32, PropertySubType::Pixel); let mut prop = Property::new("scroll", PropertyType::Float32, PropertySubType::Pixel);
prop.set_range_f32(0., f32::MAX); prop.set_range_f32(0., f32::MAX);
node.add_property(prop).unwrap(); node.add_property(prop).unwrap();

View File

@@ -47,12 +47,13 @@ const LIGHTMODE: bool = false;
mod android_ui_consts { mod android_ui_consts {
pub const EDITCHAT_HEIGHT: f32 = 163.; pub const EDITCHAT_HEIGHT: f32 = 163.;
pub const EDITCHAT_BOTTOM_PAD: f32 = 70.; pub const EDITCHAT_BOTTOM_PAD: f32 = 50.;
pub const EDITCHAT_CURSOR_ASCENT: f32 = 50.; pub const EDITCHAT_CURSOR_ASCENT: f32 = 50.;
pub const EDITCHAT_CURSOR_DESCENT: f32 = 20.; pub const EDITCHAT_CURSOR_DESCENT: f32 = 20.;
pub const EDITCHAT_SELECT_ASCENT: f32 = 40.; pub const EDITCHAT_SELECT_ASCENT: f32 = 40.;
pub const EDITCHAT_SELECT_DESCENT: f32 = 8.; pub const EDITCHAT_SELECT_DESCENT: f32 = 8.;
pub const TEXTBAR_BASELINE: f32 = 93.; pub const TEXTBAR_BASELINE: f32 = 93.;
pub const TEXT_DESCENT: f32 = 20.;
pub const EDITCHAT_LHS_PAD: f32 = 30.; pub const EDITCHAT_LHS_PAD: f32 = 30.;
pub const SENDLABEL_WIDTH: f32 = 200.; pub const SENDLABEL_WIDTH: f32 = 200.;
pub const SENDLABEL_LHS_PAD: f32 = 40.; pub const SENDLABEL_LHS_PAD: f32 = 40.;
@@ -89,12 +90,13 @@ mod ui_consts {
pub const KING_PATH: &str = "assets/king.png"; pub const KING_PATH: &str = "assets/king.png";
pub const BG_PATH: &str = "assets/bg.png"; pub const BG_PATH: &str = "assets/bg.png";
pub const EDITCHAT_HEIGHT: f32 = 50.; pub const EDITCHAT_HEIGHT: f32 = 50.;
pub const EDITCHAT_BOTTOM_PAD: f32 = 16.; pub const EDITCHAT_BOTTOM_PAD: f32 = 6.;
pub const EDITCHAT_CURSOR_ASCENT: f32 = 25.; pub const EDITCHAT_CURSOR_ASCENT: f32 = 25.;
pub const EDITCHAT_CURSOR_DESCENT: f32 = 8.; pub const EDITCHAT_CURSOR_DESCENT: f32 = 8.;
pub const EDITCHAT_SELECT_ASCENT: f32 = 30.; pub const EDITCHAT_SELECT_ASCENT: f32 = 30.;
pub const EDITCHAT_SELECT_DESCENT: f32 = 10.; pub const EDITCHAT_SELECT_DESCENT: f32 = 10.;
pub const TEXTBAR_BASELINE: f32 = 34.; pub const TEXTBAR_BASELINE: f32 = 34.;
pub const TEXT_DESCENT: f32 = 10.;
pub const EDITCHAT_LHS_PAD: f32 = 20.; pub const EDITCHAT_LHS_PAD: f32 = 20.;
pub const SENDLABEL_WIDTH: f32 = 120.; pub const SENDLABEL_WIDTH: f32 = 120.;
pub const SENDLABEL_LHS_PAD: f32 = 30.; pub const SENDLABEL_LHS_PAD: f32 = 30.;
@@ -730,12 +732,15 @@ pub(super) async fn make(app: &App, window: SceneNodePtr) {
let node = create_vector_art("editbox_bg"); let node = create_vector_art("editbox_bg");
let prop = node.get_property("rect").unwrap(); let prop = node.get_property("rect").unwrap();
prop.set_f32(Role::App, 0, 0.).unwrap(); prop.set_f32(Role::App, 0, 0.).unwrap();
let code = cc.compile("h - EDITCHAT_HEIGHT").unwrap(); let code = cc.compile("h - editz_h").unwrap();
prop.set_expr(Role::App, 1, code).unwrap(); prop.set_expr(Role::App, 1, code).unwrap();
prop.set_expr(Role::App, 2, expr::load_var("w")).unwrap(); prop.set_expr(Role::App, 2, expr::load_var("w")).unwrap();
prop.set_f32(Role::App, 3, EDITCHAT_HEIGHT).unwrap(); let code = cc.compile("editz_h").unwrap();
prop.set_expr(Role::App, 3, code).unwrap();
node.set_property_u32(Role::App, "z_index", 2).unwrap(); node.set_property_u32(Role::App, "z_index", 2).unwrap();
let editbox_bg_rect_prop = prop.clone();
let mut shape = VectorShape::new(); let mut shape = VectorShape::new();
shape.add_filled_box( shape.add_filled_box(
expr::const_f32(0.), expr::const_f32(0.),
@@ -818,8 +823,10 @@ pub(super) async fn make(app: &App, window: SceneNodePtr) {
prop.set_f32(Role::App, 3, EDITCHAT_HEIGHT).unwrap(); prop.set_f32(Role::App, 3, EDITCHAT_HEIGHT).unwrap();
chatview_rect_prop.add_depend(&prop, 3, "editz_h"); chatview_rect_prop.add_depend(&prop, 3, "editz_h");
editbox_bg_rect_prop.add_depend(&prop, 3, "editz_h");
node.set_property_f32(Role::App, "baseline", TEXTBAR_BASELINE).unwrap(); node.set_property_f32(Role::App, "baseline", TEXTBAR_BASELINE).unwrap();
node.set_property_f32(Role::App, "descent", TEXT_DESCENT).unwrap();
node.set_property_f32(Role::App, "font_size", FONTSIZE).unwrap(); node.set_property_f32(Role::App, "font_size", FONTSIZE).unwrap();
//node.set_property_str(Role::App, "text", "hello king!😁🍆jelly 🍆1234").unwrap(); //node.set_property_str(Role::App, "text", "hello king!😁🍆jelly 🍆1234").unwrap();
let prop = node.get_property("text_color").unwrap(); let prop = node.get_property("text_color").unwrap();
@@ -912,72 +919,4 @@ pub(super) async fn make(app: &App, window: SceneNodePtr) {
let node = node.setup(|me| Button::new(me, app.ex.clone())).await; let node = node.setup(|me| Button::new(me, app.ex.clone())).await;
layer_node.clone().link(node); layer_node.clone().link(node);
// Create a popup layer to show upgrade msg
let node = create_layer("upgrade_popup");
let prop = node.get_property("rect").unwrap();
prop.set_f32(Role::App, 0, 0.).unwrap();
prop.set_f32(Role::App, 1, 0.).unwrap();
prop.set_expr(Role::App, 2, expr::load_var("w")).unwrap();
let code = cc.compile("h / 2").unwrap();
prop.set_expr(Role::App, 3, code).unwrap();
node.set_property_bool(Role::App, "is_visible", false).unwrap();
node.set_property_u32(Role::App, "z_index", 10).unwrap();
let popup_layer_node =
node.setup(|me| Layer::new(me, app.render_api.clone(), app.ex.clone())).await;
layer_node.clone().link(popup_layer_node.clone());
// Background for popup
let node = create_vector_art("upgradebg");
let prop = node.get_property("rect").unwrap();
prop.set_f32(Role::App, 0, 0.).unwrap();
prop.set_f32(Role::App, 1, 0.).unwrap();
prop.set_expr(Role::App, 2, expr::load_var("w")).unwrap();
prop.set_expr(Role::App, 3, expr::load_var("h")).unwrap();
node.set_property_u32(Role::App, "z_index", 0).unwrap();
// Setup the pimpl
let verts = vec![
ShapeVertex::from_xy(0., 0., [1., 0., 0., 1.]),
ShapeVertex::new(expr::load_var("w"), expr::const_f32(0.), [1., 0., 1., 1.]),
ShapeVertex::new(expr::const_f32(0.), expr::load_var("h"), [0., 0., 1., 1.]),
ShapeVertex::new(expr::load_var("w"), expr::load_var("h"), [1., 1., 0., 1.]),
];
let indices = vec![0, 2, 1, 1, 2, 3];
let shape = VectorShape { verts, indices };
let node =
node.setup(|me| VectorArt::new(me, shape, app.render_api.clone(), app.ex.clone())).await;
popup_layer_node.clone().link(node);
// Create some text
let node = create_text("send_label");
let prop = node.get_property("rect").unwrap();
prop.set_f32(Role::App, 0, 10.).unwrap();
prop.set_f32(Role::App, 1, 10.).unwrap();
prop.set_expr(Role::App, 2, expr::load_var("w")).unwrap();
prop.set_expr(Role::App, 3, expr::load_var("h")).unwrap();
node.set_property_f32(Role::App, "baseline", TEXTBAR_BASELINE).unwrap();
node.set_property_f32(Role::App, "font_size", 2. * FONTSIZE).unwrap();
node.set_property_str(Role::App, "text", "YO THERE'S A NEW VERSION!!! UPGRADE TIEM!!!")
.unwrap();
//node.set_property_str(Role::App, "text", "anon1").unwrap();
let prop = node.get_property("text_color").unwrap();
prop.set_f32(Role::App, 0, 0.).unwrap();
prop.set_f32(Role::App, 1, 1.).unwrap();
prop.set_f32(Role::App, 2, 0.94).unwrap();
prop.set_f32(Role::App, 3, 1.).unwrap();
node.set_property_u32(Role::App, "z_index", 1).unwrap();
let node = node
.setup(|me| {
Text::new(
me,
window_scale.clone(),
app.render_api.clone(),
app.text_shaper.clone(),
app.ex.clone(),
)
})
.await;
popup_layer_node.clone().link(node);
} }

View File

@@ -147,6 +147,7 @@ pub struct ChatEdit {
max_height: PropertyFloat32, max_height: PropertyFloat32,
rect: PropertyRect, rect: PropertyRect,
baseline: PropertyFloat32, baseline: PropertyFloat32,
descent: PropertyFloat32,
scroll: PropertyFloat32, scroll: PropertyFloat32,
scroll_speed: PropertyFloat32, scroll_speed: PropertyFloat32,
cursor_pos: PropertyUint32, cursor_pos: PropertyUint32,
@@ -201,6 +202,7 @@ impl ChatEdit {
let max_height = PropertyFloat32::wrap(node_ref, Role::Internal, "max_height", 0).unwrap(); let max_height = PropertyFloat32::wrap(node_ref, Role::Internal, "max_height", 0).unwrap();
let rect = PropertyRect::wrap(node_ref, Role::Internal, "rect").unwrap(); let rect = PropertyRect::wrap(node_ref, Role::Internal, "rect").unwrap();
let baseline = PropertyFloat32::wrap(node_ref, Role::Internal, "baseline", 0).unwrap(); let baseline = PropertyFloat32::wrap(node_ref, Role::Internal, "baseline", 0).unwrap();
let descent = PropertyFloat32::wrap(node_ref, Role::Internal, "descent", 0).unwrap();
let scroll = PropertyFloat32::wrap(node_ref, Role::Internal, "scroll", 0).unwrap(); let scroll = PropertyFloat32::wrap(node_ref, Role::Internal, "scroll", 0).unwrap();
let scroll_speed = let scroll_speed =
PropertyFloat32::wrap(node_ref, Role::Internal, "scroll_speed", 0).unwrap(); PropertyFloat32::wrap(node_ref, Role::Internal, "scroll_speed", 0).unwrap();
@@ -252,6 +254,7 @@ impl ChatEdit {
max_height, max_height,
rect, rect,
baseline: baseline.clone(), baseline: baseline.clone(),
descent,
scroll: scroll.clone(), scroll: scroll.clone(),
scroll_speed, scroll_speed,
cursor_pos, cursor_pos,
@@ -326,8 +329,7 @@ impl ChatEdit {
let total_height = wrapped_lines_len as f32 * baseline; let total_height = wrapped_lines_len as f32 * baseline;
//let height = std::cmp::min(total_height, self.max_height.get()); //let height = std::cmp::min(total_height, self.max_height.get());
let height = total_height; let height = total_height + self.descent.get();
debug!("height = {height}");
self.rect.prop().set_f32(Role::Internal, 3, height); self.rect.prop().set_f32(Role::Internal, 3, height);
@@ -341,7 +343,6 @@ impl ChatEdit {
("rect_h".to_string(), height), ("rect_h".to_string(), height),
], ],
); );
debug!("rect = {:?}", self.rect.get());
let mut clip = self.rect.get(); let mut clip = self.rect.get();
clip.x = 0.; clip.x = 0.;
@@ -416,43 +417,60 @@ impl ChatEdit {
mesh.alloc(&self.render_api).draw_untextured() mesh.alloc(&self.render_api).draw_untextured()
} }
fn cursor_px_offset(&self) -> f32 { fn get_cursor_pos(&self) -> Point {
assert!(self.is_focused.get()); assert!(self.is_focused.get());
let (cursor_pos, glyphs) = {
let editable = self.editable.lock().unwrap();
let rendered = editable.render();
let cursor_pos = editable.get_cursor_pos(&rendered);
(cursor_pos, rendered.glyphs)
};
let font_size = self.font_size.get(); let font_size = self.font_size.get();
let window_scale = self.window_scale.get(); let window_scale = self.window_scale.get();
let baseline = self.baseline.get(); let baseline = self.baseline.get();
let scroll = self.scroll.get();
// Add composer glyphs too let width = self.rect.prop().get_f32(2).unwrap();
let glyph_pos_iter = GlyphPositionIter::new(font_size, window_scale, &glyphs, baseline);
let (cursor_pos, wrap_glyphs) = {
let editable = self.editable.lock().unwrap();
let rendered = editable.render();
let cursor_pos = editable.get_cursor_pos(&rendered);
let glyphs = text::wrap(width, font_size, window_scale, &rendered.glyphs);
(cursor_pos, glyphs)
};
// Convert cursor glyph pos to a coord (x, y)
let mut glyph_idx = 0;
// Used for drawing the cursor when it's at the end of the line. // Used for drawing the cursor when it's at the end of the line.
let mut rhs = 0.; let mut rhs = 0.;
let mut y_pos = 0.;
if cursor_pos == 0 { if cursor_pos == 0 {
return 0.; return Point::zero();
} }
for (glyph_idx, (mut glyph_rect, glyph)) in glyph_pos_iter.zip(glyphs.iter()).enumerate() { for (line_idx, glyphs) in wrap_glyphs.iter().enumerate() {
glyph_rect.x -= scroll; debug!("glyph_idx = {glyph_idx}, y_pos = {y_pos}, rhs = {rhs}");
let glyph_pos_iter = GlyphPositionIter::new(font_size, window_scale, glyphs, baseline);
if cursor_pos == glyph_idx { if line_idx > 0 {
return glyph_rect.x; // +1 for the EOL whitespace
glyph_idx += 1;
y_pos += baseline;
} }
rhs = glyph_rect.rhs(); for (mut glyph_rect, glyph) in glyph_pos_iter.zip(glyphs.iter()) {
if cursor_pos == glyph_idx {
let rhs = glyph_rect.rhs();
debug!("retvrn {rhs}, {y_pos}");
return Point::new(rhs, y_pos)
}
rhs = glyph_rect.rhs();
glyph_idx += 1;
}
} }
assert!(cursor_pos == glyphs.len()); if !wrap_glyphs.is_empty() {
rhs += eol_nudge(font_size, &wrap_glyphs.last().unwrap());
rhs += eol_nudge(font_size, &glyphs); }
rhs Point::new(rhs, y_pos)
} }
fn mark_selected_glyphs(&self, glyphs: &Vec<Glyph>, selections: Vec<Selection>) -> Vec<bool> { fn mark_selected_glyphs(&self, glyphs: &Vec<Glyph>, selections: Vec<Selection>) -> Vec<bool> {
@@ -1209,11 +1227,7 @@ impl ChatEdit {
let rect_w = self.rect.get().w; let rect_w = self.rect.get().w;
let mut cursor_pos = Point::zero(); let cursor_pos = self.get_cursor_pos();
cursor_pos.x += self.cursor_px_offset();
if cursor_pos.x > rect_w {
return vec![]
}
cursor_instrs.push(GfxDrawInstruction::Move(cursor_pos)); cursor_instrs.push(GfxDrawInstruction::Move(cursor_pos));
let cursor_mesh = { let cursor_mesh = {
@@ -1439,10 +1453,23 @@ impl UIObject for ChatEdit {
let window_scale = self.window_scale.get(); let window_scale = self.window_scale.get();
let baseline = self.baseline.get(); let baseline = self.baseline.get();
// Convert y offset within rect to an x off based off line wrapping
let y_off = mouse_pos.y - rect.y;
let mut x_off = 0.;
let width = self.rect.prop().get_f32(2).unwrap();
let rendered = self.editable.lock().unwrap().render();
let wrapped_glyphs = text::wrap(width, font_size, window_scale, &rendered.glyphs);
for glyphs in wrapped_glyphs {
let glyph_pos_iter = GlyphPositionIter::new(font_size, window_scale, &glyphs, baseline);
let last_rect = glyph_pos_iter.last().unwrap();
x_off += last_rect.rhs();
}
{ {
let mut editable = self.editable.lock().unwrap(); let mut editable = self.editable.lock().unwrap();
let rendered = editable.render(); let rendered = editable.render();
let x = mouse_pos.x - rect.x + self.scroll.get(); let x = x_off + mouse_pos.x - rect.x + self.scroll.get();
let cpos = rendered.x_to_pos(x, font_size, window_scale, baseline); let cpos = rendered.x_to_pos(x, font_size, window_scale, baseline);
let cidx = rendered.pos_to_idx(cpos); let cidx = rendered.pos_to_idx(cpos);

View File

@@ -106,7 +106,6 @@ impl VectorArt {
//debug!(target: "ui::vector_art", "=> {verts:#?}"); //debug!(target: "ui::vector_art", "=> {verts:#?}");
let vertex_buffer = self.render_api.new_vertex_buffer(verts); let vertex_buffer = self.render_api.new_vertex_buffer(verts);
// You are one lazy motherfucker
let index_buffer = self.render_api.new_index_buffer(self.shape.indices.clone()); let index_buffer = self.render_api.new_index_buffer(self.shape.indices.clone());
let mesh = GfxDrawMesh { let mesh = GfxDrawMesh {
vertex_buffer, vertex_buffer,