Skip to content

Commit

Permalink
wallet/chatedit: resize with wrapped text
Browse files Browse the repository at this point in the history
  • Loading branch information
darkfi committed Dec 22, 2024
1 parent f62f317 commit a41dfb9
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 101 deletions.
3 changes: 3 additions & 0 deletions bin/darkwallet/src/app/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,9 @@ pub fn create_chatedit(name: &str) -> SceneNode {
let prop = Property::new("baseline", PropertyType::Float32, PropertySubType::Pixel);
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);
prop.set_range_f32(0., f32::MAX);
node.add_property(prop).unwrap();
Expand Down
83 changes: 11 additions & 72 deletions bin/darkwallet/src/app/schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,13 @@ const LIGHTMODE: bool = false;

mod android_ui_consts {
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_DESCENT: f32 = 20.;
pub const EDITCHAT_SELECT_ASCENT: f32 = 40.;
pub const EDITCHAT_SELECT_DESCENT: f32 = 8.;
pub const TEXTBAR_BASELINE: f32 = 93.;
pub const TEXT_DESCENT: f32 = 20.;
pub const EDITCHAT_LHS_PAD: f32 = 30.;
pub const SENDLABEL_WIDTH: f32 = 200.;
pub const SENDLABEL_LHS_PAD: f32 = 40.;
Expand Down Expand Up @@ -89,12 +90,13 @@ mod ui_consts {
pub const KING_PATH: &str = "assets/king.png";
pub const BG_PATH: &str = "assets/bg.png";
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_DESCENT: f32 = 8.;
pub const EDITCHAT_SELECT_ASCENT: f32 = 30.;
pub const EDITCHAT_SELECT_DESCENT: f32 = 10.;
pub const TEXTBAR_BASELINE: f32 = 34.;
pub const TEXT_DESCENT: f32 = 10.;
pub const EDITCHAT_LHS_PAD: f32 = 20.;
pub const SENDLABEL_WIDTH: f32 = 120.;
pub const SENDLABEL_LHS_PAD: f32 = 30.;
Expand Down Expand Up @@ -730,12 +732,15 @@ pub(super) async fn make(app: &App, window: SceneNodePtr) {
let node = create_vector_art("editbox_bg");
let prop = node.get_property("rect").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, 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();

let editbox_bg_rect_prop = prop.clone();

let mut shape = VectorShape::new();
shape.add_filled_box(
expr::const_f32(0.),
Expand Down Expand Up @@ -818,8 +823,10 @@ pub(super) async fn make(app: &App, window: SceneNodePtr) {
prop.set_f32(Role::App, 3, EDITCHAT_HEIGHT).unwrap();

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, "descent", TEXT_DESCENT).unwrap();
node.set_property_f32(Role::App, "font_size", FONTSIZE).unwrap();
//node.set_property_str(Role::App, "text", "hello king!😁🍆jelly 🍆1234").unwrap();
let prop = node.get_property("text_color").unwrap();
Expand Down Expand Up @@ -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;
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);
}
83 changes: 55 additions & 28 deletions bin/darkwallet/src/ui/chatedit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ pub struct ChatEdit {
max_height: PropertyFloat32,
rect: PropertyRect,
baseline: PropertyFloat32,
descent: PropertyFloat32,
scroll: PropertyFloat32,
scroll_speed: PropertyFloat32,
cursor_pos: PropertyUint32,
Expand Down Expand Up @@ -201,6 +202,7 @@ impl ChatEdit {
let max_height = PropertyFloat32::wrap(node_ref, Role::Internal, "max_height", 0).unwrap();
let rect = PropertyRect::wrap(node_ref, Role::Internal, "rect").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_speed =
PropertyFloat32::wrap(node_ref, Role::Internal, "scroll_speed", 0).unwrap();
Expand Down Expand Up @@ -252,6 +254,7 @@ impl ChatEdit {
max_height,
rect,
baseline: baseline.clone(),
descent,
scroll: scroll.clone(),
scroll_speed,
cursor_pos,
Expand Down Expand Up @@ -326,8 +329,7 @@ impl ChatEdit {

let total_height = wrapped_lines_len as f32 * baseline;
//let height = std::cmp::min(total_height, self.max_height.get());
let height = total_height;
debug!("height = {height}");
let height = total_height + self.descent.get();

self.rect.prop().set_f32(Role::Internal, 3, height);

Expand All @@ -341,7 +343,6 @@ impl ChatEdit {
("rect_h".to_string(), height),
],
);
debug!("rect = {:?}", self.rect.get());

let mut clip = self.rect.get();
clip.x = 0.;
Expand Down Expand Up @@ -416,43 +417,60 @@ impl ChatEdit {
mesh.alloc(&self.render_api).draw_untextured()
}

fn cursor_px_offset(&self) -> f32 {
fn get_cursor_pos(&self) -> Point {
assert!(self.is_focused.get());

let (cursor_pos, glyphs) = {
let font_size = self.font_size.get();
let window_scale = self.window_scale.get();
let baseline = self.baseline.get();

let width = self.rect.prop().get_f32(2).unwrap();

let (cursor_pos, wrap_glyphs) = {
let editable = self.editable.lock().unwrap();
let rendered = editable.render();
let cursor_pos = editable.get_cursor_pos(&rendered);
(cursor_pos, rendered.glyphs)
let glyphs = text::wrap(width, font_size, window_scale, &rendered.glyphs);
(cursor_pos, glyphs)
};

let font_size = self.font_size.get();
let window_scale = self.window_scale.get();
let baseline = self.baseline.get();
let scroll = self.scroll.get();
// Add composer glyphs too
let glyph_pos_iter = GlyphPositionIter::new(font_size, window_scale, &glyphs, baseline);
// 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.
let mut rhs = 0.;
let mut y_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() {
glyph_rect.x -= scroll;
for (line_idx, glyphs) in wrap_glyphs.iter().enumerate() {
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 {
return glyph_rect.x;
if line_idx > 0 {
// +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)
}

assert!(cursor_pos == glyphs.len());
rhs = glyph_rect.rhs();

rhs += eol_nudge(font_size, &glyphs);
rhs
glyph_idx += 1;
}
}

if !wrap_glyphs.is_empty() {
rhs += eol_nudge(font_size, &wrap_glyphs.last().unwrap());
}
Point::new(rhs, y_pos)
}

fn mark_selected_glyphs(&self, glyphs: &Vec<Glyph>, selections: Vec<Selection>) -> Vec<bool> {
Expand Down Expand Up @@ -1209,11 +1227,7 @@ impl ChatEdit {

let rect_w = self.rect.get().w;

let mut cursor_pos = Point::zero();
cursor_pos.x += self.cursor_px_offset();
if cursor_pos.x > rect_w {
return vec![]
}
let cursor_pos = self.get_cursor_pos();
cursor_instrs.push(GfxDrawInstruction::Move(cursor_pos));

let cursor_mesh = {
Expand Down Expand Up @@ -1439,10 +1453,23 @@ impl UIObject for ChatEdit {
let window_scale = self.window_scale.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 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 cidx = rendered.pos_to_idx(cpos);
Expand Down
1 change: 0 additions & 1 deletion bin/darkwallet/src/ui/vector_art/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,6 @@ impl VectorArt {

//debug!(target: "ui::vector_art", "=> {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 mesh = GfxDrawMesh {
vertex_buffer,
Expand Down

0 comments on commit a41dfb9

Please sign in to comment.