Renaming: part 2

This commit is contained in:
Alexandre Bury 2019-11-15 11:41:05 -08:00
parent c86eaa5875
commit e1585e176e
46 changed files with 218 additions and 236 deletions

View File

@ -36,6 +36,7 @@ lazy_static = "1"
chrono = "0.4.7"
cfg-if = "0.1.9"
ahash = "0.2.12"
stack_list = "0.1.0"
[dependencies.toml]
optional = true

View File

@ -102,9 +102,9 @@ We could do:
let select = BoxView::with_fixed_size((10, 5), SelectView::<String>::new());
```
But there is another shorter way: the [`Boxable`] trait is conveniently
But there is another shorter way: the [`Resizable`] trait is conveniently
implemented for any `View`, and allow to wrap in a `BoxView` with a chainable
call. `Boxable`, and a few other useful traits, are conveniently bundled in
call. `Resizable`, and a few other useful traits, are conveniently bundled in
the [`traits`] prelude, ready to be imported:
```rust,ignore
@ -140,7 +140,7 @@ replace the layer with a simple dialog.
[`SelectView`]: https://docs.rs/cursive/0/cursive/views/struct.SelectView.html
[`BoxView`]: https://docs.rs/cursive/0/cursive/views/struct.BoxView.html
[`Boxable`]: https://docs.rs/cursive/0/cursive/view/trait.Boxable.html
[`Resizable`]: https://docs.rs/cursive/0/cursive/view/trait.Resizable.html
[`traits`]: https://docs.rs/cursive/0/cursive/traits/index.html
[`SelectView::on_submit`]: https://docs.rs/cursive/0/cursive/views/struct.SelectView.html#method.on_submit

View File

@ -1,5 +1,5 @@
use cursive::theme::{Color, ColorStyle};
use cursive::view::Boxable;
use cursive::traits::Resizable as _;
use cursive::views::Canvas;
use cursive::{Cursive, Printer};

View File

