Skip to content

Commit 8163550

Browse files
committed
Make TextBox generic over its data
This data must be TextStorage + EditableText, which means that *currently* it is only String, but just imagine what the future might hold? Discussion: there's still something funny going on with the TextStorage trait; this stuff as written isn't suitable for use with xi_rope, which was sort of the whole point.
1 parent 400fa04 commit 8163550

File tree

3 files changed

+30
-30
lines changed

3 files changed

+30
-30
lines changed

docs/book_examples/src/custom_widgets_md.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,10 @@ impl TextBoxActionController {
4949
}
5050
}
5151

52-
impl Controller<String, TextBox> for TextBoxActionController {
52+
impl Controller<String, TextBox<String>> for TextBoxActionController {
5353
fn event(
5454
&mut self,
55-
child: &mut TextBox,
55+
child: &mut TextBox<String>,
5656
ctx: &mut EventCtx,
5757
event: &Event,
5858
data: &mut String,

druid/src/widget/textbox.rs

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@
1717
use std::time::Duration;
1818

1919
use crate::kurbo::{Affine, Insets, Point, Size, Vec2};
20-
use crate::text::{BasicTextInput, EditAction, Editor, TextInput, TextLayout};
20+
use crate::text::{
21+
BasicTextInput, EditAction, EditableText, Editor, TextInput, TextLayout, TextStorage,
22+
};
2123
use crate::theme;
2224
use crate::widget::prelude::*;
2325
use crate::{
@@ -32,9 +34,9 @@ const CURSOR_BLINK_DURATION: Duration = Duration::from_millis(500);
3234

3335
/// A widget that allows user text input.
3436
#[derive(Debug, Clone)]
35-
pub struct TextBox {
37+
pub struct TextBox<T> {
3638
placeholder: TextLayout<String>,
37-
editor: Editor<String>,
39+
editor: Editor<T>,
3840
// this can be Box<dyn TextInput> in the future
3941
input_handler: BasicTextInput,
4042
hscroll_offset: f64,
@@ -45,13 +47,15 @@ pub struct TextBox {
4547
multiline: bool,
4648
}
4749

48-
impl TextBox {
50+
impl TextBox<()> {
4951
/// Perform an `EditAction`. The payload *must* be an `EditAction`.
5052
pub const PERFORM_EDIT: Selector<EditAction> =
5153
Selector::new("druid-builtin.textbox.perform-edit");
54+
}
5255

56+
impl<T> TextBox<T> {
5357
/// Create a new TextBox widget
54-
pub fn new() -> TextBox {
58+
pub fn new() -> Self {
5559
let mut placeholder = TextLayout::from_text("");
5660
placeholder.set_text_color(theme::PLACEHOLDER_COLOR);
5761
Self {
@@ -67,7 +71,7 @@ impl TextBox {
6771
}
6872

6973
/// Create a new multi-line `TextBox`.
70-
pub fn multiline() -> TextBox {
74+
pub fn multiline() -> Self {
7175
let mut this = TextBox::new();
7276
this.editor.set_multiline(true);
7377
this.multiline = true;
@@ -127,7 +131,9 @@ impl TextBox {
127131
self.editor.layout().set_font(font.clone());
128132
self.placeholder.set_font(font);
129133
}
134+
}
130135

136+
impl<T: TextStorage + EditableText> TextBox<T> {
131137
/// Calculate a stateful scroll offset
132138
fn update_hscroll(&mut self, self_width: f64) {
133139
let cursor_x = self.editor.cursor_line().p0.x;
@@ -162,8 +168,8 @@ impl TextBox {
162168
}
163169
}
164170

165-
impl Widget<String> for TextBox {
166-
fn event(&mut self, ctx: &mut EventCtx, event: &Event, data: &mut String, _env: &Env) {
171+
impl<T: TextStorage + EditableText> Widget<T> for TextBox<T> {
172+
fn event(&mut self, ctx: &mut EventCtx, event: &Event, data: &mut T, _env: &Env) {
167173
self.suppress_adjust_hscroll = false;
168174
match event {
169175
Event::MouseDown(mouse) => {
@@ -237,7 +243,7 @@ impl Widget<String> for TextBox {
237243
}
238244
}
239245

240-
fn lifecycle(&mut self, ctx: &mut LifeCycleCtx, event: &LifeCycle, data: &String, env: &Env) {
246+
fn lifecycle(&mut self, ctx: &mut LifeCycleCtx, event: &LifeCycle, data: &T, env: &Env) {
241247
match event {
242248
LifeCycle::WidgetAdded => {
243249
ctx.register_for_focus();
@@ -252,7 +258,7 @@ impl Widget<String> for TextBox {
252258
}
253259
}
254260

255-
fn update(&mut self, ctx: &mut UpdateCtx, _: &String, data: &String, env: &Env) {
261+
fn update(&mut self, ctx: &mut UpdateCtx, _: &T, data: &T, env: &Env) {
256262
self.editor.update(ctx, data, env);
257263
if !self.suppress_adjust_hscroll && !self.multiline {
258264
self.update_hscroll(ctx.size().width);
@@ -262,13 +268,7 @@ impl Widget<String> for TextBox {
262268
}
263269
}
264270

265-
fn layout(
266-
&mut self,
267-
ctx: &mut LayoutCtx,
268-
bc: &BoxConstraints,
269-
_data: &String,
270-
env: &Env,
271-
) -> Size {
271+
fn layout(&mut self, ctx: &mut LayoutCtx, bc: &BoxConstraints, _data: &T, env: &Env) -> Size {
272272
self.placeholder.rebuild_if_needed(ctx.text(), env);
273273
if self.multiline {
274274
self.editor
@@ -286,7 +286,7 @@ impl Widget<String> for TextBox {
286286
bc.constrain((width, height))
287287
}
288288

289-
fn paint(&mut self, ctx: &mut PaintCtx, data: &String, env: &Env) {
289+
fn paint(&mut self, ctx: &mut PaintCtx, data: &T, env: &Env) {
290290
let size = ctx.size();
291291
let text_size = self.editor.layout().size();
292292
let background_color = env.get(theme::BACKGROUND_LIGHT);
@@ -357,7 +357,7 @@ impl Widget<String> for TextBox {
357357
}
358358
}
359359

360-
impl Default for TextBox {
360+
impl<T> Default for TextBox<T> {
361361
fn default() -> Self {
362362
TextBox::new()
363363
}

druid/src/widget/widget_ext.rs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -286,21 +286,21 @@ impl<T: Data, W> EnvScope<T, W> {
286286
#[cfg(test)]
287287
mod tests {
288288
use super::*;
289-
use crate::widget::TextBox;
289+
use crate::widget::Slider;
290290
use crate::Color;
291291

292292
#[test]
293293
fn container_reuse() {
294-
// this should be Container<Align<Container<TextBox>>>
295-
let widget = TextBox::new()
294+
// this should be Container<Align<Container<Slider>>>
295+
let widget = Slider::new()
296296
.background(Color::BLACK)
297297
.align_left()
298298
.border(Color::BLACK, 1.0);
299299
assert!(widget.border_is_some());
300300
assert!(!widget.background_is_some());
301301

302-
// this should be Container<TextBox>
303-
let widget = TextBox::new()
302+
// this should be Container<Slider>
303+
let widget = Slider::new()
304304
.background(Color::BLACK)
305305
.border(Color::BLACK, 1.0);
306306
assert!(widget.background_is_some());
@@ -309,12 +309,12 @@ mod tests {
309309

310310
#[test]
311311
fn sized_box_reuse() {
312-
// this should be SizedBox<Align<SizedBox<TextBox>>>
313-
let widget = TextBox::new().fix_height(10.0).align_left().fix_width(1.0);
312+
// this should be SizedBox<Align<SizedBox<Slider>>>
313+
let widget = Slider::new().fix_height(10.0).align_left().fix_width(1.0);
314314
assert_eq!(widget.width_and_height(), (Some(1.0), None));
315315

316-
// this should be SizedBox<TextBox>
317-
let widget = TextBox::new().fix_height(10.0).fix_width(1.0);
316+
// this should be SizedBox<Slider>
317+
let widget = Slider::new().fix_height(10.0).fix_width(1.0);
318318
assert_eq!(widget.width_and_height(), (Some(1.0), Some(10.0)));
319319
}
320320
}

0 commit comments

Comments
 (0)