mirror of
https://github.com/FliegendeWurst/cursive.git
synced 2024-11-09 19:00:46 +00:00
Add comments to examples
This commit is contained in:
parent
51eb6bf34c
commit
868e59a4fa
@ -5,6 +5,17 @@ use cursive::theme::{Color, ColorStyle};
|
||||
use cursive::view::Boxable;
|
||||
use cursive::views::Canvas;
|
||||
|
||||
// This example will draw a colored square with a gradient.
|
||||
//
|
||||
// We'll use a Canvas, which lets us only define a draw method.
|
||||
//
|
||||
// We will combine 2 gradients: one for the background,
|
||||
// and one for the foreground.
|
||||
//
|
||||
// Note: color reproduction is not as good on all backends.
|
||||
// termion can do full 16M true colors, but ncurses is currently limited to
|
||||
// 256 colors.
|
||||
|
||||
fn main() {
|
||||
let mut siv = Cursive::new();
|
||||
|
||||
@ -15,28 +26,14 @@ fn main() {
|
||||
siv.run();
|
||||
}
|
||||
|
||||
fn front_color(x: u8, y: u8, x_max: u8, y_max: u8) -> Color {
|
||||
Color::Rgb(
|
||||
x * (255 / x_max),
|
||||
y * (255 / y_max),
|
||||
(x + 2 * y) * (255 / (x_max + 2 * y_max)),
|
||||
)
|
||||
}
|
||||
|
||||
fn back_color(x: u8, y: u8, x_max: u8, y_max: u8) -> Color {
|
||||
Color::Rgb(
|
||||
128 + (2 * y_max + x - 2 * y) * (128 / (x_max + 2 * y_max)),
|
||||
255 - y * (255 / y_max),
|
||||
255 - x * (255 / x_max),
|
||||
)
|
||||
}
|
||||
|
||||
fn draw(_: &(), p: &Printer) {
|
||||
// We use the view size to calibrate the color
|
||||
let x_max = p.size.x as u8;
|
||||
let y_max = p.size.y as u8;
|
||||
|
||||
for x in 0..x_max {
|
||||
for y in 0..y_max {
|
||||
// We'll use a different style for each cell
|
||||
let style = ColorStyle::Custom {
|
||||
front: front_color(x, y, x_max, y_max),
|
||||
back: back_color(x, y, x_max, y_max),
|
||||
@ -48,3 +45,21 @@ fn draw(_: &(), p: &Printer) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Gradient for the front color
|
||||
fn front_color(x: u8, y: u8, x_max: u8, y_max: u8) -> Color {
|
||||
Color::Rgb(
|
||||
x * (255 / x_max),
|
||||
y * (255 / y_max),
|
||||
(x + 2 * y) * (255 / (x_max + 2 * y_max)),
|
||||
)
|
||||
}
|
||||
|
||||
// Gradient for the background color
|
||||
fn back_color(x: u8, y: u8, x_max: u8, y_max: u8) -> Color {
|
||||
Color::Rgb(
|
||||
128 + (2 * y_max + x - 2 * y) * (128 / (x_max + 2 * y_max)),
|
||||
255 - y * (255 / y_max),
|
||||
255 - x * (255 / x_max),
|
||||
)
|
||||
}
|
||||
|
@ -9,6 +9,7 @@ fn main() {
|
||||
|
||||
// Creates a dialog with a single "Quit" button
|
||||
siv.add_layer(
|
||||
// Most views can be configured in a chainable way
|
||||
Dialog::around(TextView::new("Hello Dialog!"))
|
||||
.title("Cursive")
|
||||
.button("Quit", |s| s.quit()),
|
||||
|
@ -13,6 +13,7 @@ fn main() {
|
||||
siv.add_layer(
|
||||
Dialog::new()
|
||||
.title("Enter your name")
|
||||
// Padding is (left, right, top, bottom)
|
||||
.padding((1, 1, 1, 0))
|
||||
.content(
|
||||
EditView::new()
|
||||
@ -21,9 +22,14 @@ fn main() {
|
||||
.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| {
|
||||
// We can return content from the closure!
|
||||
view.get_content()
|
||||
}).unwrap();
|
||||
|
||||
// Run the next step
|
||||
show_popup(s, &name);
|
||||
}),
|
||||
);
|
||||
@ -31,6 +37,8 @@ fn main() {
|
||||
siv.run();
|
||||
}
|
||||
|
||||
// This will replace the current layer with a new popup.
|
||||
// If the name is empty, we'll show an error message instead.
|
||||
fn show_popup(s: &mut Cursive, name: &str) {
|
||||
if name.is_empty() {
|
||||
s.add_layer(Dialog::info("Please enter a name!"));
|
||||
|
@ -9,10 +9,12 @@ fn main() {
|
||||
// We can quit by pressing `q`
|
||||
siv.add_global_callback('q', Cursive::quit);
|
||||
|
||||
// Add a simple view
|
||||
siv.add_layer(TextView::new(
|
||||
"Hello World!\n\
|
||||
Press q to quit the application.",
|
||||
));
|
||||
|
||||
// Run the event loop
|
||||
siv.run();
|
||||
}
|
||||
|
@ -4,14 +4,17 @@ use cursive::{Cursive, Printer};
|
||||
use cursive::event::{Event, EventResult};
|
||||
use cursive::traits::*;
|
||||
|
||||
// This example define a custom view that prints any event it receives.
|
||||
// This is a handy way to check the input received by cursive.
|
||||
|
||||
fn main() {
|
||||
let mut siv = Cursive::new();
|
||||
|
||||
siv.add_layer(KeyCodeView::new(10).full_width().fixed_height(10));
|
||||
|
||||
siv.run();
|
||||
}
|
||||
|
||||
// Our view will have a small history of the last events.
|
||||
struct KeyCodeView {
|
||||
history: Vec<String>,
|
||||
size: usize,
|
||||
@ -28,19 +31,23 @@ impl KeyCodeView {
|
||||
|
||||
impl View for KeyCodeView {
|
||||
fn draw(&self, printer: &Printer) {
|
||||
// We simply draw every event from the history.
|
||||
for (y, line) in self.history.iter().enumerate() {
|
||||
printer.print((0, y), line);
|
||||
}
|
||||
}
|
||||
|
||||
fn on_event(&mut self, event: Event) -> EventResult {
|
||||
// Each line will be a debug-format of the event.
|
||||
let line = format!("{:?}", event);
|
||||
self.history.push(line);
|
||||
|
||||
// Keep a fixed-sized history.
|
||||
while self.history.len() > self.size {
|
||||
self.history.remove(0);
|
||||
}
|
||||
|
||||
// No need to return any callback.
|
||||
EventResult::Consumed(None)
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,9 @@ extern crate cursive;
|
||||
use cursive::Cursive;
|
||||
use cursive::align::HAlign;
|
||||
use cursive::traits::*;
|
||||
use cursive::views::{Dialog, LinearLayout, TextView};
|
||||
use cursive::views::{Dialog, DummyView, LinearLayout, TextView};
|
||||
|
||||
// This example uses a LinearLayout to stick multiple views next to each other.
|
||||
|
||||
fn main() {
|
||||
let mut siv = Cursive::new();
|
||||
@ -18,12 +20,16 @@ fn main() {
|
||||
Dialog::around(
|
||||
LinearLayout::vertical()
|
||||
.child(TextView::new("Title").h_align(HAlign::Center))
|
||||
// Box the textview, so it doesn't get too wide.
|
||||
// A 0 height value means it will be unconstrained.
|
||||
.child(TextView::new(text).scrollable(false).fixed_width(30))
|
||||
.child(TextView::new(text).fixed_width(30))
|
||||
.child(TextView::new(text).fixed_width(30))
|
||||
.child(TextView::new(text).fixed_width(30)),
|
||||
// Dummy views can be used for spacing
|
||||
.child(DummyView.fixed_height(1))
|
||||
// Disabling scrolling means the view cannot shrink.
|
||||
// Try resizing the window, and see what happens!
|
||||
.child(TextView::new(text).scrollable(false))
|
||||
.child(TextView::new(text))
|
||||
.child(TextView::new(text))
|
||||
.child(TextView::new(text))
|
||||
// Give everything a fixed width so it doesn't get too wide
|
||||
.fixed_width(30),
|
||||
).button("Quit", |s| s.quit())
|
||||
.h_align(HAlign::Center),
|
||||
);
|
||||
|
@ -5,6 +5,10 @@ use cursive::traits::*;
|
||||
use cursive::views::{Checkbox, Dialog, EditView, LinearLayout, ListView,
|
||||
SelectView, TextView};
|
||||
|
||||
// This example uses a ListView.
|
||||
//
|
||||
// ListView can be used to build forms, with a list of inputs.
|
||||
|
||||
fn main() {
|
||||
let mut siv = Cursive::new();
|
||||
|
||||
@ -14,10 +18,12 @@ fn main() {
|
||||
.button("Ok", |s| s.quit())
|
||||
.content(
|
||||
ListView::new()
|
||||
// Each child is a single-line view with a label
|
||||
.child("Name", EditView::new().fixed_width(10))
|
||||
.child(
|
||||
"Receive spam?",
|
||||
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)
|
||||
@ -30,6 +36,8 @@ fn main() {
|
||||
)
|
||||
.child(
|
||||
"Email",
|
||||
// Each child must have a height of 1 line,
|
||||
// but we can still combine multiple views!
|
||||
LinearLayout::horizontal()
|
||||
.child(
|
||||
EditView::new()
|
||||
@ -45,9 +53,11 @@ fn main() {
|
||||
.fixed_width(10),
|
||||
),
|
||||
)
|
||||
// Delimiter currently are just a blank line
|
||||
.delimiter()
|
||||
.child(
|
||||
"Age",
|
||||
// Popup-mode SelectView are small enough to fit here
|
||||
SelectView::new()
|
||||
.popup()
|
||||
.item_str("0-18")
|
||||
@ -56,6 +66,7 @@ fn main() {
|
||||
.item_str("41+"),
|
||||
)
|
||||
.with(|list| {
|
||||
// We can also add children procedurally
|
||||
for i in 0..50 {
|
||||
list.add_child(
|
||||
&format!("Item {}", i),
|
||||
|
@ -8,6 +8,10 @@ use std::sync::mpsc;
|
||||
use std::thread;
|
||||
use std::time::Duration;
|
||||
|
||||
// This example will print a stream of logs generated from a separate thread.
|
||||
//
|
||||
// We will use a custom view using a channel to receive data asynchronously.
|
||||
|
||||
fn main() {
|
||||
// As usual, create the Cursive root
|
||||
let mut siv = Cursive::new();
|
||||
|
@ -18,6 +18,7 @@ fn main() {
|
||||
// and will adapt to the terminal size.
|
||||
siv.add_fullscreen_layer(
|
||||
Dialog::around(Panel::new(TextView::new(content)))
|
||||
// This is the alignment for the button
|
||||
.h_align(HAlign::Center)
|
||||
.button("Quit", |s| s.quit())
|
||||
.full_screen(),
|
||||
|
@ -12,12 +12,15 @@ use cursive::views::{Dialog, TextView};
|
||||
fn main() {
|
||||
let mut siv = Cursive::new();
|
||||
|
||||
// If markdown is enabled, parse a small text.
|
||||
|
||||
#[cfg(feature = "markdown")]
|
||||
let text = markdown::parse("Isn't *that* **cool**?");
|
||||
|
||||
#[cfg(not(feature = "markdown"))]
|
||||
let text = "Rebuild with --features markdown ;)";
|
||||
|
||||
// TextView can natively accept StyledString.
|
||||
siv.add_layer(
|
||||
Dialog::around(TextView::new(text)).button("Hell yeah!", |s| s.quit()),
|
||||
);
|
||||
|
@ -7,6 +7,9 @@ use cursive::traits::*;
|
||||
use cursive::views::Dialog;
|
||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
|
||||
// This examples shows how to configure and use a menubar at the top of the
|
||||
// application.
|
||||
|
||||
fn main() {
|
||||
let mut siv = Cursive::new();
|
||||
|
||||
|
@ -5,26 +5,7 @@ use cursive::traits::*;
|
||||
use cursive::view::{Offset, Position};
|
||||
use cursive::views::{Dialog, OnEventView, TextView};
|
||||
|
||||
fn show_popup(siv: &mut Cursive) {
|
||||
// Let's center the popup horizontally, but offset it down a few rows
|
||||
siv.screen_mut().add_layer_at(
|
||||
Position::new(Offset::Center, Offset::Parent(3)),
|
||||
Dialog::around(TextView::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| {
|
||||
let content = reverse(view.get_content().source());
|
||||
view.set_content(content);
|
||||
});
|
||||
})
|
||||
.dismiss_button("Ok"),
|
||||
);
|
||||
}
|
||||
|
||||
fn reverse(text: &str) -> String {
|
||||
text.chars().rev().collect()
|
||||
}
|
||||
// This example modifies a view after creation.
|
||||
|
||||
fn main() {
|
||||
let mut siv = Cursive::new();
|
||||
@ -44,3 +25,29 @@ fn main() {
|
||||
|
||||
siv.run();
|
||||
}
|
||||
|
||||
fn show_popup(siv: &mut Cursive) {
|
||||
// Let's center the popup horizontally, but offset it down a few rows,
|
||||
// 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!"))
|
||||
.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| {
|
||||
let content = reverse(view.get_content().source());
|
||||
view.set_content(content);
|
||||
});
|
||||
})
|
||||
.dismiss_button("Ok"),
|
||||
);
|
||||
}
|
||||
|
||||
// This just reverses each character
|
||||
//
|
||||
// Note: it would be more correct to iterate on graphemes instead.
|
||||
// Check the unicode_segmentation crate!
|
||||
fn reverse(text: &str) -> String {
|
||||
text.chars().rev().collect()
|
||||
}
|
||||
|
@ -10,6 +10,12 @@ use std::cmp::min;
|
||||
use std::thread;
|
||||
use std::time::Duration;
|
||||
|
||||
// This example shows a ProgressBar reporting the status from an asynchronous
|
||||
// job.
|
||||
//
|
||||
// It works by sharing a counter with the job thread. This counter can be
|
||||
// "ticked" to indicate progress.
|
||||
|
||||
fn main() {
|
||||
let mut siv = Cursive::new();
|
||||
|
||||
@ -27,15 +33,6 @@ fn main() {
|
||||
siv.run();
|
||||
}
|
||||
|
||||
// Function to simulate a long process.
|
||||
fn fake_load(n_max: usize, counter: &Counter) {
|
||||
for _ in 0..n_max {
|
||||
thread::sleep(Duration::from_millis(5));
|
||||
// The `counter.tick()` method increases the progress value
|
||||
counter.tick(1);
|
||||
}
|
||||
}
|
||||
|
||||
fn phase_1(s: &mut Cursive) {
|
||||
// Phase 1 is easy: a simple pre-loading.
|
||||
|
||||
@ -48,6 +45,7 @@ fn phase_1(s: &mut Cursive) {
|
||||
s.pop_layer();
|
||||
s.add_layer(Dialog::around(
|
||||
ProgressBar::new()
|
||||
// We need to know how many ticks represent a full bar.
|
||||
.range(0, n_max)
|
||||
.with_task(move |counter| {
|
||||
// This closure will be called in a separate thread.
|
||||
@ -131,3 +129,12 @@ fn final_step(s: &mut Cursive) {
|
||||
.button("That's it?", |s| s.quit()),
|
||||
);
|
||||
}
|
||||
|
||||
// Function to simulate a long process.
|
||||
fn fake_load(n_max: usize, counter: &Counter) {
|
||||
for _ in 0..n_max {
|
||||
thread::sleep(Duration::from_millis(5));
|
||||
// The `counter.tick()` method increases the progress value
|
||||
counter.tick(1);
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,8 @@ extern crate cursive;
|
||||
use cursive::Cursive;
|
||||
use cursive::views::{Dialog, DummyView, LinearLayout, RadioGroup};
|
||||
|
||||
// This example uses radio buttons.
|
||||
|
||||
fn main() {
|
||||
let mut siv = Cursive::new();
|
||||
|
||||
@ -17,13 +19,16 @@ fn main() {
|
||||
.content(LinearLayout::horizontal()
|
||||
.child(LinearLayout::vertical()
|
||||
// The color group uses the label itself as stored value
|
||||
// By default, the first item is selected.
|
||||
.child(color_group.button_str("Red"))
|
||||
.child(color_group.button_str("Green"))
|
||||
.child(color_group.button_str("Blue")))
|
||||
// A DummyView is used as a spacer
|
||||
.child(DummyView)
|
||||
.child(LinearLayout::vertical()
|
||||
// For the size, we store a number separately
|
||||
.child(size_group.button(5, "Small"))
|
||||
// The initial selection can also be overriden
|
||||
.child(size_group.button(15, "Medium").selected())
|
||||
// The large size is out of stock, sorry!
|
||||
.child(size_group.button(25, "Large").disabled())))
|
||||
@ -34,9 +39,8 @@ fn main() {
|
||||
|
||||
s.pop_layer();
|
||||
// And we simply print the result.
|
||||
s.add_layer(Dialog::text(format!("Color: {}\nSize: {}cm",
|
||||
color,
|
||||
size))
|
||||
let text = format!("Color: {}\nSize: {}cm", color, size);
|
||||
s.add_layer(Dialog::text(text)
|
||||
.button("Ok", |s| s.quit()));
|
||||
}),
|
||||
);
|
||||
|
@ -4,6 +4,8 @@ use cursive::Cursive;
|
||||
use cursive::view::{Boxable, Identifiable};
|
||||
use cursive::views::{Dialog, EditView, LinearLayout, TextView};
|
||||
|
||||
// This example shows a way to access multiple views at the same time.
|
||||
|
||||
fn main() {
|
||||
let mut siv = Cursive::new();
|
||||
|
||||
@ -34,6 +36,7 @@ fn on_edit(siv: &mut Cursive, _content: &str, _cursor: usize) {
|
||||
|
||||
// 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| {
|
||||
v.set_content(if matches { "match" } else { "no match" })
|
||||
});
|
||||
|
@ -6,6 +6,11 @@ use cursive::event::EventResult;
|
||||
use cursive::traits::*;
|
||||
use cursive::views::{Dialog, OnEventView, SelectView, TextView};
|
||||
|
||||
// We'll use a SelectView here.
|
||||
//
|
||||
// A SelectView is a scrollable list of items, from which the user can select
|
||||
// one.
|
||||
|
||||
fn main() {
|
||||
let mut select = SelectView::new().h_align(HAlign::Center);
|
||||
|
||||
|
@ -7,12 +7,16 @@ use cursive::views::{Dialog, SliderView};
|
||||
fn main() {
|
||||
let mut siv = Cursive::new();
|
||||
|
||||
siv.add_global_callback('q', |s| s.quit());
|
||||
|
||||
// Let's add a simple slider in a dialog.
|
||||
// Moving the slider will update the dialog's title.
|
||||
// And pressing "Enter" will show a new dialog.
|
||||
siv.add_layer(
|
||||
Dialog::around(
|
||||
// We give the number of steps in the constructor
|
||||
SliderView::horizontal(15)
|
||||
// Sets the initial value
|
||||
.value(7)
|
||||
.on_change(|s, v| {
|
||||
let title = format!("[ {} ]", v);
|
||||
|
@ -4,19 +4,19 @@ use cursive::Cursive;
|
||||
use cursive::theme::{Color, Theme};
|
||||
use cursive::views::TextView;
|
||||
|
||||
fn custom_theme_from_cursive(siv: &Cursive) -> Theme {
|
||||
let mut theme = siv.current_theme().clone();
|
||||
theme.colors.background = Color::TerminalDefault;
|
||||
theme
|
||||
}
|
||||
// This example sets the background color to the terminal default.
|
||||
//
|
||||
// This way, it looks more natural.
|
||||
|
||||
fn main() {
|
||||
let mut siv = Cursive::new();
|
||||
|
||||
let theme = custom_theme_from_cursive(&siv);
|
||||
siv.set_theme(theme);
|
||||
|
||||
// We can quit by pressing `q`
|
||||
siv.add_global_callback('q', Cursive::quit);
|
||||
siv.set_theme(theme);
|
||||
|
||||
|
||||
siv.add_layer(TextView::new(
|
||||
"Hello World with default terminal background color!\n\
|
||||
@ -25,3 +25,12 @@ fn main() {
|
||||
|
||||
siv.run();
|
||||
}
|
||||
|
||||
fn custom_theme_from_cursive(siv: &Cursive) -> Theme {
|
||||
// We'll return the current theme with a small modification.
|
||||
let mut theme = siv.current_theme().clone();
|
||||
|
||||
theme.colors.background = Color::TerminalDefault;
|
||||
|
||||
theme
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user