|
@@ -1,10 +1,14 @@
|
|
|
use crate::{
|
|
|
input::MouseButton,
|
|
|
- layout::{HorizontalAlignment, LayoutNode, LayoutNodeAccess, LayoutTreeNode, LeafLayoutNode, SizePolicy},
|
|
|
+ layout::{
|
|
|
+ HorizontalAlignment, LayoutNode, LayoutNodeAccess, LayoutTreeNode, LeafLayoutNode,
|
|
|
+ SizePolicy,
|
|
|
+ },
|
|
|
prelude::*,
|
|
|
render::{ColourChoice, RenderTarget, TextCache},
|
|
|
ui::UIHandle,
|
|
|
};
|
|
|
+use kahlo::math::{PixelBox, PixelPoint, PixelSideOffsets, PixelSize};
|
|
|
use winit::keyboard::{Key, NamedKey};
|
|
|
|
|
|
pub enum CursorPosition {
|
|
@@ -13,9 +17,12 @@ pub enum CursorPosition {
|
|
|
End,
|
|
|
}
|
|
|
|
|
|
+/*impl CursorPosition {
|
|
|
+
|
|
|
+}*/
|
|
|
+
|
|
|
pub struct TextEdit<C: Component> {
|
|
|
- lnode: LayoutNode,
|
|
|
- cursor_node: LeafLayoutNode,
|
|
|
+ lnode: LeafLayoutNode,
|
|
|
text: TextCache,
|
|
|
cursor_pos: CursorPosition,
|
|
|
onchange: Option<Box<dyn Fn(&str) -> Option<C::Msg>>>,
|
|
@@ -30,22 +37,15 @@ impl<C: Component> TextEdit<C> {
|
|
|
.set_width_policy(SizePolicy::expanding(1))
|
|
|
.set_height_policy(SizePolicy::fixed(minheight));
|
|
|
|
|
|
- let mut cursor_node = uih.new_layout_node();
|
|
|
- cursor_node
|
|
|
- .set_width_policy(SizePolicy::fixed(2))
|
|
|
- .set_height_policy(SizePolicy::fixed(minheight))
|
|
|
- .set_halign(HorizontalAlignment::Left);
|
|
|
-
|
|
|
Self {
|
|
|
- lnode,
|
|
|
- cursor_node: LeafLayoutNode::new(cursor_node),
|
|
|
+ lnode: LeafLayoutNode::new(lnode),
|
|
|
text: TextCache::new_with_font_and_size(
|
|
|
uih.theme().ui_font.clone(),
|
|
|
uih.theme().ui_font_size,
|
|
|
),
|
|
|
- cursor_pos: CursorPosition::End,
|
|
|
+ cursor_pos: CursorPosition::Start,
|
|
|
onchange: None,
|
|
|
- focused: false
|
|
|
+ focused: false,
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -54,24 +54,8 @@ impl<C: Component> TextEdit<C> {
|
|
|
}
|
|
|
|
|
|
/*pub fn set_cursor_position(&mut self, to: CursorPosition) {
|
|
|
-
|
|
|
- }*/
|
|
|
-}
|
|
|
|
|
|
-impl<C: Component> LayoutTreeNode<()> for TextEdit<C> {
|
|
|
- fn child(&self, ndx: usize) -> Option<LayoutNodeAccess<'_>> {
|
|
|
- if ndx == 0 {
|
|
|
- Some(self.cursor_node.access())
|
|
|
- } else {
|
|
|
- None
|
|
|
- }
|
|
|
- }
|
|
|
- fn child_count(&self) -> usize {
|
|
|
- 1
|
|
|
- }
|
|
|
- fn current_node(&self) -> &LayoutNode {
|
|
|
- &self.lnode
|
|
|
- }
|
|
|
+ }*/
|
|
|
}
|
|
|
|
|
|
impl<C: Component> Widget<C> for TextEdit<C> {
|
|
@@ -85,6 +69,7 @@ impl<C: Component> Widget<C> for TextEdit<C> {
|
|
|
};
|
|
|
|
|
|
if istate.is_focused(self.lnode.id()) {
|
|
|
+ let mut key_press_eaten = true;
|
|
|
if let Some(kp) = &istate.keypress {
|
|
|
match kp {
|
|
|
Key::Named(NamedKey::Backspace) => {
|
|
@@ -95,36 +80,40 @@ impl<C: Component> Widget<C> for TextEdit<C> {
|
|
|
self.text.change(String::pop);
|
|
|
self.lnode.render_needed();
|
|
|
}
|
|
|
+ Key::Named(NamedKey::Space) => {
|
|
|
+ self.text.change(|v| v.push(' '));
|
|
|
+ self.lnode.render_needed();
|
|
|
+ }
|
|
|
Key::Named(NamedKey::Enter) => {
|
|
|
istate.clear_focus();
|
|
|
}
|
|
|
- _ => {
|
|
|
- if let Some(inp) = &istate.text_input {
|
|
|
- self.text.change(|s| s.push_str(inp.as_str()));
|
|
|
- self.lnode.render_needed();
|
|
|
- }
|
|
|
- }
|
|
|
+ Key::Named(_) => {}
|
|
|
+ _ => key_press_eaten = false,
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if !key_press_eaten {
|
|
|
+ if let Some(text) = &istate.text_input {
|
|
|
+ println!("adding text {text:?}");
|
|
|
+ self.text.change(|s| s.push_str(text.as_str()));
|
|
|
+ self.lnode.render_needed();
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
let render_area = self.lnode.render_area().unwrap();
|
|
|
if istate
|
|
|
.mouse_status_in(render_area, MouseButton::Left)
|
|
|
.is_click()
|
|
|
{
|
|
|
istate.focus_on(self.lnode.id());
|
|
|
- self.focused = true;
|
|
|
println!("click offset: {:?}", istate.mouse.pos - render_area.min);
|
|
|
-
|
|
|
- let cbar_offset = self.text.size_hint().width;
|
|
|
- self.cursor_node.margin_mut().left = cbar_offset;
|
|
|
}
|
|
|
|
|
|
let was_focused = self.focused;
|
|
|
self.focused = istate.is_focused(self.lnode.id());
|
|
|
|
|
|
if self.focused != was_focused {
|
|
|
- self.cursor_node.render_needed();
|
|
|
+ println!("self.focused is now {}", self.focused);
|
|
|
self.lnode.render_needed();
|
|
|
}
|
|
|
|
|
@@ -132,7 +121,7 @@ impl<C: Component> Widget<C> for TextEdit<C> {
|
|
|
}
|
|
|
|
|
|
fn layout_node(&self) -> LayoutNodeAccess {
|
|
|
- LayoutNodeAccess::new(self)
|
|
|
+ self.lnode.access()
|
|
|
}
|
|
|
fn layout_node_mut(&mut self) -> &mut LayoutNode {
|
|
|
&mut self.lnode
|
|
@@ -142,11 +131,24 @@ impl<C: Component> Widget<C> for TextEdit<C> {
|
|
|
target
|
|
|
.with_node(&self.lnode)
|
|
|
.fill(ColourChoice::Background)
|
|
|
- .simple_text(&self.text, ColourChoice::Foreground);
|
|
|
-
|
|
|
- if self.focused {
|
|
|
- target.with_node(&self.cursor_node)
|
|
|
- .fill(ColourChoice::Foreground);
|
|
|
- }
|
|
|
+ .simple_text(&self.text, ColourChoice::Foreground)
|
|
|
+ .seq(|target| {
|
|
|
+ if self.focused {
|
|
|
+ let cbar_offset = match self.cursor_pos {
|
|
|
+ CursorPosition::Start => 0,
|
|
|
+ CursorPosition::Index(idx) => {
|
|
|
+ *self.text.x_offsets.borrow().get(idx).unwrap() as i32
|
|
|
+ }
|
|
|
+ CursorPosition::End => self.text.size_hint().width,
|
|
|
+ };
|
|
|
+ target.fill_relative_box(
|
|
|
+ PixelBox::from_origin_and_size(
|
|
|
+ PixelPoint::new(cbar_offset, 0),
|
|
|
+ PixelSize::new(2, self.text.size_hint().height),
|
|
|
+ ),
|
|
|
+ ColourChoice::Foreground,
|
|
|
+ );
|
|
|
+ }
|
|
|
+ });
|
|
|
}
|
|
|
}
|