pub struct Span<'a> {
pub style: Style,
pub content: Cow<'a, str>,
}
Expand description
Represents a part of a line that is contiguous and where all characters share the same style.
A Span
is the smallest unit of text that can be styled. It is usually combined in the Line
type to represent a line of text where each Span
may have a different style.
§Constructor Methods
Span::default
creates an span with empty content and the default style.Span::raw
creates an span with the specified content and the default style.Span::styled
creates an span with the specified content and style.
§Setter Methods
These methods are fluent setters. They return a new Span
with the specified property set.
Span::content
sets the content of the span.Span::style
sets the style of the span.
§Other Methods
Span::patch_style
patches the style of the span, adding modifiers from the given style.Span::reset_style
resets the style of the span.Span::width
returns the unicode width of the content held by this span.Span::styled_graphemes
returns an iterator over the graphemes held by this span.
§Examples
A Span
with style
set to Style::default()
can be created from a &str
, a String
, or
any type convertible to Cow<str>
.
use ratatui::text::Span;
let span = Span::raw("test content");
let span = Span::raw(String::from("test content"));
let span = Span::from("test content");
let span = Span::from(String::from("test content"));
let span: Span = "test content".into();
let span: Span = String::from("test content").into();
Styled spans can be created using Span::styled
or by converting strings using methods from
the Stylize
trait.
use ratatui::{
style::{Style, Stylize},
text::Span,
};
let span = Span::styled("test content", Style::new().green());
let span = Span::styled(String::from("test content"), Style::new().green());
// using Stylize trait shortcuts
let span = "test content".green();
let span = String::from("test content").green();
Span
implements the Styled
trait, which allows it to be styled using the shortcut methods
defined in the Stylize
trait.
use ratatui::{style::Stylize, text::Span};
let span = Span::raw("test content").green().on_yellow().italic();
let span = Span::raw(String::from("test content"))
.green()
.on_yellow()
.italic();
Span
implements the Widget
trait, which allows it to be rendered to a Buffer
. Usually
apps will use the Paragraph
widget instead of rendering Span
directly, as it handles text
wrapping and alignment for you.
use ratatui::{style::Stylize, Frame};
frame.render_widget("test content".green().on_yellow().italic(), frame.area());
Fields§
§style: Style
The style of the span.
content: Cow<'a, str>
The content of the span as a Clone-on-write string.
Implementations§
Source§impl<'a> Span<'a>
impl<'a> Span<'a>
Sourcepub fn raw<T>(content: T) -> Self
pub fn raw<T>(content: T) -> Self
Create a span with the default style.
§Examples
use ratatui::text::Span;
Span::raw("test content");
Span::raw(String::from("test content"));
Examples found in repository?
132 fn render_animated_chart(&self, frame: &mut Frame, area: Rect) {
133 let x_labels = vec![
134 Span::styled(
135 format!("{}", self.window[0]),
136 Style::default().add_modifier(Modifier::BOLD),
137 ),
138 Span::raw(format!("{}", (self.window[0] + self.window[1]) / 2.0)),
139 Span::styled(
140 format!("{}", self.window[1]),
141 Style::default().add_modifier(Modifier::BOLD),
142 ),
143 ];
144 let datasets = vec![
145 Dataset::default()
146 .name("data2")
147 .marker(symbols::Marker::Dot)
148 .style(Style::default().fg(Color::Cyan))
149 .data(&self.data1),
150 Dataset::default()
151 .name("data3")
152 .marker(symbols::Marker::Braille)
153 .style(Style::default().fg(Color::Yellow))
154 .data(&self.data2),
155 ];
156
157 let chart = Chart::new(datasets)
158 .block(Block::bordered())
159 .x_axis(
160 Axis::default()
161 .title("X Axis")
162 .style(Style::default().fg(Color::Gray))
163 .labels(x_labels)
164 .bounds(self.window),
165 )
166 .y_axis(
167 Axis::default()
168 .title("Y Axis")
169 .style(Style::default().fg(Color::Gray))
170 .labels(["-20".bold(), "0".into(), "20".bold()])
171 .bounds([-20.0, 20.0]),
172 );
173
174 frame.render_widget(chart, area);
175 }
More examples
231fn draw(frame: &mut Frame, downloads: &Downloads) {
232 let area = frame.area();
233
234 let block = Block::new().title(Line::from("Progress").centered());
235 frame.render_widget(block, area);
236
237 let vertical = Layout::vertical([Constraint::Length(2), Constraint::Length(4)]).margin(1);
238 let horizontal = Layout::horizontal([Constraint::Percentage(20), Constraint::Percentage(80)]);
239 let [progress_area, main] = vertical.areas(area);
240 let [list_area, gauge_area] = horizontal.areas(main);
241
242 // total progress
243 let done = NUM_DOWNLOADS - downloads.pending.len() - downloads.in_progress.len();
244 #[allow(clippy::cast_precision_loss)]
245 let progress = LineGauge::default()
246 .filled_style(Style::default().fg(Color::Blue))
247 .label(format!("{done}/{NUM_DOWNLOADS}"))
248 .ratio(done as f64 / NUM_DOWNLOADS as f64);
249 frame.render_widget(progress, progress_area);
250
251 // in progress downloads
252 let items: Vec<ListItem> = downloads
253 .in_progress
254 .values()
255 .map(|download| {
256 ListItem::new(Line::from(vec![
257 Span::raw(symbols::DOT),
258 Span::styled(
259 format!(" download {:>2}", download.id),
260 Style::default()
261 .fg(Color::LightGreen)
262 .add_modifier(Modifier::BOLD),
263 ),
264 Span::raw(format!(
265 " ({}ms)",
266 download.started_at.elapsed().as_millis()
267 )),
268 ]))
269 })
270 .collect();
271 let list = List::new(items);
272 frame.render_widget(list, list_area);
273
274 #[allow(clippy::cast_possible_truncation)]
275 for (i, (_, download)) in downloads.in_progress.iter().enumerate() {
276 let gauge = Gauge::default()
277 .gauge_style(Style::default().fg(Color::Yellow))
278 .ratio(download.progress / 100.0);
279 if gauge_area.top().saturating_add(i as u16) > area.bottom() {
280 continue;
281 }
282 frame.render_widget(
283 gauge,
284 Rect {
285 x: gauge_area.left(),
286 y: gauge_area.top().saturating_add(i as u16),
287 width: gauge_area.width,
288 height: 1,
289 },
290 );
291 }
292}
169 fn draw(&self, frame: &mut Frame) {
170 let vertical = Layout::vertical([
171 Constraint::Length(1),
172 Constraint::Length(3),
173 Constraint::Min(1),
174 ]);
175 let [help_area, input_area, messages_area] = vertical.areas(frame.area());
176
177 let (msg, style) = match self.input_mode {
178 InputMode::Normal => (
179 vec![
180 "Press ".into(),
181 "q".bold(),
182 " to exit, ".into(),
183 "e".bold(),
184 " to start editing.".bold(),
185 ],
186 Style::default().add_modifier(Modifier::RAPID_BLINK),
187 ),
188 InputMode::Editing => (
189 vec![
190 "Press ".into(),
191 "Esc".bold(),
192 " to stop editing, ".into(),
193 "Enter".bold(),
194 " to record the message".into(),
195 ],
196 Style::default(),
197 ),
198 };
199 let text = Text::from(Line::from(msg)).patch_style(style);
200 let help_message = Paragraph::new(text);
201 frame.render_widget(help_message, help_area);
202
203 let input = Paragraph::new(self.input.as_str())
204 .style(match self.input_mode {
205 InputMode::Normal => Style::default(),
206 InputMode::Editing => Style::default().fg(Color::Yellow),
207 })
208 .block(Block::bordered().title("Input"));
209 frame.render_widget(input, input_area);
210 match self.input_mode {
211 // Hide the cursor. `Frame` does this by default, so we don't need to do anything here
212 InputMode::Normal => {}
213
214 // Make the cursor visible and ask ratatui to put it at the specified coordinates after
215 // rendering
216 #[allow(clippy::cast_possible_truncation)]
217 InputMode::Editing => frame.set_cursor_position(Position::new(
218 // Draw the cursor at the current position in the input field.
219 // This position is can be controlled via the left and right arrow key
220 input_area.x + self.character_index as u16 + 1,
221 // Move one line down, from the border to the input line
222 input_area.y + 1,
223 )),
224 }
225
226 let messages: Vec<ListItem> = self
227 .messages
228 .iter()
229 .enumerate()
230 .map(|(i, m)| {
231 let content = Line::from(Span::raw(format!("{i}: {m}")));
232 ListItem::new(content)
233 })
234 .collect();
235 let messages = List::new(messages).block(Block::bordered().title("Messages"));
236 frame.render_widget(messages, messages_area);
237 }
92 fn draw(&mut self, frame: &mut Frame) {
93 let area = frame.area();
94
95 // Words made "loooong" to demonstrate line breaking.
96 let s =
97 "Veeeeeeeeeeeeeeeery loooooooooooooooooong striiiiiiiiiiiiiiiiiiiiiiiiiing. ";
98 let mut long_line = s.repeat(usize::from(area.width) / s.len() + 4);
99 long_line.push('\n');
100
101 let chunks = Layout::vertical([
102 Constraint::Min(1),
103 Constraint::Percentage(25),
104 Constraint::Percentage(25),
105 Constraint::Percentage(25),
106 Constraint::Percentage(25),
107 ])
108 .split(area);
109
110 let text = vec![
111 Line::from("This is a line "),
112 Line::from("This is a line ".red()),
113 Line::from("This is a line".on_dark_gray()),
114 Line::from("This is a longer line".crossed_out()),
115 Line::from(long_line.clone()),
116 Line::from("This is a line".reset()),
117 Line::from(vec![
118 Span::raw("Masked text: "),
119 Span::styled(Masked::new("password", '*'), Style::new().fg(Color::Red)),
120 ]),
121 Line::from("This is a line "),
122 Line::from("This is a line ".red()),
123 Line::from("This is a line".on_dark_gray()),
124 Line::from("This is a longer line".crossed_out()),
125 Line::from(long_line.clone()),
126 Line::from("This is a line".reset()),
127 Line::from(vec![
128 Span::raw("Masked text: "),
129 Span::styled(Masked::new("password", '*'), Style::new().fg(Color::Red)),
130 ]),
131 ];
132 self.vertical_scroll_state = self.vertical_scroll_state.content_length(text.len());
133 self.horizontal_scroll_state = self.horizontal_scroll_state.content_length(long_line.len());
134
135 let create_block = |title: &'static str| Block::bordered().gray().title(title.bold());
136
137 let title = Block::new()
138 .title_alignment(Alignment::Center)
139 .title("Use h j k l or ◄ ▲ ▼ ► to scroll ".bold());
140 frame.render_widget(title, chunks[0]);
141
142 let paragraph = Paragraph::new(text.clone())
143 .gray()
144 .block(create_block("Vertical scrollbar with arrows"))
145 .scroll((self.vertical_scroll as u16, 0));
146 frame.render_widget(paragraph, chunks[1]);
147 frame.render_stateful_widget(
148 Scrollbar::new(ScrollbarOrientation::VerticalRight)
149 .begin_symbol(Some("↑"))
150 .end_symbol(Some("↓")),
151 chunks[1],
152 &mut self.vertical_scroll_state,
153 );
154
155 let paragraph = Paragraph::new(text.clone())
156 .gray()
157 .block(create_block(
158 "Vertical scrollbar without arrows, without track symbol and mirrored",
159 ))
160 .scroll((self.vertical_scroll as u16, 0));
161 frame.render_widget(paragraph, chunks[2]);
162 frame.render_stateful_widget(
163 Scrollbar::new(ScrollbarOrientation::VerticalLeft)
164 .symbols(scrollbar::VERTICAL)
165 .begin_symbol(None)
166 .track_symbol(None)
167 .end_symbol(None),
168 chunks[2].inner(Margin {
169 vertical: 1,
170 horizontal: 0,
171 }),
172 &mut self.vertical_scroll_state,
173 );
174
175 let paragraph = Paragraph::new(text.clone())
176 .gray()
177 .block(create_block(
178 "Horizontal scrollbar with only begin arrow & custom thumb symbol",
179 ))
180 .scroll((0, self.horizontal_scroll as u16));
181 frame.render_widget(paragraph, chunks[3]);
182 frame.render_stateful_widget(
183 Scrollbar::new(ScrollbarOrientation::HorizontalBottom)
184 .thumb_symbol("🬋")
185 .end_symbol(None),
186 chunks[3].inner(Margin {
187 vertical: 0,
188 horizontal: 1,
189 }),
190 &mut self.horizontal_scroll_state,
191 );
192
193 let paragraph = Paragraph::new(text.clone())
194 .gray()
195 .block(create_block(
196 "Horizontal scrollbar without arrows & custom thumb and track symbol",
197 ))
198 .scroll((0, self.horizontal_scroll as u16));
199 frame.render_widget(paragraph, chunks[4]);
200 frame.render_stateful_widget(
201 Scrollbar::new(ScrollbarOrientation::HorizontalBottom)
202 .thumb_symbol("░")
203 .track_symbol(Some("─")),
204 chunks[4].inner(Margin {
205 vertical: 0,
206 horizontal: 1,
207 }),
208 &mut self.horizontal_scroll_state,
209 );
210 }
Sourcepub fn styled<T, S>(content: T, style: S) -> Self
pub fn styled<T, S>(content: T, style: S) -> Self
Create a span with the specified style.
content
accepts any type that is convertible to Cow<str>
(e.g. &str
, String
,
&String
, etc.).
style
accepts any type that is convertible to Style
(e.g. Style
, Color
, or
your own type that implements Into<Style>
).
§Examples
use ratatui::{
style::{Style, Stylize},
text::Span,
};
let style = Style::new().yellow().on_green().italic();
Span::styled("test content", style);
Span::styled(String::from("test content"), style);
Examples found in repository?
160 fn render_gauge2(&self, area: Rect, buf: &mut Buffer) {
161 let title = title_block("Gauge with ratio and custom label");
162 let label = Span::styled(
163 format!("{:.1}/100", self.progress2),
164 Style::new().italic().bold().fg(CUSTOM_LABEL_COLOR),
165 );
166 Gauge::default()
167 .block(title)
168 .gauge_style(GAUGE2_COLOR)
169 .ratio(self.progress2 / 100.0)
170 .label(label)
171 .render(area, buf);
172 }
More examples
157 fn render_title_bar(&self, area: Rect, buf: &mut Buffer) {
158 let layout = Layout::horizontal([Constraint::Min(0), Constraint::Length(43)]);
159 let [title, tabs] = layout.areas(area);
160
161 Span::styled("Ratatui", THEME.app_title).render(title, buf);
162 let titles = Tab::iter().map(Tab::title);
163 Tabs::new(titles)
164 .style(THEME.tabs)
165 .highlight_style(THEME.tabs_selected)
166 .select(self.tab as usize)
167 .divider("")
168 .padding("", "")
169 .render(tabs, buf);
170 }
171
172 fn render_selected_tab(&self, area: Rect, buf: &mut Buffer) {
173 match self.tab {
174 Tab::About => self.about_tab.render(area, buf),
175 Tab::Recipe => self.recipe_tab.render(area, buf),
176 Tab::Email => self.email_tab.render(area, buf),
177 Tab::Traceroute => self.traceroute_tab.render(area, buf),
178 Tab::Weather => self.weather_tab.render(area, buf),
179 };
180 }
181
182 fn render_bottom_bar(area: Rect, buf: &mut Buffer) {
183 let keys = [
184 ("H/←", "Left"),
185 ("L/→", "Right"),
186 ("K/↑", "Up"),
187 ("J/↓", "Down"),
188 ("D/Del", "Destroy"),
189 ("Q/Esc", "Quit"),
190 ];
191 let spans = keys
192 .iter()
193 .flat_map(|(key, desc)| {
194 let key = Span::styled(format!(" {key} "), THEME.key_binding.key);
195 let desc = Span::styled(format!(" {desc} "), THEME.key_binding.description);
196 [key, desc]
197 })
198 .collect_vec();
199 Line::from(spans)
200 .centered()
201 .style((Color::Indexed(236), Color::Indexed(232)))
202 .render(area, buf);
203 }
128fn create_lines(area: Rect) -> Vec<Line<'static>> {
129 let short_line = "A long line to demonstrate line wrapping. ";
130 let long_line = short_line.repeat(usize::from(area.width) / short_line.len() + 4);
131 let mut styled_spans = vec![];
132 for span in [
133 "Styled".blue(),
134 "Spans".red().on_white(),
135 "Bold".bold(),
136 "Italic".italic(),
137 "Underlined".underlined(),
138 "Strikethrough".crossed_out(),
139 ] {
140 styled_spans.push(span);
141 styled_spans.push(" ".into());
142 }
143 vec![
144 Line::raw("Unstyled Line"),
145 Line::raw("Styled Line").black().on_red().bold().italic(),
146 Line::from(styled_spans),
147 Line::from(long_line.green().italic()),
148 Line::from_iter([
149 "Masked text: ".into(),
150 Span::styled(Masked::new("my secret password", '*'), Color::Red),
151 ]),
152 ]
153}
132 fn render_animated_chart(&self, frame: &mut Frame, area: Rect) {
133 let x_labels = vec![
134 Span::styled(
135 format!("{}", self.window[0]),
136 Style::default().add_modifier(Modifier::BOLD),
137 ),
138 Span::raw(format!("{}", (self.window[0] + self.window[1]) / 2.0)),
139 Span::styled(
140 format!("{}", self.window[1]),
141 Style::default().add_modifier(Modifier::BOLD),
142 ),
143 ];
144 let datasets = vec![
145 Dataset::default()
146 .name("data2")
147 .marker(symbols::Marker::Dot)
148 .style(Style::default().fg(Color::Cyan))
149 .data(&self.data1),
150 Dataset::default()
151 .name("data3")
152 .marker(symbols::Marker::Braille)
153 .style(Style::default().fg(Color::Yellow))
154 .data(&self.data2),
155 ];
156
157 let chart = Chart::new(datasets)
158 .block(Block::bordered())
159 .x_axis(
160 Axis::default()
161 .title("X Axis")
162 .style(Style::default().fg(Color::Gray))
163 .labels(x_labels)
164 .bounds(self.window),
165 )
166 .y_axis(
167 Axis::default()
168 .title("Y Axis")
169 .style(Style::default().fg(Color::Gray))
170 .labels(["-20".bold(), "0".into(), "20".bold()])
171 .bounds([-20.0, 20.0]),
172 );
173
174 frame.render_widget(chart, area);
175 }
170fn run(
171 terminal: &mut Terminal<impl Backend>,
172 workers: Vec<Worker>,
173 mut downloads: Downloads,
174 rx: mpsc::Receiver<Event>,
175) -> Result<()> {
176 let mut redraw = true;
177 loop {
178 if redraw {
179 terminal.draw(|frame| draw(frame, &downloads))?;
180 }
181 redraw = true;
182
183 match rx.recv()? {
184 Event::Input(event) => {
185 if event.code == event::KeyCode::Char('q') {
186 break;
187 }
188 }
189 Event::Resize => {
190 terminal.autoresize()?;
191 }
192 Event::Tick => {}
193 Event::DownloadUpdate(worker_id, _download_id, progress) => {
194 let download = downloads.in_progress.get_mut(&worker_id).unwrap();
195 download.progress = progress;
196 redraw = false;
197 }
198 Event::DownloadDone(worker_id, download_id) => {
199 let download = downloads.in_progress.remove(&worker_id).unwrap();
200 terminal.insert_before(1, |buf| {
201 Paragraph::new(Line::from(vec![
202 Span::from("Finished "),
203 Span::styled(
204 format!("download {download_id}"),
205 Style::default().add_modifier(Modifier::BOLD),
206 ),
207 Span::from(format!(
208 " in {}ms",
209 download.started_at.elapsed().as_millis()
210 )),
211 ]))
212 .render(buf.area, buf);
213 })?;
214 match downloads.next(worker_id) {
215 Some(d) => workers[worker_id].tx.send(d).unwrap(),
216 None => {
217 if downloads.in_progress.is_empty() {
218 terminal.insert_before(1, |buf| {
219 Paragraph::new("Done !").render(buf.area, buf);
220 })?;
221 break;
222 }
223 }
224 };
225 }
226 };
227 }
228 Ok(())
229}
230
231fn draw(frame: &mut Frame, downloads: &Downloads) {
232 let area = frame.area();
233
234 let block = Block::new().title(Line::from("Progress").centered());
235 frame.render_widget(block, area);
236
237 let vertical = Layout::vertical([Constraint::Length(2), Constraint::Length(4)]).margin(1);
238 let horizontal = Layout::horizontal([Constraint::Percentage(20), Constraint::Percentage(80)]);
239 let [progress_area, main] = vertical.areas(area);
240 let [list_area, gauge_area] = horizontal.areas(main);
241
242 // total progress
243 let done = NUM_DOWNLOADS - downloads.pending.len() - downloads.in_progress.len();
244 #[allow(clippy::cast_precision_loss)]
245 let progress = LineGauge::default()
246 .filled_style(Style::default().fg(Color::Blue))
247 .label(format!("{done}/{NUM_DOWNLOADS}"))
248 .ratio(done as f64 / NUM_DOWNLOADS as f64);
249 frame.render_widget(progress, progress_area);
250
251 // in progress downloads
252 let items: Vec<ListItem> = downloads
253 .in_progress
254 .values()
255 .map(|download| {
256 ListItem::new(Line::from(vec![
257 Span::raw(symbols::DOT),
258 Span::styled(
259 format!(" download {:>2}", download.id),
260 Style::default()
261 .fg(Color::LightGreen)
262 .add_modifier(Modifier::BOLD),
263 ),
264 Span::raw(format!(
265 " ({}ms)",
266 download.started_at.elapsed().as_millis()
267 )),
268 ]))
269 })
270 .collect();
271 let list = List::new(items);
272 frame.render_widget(list, list_area);
273
274 #[allow(clippy::cast_possible_truncation)]
275 for (i, (_, download)) in downloads.in_progress.iter().enumerate() {
276 let gauge = Gauge::default()
277 .gauge_style(Style::default().fg(Color::Yellow))
278 .ratio(download.progress / 100.0);
279 if gauge_area.top().saturating_add(i as u16) > area.bottom() {
280 continue;
281 }
282 frame.render_widget(
283 gauge,
284 Rect {
285 x: gauge_area.left(),
286 y: gauge_area.top().saturating_add(i as u16),
287 width: gauge_area.width,
288 height: 1,
289 },
290 );
291 }
292}
92 fn draw(&mut self, frame: &mut Frame) {
93 let area = frame.area();
94
95 // Words made "loooong" to demonstrate line breaking.
96 let s =
97 "Veeeeeeeeeeeeeeeery loooooooooooooooooong striiiiiiiiiiiiiiiiiiiiiiiiiing. ";
98 let mut long_line = s.repeat(usize::from(area.width) / s.len() + 4);
99 long_line.push('\n');
100
101 let chunks = Layout::vertical([
102 Constraint::Min(1),
103 Constraint::Percentage(25),
104 Constraint::Percentage(25),
105 Constraint::Percentage(25),
106 Constraint::Percentage(25),
107 ])
108 .split(area);
109
110 let text = vec![
111 Line::from("This is a line "),
112 Line::from("This is a line ".red()),
113 Line::from("This is a line".on_dark_gray()),
114 Line::from("This is a longer line".crossed_out()),
115 Line::from(long_line.clone()),
116 Line::from("This is a line".reset()),
117 Line::from(vec![
118 Span::raw("Masked text: "),
119 Span::styled(Masked::new("password", '*'), Style::new().fg(Color::Red)),
120 ]),
121 Line::from("This is a line "),
122 Line::from("This is a line ".red()),
123 Line::from("This is a line".on_dark_gray()),
124 Line::from("This is a longer line".crossed_out()),
125 Line::from(long_line.clone()),
126 Line::from("This is a line".reset()),
127 Line::from(vec![
128 Span::raw("Masked text: "),
129 Span::styled(Masked::new("password", '*'), Style::new().fg(Color::Red)),
130 ]),
131 ];
132 self.vertical_scroll_state = self.vertical_scroll_state.content_length(text.len());
133 self.horizontal_scroll_state = self.horizontal_scroll_state.content_length(long_line.len());
134
135 let create_block = |title: &'static str| Block::bordered().gray().title(title.bold());
136
137 let title = Block::new()
138 .title_alignment(Alignment::Center)
139 .title("Use h j k l or ◄ ▲ ▼ ► to scroll ".bold());
140 frame.render_widget(title, chunks[0]);
141
142 let paragraph = Paragraph::new(text.clone())
143 .gray()
144 .block(create_block("Vertical scrollbar with arrows"))
145 .scroll((self.vertical_scroll as u16, 0));
146 frame.render_widget(paragraph, chunks[1]);
147 frame.render_stateful_widget(
148 Scrollbar::new(ScrollbarOrientation::VerticalRight)
149 .begin_symbol(Some("↑"))
150 .end_symbol(Some("↓")),
151 chunks[1],
152 &mut self.vertical_scroll_state,
153 );
154
155 let paragraph = Paragraph::new(text.clone())
156 .gray()
157 .block(create_block(
158 "Vertical scrollbar without arrows, without track symbol and mirrored",
159 ))
160 .scroll((self.vertical_scroll as u16, 0));
161 frame.render_widget(paragraph, chunks[2]);
162 frame.render_stateful_widget(
163 Scrollbar::new(ScrollbarOrientation::VerticalLeft)
164 .symbols(scrollbar::VERTICAL)
165 .begin_symbol(None)
166 .track_symbol(None)
167 .end_symbol(None),
168 chunks[2].inner(Margin {
169 vertical: 1,
170 horizontal: 0,
171 }),
172 &mut self.vertical_scroll_state,
173 );
174
175 let paragraph = Paragraph::new(text.clone())
176 .gray()
177 .block(create_block(
178 "Horizontal scrollbar with only begin arrow & custom thumb symbol",
179 ))
180 .scroll((0, self.horizontal_scroll as u16));
181 frame.render_widget(paragraph, chunks[3]);
182 frame.render_stateful_widget(
183 Scrollbar::new(ScrollbarOrientation::HorizontalBottom)
184 .thumb_symbol("🬋")
185 .end_symbol(None),
186 chunks[3].inner(Margin {
187 vertical: 0,
188 horizontal: 1,
189 }),
190 &mut self.horizontal_scroll_state,
191 );
192
193 let paragraph = Paragraph::new(text.clone())
194 .gray()
195 .block(create_block(
196 "Horizontal scrollbar without arrows & custom thumb and track symbol",
197 ))
198 .scroll((0, self.horizontal_scroll as u16));
199 frame.render_widget(paragraph, chunks[4]);
200 frame.render_stateful_widget(
201 Scrollbar::new(ScrollbarOrientation::HorizontalBottom)
202 .thumb_symbol("░")
203 .track_symbol(Some("─")),
204 chunks[4].inner(Margin {
205 vertical: 0,
206 horizontal: 1,
207 }),
208 &mut self.horizontal_scroll_state,
209 );
210 }
Sourcepub fn style<S: Into<Style>>(self, style: S) -> Self
pub fn style<S: Into<Style>>(self, style: S) -> Self
Sets the style of the span.
This is a fluent setter method which must be chained or used as it consumes self
In contrast to Span::patch_style
, this method replaces the style of the span instead of
patching it.
style
accepts any type that is convertible to Style
(e.g. Style
, Color
, or
your own type that implements Into<Style>
).
§Examples
use ratatui::{
style::{Style, Stylize},
text::Span,
};
let mut span = Span::default().style(Style::new().green());
Sourcepub fn patch_style<S: Into<Style>>(self, style: S) -> Self
pub fn patch_style<S: Into<Style>>(self, style: S) -> Self
Patches the style of the Span, adding modifiers from the given style.
style
accepts any type that is convertible to Style
(e.g. Style
, Color
, or
your own type that implements Into<Style>
).
This is a fluent setter method which must be chained or used as it consumes self
§Example
use ratatui::{
style::{Style, Stylize},
text::Span,
};
let span = Span::styled("test content", Style::new().green().italic())
.patch_style(Style::new().red().on_yellow().bold());
assert_eq!(span.style, Style::new().red().on_yellow().italic().bold());
Sourcepub fn reset_style(self) -> Self
pub fn reset_style(self) -> Self
Resets the style of the Span.
This is Equivalent to calling patch_style(Style::reset())
.
This is a fluent setter method which must be chained or used as it consumes self
§Example
use ratatui::{
style::{Style, Stylize},
text::Span,
};
let span = Span::styled(
"Test Content",
Style::new().dark_gray().on_yellow().italic(),
)
.reset_style();
assert_eq!(span.style, Style::reset());
Sourcepub fn styled_graphemes<S: Into<Style>>(
&'a self,
base_style: S,
) -> impl Iterator<Item = StyledGrapheme<'a>>
pub fn styled_graphemes<S: Into<Style>>( &'a self, base_style: S, ) -> impl Iterator<Item = StyledGrapheme<'a>>
Returns an iterator over the graphemes held by this span.
base_style
is the Style
that will be patched with the Span
’s style
to get the
resulting Style
.
base_style
accepts any type that is convertible to Style
(e.g. Style
, Color
,
or your own type that implements Into<Style>
).
§Example
use std::iter::Iterator;
use ratatui::{
style::{Style, Stylize},
text::{Span, StyledGrapheme},
};
let span = Span::styled("Test", Style::new().green().italic());
let style = Style::new().red().on_yellow();
assert_eq!(
span.styled_graphemes(style)
.collect::<Vec<StyledGrapheme>>(),
vec![
StyledGrapheme::new("T", Style::new().green().on_yellow().italic()),
StyledGrapheme::new("e", Style::new().green().on_yellow().italic()),
StyledGrapheme::new("s", Style::new().green().on_yellow().italic()),
StyledGrapheme::new("t", Style::new().green().on_yellow().italic()),
],
);
Sourcepub fn into_left_aligned_line(self) -> Line<'a>
pub fn into_left_aligned_line(self) -> Line<'a>
pub fn to_left_aligned_line(self) -> Line<'a>
Sourcepub fn into_centered_line(self) -> Line<'a>
pub fn into_centered_line(self) -> Line<'a>
Converts this Span into a center-aligned Line
§Example
use ratatui::style::Stylize;
let line = "Test Content".green().italic().into_centered_line();
Examples found in repository?
More examples
277 fn header() -> impl Widget {
278 let text = "Constraint Explorer";
279 text.bold().fg(Self::HEADER_COLOR).into_centered_line()
280 }
281
282 fn instructions() -> impl Widget {
283 let text = "◄ ►: select, ▲ ▼: edit, 1-6: swap, a: add, x: delete, q: quit, + -: spacing";
284 Paragraph::new(text)
285 .fg(Self::TEXT_COLOR)
286 .centered()
287 .wrap(Wrap { trim: false })
288 }
289
290 fn swap_legend() -> impl Widget {
291 #[allow(unstable_name_collisions)]
292 Paragraph::new(
293 Line::from(
294 [
295 ConstraintName::Min,
296 ConstraintName::Max,
297 ConstraintName::Length,
298 ConstraintName::Percentage,
299 ConstraintName::Ratio,
300 ConstraintName::Fill,
301 ]
302 .iter()
303 .enumerate()
304 .map(|(i, name)| {
305 format!(" {i}: {name} ", i = i + 1)
306 .fg(SLATE.c200)
307 .bg(name.color())
308 })
309 .intersperse(Span::from(" "))
310 .collect_vec(),
311 )
312 .centered(),
313 )
314 .wrap(Wrap { trim: false })
315 }
316
317 /// A bar like `<----- 80 px (gap: 2 px) ----->`
318 ///
319 /// Only shows the gap when spacing is not zero
320 fn axis(&self, width: u16) -> impl Widget {
321 let label = if self.spacing != 0 {
322 format!("{} px (gap: {} px)", width, self.spacing)
323 } else {
324 format!("{width} px")
325 };
326 let bar_width = width.saturating_sub(2) as usize; // we want to `<` and `>` at the ends
327 let width_bar = format!("<{label:-^bar_width$}>");
328 Paragraph::new(width_bar).fg(Self::AXIS_COLOR).centered()
329 }
330
331 fn render_layout_blocks(&self, area: Rect, buf: &mut Buffer) {
332 let [user_constraints, area] = Layout::vertical([Length(3), Fill(1)])
333 .spacing(1)
334 .areas(area);
335
336 self.render_user_constraints_legend(user_constraints, buf);
337
338 let [start, center, end, space_around, space_between] =
339 Layout::vertical([Length(7); 5]).areas(area);
340
341 self.render_layout_block(Flex::Start, start, buf);
342 self.render_layout_block(Flex::Center, center, buf);
343 self.render_layout_block(Flex::End, end, buf);
344 self.render_layout_block(Flex::SpaceAround, space_around, buf);
345 self.render_layout_block(Flex::SpaceBetween, space_between, buf);
346 }
347
348 fn render_user_constraints_legend(&self, area: Rect, buf: &mut Buffer) {
349 let constraints = self.constraints.iter().map(|_| Constraint::Fill(1));
350 let blocks = Layout::horizontal(constraints).split(area);
351
352 for (i, (area, constraint)) in blocks.iter().zip(self.constraints.iter()).enumerate() {
353 let selected = self.selected_index == i;
354 ConstraintBlock::new(*constraint, selected, true).render(*area, buf);
355 }
356 }
357
358 fn render_layout_block(&self, flex: Flex, area: Rect, buf: &mut Buffer) {
359 let [label_area, axis_area, blocks_area] =
360 Layout::vertical([Length(1), Max(1), Length(4)]).areas(area);
361
362 if label_area.height > 0 {
363 format!("Flex::{flex:?}").bold().render(label_area, buf);
364 }
365
366 self.axis(area.width).render(axis_area, buf);
367
368 let (blocks, spacers) = Layout::horizontal(&self.constraints)
369 .flex(flex)
370 .spacing(self.spacing)
371 .split_with_spacers(blocks_area);
372
373 for (i, (area, constraint)) in blocks.iter().zip(self.constraints.iter()).enumerate() {
374 let selected = self.selected_index == i;
375 ConstraintBlock::new(*constraint, selected, false).render(*area, buf);
376 }
377
378 for area in spacers.iter() {
379 SpacerBlock.render(*area, buf);
380 }
381 }
382}
383
384impl Widget for ConstraintBlock {
385 fn render(self, area: Rect, buf: &mut Buffer) {
386 match area.height {
387 1 => self.render_1px(area, buf),
388 2 => self.render_2px(area, buf),
389 _ => self.render_4px(area, buf),
390 }
391 }
392}
393
394impl ConstraintBlock {
395 const TEXT_COLOR: Color = SLATE.c200;
396
397 const fn new(constraint: Constraint, selected: bool, legend: bool) -> Self {
398 Self {
399 constraint,
400 legend,
401 selected,
402 }
403 }
404
405 fn label(&self, width: u16) -> String {
406 let long_width = format!("{width} px");
407 let short_width = format!("{width}");
408 // border takes up 2 columns
409 let available_space = width.saturating_sub(2) as usize;
410 let width_label = if long_width.len() < available_space {
411 long_width
412 } else if short_width.len() < available_space {
413 short_width
414 } else {
415 String::new()
416 };
417 format!("{}\n{}", self.constraint, width_label)
418 }
419
420 fn render_1px(&self, area: Rect, buf: &mut Buffer) {
421 let lighter_color = ConstraintName::from(self.constraint).lighter_color();
422 let main_color = ConstraintName::from(self.constraint).color();
423 let selected_color = if self.selected {
424 lighter_color
425 } else {
426 main_color
427 };
428 Block::new()
429 .fg(Self::TEXT_COLOR)
430 .bg(selected_color)
431 .render(area, buf);
432 }
433
434 fn render_2px(&self, area: Rect, buf: &mut Buffer) {
435 let lighter_color = ConstraintName::from(self.constraint).lighter_color();
436 let main_color = ConstraintName::from(self.constraint).color();
437 let selected_color = if self.selected {
438 lighter_color
439 } else {
440 main_color
441 };
442 Block::bordered()
443 .border_set(symbols::border::QUADRANT_OUTSIDE)
444 .border_style(Style::reset().fg(selected_color).reversed())
445 .render(area, buf);
446 }
447
448 fn render_4px(&self, area: Rect, buf: &mut Buffer) {
449 let lighter_color = ConstraintName::from(self.constraint).lighter_color();
450 let main_color = ConstraintName::from(self.constraint).color();
451 let selected_color = if self.selected {
452 lighter_color
453 } else {
454 main_color
455 };
456 let color = if self.legend {
457 selected_color
458 } else {
459 main_color
460 };
461 let label = self.label(area.width);
462 let block = Block::bordered()
463 .border_set(symbols::border::QUADRANT_OUTSIDE)
464 .border_style(Style::reset().fg(color).reversed())
465 .fg(Self::TEXT_COLOR)
466 .bg(color);
467 Paragraph::new(label)
468 .centered()
469 .fg(Self::TEXT_COLOR)
470 .bg(color)
471 .block(block)
472 .render(area, buf);
473
474 if !self.legend {
475 let border_color = if self.selected {
476 lighter_color
477 } else {
478 main_color
479 };
480 if let Some(last_row) = area.rows().last() {
481 buf.set_style(last_row, border_color);
482 }
483 }
484 }
485}
486
487impl Widget for SpacerBlock {
488 fn render(self, area: Rect, buf: &mut Buffer) {
489 match area.height {
490 1 => (),
491 2 => Self::render_2px(area, buf),
492 3 => Self::render_3px(area, buf),
493 _ => Self::render_4px(area, buf),
494 }
495 }
496}
497
498impl SpacerBlock {
499 const TEXT_COLOR: Color = SLATE.c500;
500 const BORDER_COLOR: Color = SLATE.c600;
501
502 /// A block with a corner borders
503 fn block() -> impl Widget {
504 let corners_only = symbols::border::Set {
505 top_left: line::NORMAL.top_left,
506 top_right: line::NORMAL.top_right,
507 bottom_left: line::NORMAL.bottom_left,
508 bottom_right: line::NORMAL.bottom_right,
509 vertical_left: " ",
510 vertical_right: " ",
511 horizontal_top: " ",
512 horizontal_bottom: " ",
513 };
514 Block::bordered()
515 .border_set(corners_only)
516 .border_style(Self::BORDER_COLOR)
517 }
518
519 /// A vertical line used if there is not enough space to render the block
520 fn line() -> impl Widget {
521 Paragraph::new(Text::from(vec![
522 Line::from(""),
523 Line::from("│"),
524 Line::from("│"),
525 Line::from(""),
526 ]))
527 .style(Self::BORDER_COLOR)
528 }
529
530 /// A label that says "Spacer" if there is enough space
531 fn spacer_label(width: u16) -> impl Widget {
532 let label = if width >= 6 { "Spacer" } else { "" };
533 label.fg(Self::TEXT_COLOR).into_centered_line()
534 }
67 fn draw(&self, frame: &mut Frame) {
68 let [title, vertical, horizontal] = Layout::vertical([
69 Constraint::Length(1),
70 Constraint::Fill(1),
71 Constraint::Fill(1),
72 ])
73 .spacing(1)
74 .areas(frame.area());
75
76 frame.render_widget("Barchart".bold().into_centered_line(), title);
77 frame.render_widget(vertical_barchart(&self.temperatures), vertical);
78 frame.render_widget(horizontal_barchart(&self.temperatures), horizontal);
79 }
pub fn to_centered_line(self) -> Line<'a>
Sourcepub fn into_right_aligned_line(self) -> Line<'a>
pub fn into_right_aligned_line(self) -> Line<'a>
pub fn to_right_aligned_line(self) -> Line<'a>
Trait Implementations§
Source§impl<'a> Add<Span<'a>> for Line<'a>
Adds a Span
to a Line
, returning a new Line
with the Span
added.
impl<'a> Add<Span<'a>> for Line<'a>
Adds a Span
to a Line
, returning a new Line
with the Span
added.
Source§impl<'a> AddAssign<Span<'a>> for Line<'a>
impl<'a> AddAssign<Span<'a>> for Line<'a>
Source§fn add_assign(&mut self, rhs: Span<'a>)
fn add_assign(&mut self, rhs: Span<'a>)
+=
operation. Read moreSource§impl<'a> Extend<Span<'a>> for Line<'a>
impl<'a> Extend<Span<'a>> for Line<'a>
Source§fn extend<T: IntoIterator<Item = Span<'a>>>(&mut self, iter: T)
fn extend<T: IntoIterator<Item = Span<'a>>>(&mut self, iter: T)
Source§fn extend_one(&mut self, item: A)
fn extend_one(&mut self, item: A)
extend_one
)Source§fn extend_reserve(&mut self, additional: usize)
fn extend_reserve(&mut self, additional: usize)
extend_one
)Source§impl WidgetRef for Span<'_>
impl WidgetRef for Span<'_>
Source§fn render_ref(&self, area: Rect, buf: &mut Buffer)
fn render_ref(&self, area: Rect, buf: &mut Buffer)
unstable-widget-ref
only.impl<'a> Eq for Span<'a>
impl<'a> StructuralPartialEq for Span<'a>
Auto Trait Implementations§
impl<'a> Freeze for Span<'a>
impl<'a> RefUnwindSafe for Span<'a>
impl<'a> Send for Span<'a>
impl<'a> Sync for Span<'a>
impl<'a> Unpin for Span<'a>
impl<'a> UnwindSafe for Span<'a>
Blanket Implementations§
Source§impl<S, D, Swp, Dwp, T> AdaptInto<D, Swp, Dwp, T> for Swhere
T: Real + Zero + Arithmetics + Clone,
Swp: WhitePoint<T>,
Dwp: WhitePoint<T>,
D: AdaptFrom<S, Swp, Dwp, T>,
impl<S, D, Swp, Dwp, T> AdaptInto<D, Swp, Dwp, T> for Swhere
T: Real + Zero + Arithmetics + Clone,
Swp: WhitePoint<T>,
Dwp: WhitePoint<T>,
D: AdaptFrom<S, Swp, Dwp, T>,
Source§fn adapt_into_using<M>(self, method: M) -> Dwhere
M: TransformMatrix<T>,
fn adapt_into_using<M>(self, method: M) -> Dwhere
M: TransformMatrix<T>,
Source§fn adapt_into(self) -> D
fn adapt_into(self) -> D
Source§impl<T, C> ArraysFrom<C> for Twhere
C: IntoArrays<T>,
impl<T, C> ArraysFrom<C> for Twhere
C: IntoArrays<T>,
Source§fn arrays_from(colors: C) -> T
fn arrays_from(colors: C) -> T
Source§impl<T, C> ArraysInto<C> for Twhere
C: FromArrays<T>,
impl<T, C> ArraysInto<C> for Twhere
C: FromArrays<T>,
Source§fn arrays_into(self) -> C
fn arrays_into(self) -> C
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<WpParam, T, U> Cam16IntoUnclamped<WpParam, T> for Uwhere
T: FromCam16Unclamped<WpParam, U>,
impl<WpParam, T, U> Cam16IntoUnclamped<WpParam, T> for Uwhere
T: FromCam16Unclamped<WpParam, U>,
Source§type Scalar = <T as FromCam16Unclamped<WpParam, U>>::Scalar
type Scalar = <T as FromCam16Unclamped<WpParam, U>>::Scalar
parameters
when converting.Source§fn cam16_into_unclamped(
self,
parameters: BakedParameters<WpParam, <U as Cam16IntoUnclamped<WpParam, T>>::Scalar>,
) -> T
fn cam16_into_unclamped( self, parameters: BakedParameters<WpParam, <U as Cam16IntoUnclamped<WpParam, T>>::Scalar>, ) -> T
self
into C
, using the provided parameters.Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T, C> ComponentsFrom<C> for Twhere
C: IntoComponents<T>,
impl<T, C> ComponentsFrom<C> for Twhere
C: IntoComponents<T>,
Source§fn components_from(colors: C) -> T
fn components_from(colors: C) -> T
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key
and return true
if they are equal.Source§impl<T> FromAngle<T> for T
impl<T> FromAngle<T> for T
Source§fn from_angle(angle: T) -> T
fn from_angle(angle: T) -> T
angle
.Source§impl<T, U> FromStimulus<U> for Twhere
U: IntoStimulus<T>,
impl<T, U> FromStimulus<U> for Twhere
U: IntoStimulus<T>,
Source§fn from_stimulus(other: U) -> T
fn from_stimulus(other: U) -> T
other
into Self
, while performing the appropriate scaling,
rounding and clamping.Source§impl<T, U> IntoAngle<U> for Twhere
U: FromAngle<T>,
impl<T, U> IntoAngle<U> for Twhere
U: FromAngle<T>,
Source§fn into_angle(self) -> U
fn into_angle(self) -> U
T
.Source§impl<WpParam, T, U> IntoCam16Unclamped<WpParam, T> for Uwhere
T: Cam16FromUnclamped<WpParam, U>,
impl<WpParam, T, U> IntoCam16Unclamped<WpParam, T> for Uwhere
T: Cam16FromUnclamped<WpParam, U>,
Source§type Scalar = <T as Cam16FromUnclamped<WpParam, U>>::Scalar
type Scalar = <T as Cam16FromUnclamped<WpParam, U>>::Scalar
parameters
when converting.Source§fn into_cam16_unclamped(
self,
parameters: BakedParameters<WpParam, <U as IntoCam16Unclamped<WpParam, T>>::Scalar>,
) -> T
fn into_cam16_unclamped( self, parameters: BakedParameters<WpParam, <U as IntoCam16Unclamped<WpParam, T>>::Scalar>, ) -> T
self
into C
, using the provided parameters.Source§impl<T, U> IntoColor<U> for Twhere
U: FromColor<T>,
impl<T, U> IntoColor<U> for Twhere
U: FromColor<T>,
Source§fn into_color(self) -> U
fn into_color(self) -> U
Source§impl<T, U> IntoColorUnclamped<U> for Twhere
U: FromColorUnclamped<T>,
impl<T, U> IntoColorUnclamped<U> for Twhere
U: FromColorUnclamped<T>,
Source§fn into_color_unclamped(self) -> U
fn into_color_unclamped(self) -> U
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self
into a Left
variant of Either<Self, Self>
if into_left
is true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self
into a Left
variant of Either<Self, Self>
if into_left(&self)
returns true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read moreSource§impl<T> IntoStimulus<T> for T
impl<T> IntoStimulus<T> for T
Source§fn into_stimulus(self) -> T
fn into_stimulus(self) -> T
self
into T
, while performing the appropriate scaling,
rounding and clamping.Source§impl<'a, T, U> Stylize<'a, T> for Uwhere
U: Styled<Item = T>,
impl<'a, T, U> Stylize<'a, T> for Uwhere
U: Styled<Item = T>,
fn bg<C>(self, color: C) -> T
fn fg<C>(self, color: C) -> T
fn add_modifier(self, modifier: Modifier) -> T
fn remove_modifier(self, modifier: Modifier) -> T
fn reset(self) -> T
Source§fn on_magenta(self) -> T
fn on_magenta(self) -> T
magenta
.Source§fn on_dark_gray(self) -> T
fn on_dark_gray(self) -> T
dark_gray
.Source§fn on_light_red(self) -> T
fn on_light_red(self) -> T
light_red
.Source§fn light_green(self) -> T
fn light_green(self) -> T
light_green
.Source§fn on_light_green(self) -> T
fn on_light_green(self) -> T
light_green
.Source§fn light_yellow(self) -> T
fn light_yellow(self) -> T
light_yellow
.Source§fn on_light_yellow(self) -> T
fn on_light_yellow(self) -> T
light_yellow
.Source§fn light_blue(self) -> T
fn light_blue(self) -> T
light_blue
.Source§fn on_light_blue(self) -> T
fn on_light_blue(self) -> T
light_blue
.Source§fn light_magenta(self) -> T
fn light_magenta(self) -> T
light_magenta
.Source§fn on_light_magenta(self) -> T
fn on_light_magenta(self) -> T
light_magenta
.Source§fn light_cyan(self) -> T
fn light_cyan(self) -> T
light_cyan
.Source§fn on_light_cyan(self) -> T
fn on_light_cyan(self) -> T
light_cyan
.Source§fn not_italic(self) -> T
fn not_italic(self) -> T
ITALIC
modifier.Source§fn underlined(self) -> T
fn underlined(self) -> T
UNDERLINED
modifier.Source§fn not_underlined(self) -> T
fn not_underlined(self) -> T
UNDERLINED
modifier.Source§fn slow_blink(self) -> T
fn slow_blink(self) -> T
SLOW_BLINK
modifier.Source§fn not_slow_blink(self) -> T
fn not_slow_blink(self) -> T
SLOW_BLINK
modifier.Source§fn rapid_blink(self) -> T
fn rapid_blink(self) -> T
RAPID_BLINK
modifier.Source§fn not_rapid_blink(self) -> T
fn not_rapid_blink(self) -> T
RAPID_BLINK
modifier.Source§fn not_reversed(self) -> T
fn not_reversed(self) -> T
REVERSED
modifier.HIDDEN
modifier.HIDDEN
modifier.Source§fn crossed_out(self) -> T
fn crossed_out(self) -> T
CROSSED_OUT
modifier.Source§fn not_crossed_out(self) -> T
fn not_crossed_out(self) -> T
CROSSED_OUT
modifier.Source§impl<T> ToCompactString for Twhere
T: Display,
impl<T> ToCompactString for Twhere
T: Display,
Source§fn try_to_compact_string(&self) -> Result<CompactString, ToCompactStringError>
fn try_to_compact_string(&self) -> Result<CompactString, ToCompactStringError>
ToCompactString::to_compact_string()
Read moreSource§fn to_compact_string(&self) -> CompactString
fn to_compact_string(&self) -> CompactString
CompactString
. Read moreSource§impl<T, C> TryComponentsInto<C> for Twhere
C: TryFromComponents<T>,
impl<T, C> TryComponentsInto<C> for Twhere
C: TryFromComponents<T>,
Source§type Error = <C as TryFromComponents<T>>::Error
type Error = <C as TryFromComponents<T>>::Error
try_into_colors
fails to cast.Source§fn try_components_into(self) -> Result<C, <T as TryComponentsInto<C>>::Error>
fn try_components_into(self) -> Result<C, <T as TryComponentsInto<C>>::Error>
Source§impl<T, U> TryIntoColor<U> for Twhere
U: TryFromColor<T>,
impl<T, U> TryIntoColor<U> for Twhere
U: TryFromColor<T>,
Source§fn try_into_color(self) -> Result<U, OutOfBounds<U>>
fn try_into_color(self) -> Result<U, OutOfBounds<U>>
OutOfBounds
error is returned which contains
the unclamped color. Read more