Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

[WIP] Return events from TextEdit #1137

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ fnv = "1.0"
num = "0.1.30"
pistoncore-input = "0.20.0"
rusttype = { version = "0.4.0", features = ["gpu_cache"] }
smallstring = "0.1"
void = "1"

# Optional dependencies and features
# ----------------------------------
Expand Down
2 changes: 1 addition & 1 deletion examples/text_edit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ mod feature {
.restrict_to_height(false) // Let the height grow infinitely and scroll.
.set(ids.text_edit, ui)
{
*demo_text = edit;
edit.apply(demo_text);
}

widget::Scrollbar::y_axis(ids.canvas).auto_hide(true).set(ids.scrollbar, ui);
Expand Down
2 changes: 2 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ extern crate fnv;
extern crate num;
extern crate input as piston_input;
extern crate rusttype;
extern crate smallstring;
extern crate void;

#[cfg(feature="glium")] #[macro_use] pub extern crate glium;
#[cfg(feature="gfx_rs")] #[macro_use] pub extern crate gfx;
Expand Down
66 changes: 48 additions & 18 deletions src/widget/text_box.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
//! A widget for displaying and mutating a one-line field of text.

use std::borrow::Cow;

use {Color, Colorable, FontSize, Borderable, Positionable, Sizeable, Widget};
use event;
use input;
use position::{Range, Rect, Scalar};
use text;
use widget;
use widget::text_edit::TextEvent;

/// A widget for displaying and mutating a small, one-line field of text, given by the user in the
/// form of a `String`.
Expand Down Expand Up @@ -161,34 +164,61 @@ impl<'a> Widget for TextBox<'a> {

let text_color = style.text_color(ui.theme());
let font_id = style.font_id(&ui.theme).or(ui.fonts.ids().next());
if let Some(new_string) = widget::TextEdit::new(text)

// TODO: work on event passthrough... that is, having TextBox also do the same thing of returning TextEvents.


// This is a way to get "enter" events passed through, without them actually applying to text.
// We create an EnterPressedPlaceholder whenever '\n' is pressed, then grab it on the way out
// and create an Event::Return.
struct EnterPressedPlaceholder;

let transfomer = |event| -> TextEvent<EnterPressedPlaceholder> {
match event {
TextEvent::Splice { start_index: _, length, ref text } if length == 0 && &**text == "\n" => {
// TODO: handle the case where some other text then "Enter" then other text was submitted...
// this will require having event_transformer return SmallVec<[TextEvent; 1]> & making it easy
// to accommodate that in text_edit's post-event checks.

TextEvent::PassthroughData { data: EnterPressedPlaceholder }
},
other => other.into_specific_event(),
}
};

let inner_events = widget::TextEdit::with_transform(text, transfomer)
.and_then(font_id, widget::TextEdit::font_id)
.wh(text_rect.dim())
.xy(text_rect.xy())
.font_size(font_size)
.color(text_color)
.justify(justify)
.parent(id)
.set(state.ids.text_edit, ui)
{
events.push(Event::Update(new_string));
}

// Produce an event for any `Enter`/`Return` presses.
//
// TODO: We should probably be doing this via the `TextEdit` widget.
for widget_event in ui.widget_input(state.ids.text_edit).events() {
match widget_event {
event::Widget::Press(press) => match press.button {
event::Button::Keyboard(key) => match key {
input::Key::Return => events.push(Event::Enter),
_ => (),
},
_ => (),
.set(state.ids.text_edit, ui);

// this is inefficient, but it will be replaced with events being passed through eventually.
let mut updated_string = Cow::Borrowed(text);
let mut updates_included = false;
for event in inner_events {
match event {
TextEvent::PassthroughData { data: EnterPressedPlaceholder } => {
if !updates_included {
updates_included = true;
events.push(Event::Update(updated_string.as_ref().to_owned()));
}
events.push(Event::Enter);
},
_ => (),
other => {
if !other.no_op() {
updates_included = false;
other.apply(updated_string.to_mut());
}
}
}
}
if !updates_included {
events.push(Event::Update(updated_string.into_owned()));
}

events
}
Expand Down
Loading