mirror of
https://github.com/FliegendeWurst/cursive.git
synced 2024-11-23 17:35:00 +00:00
Use StyledString in SelectView
This commit is contained in:
parent
612c7d9ea7
commit
6b278495d5
@ -84,9 +84,24 @@ impl<'a, 'b> Printer<'a, 'b> {
|
|||||||
.clear(self.theme.palette[PaletteColor::Background]);
|
.clear(self.theme.palette[PaletteColor::Background]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Prints some styled text at the given position.
|
||||||
|
pub fn print_styled<S>(
|
||||||
|
&self, start: S, text: ::utils::span::SpannedStr<'_, Style>,
|
||||||
|
) where
|
||||||
|
S: Into<Vec2>,
|
||||||
|
{
|
||||||
|
let Vec2 { mut x, y } = start.into();
|
||||||
|
for span in text.spans() {
|
||||||
|
self.with_style(*span.attr, |printer| {
|
||||||
|
printer.print((x, y), span.content);
|
||||||
|
x += span.content.width();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: use &mut self? We don't *need* it, but it may make sense.
|
// TODO: use &mut self? We don't *need* it, but it may make sense.
|
||||||
// We don't want people to start calling prints in parallel?
|
// We don't want people to start calling prints in parallel?
|
||||||
/// Prints some text at the given position relative to the window.
|
/// Prints some text at the given position
|
||||||
pub fn print<S: Into<Vec2>>(&self, start: S, text: &str) {
|
pub fn print<S: Into<Vec2>>(&self, start: S, text: &str) {
|
||||||
// Where we are asked to start printing. Oh boy.
|
// Where we are asked to start printing. Oh boy.
|
||||||
let start = start.into();
|
let start = start.into();
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
//! This module defines various structs describing a span of text from a
|
//! This module defines various structs describing a span of text from a
|
||||||
//! larger string.
|
//! larger string.
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
use unicode_width::UnicodeWidthStr;
|
||||||
|
|
||||||
/// A string with associated spans.
|
/// A string with associated spans.
|
||||||
///
|
///
|
||||||
@ -117,11 +118,12 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Gives access to the parsed styled spans.
|
/// Gives access to the parsed styled spans.
|
||||||
pub fn spans(&self) -> Vec<Span<'a, T>> {
|
pub fn spans<'b>(&'b self) -> impl Iterator<Item = Span<'a, T>> + 'b
|
||||||
self.spans
|
where
|
||||||
.iter()
|
'a: 'b,
|
||||||
.map(|span| span.resolve(self.source))
|
{
|
||||||
.collect()
|
let source = self.source;
|
||||||
|
self.spans.iter().map(move |span| span.resolve(source))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a reference to the indexed spans.
|
/// Returns a reference to the indexed spans.
|
||||||
@ -232,12 +234,9 @@ impl<T> SpannedString<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Gives access to the parsed styled spans.
|
/// Gives access to the parsed styled spans.
|
||||||
#[cfg_attr(feature = "cargo-clippy", allow(needless_lifetimes))]
|
pub fn spans<'a>(&'a self) -> impl Iterator<Item = Span<'a, T>> {
|
||||||
pub fn spans<'a>(&'a self) -> Vec<Span<'a, T>> {
|
let source = &self.source;
|
||||||
self.spans
|
self.spans.iter().map(move |span| span.resolve(source))
|
||||||
.iter()
|
|
||||||
.map(|span| span.resolve(&self.source))
|
|
||||||
.collect()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a reference to the indexed spans.
|
/// Returns a reference to the indexed spans.
|
||||||
@ -256,6 +255,13 @@ impl<T> SpannedString<T> {
|
|||||||
pub fn is_empty(&self) -> bool {
|
pub fn is_empty(&self) -> bool {
|
||||||
self.source.is_empty() || self.spans.is_empty()
|
self.source.is_empty() || self.spans.is_empty()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the width taken by this string.
|
||||||
|
///
|
||||||
|
/// This is the sum of the width of each span.
|
||||||
|
pub fn width(&self) -> usize {
|
||||||
|
self.spans().map(|s| s.content.width()).sum()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T> From<&'a SpannedString<T>> for SpannedStr<'a, T> {
|
impl<'a, T> From<&'a SpannedString<T>> for SpannedStr<'a, T> {
|
||||||
|
@ -8,7 +8,7 @@ use std::cell::Cell;
|
|||||||
use std::cmp::min;
|
use std::cmp::min;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use theme::ColorStyle;
|
use theme::ColorStyle;
|
||||||
use unicode_width::UnicodeWidthStr;
|
use utils::markup::StyledString;
|
||||||
use vec::Vec2;
|
use vec::Vec2;
|
||||||
use view::{Position, View};
|
use view::{Position, View};
|
||||||
use views::MenuPopup;
|
use views::MenuPopup;
|
||||||
@ -253,7 +253,7 @@ impl<T: 'static> SelectView<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Adds a item to the list, with given label and value.
|
/// Adds a item to the list, with given label and value.
|
||||||
pub fn add_item<S: Into<String>>(&mut self, label: S, value: T) {
|
pub fn add_item<S: Into<StyledString>>(&mut self, label: S, value: T) {
|
||||||
self.items.push(Item::new(label.into(), value));
|
self.items.push(Item::new(label.into(), value));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -267,13 +267,13 @@ impl<T: 'static> SelectView<T> {
|
|||||||
/// assert_eq!(select.get_item(0), Some(("Short", &1)));
|
/// assert_eq!(select.get_item(0), Some(("Short", &1)));
|
||||||
/// ```
|
/// ```
|
||||||
pub fn get_item(&self, i: usize) -> Option<(&str, &T)> {
|
pub fn get_item(&self, i: usize) -> Option<(&str, &T)> {
|
||||||
self.items
|
self.iter().nth(i)
|
||||||
.get(i)
|
|
||||||
.map(|item| (item.label.as_ref(), &*item.value))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets a mut item at given idx or None.
|
/// Gets a mut item at given idx or None.
|
||||||
pub fn get_item_mut(&mut self, i: usize) -> Option<(&mut String, &mut T)> {
|
pub fn get_item_mut(
|
||||||
|
&mut self, i: usize,
|
||||||
|
) -> Option<(&mut StyledString, &mut T)> {
|
||||||
if i >= self.items.len() {
|
if i >= self.items.len() {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
@ -293,7 +293,7 @@ impl<T: 'static> SelectView<T> {
|
|||||||
pub fn iter(&self) -> impl Iterator<Item = (&str, &T)> {
|
pub fn iter(&self) -> impl Iterator<Item = (&str, &T)> {
|
||||||
self.items
|
self.items
|
||||||
.iter()
|
.iter()
|
||||||
.map(|item| (item.label.as_str(), &*item.value))
|
.map(|item| (item.label.source(), &*item.value))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Removes an item from the list.
|
/// Removes an item from the list.
|
||||||
@ -315,7 +315,7 @@ impl<T: 'static> SelectView<T> {
|
|||||||
/// the right.
|
/// the right.
|
||||||
pub fn insert_item<S>(&mut self, index: usize, label: S, value: T)
|
pub fn insert_item<S>(&mut self, index: usize, label: S, value: T)
|
||||||
where
|
where
|
||||||
S: Into<String>,
|
S: Into<StyledString>,
|
||||||
{
|
{
|
||||||
self.items.insert(index, Item::new(label.into(), value));
|
self.items.insert(index, Item::new(label.into(), value));
|
||||||
}
|
}
|
||||||
@ -328,7 +328,7 @@ impl<T: 'static> SelectView<T> {
|
|||||||
/// Adds all items from from an iterator.
|
/// Adds all items from from an iterator.
|
||||||
pub fn add_all<S, I>(&mut self, iter: I)
|
pub fn add_all<S, I>(&mut self, iter: I)
|
||||||
where
|
where
|
||||||
S: Into<String>,
|
S: Into<StyledString>,
|
||||||
I: IntoIterator<Item = (S, T)>,
|
I: IntoIterator<Item = (S, T)>,
|
||||||
{
|
{
|
||||||
for (s, t) in iter {
|
for (s, t) in iter {
|
||||||
@ -351,7 +351,7 @@ impl<T: 'static> SelectView<T> {
|
|||||||
let l = self.items[i].label.width();
|
let l = self.items[i].label.width();
|
||||||
let x = self.align.h.get_offset(l, printer.size.x);
|
let x = self.align.h.get_offset(l, printer.size.x);
|
||||||
printer.print_hline((0, 0), x, " ");
|
printer.print_hline((0, 0), x, " ");
|
||||||
printer.print((x, 0), &self.items[i].label);
|
printer.print_styled((x, 0), (&self.items[i].label).into());
|
||||||
if l < printer.size.x {
|
if l < printer.size.x {
|
||||||
assert!((l + x) <= printer.size.x);
|
assert!((l + x) <= printer.size.x);
|
||||||
printer.print_hline((x + l, 0), printer.size.x - (l + x), " ");
|
printer.print_hline((x + l, 0), printer.size.x - (l + x), " ");
|
||||||
@ -554,7 +554,7 @@ impl<T: 'static> SelectView<T> {
|
|||||||
let focus = Rc::clone(&self.focus);
|
let focus = Rc::clone(&self.focus);
|
||||||
let on_submit = self.on_submit.as_ref().cloned();
|
let on_submit = self.on_submit.as_ref().cloned();
|
||||||
let value = Rc::clone(&item.value);
|
let value = Rc::clone(&item.value);
|
||||||
tree.add_leaf(item.label.clone(), move |s| {
|
tree.add_leaf(item.label.source(), move |s| {
|
||||||
// TODO: What if an item was removed in the meantime?
|
// TODO: What if an item was removed in the meantime?
|
||||||
focus.set(i);
|
focus.set(i);
|
||||||
if let Some(ref on_submit) = on_submit {
|
if let Some(ref on_submit) = on_submit {
|
||||||
@ -570,7 +570,7 @@ impl<T: 'static> SelectView<T> {
|
|||||||
// This is the offset for the label text.
|
// This is the offset for the label text.
|
||||||
// We'll want to show the popup so that the text matches.
|
// We'll want to show the popup so that the text matches.
|
||||||
// It'll be soo cool.
|
// It'll be soo cool.
|
||||||
let item_length = self.items[focus].label.len();
|
let item_length = self.items[focus].label.width();
|
||||||
let text_offset = (self.last_size.x.saturating_sub(item_length)) / 2;
|
let text_offset = (self.last_size.x.saturating_sub(item_length)) / 2;
|
||||||
// The total offset for the window is:
|
// The total offset for the window is:
|
||||||
// * the last absolute offset at which we drew this view
|
// * the last absolute offset at which we drew this view
|
||||||
@ -698,9 +698,9 @@ impl<T: 'static> View for SelectView<T> {
|
|||||||
let label = &self.items[self.focus()].label;
|
let label = &self.items[self.focus()].label;
|
||||||
|
|
||||||
// And center the text?
|
// And center the text?
|
||||||
let offset = HAlign::Center.get_offset(label.len(), x + 1);
|
let offset = HAlign::Center.get_offset(label.width(), x + 1);
|
||||||
|
|
||||||
printer.print((offset, 0), label);
|
printer.print_styled((offset, 0), label.into());
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
// Non-popup mode: we always print the entire list.
|
// Non-popup mode: we always print the entire list.
|
||||||
@ -772,15 +772,13 @@ impl<T: 'static> View for SelectView<T> {
|
|||||||
|
|
||||||
// We wrap each value in a `Rc` and add a label
|
// We wrap each value in a `Rc` and add a label
|
||||||
struct Item<T> {
|
struct Item<T> {
|
||||||
label: String,
|
label: StyledString,
|
||||||
value: Rc<T>,
|
value: Rc<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Item<T> {
|
impl<T> Item<T> {
|
||||||
fn new(label: String, value: T) -> Self {
|
fn new(label: StyledString, value: T) -> Self {
|
||||||
Item {
|
let value = Rc::new(value);
|
||||||
label,
|
Item { label, value }
|
||||||
value: Rc::new(value),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user