@ -1,4 +1,4 @@
use cursive::views::{CircularFocus, Dialog, TextView};
use cursive::views::{CircularFocus, Dialog, Text};
use cursive::Cursive;
fn main() {
@ -9,7 +9,7 @@ fn main() {
siv.add_layer(
// Most views can be configured in a chainable way
CircularFocus::wrap_tab(
Dialog::around(TextView::new("Hello Dialog!"))
Dialog::around(Text::new("Hello Dialog!"))
.title("Cursive")
.button("Foo", |_s| ())
.button("Quit", |s| s.quit()),

View File

@ -1,5 +1,5 @@
use cursive::traits::*;
use cursive::views::{Dialog, EditView, TextView};
use cursive::views::{Dialog, Edit, Text};
use cursive::Cursive;
fn main() {
@ -14,21 +14,21 @@ fn main() {
// Padding is (left, right, top, bottom)
.padding((1, 1, 1, 0))
.content(
EditView::new()
Edit::new()
// Call `show_popup` when the user presses `Enter`
.on_submit(show_popup)
// Give the `EditView` a name so we can refer to it later.
// Give the `Edit` a name so we can refer to it later.
.with_id("name")
// Wrap this in a `BoxView` with a fixed width.
// Do this _after_ `with_id` or the name will point to the
// `BoxView` instead of `EditView`!
// `BoxView` instead of `Edit`!
.fixed_width(20),
)
.button("Ok", |s| {
// This will run the given closure, *ONLY* if a view with the
// correct type and the given ID is found.
let name = s
.call_on_id("name", |view: &mut EditView| {
.call_on_id("name", |view: &mut Edit| {
// We can return content from the closure!
view.get_content()
})
@ -54,8 +54,7 @@ fn show_popup(s: &mut Cursive, name: &str) {
s.pop_layer();
// And put a new one instead
s.add_layer(
Dialog::around(TextView::new(content))
.button("Quit", |s| s.quit()),
Dialog::around(Text::new(content)).button("Quit", |s| s.quit()),
);
}
}

View File

@ -1,4 +1,4 @@
use cursive::views::TextView;
use cursive::views::Text;
use cursive::Cursive;
fn main() {
@ -8,7 +8,7 @@ fn main() {
siv.add_global_callback('q', Cursive::quit);
// Add a simple view
siv.add_layer(TextView::new(
siv.add_layer(Text::new(
"Hello World!\n\
Press q to quit the application.",
));

View File

@ -29,7 +29,7 @@ impl KeyCodeView {
// Let's implement the `View` trait.
// `View` contains many methods, but only a few are required.
impl View for KeyCodeView {
impl cursive::View for KeyCodeView {
fn draw(&self, printer: &Printer) {
// We simply draw every event from the history.
for (y, line) in self.history.iter().enumerate() {

View File

@ -1,6 +1,6 @@
use cursive::align::HAlign;
use cursive::traits::*;
use cursive::views::{Dialog, DummyView, LinearLayout, TextView};
use cursive::views::{Dialog, Dummy, LinearLayout, Text};
use cursive::Cursive;
// This example uses a LinearLayout to stick multiple views next to each other.
@ -13,19 +13,19 @@ fn main() {
are present, a short title above, and this text. The text \
has a fixed width, and the title is centered horizontally.";
// We'll create a dialog with a TextView serving as a title
// We'll create a dialog with a Text serving as a title
siv.add_layer(
Dialog::around(
LinearLayout::vertical()
.child(TextView::new("Title").h_align(HAlign::Center))
// Use a DummyView as spacer
.child(DummyView.fixed_height(1))
.child(Text::new("Title").h_align(HAlign::Center))
// Use a Dummy as spacer
.child(Dummy.fixed_height(1))
// Disabling scrollable means the view cannot shrink.
.child(TextView::new(text))
.child(Text::new(text))
// The other views will share the remaining space.
.child(TextView::new(text).scrollable())
.child(TextView::new(text).scrollable())
.child(TextView::new(text).scrollable())
.child(Text::new(text).scrollable())
.child(Text::new(text).scrollable())
.child(Text::new(text).scrollable())
.fixed_width(30),
)
.button("Quit", |s| s.quit())

View File

@ -1,32 +1,33 @@
use cursive::traits::*;
use cursive::views::{
Checkbox, Dialog, EditView, LinearLayout, ListView, SelectView, TextView,
};
use cursive::views;
use cursive::Cursive;
// This example uses a ListView.
// This example uses a views::List.
//
// ListView can be used to build forms, with a list of inputs.
// views::List can be used to build forms, with a list of inputs.
fn main() {
let mut siv = Cursive::default();
siv.add_layer(
Dialog::new()
views::Dialog::new()
.title("Please fill out this form")
.button("Ok", |s| s.quit())
.content(
ListView::new()
views::List::new()
// Each child is a single-line view with a label
.child("Name", EditView::new().fixed_width(10))
.child("Name", views::Edit::new().fixed_width(10))
.child(
"Receive spam?",
Checkbox::new().on_change(|s, checked| {
views::Checkbox::new().on_change(|s, checked| {
// Enable/Disable the next field depending on this checkbox
for name in &["email1", "email2"] {
s.call_on_id(name, |view: &mut EditView| {
view.set_enabled(checked)
});
s.call_on_id(
name,
|view: &mut views::Edit| {
view.set_enabled(checked)
},
);
if checked {
s.focus_id("email1").unwrap();
}
@ -37,16 +38,16 @@ fn main() {
"Email",
// Each child must have a height of 1 line,
// but we can still combine multiple views!
LinearLayout::horizontal()
views::LinearLayout::horizontal()
.child(
EditView::new()
views::Edit::new()
.disabled()
.with_id("email1")
.fixed_width(15),
)
.child(TextView::new("@"))
.child(views::Text::new("@"))
.child(
EditView::new()
views::Edit::new()
.disabled()
.with_id("email2")
.fixed_width(10),
@ -56,8 +57,8 @@ fn main() {
.delimiter()
.child(
"Age",
// Popup-mode SelectView are small enough to fit here
SelectView::new()
// Popup-mode views::Select are small enough to fit here
views::Select::new()
.popup()
.item_str("0-18")
.item_str("19-30")
@ -69,7 +70,7 @@ fn main() {
for i in 0..50 {
list.add_child(
&format!("Item {}", i),
EditView::new(),
views::Edit::new(),
);
}
})

View File

@ -76,7 +76,7 @@ impl BufferView {
}
}
impl View for BufferView {
impl cursive::View for BufferView {
fn layout(&mut self, _: Vec2) {
// Before drawing, we'll want to update the buffer
self.update();

View File

@ -1,7 +1,6 @@
use cursive::align::HAlign;
use cursive::view::Scrollable;
use cursive::views::{Dialog, Panel, TextView};
use cursive::Cursive;
use cursive::traits::Scrollable as _;
use cursive::{views, Cursive};
fn main() {
// Read some long text from a file.
@ -15,14 +14,16 @@ fn main() {
// The text is too long to fit on a line, so the view will wrap lines,
// and will adapt to the terminal size.
siv.add_fullscreen_layer(
Dialog::around(Panel::new(TextView::new(content).scrollable()))
.title("Unicode and wide-character support")
// This is the alignment for the button
.h_align(HAlign::Center)
.button("Quit", |s| s.quit()),
views::Dialog::around(views::Panel::new(
views::Text::new(content).scrollable(),
))
.title("Unicode and wide-character support")
// This is the alignment for the button
.h_align(HAlign::Center)
.button("Quit", |s| s.quit()),
);
// Show a popup on top of the view.
siv.add_layer(Dialog::info(
siv.add_layer(views::Dialog::info(
"Try resizing the terminal!\n(Press 'q' to \
quit when you're done.)",
));

View File

@ -1,9 +1,6 @@
use cursive::theme::BaseColor;
use cursive::theme::Color;
use cursive::theme::Effect;
use cursive::theme::Style;
use cursive::theme::{BaseColor, Color, Effect, Style};
use cursive::utils::markup::StyledString;
use cursive::views::{Dialog, TextView};
use cursive::views;
use cursive::Cursive;
fn main() {
@ -16,9 +13,9 @@ fn main() {
Style::from(Color::Light(BaseColor::Blue)).combine(Effect::Bold),
));
// TextView can natively accept StyledString.
// views::Text can natively accept StyledString.
siv.add_layer(
Dialog::around(TextView::new(styled))
views::Dialog::around(views::Text::new(styled))
.button("Hell yeah!", |s| s.quit()),
);

View File

@ -4,7 +4,7 @@ use cursive::direction::Direction;
use cursive::event::{Event, EventResult, MouseButton, MouseEvent};
use cursive::theme::{BaseColor, Color, ColorStyle};
use cursive::vec::Vec2;
use cursive::views::{Button, Dialog, LinearLayout, Panel, SelectView};
use cursive::views::{Button, Dialog, LinearLayout, Panel, Select};
use cursive::Cursive;
use cursive::Printer;
@ -33,7 +33,7 @@ fn show_options(siv: &mut Cursive) {
Dialog::new()
.title("Select difficulty")
.content(
SelectView::new()
Select::new()
.item(
"Easy: 8x8, 10 mines",
game::Options {

View File

@ -1,6 +1,6 @@
use cursive::traits::*;
use cursive::view::{Offset, Position};
use cursive::views::{Dialog, OnEventView, TextView};
use cursive::views::{Dialog, OnEvent, Text};
use cursive::Cursive;
// This example modifies a view after creation.
@ -17,7 +17,7 @@ fn main() {
// We add the P callback on the textview only (and not globally),
// so that we can't call it when the popup is already visible.
siv.add_layer(
OnEventView::new(TextView::new(content).with_id("text"))
OnEvent::new(Text::new(content).with_id("text"))
.on_event('p', |s| show_popup(s)),
);
@ -29,11 +29,11 @@ fn show_popup(siv: &mut Cursive) {
// so the user can see both the popup and the view underneath.
siv.screen_mut().add_layer_at(
Position::new(Offset::Center, Offset::Parent(5)),
Dialog::around(TextView::new("Tak!"))
Dialog::around(Text::new("Tak!"))
.button("Change", |s| {
// Look for a view tagged "text".
// We _know_ it's there, so unwrap it.
s.call_on_id("text", |view: &mut TextView| {
s.call_on_id("text", |view: &mut Text| {
let content = reverse(view.get_content().source());
view.set_content(content);
});

View File

@ -1,6 +1,6 @@
use cursive::view::Position;
use cursive::views::LayerPosition;
use cursive::views::TextView;
use cursive::views::Text;
use cursive::Cursive;
/// Moves top layer by the specified amount
@ -31,7 +31,7 @@ fn main() {
siv.add_global_callback('d', |s| move_top(s, 1, 0));
// Add window to fly around.
siv.add_layer(TextView::new(
siv.add_layer(Text::new(
"Press w,a,s,d to move the window.\n\
Press q to quit the application.",
));

View File

@ -1,6 +1,6 @@
use cursive::traits::*;
use cursive::utils::Counter;
use cursive::views::{Button, Dialog, LinearLayout, ProgressBar, TextView};
use cursive::views::{Button, Dialog, LinearLayout, ProgressBar, Text};
use cursive::Cursive;
use rand::Rng;
use std::cmp::min;
@ -60,7 +60,7 @@ fn coffee_break(s: &mut Cursive) {
s.add_layer(
Dialog::new()
.title("Preparation complete")
.content(TextView::new("Now, the real deal!").center())
.content(Text::new("Now, the real deal!").center())
.button("Again??", phase_2),
);
}
@ -119,7 +119,7 @@ fn final_step(s: &mut Cursive) {
Dialog::new()
.title("Report")
.content(
TextView::new(
Text::new(
"Time travel was a success!\n\
We went forward a few seconds!!",
)

View File

@ -1,4 +1,4 @@
use cursive::views::{Dialog, DummyView, LinearLayout, RadioGroup};
use cursive::views::{Dialog, Dummy, LinearLayout, RadioGroup};
use cursive::Cursive;
// This example uses radio buttons.
@ -24,8 +24,8 @@ fn main() {
.child(color_group.button_str("Green"))
.child(color_group.button_str("Blue")),
)
// A DummyView is used as a spacer
.child(DummyView)
// A Dummy is used as a spacer
.child(Dummy)
.child(
LinearLayout::vertical()
// For the size, we store a number separately

View File

@ -1,5 +1,5 @@
use cursive::view::{Boxable, Identifiable};
use cursive::views::{Dialog, EditView, LinearLayout, TextView};
use cursive::traits::{Identifiable, Resizable};
use cursive::views::{Dialog, Edit, LinearLayout, Text};
use cursive::Cursive;
// This example shows a way to access multiple views at the same time.
@ -12,9 +12,9 @@ fn main() {
siv.add_layer(
Dialog::around(
LinearLayout::vertical()
.child(EditView::new().on_edit(on_edit).with_id("1"))
.child(EditView::new().on_edit(on_edit).with_id("2"))
.child(TextView::new("match").with_id("match"))
.child(Edit::new().on_edit(on_edit).with_id("1"))
.child(Edit::new().on_edit(on_edit).with_id("2"))
.child(Text::new("match").with_id("match"))
.fixed_width(10),
)
.button("Quit", Cursive::quit),
@ -24,19 +24,19 @@ fn main() {
}
// Compare the content of the two edit views,
// and update the TextView accordingly.
// and update the Text accordingly.
//
// We'll ignore the `content` and `cursor` arguments,
// and directly retrieve the content from the `Cursive` root.
fn on_edit(siv: &mut Cursive, _content: &str, _cursor: usize) {
// Get handles for each view.
let edit_1 = siv.find_id::<EditView>("1").unwrap();
let edit_2 = siv.find_id::<EditView>("2").unwrap();
let edit_1 = siv.find_id::<Edit>("1").unwrap();
let edit_2 = siv.find_id::<Edit>("2").unwrap();
// Directly compare references to edit_1 and edit_2.
let matches = edit_1.get_content() == edit_2.get_content();
siv.call_on_id("match", |v: &mut TextView| {
siv.call_on_id("match", |v: &mut Text| {
v.set_content(if matches { "match" } else { "no match" })
});
}

View File

@ -1,5 +1,4 @@
use cursive::traits::Boxable;
use cursive::view::Scrollable;
use cursive::traits::{Resizable, Scrollable};
use cursive::views::{Button, Canvas, Dialog, LinearLayout};
use cursive::Printer;

View File

@ -1,16 +1,16 @@
use cursive::align::HAlign;
use cursive::event::EventResult;
use cursive::traits::*;
use cursive::views::{Dialog, OnEventView, SelectView, TextView};
use cursive::views::{Dialog, OnEvent, Select, Text};
use cursive::Cursive;
// We'll use a SelectView here.
// We'll use a Select here.
//
// A SelectView is a scrollable list of items, from which the user can select
// A Select is a scrollable list of items, from which the user can select
// one.
fn main() {
let mut select = SelectView::new()
let mut select = Select::new()
// Center the text horizontally
.h_align(HAlign::Center)
// Use keyboard to jump to the pressed letters
@ -25,7 +25,7 @@ fn main() {
select.set_on_submit(show_next_window);
// Let's override the `j` and `k` keys for navigation
let select = OnEventView::new(select)
let select = OnEvent::new(select)
.on_pre_event_inner('k', |s, _| {
s.select_up(1);
Some(EventResult::Consumed(None))
@ -53,6 +53,6 @@ fn show_next_window(siv: &mut Cursive, city: &str) {
siv.pop_layer();
let text = format!("{} is a great city!", city);
siv.add_layer(
Dialog::around(TextView::new(text)).button("Quit", |s| s.quit()),
Dialog::around(Text::new(text)).button("Quit", |s| s.quit()),
);
}

View File

@ -1,5 +1,5 @@
use cursive::traits::*;
use cursive::views::{Dialog, SliderView};
use cursive::views::{Dialog, Slider};
use cursive::Cursive;
fn main() {
@ -13,7 +13,7 @@ fn main() {
siv.add_layer(
Dialog::around(
// We give the number of steps in the constructor
SliderView::horizontal(15)
Slider::horizontal(15)
// Sets the initial value
.value(7)
.on_change(|s, v| {

View File

@ -108,7 +108,7 @@ fn build_ui(model: Model) -> impl cursive::view::View {
views::LinearLayout::vertical()
.child(build_selector(Arc::clone(&model)))
.child(build_tester(Arc::clone(&model)))
.child(views::DummyView.fixed_height(1))
.child(views::Dummy.fixed_height(1))
.child(build_log_viewer(Arc::clone(&model)))
}
@ -151,15 +151,15 @@ fn build_selector(model: Model) -> impl cursive::view::View {
let offset = model.lock().unwrap().offset;
views::LinearLayout::horizontal()
.child(
views::EditView::new()
views::Edit::new()
.content(format!("{}", offset))
.with_id("edit")
.min_width(5),
)
.child(views::DummyView.fixed_width(1))
.child(views::Dummy.fixed_width(1))
.child(views::Button::new("Update", move |s| {
if let Some(n) = s
.call_on_id("edit", |edit: &mut views::EditView| {
.call_on_id("edit", |edit: &mut views::Edit| {
edit.get_content()
})
.and_then(|content| content.parse().ok())
@ -176,8 +176,8 @@ fn build_selector(model: Model) -> impl cursive::view::View {
/// Build a view that can run test connections.
fn build_tester(model: Model) -> impl cursive::view::View {
views::LinearLayout::horizontal()
.child(views::TextView::new("Current value:"))
.child(views::DummyView.fixed_width(1))
.child(views::Text::new("Current value:"))
.child(views::Dummy.fixed_width(1))
.child(
views::Canvas::new(model)
.with_draw(|model, printer| {
@ -188,7 +188,7 @@ fn build_tester(model: Model) -> impl cursive::view::View {
})
.with_required_size(|_, _| cursive::Vec2::new(3, 1)),
)
.child(views::DummyView.fixed_width(1))
.child(views::Dummy.fixed_width(1))
.child(views::Button::new("Test", |s| {
if let Err(err) = test_server() {
s.add_layer(

View File

@ -1,5 +1,5 @@
use cursive::theme::{Color, PaletteColor, Theme};
use cursive::views::TextView;
use cursive::views::Text;
use cursive::Cursive;
// This example sets the background color to the terminal default.
@ -15,7 +15,7 @@ fn main() {
// We can quit by pressing `q`
siv.add_global_callback('q', Cursive::quit);
siv.add_layer(TextView::new(
siv.add_layer(Text::new(
"Hello World with default terminal background color!\n\
Press q to quit the application.",
));

View File

@ -1,6 +1,6 @@
use cursive::event::{Event, Key};
use cursive::traits::*;
use cursive::views::{Dialog, EditView, OnEventView, TextArea};
use cursive::views;
use cursive::Cursive;
fn main() {
@ -9,32 +9,32 @@ fn main() {
// The main dialog will just have a textarea.
// Its size expand automatically with the content.
siv.add_layer(
Dialog::new()
views::Dialog::new()
.title("Describe your issue")
.padding((1, 1, 1, 0))
.content(TextArea::new().with_id("text"))
.content(views::TextArea::new().with_id("text"))
.button("Ok", Cursive::quit),
);
// We'll add a find feature!
siv.add_layer(Dialog::info("Hint: press Ctrl-F to find in text!"));
siv.add_layer(views::Dialog::info("Hint: press Ctrl-F to find in text!"));
siv.add_global_callback(Event::CtrlChar('f'), |s| {
// When Ctrl-F is pressed, show the Find popup.
// Pressing the Escape key will discard it.
s.add_layer(
OnEventView::new(
Dialog::new()
views::OnEvent::new(
views::Dialog::new()
.title("Find")
.content(
EditView::new()
views::Edit::new()
.on_submit(find)
.with_id("edit")
.min_width(10),
)
.button("Ok", |s| {
let text = s
.call_on_id("edit", |view: &mut EditView| {
.call_on_id("edit", |view: &mut views::Edit| {
view.get_content()
})
.unwrap();
@ -55,7 +55,7 @@ fn find(siv: &mut Cursive, text: &str) {
// First, remove the find popup
siv.pop_layer();
let res = siv.call_on_id("text", |v: &mut TextArea| {
let res = siv.call_on_id("text", |v: &mut views::TextArea| {
// Find the given text from the text area content
// Possible improvement: search after the current cursor.
if let Some(i) = v.get_content().find(text) {
@ -70,6 +70,6 @@ fn find(siv: &mut Cursive, text: &str) {
if let Some(Err(())) = res {
// If we didn't find anything, tell the user!
siv.add_layer(Dialog::info(format!("`{}` not found", text)));
siv.add_layer(views::Dialog::info(format!("`{}` not found", text)));
}
}

View File

@ -1,4 +1,4 @@
use cursive::views::{Dialog, TextView};
use cursive::views::{Dialog, Text};
use cursive::Cursive;
fn main() {
@ -13,7 +13,7 @@ fn main() {
siv.load_toml(include_str!("../assets/style.toml")).unwrap();
siv.add_layer(
Dialog::around(TextView::new(
Dialog::around(Text::new(
"This application uses a \
custom theme!",
))
@ -25,7 +25,7 @@ fn main() {
#[cfg(not(feature = "toml"))]
{
siv.add_layer(
Dialog::around(TextView::new(
Dialog::around(Text::new(
"Run this example again with the `toml` feature!\n\n\
cargo run --example theme --features toml",
))

View File

@ -1,18 +1,16 @@
use cursive::theme::{BaseColor, BorderStyle, Color, ColorStyle};
use cursive::views::{Dialog, EditView, LinearLayout, TextView};
use cursive::views::{Dialog, Edit, LinearLayout, Text};
use cursive::Cursive;
fn main() {
let mut siv = Cursive::default();
let layout = LinearLayout::vertical()
.child(TextView::new("This is a dynamic theme example!"))
.child(EditView::new().content("Woo! colors!").style(
ColorStyle::new(
Color::Rgb(200, 150, 150),
Color::Dark(BaseColor::Blue),
),
));
.child(Text::new("This is a dynamic theme example!"))
.child(Edit::new().content("Woo! colors!").style(ColorStyle::new(
Color::Rgb(200, 150, 150),
Color::Dark(BaseColor::Blue),
)));
siv.add_layer(
Dialog::around(layout)

View File

@ -1,6 +1,6 @@
use std::io;
use cursive::traits::{Boxable, With};
use cursive::traits::{Resizable, With};
use cursive::utils;
use cursive::views::{Canvas, Dialog, LinearLayout, ProgressBar};
use cursive::Cursive;

View File

@ -9,11 +9,12 @@ use crossbeam_channel::{self, Receiver, Sender};
use crate::backend;
use crate::direction;
use crate::event::{Callback, Event, EventResult};
use crate::printer::Printer;
use crate::theme;
use crate::vec::Vec2;
use crate::view::{self, Finder, IntoBoxedView, Position, View};
use crate::traits::Finder as _;
use crate::view::{self, IntoBoxedView, Position, View};
use crate::views::{self, LayerPosition};
use crate::Printer;
use crate::Vec2;
static DEBUG_VIEW_ID: &str = "_cursive_debug_view";
@ -524,12 +525,12 @@ impl Cursive {
/// # use cursive::traits::*;
/// let mut siv = Cursive::dummy();
///
/// siv.add_layer(views::TextView::new("Text #1").with_id("text"));
/// siv.add_layer(views::Text::new("Text #1").with_id("text"));
///
/// siv.add_global_callback('p', |s| {
/// s.call_on(
/// &view::Selector::Id("text"),
/// |view: &mut views::TextView| {
/// |view: &mut views::Text| {
/// view.set_content("Text #2");
/// },
/// );
@ -558,11 +559,11 @@ impl Cursive {
/// # use cursive::traits::*;
/// let mut siv = Cursive::dummy();
///
/// siv.add_layer(views::TextView::new("Text #1")
/// siv.add_layer(views::Text::new("Text #1")
/// .with_id("text"));
///
/// siv.add_global_callback('p', |s| {
/// s.call_on_id("text", |view: &mut views::TextView| {
/// s.call_on_id("text", |view: &mut views::Text| {
/// view.set_content("Text #2");
/// });
/// });
@ -585,37 +586,37 @@ impl Cursive {
///
/// ```rust
/// # use cursive::Cursive;
/// # use cursive::views::{TextView, ViewRef};
/// # use cursive::views::{Text, ViewRef};
/// # let mut siv = Cursive::dummy();
/// use cursive::traits::Identifiable;
///
/// siv.add_layer(TextView::new("foo").with_id("id"));
/// siv.add_layer(Text::new("foo").with_id("id"));
///
/// // Could be called in a callback
/// let mut view: ViewRef<TextView> = siv.find_id("id").unwrap();
/// let mut view: ViewRef<Text> = siv.find_id("id").unwrap();
/// view.set_content("bar");
/// ```
///
/// Note that you must specify the exact type for the view you're after; for example, using the
/// wrong item type in a `SelectView` will not find anything:
/// wrong item type in a `Select` will not find anything:
///
/// ```rust
/// # use cursive::Cursive;
/// # use cursive::views::{SelectView};
/// # use cursive::views::{Select};
/// # let mut siv = Cursive::dummy();
/// use cursive::traits::Identifiable;
///
/// let select = SelectView::new().item("zero", 0u32).item("one", 1u32);
/// let select = Select::new().item("zero", 0u32).item("one", 1u32);
/// siv.add_layer(select.with_id("select"));
///
/// // Specifying a wrong type will not return anything.
/// assert!(siv.find_id::<SelectView<String>>("select").is_none());
/// assert!(siv.find_id::<Select<String>>("select").is_none());
///
/// // Omitting the type will use the default type, in this case `String`.
/// assert!(siv.find_id::<SelectView>("select").is_none());
/// assert!(siv.find_id::<Select>("select").is_none());
///
/// // But with the correct type, it works fine.
/// assert!(siv.find_id::<SelectView<u32>>("select").is_some());
/// assert!(siv.find_id::<Select<u32>>("select").is_some());
/// ```
///
/// [`Named`]: views/struct.Named.html
@ -688,7 +689,7 @@ impl Cursive {
/// use cursive::{Cursive, views};
/// let mut siv = Cursive::dummy();
///
/// siv.add_layer(views::TextView::new("Hello world!"));
/// siv.add_layer(views::Text::new("Hello world!"));
/// ```
pub fn add_layer<T>(&mut self, view: T)
where

View File

@ -34,11 +34,11 @@
//!
//! ```rust
//! use cursive::Cursive;
//! use cursive::views::TextView;
//! use cursive::views::Text;
//!
//! let mut siv = Cursive::dummy();
//!
//! siv.add_layer(TextView::new("Hello World!\nPress q to quit."));
//! siv.add_layer(Text::new("Hello World!\nPress q to quit."));
//!
//! siv.add_global_callback('q', |s| s.quit());
//!
@ -92,7 +92,6 @@ pub mod views;
mod cursive;
mod printer;
mod rect;
mod with;
mod xy;
mod div;
@ -104,7 +103,7 @@ pub use self::cursive::{CbSink, Cursive, ScreenId};
pub use self::direction::Direction;
pub use self::printer::Printer;
pub use self::rect::Rect;
pub use self::traits::With;
pub use self::vec::Vec2;
pub use self::view::View;
pub use self::with::With;
pub use self::xy::XY;

View File

@ -7,7 +7,7 @@ use crate::theme::{
};
use crate::utils::lines::simple::{prefix, suffix};
use crate::vec::Vec2;
use crate::with::With;
use crate::With;
use enumset::EnumSet;
use std::cmp::min;
use unicode_segmentation::UnicodeSegmentation;

View File

@ -1,15 +0,0 @@
//! Commonly used traits bundled for easy import.
//!
//! This module provides an easy way to import some traits.
//!
//! # Examples
//!
//! ```
//! use cursive::traits::*;
//! ```
#[doc(no_inline)]
pub use crate::view::{Boxable, Finder, Identifiable, Scrollable, View};
#[doc(no_inline)]
pub use crate::With;

View File

@ -1,4 +1,4 @@
use crate::view::{View, ViewPath, ViewWrapper};
use crate::view::{Selector, View, ViewWrapper};
use crate::views::{Named, ViewRef};
use std::any::Any;
@ -77,11 +77,3 @@ impl<T: View> Finder for T {
result
}
}
/// Selects a single view (if any) in the tree.
pub enum Selector<'a> {
/// Selects a view from its ID.
Id(&'a str),
/// Selects a view from its path.
Path(&'a ViewPath),
}

View File

@ -15,19 +15,19 @@ pub trait Identifiable: View + Sized {
///
/// ```rust
/// # use cursive::Cursive;
/// # use cursive::views::TextView;
/// # use cursive::view::Boxable;
/// use cursive::view::Identifiable;
/// # use cursive::views::Text;
/// # use cursive::traits::Resizable;
/// use cursive::traits::Identifiable as _;
///
/// let mut siv = Cursive::dummy();
/// siv.add_layer(
/// TextView::new("foo")
/// Text::new("foo")
/// .with_id("text")
/// .fixed_width(10)
/// );
///
/// // You could call this from an event callback
/// siv.call_on_id("text", |view: &mut TextView| {
/// siv.call_on_id("text", |view: &mut Text| {
/// view.set_content("New content!");
/// });
/// ```
@ -38,7 +38,7 @@ pub trait Identifiable: View + Sized {
/// before other wrappers like [`fixed_width`]. Otherwise, you would be
/// retrieving a [`BoxView`]!
///
/// [`fixed_width`]: trait.Boxable.html#method.fixed_width
/// [`fixed_width`]: trait.Resizable.html#method.fixed_width
/// [`BoxView`]: ../views/struct.BoxView.html
///
fn with_id<S: Into<String>>(self, id: S) -> Named<Self> {

12
src/traits/mod.rs Normal file
View File

@ -0,0 +1,12 @@
//! This module defines some helper traits with blanket implementations.
mod finder;
mod identifiable;
mod resizable;
mod scrollable;
mod with;
pub use self::finder::Finder;
pub use self::identifiable::Identifiable;
pub use self::resizable::Resizable;
pub use self::scrollable::Scrollable;
pub use self::with::With;

View File

@ -5,7 +5,7 @@ use crate::views::Resized;
/// Makes a view wrappable in a [`Resized`].
///
/// [`Resized`]: ../views/struct.Resized.html
pub trait Boxable: View + Sized {
pub trait Resizable: View + Sized {
/// Wraps `self` in a `Resized` with the given size constraints.
fn boxed(
self,
@ -76,4 +76,4 @@ pub trait Boxable: View + Sized {
}
}
impl<T: View> Boxable for T {}
impl<T: View> Resizable for T {}

View File

@ -18,10 +18,10 @@ pub trait AnyView {
/// # Examples
///
/// ```rust
/// # use cursive::views::TextView;
/// # use cursive::views::Text;
/// # use cursive::view::View;
/// let boxed: Box<View> = Box::new(TextView::new("text"));
/// let text: Box<TextView> = boxed.as_boxed_any().downcast().unwrap();
/// let boxed: Box<dyn View> = Box::new(Text::new("text"));
/// let text: Box<Text> = boxed.as_boxed_any().downcast().unwrap();
/// ```
fn as_boxed_any(self: Box<Self>) -> Box<dyn Any>;
}

View File

@ -84,35 +84,28 @@ mod view_wrapper;
// Essentials components
mod any;
mod finder;
mod margins;
mod position;
mod selector;
mod size_cache;
mod size_constraint;
mod view_path;
mod view_trait;
// Helper bases
mod boxable;
mod identifiable;
#[macro_use]
pub mod scroll;
mod scroll_base;
mod scrollable;
mod into_boxed_view;
pub use self::any::AnyView;
pub use self::boxable::Boxable;
pub use self::finder::{Finder, Selector};
pub use self::identifiable::Identifiable;
pub use self::into_boxed_view::IntoBoxedView;
pub use self::margins::Margins;
pub use self::position::{Offset, Position};
pub use self::scroll::ScrollStrategy;
pub use self::scroll_base::ScrollBase;
pub use self::scrollable::Scrollable;
pub use self::selector::Selector;
pub use self::size_cache::SizeCache;
pub use self::size_constraint::SizeConstraint;
pub use self::view_path::ViewPath;

View File

@ -7,7 +7,7 @@ use crate::rect::Rect;
use crate::theme::ColorStyle;
use crate::vec::Vec2;
use crate::view::{ScrollStrategy, Selector, SizeCache};
use crate::with::With;
use crate::With as _;
use crate::XY;
/// Describes an item with a scroll core.

9
src/view/selector.rs Normal file
View File

@ -0,0 +1,9 @@
use crate::view::ViewPath;
/// Selects a single view (if any) in the tree.
pub enum Selector<'a> {
/// Selects a view from its ID.
Id(&'a str),
/// Selects a view from its path.
Path(&'a ViewPath<'a>),
}

View File

@ -1,34 +1,28 @@
/// Represents a path to a single view in the layout.
pub struct ViewPath {
pub struct ViewPath<'a> {
/// List of turns to make on decision nodes when descending the view tree.
/// Simple nodes (with one fixed child) are skipped.
pub path: Vec<usize>,
pub path: stack_list::Node<'a, usize>,
}
new_default!(ViewPath);
impl Default for ViewPath<'_> {
fn default() -> Self {
Self::new()
}
}
impl ViewPath {
impl<'a> ViewPath<'a> {
/// Creates a new empty path.
pub fn new() -> Self {
ViewPath { path: Vec::new() }
}
/// Creates a path from the given item.
pub fn from<T: ToPath>(path: T) -> Self {
path.to_path()
}
}
/// Generic trait for elements that can be converted into a `ViewPath`.
pub trait ToPath {
/// Creates a path from the element.
fn to_path(self) -> ViewPath;
}
impl<'a> ToPath for &'a [usize] {
fn to_path(self) -> ViewPath {
ViewPath {
path: self.to_owned(),
path: stack_list::Node::new(),
}
}
/// Creates a new `ViewPath` with an extra step.
pub fn add(&'a self, n: usize) -> Self {
ViewPath {
path: self.path.prepend(n),
}
}
}

View File

@ -15,11 +15,11 @@ use std::ops::Deref;
/// # Examples
///
/// ```
/// use cursive::views::{Button, LinearLayout, TextView, TextArea};
/// use cursive::traits::Boxable;
/// use cursive::views::{Button, LinearLayout, Text, TextArea};
/// use cursive::traits::Resizable;
///
/// let linear_layout = LinearLayout::horizontal()
/// .child(TextView::new("Top of the page"))
/// .child(Text::new("Top of the page"))
/// .child(TextArea::new().fixed_size((20, 5)))
/// .child(Button::new("Ok", |s| s.quit()));
/// ```

View File

@ -16,13 +16,13 @@ use crate::XY;
/// # Examples
///
/// ```
/// use cursive::views::{Resized, TextView};
/// use cursive::views::{Resized, Text};
///
/// // Creates a 20x4 Resized with a TextView content.
/// let view = Resized::with_fixed_size((20,4), TextView::new("Hello!"));
/// // Creates a 20x4 Resized with a Text content.
/// let view = Resized::with_fixed_size((20,4), Text::new("Hello!"));
/// ```
///
/// See also [`Boxable`](crate::view::Boxable) for an easy way to wrap any view.
/// See also [`Resizable`](crate::traits::Resizable) for an easy way to wrap any view.
pub struct Resized<T: View> {
/// Constraint on each axis
size: XY<SizeConstraint>,
@ -222,29 +222,30 @@ impl<T: View> ViewWrapper for Resized<T> {
#[cfg(test)]
mod tests {
use crate::traits::Resizable as _;
use crate::vec::Vec2;
use crate::view::{Boxable, View};
use crate::views::DummyView;
use crate::view::View;
use crate::views::Dummy;
// No need to test `draw()` method as it's directly forwarded.
#[test]
fn min_size() {
let mut min_w = DummyView.full_screen().min_width(5);
let mut min_w = Dummy.full_screen().min_width(5);
assert_eq!(Vec2::new(5, 1), min_w.required_size(Vec2::new(1, 1)));
assert_eq!(Vec2::new(5, 10), min_w.required_size(Vec2::new(1, 10)));
assert_eq!(Vec2::new(10, 1), min_w.required_size(Vec2::new(10, 1)));
assert_eq!(Vec2::new(10, 10), min_w.required_size(Vec2::new(10, 10)));
let mut min_h = DummyView.full_screen().min_height(5);
let mut min_h = Dummy.full_screen().min_height(5);
assert_eq!(Vec2::new(1, 5), min_h.required_size(Vec2::new(1, 1)));
assert_eq!(Vec2::new(1, 10), min_h.required_size(Vec2::new(1, 10)));
assert_eq!(Vec2::new(10, 5), min_h.required_size(Vec2::new(10, 1)));
assert_eq!(Vec2::new(10, 10), min_h.required_size(Vec2::new(10, 10)));
let mut min_s = DummyView.full_screen().min_size((5, 5));
let mut min_s = Dummy.full_screen().min_size((5, 5));
assert_eq!(Vec2::new(5, 5), min_s.required_size(Vec2::new(1, 1)));
assert_eq!(Vec2::new(5, 10), min_s.required_size(Vec2::new(1, 10)));
@ -254,21 +255,21 @@ mod tests {
#[test]
fn max_size() {
let mut max_w = DummyView.full_screen().max_width(5);
let mut max_w = Dummy.full_screen().max_width(5);
assert_eq!(Vec2::new(1, 1), max_w.required_size(Vec2::new(1, 1)));
assert_eq!(Vec2::new(1, 10), max_w.required_size(Vec2::new(1, 10)));
assert_eq!(Vec2::new(5, 1), max_w.required_size(Vec2::new(10, 1)));
assert_eq!(Vec2::new(5, 10), max_w.required_size(Vec2::new(10, 10)));
let mut max_h = DummyView.full_screen().max_height(5);
let mut max_h = Dummy.full_screen().max_height(5);
assert_eq!(Vec2::new(1, 1), max_h.required_size(Vec2::new(1, 1)));
assert_eq!(Vec2::new(1, 5), max_h.required_size(Vec2::new(1, 10)));
assert_eq!(Vec2::new(10, 1), max_h.required_size(Vec2::new(10, 1)));
assert_eq!(Vec2::new(10, 5), max_h.required_size(Vec2::new(10, 10)));
let mut max_s = DummyView.full_screen().max_size((5, 5));
let mut max_s = Dummy.full_screen().max_size((5, 5));
assert_eq!(Vec2::new(1, 1), max_s.required_size(Vec2::new(1, 1)));
assert_eq!(Vec2::new(1, 5), max_s.required_size(Vec2::new(1, 10)));
@ -278,7 +279,7 @@ mod tests {
#[test]
fn full_screen() {
let mut full = DummyView.full_screen();
let mut full = Dummy.full_screen();
assert_eq!(Vec2::new(1, 1), full.required_size(Vec2::new(1, 1)));
assert_eq!(Vec2::new(1, 10), full.required_size(Vec2::new(1, 10)));
@ -288,17 +289,17 @@ mod tests {
#[test]
fn test_get_inner() {
use crate::views::TextView;
use crate::views::Text;
let parent = TextView::new("abc").full_screen();
let parent = Text::new("abc").full_screen();
let child = parent.get_inner();
assert_eq!(child.get_content().source(), "abc");
}
#[test]
fn test_get_inner_mut() {
use crate::views::TextView;
use crate::views::Text;
let mut parent = TextView::new("").full_screen();
let mut parent = Text::new("").full_screen();
let new_value = "new";
let child = parent.get_inner_mut();

View File

@ -309,7 +309,7 @@ impl Stack {
///
/// ```rust
/// # use cursive::views::{Text, Stack, Dialog, LayerPosition};
/// # use cursive::view::Identifiable;
/// # use cursive::traits::Identifiable;
/// let mut stack = Stack::new();
/// stack.add_layer(Text::new("Back"));
/// stack.add_layer(Dialog::around(Text::new("Middle").with_id("text")));

View File

@ -20,7 +20,7 @@ use unicode_width::UnicodeWidthStr;
/// # Examples
///
/// ```
/// use cursive::traits::{Boxable, Identifiable};
/// use cursive::traits::{Resizable, Identifiable};
/// use cursive::views::TextArea;
///
/// let text_area = TextArea::new()