...
 
Commits (4)
......@@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### 0.3.1-alpha3
* Update caret position on TextBox by mouse click
* Text input support for ', /, \, [, ], {, }
* Multiple window support
* Pathfinder / Glutin backend (experimental)
......@@ -63,4 +64,4 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
* TextBlock widget
* TextBox widget
* ToggleButton widget
* Window widget
\ No newline at end of file
* Window widget
......@@ -83,12 +83,55 @@ impl TextBoxState {
}
}
fn request_focus(&self, ctx: &mut Context<'_>) {
fn request_focus(&self, ctx: &mut Context<'_>, p: Mouse) {
ctx.push_event_by_window(FocusEvent::RequestFocus(ctx.entity));
if ctx.widget().get::<String16>("text").len() > 0 {
// select all text if there is text and the element is not focused yet.
if ctx.widget().get::<String16>("text").len() > 0 && !(*ctx.widget().get::<bool>("focused")) {
self.select_all(ctx);
return;
}
// change only the caret position if the text is already selected or if the element is focused already
if *ctx.get_widget(self.cursor).get::<bool>("expanded") || *ctx.widget().get::<bool>("focused") {
ctx.widget()
.get_mut::<TextSelection>("text_selection")
.start_index = self.get_new_caret_position(ctx, p);
ctx.widget()
.get_mut::<TextSelection>("text_selection")
.length = 0;
}
}
// Get new position for the caret based on current mouse position
fn get_new_caret_position(&self, ctx: &mut Context<'_>, p: Mouse) -> usize {
if let Some((index, _x)) = self.map_chars_index_to_position(ctx).iter().min_by_key(|(_index, x)| (p.x - x).abs() as u64) {
return *index;
}
0
}
// Returns a vector with a tuple of each char's starting index (usize) and position (f64)
fn map_chars_index_to_position(&self, ctx: &mut Context<'_>) -> Vec<(usize, f64)> {
let text: String = ctx.widget().get::<String16>("text").as_string();
// start x position of the cursor is start position of the text element + padding left
let start_position: f64 = ctx.widget().get::<Point>("position").x + ctx.widget().get::<Thickness>("padding").left;
// array which will hold char index and it's x position
let mut position_index: Vec<(usize, f64)> = Vec::with_capacity(text.len());
position_index.push((0, start_position));
// current text font family and size
let font: String = ctx.widget().clone_or_default::<String>("font");
let font_size: f64 = ctx.widget().clone_or_default::<f64>("font_size");
for (index, _) in text.chars().enumerate() {
let bound_width: f64 = ctx.render_context_2_d().measure(&text[..index + 1], font_size, &font).width;
let next_position: f64 = start_position + bound_width;
position_index.push((index + 1, next_position));
}
position_index
}
// Reset selection and offset if text is changed from outside
......@@ -304,8 +347,8 @@ impl State for TextBoxState {
TextBoxAction::Key(event) => {
self.handle_key_event(event, ctx);
}
TextBoxAction::Mouse(_p) => {
self.request_focus(ctx);
TextBoxAction::Mouse(p) => {
self.request_focus(ctx, p);
}
}
}
......