cosmic-text/examples/rich-text/src/main.rs
Ian Douglas Scott 0d3fb1dd9d Use ouroboros in FontSystem to avoid lifetime bound
Perhaps not quite what ouroboros is expected to be used for, but it's
not too bad, and avoiding the lifetime bound can be a huge help.
2022-11-04 10:37:32 -06:00

205 lines
7.5 KiB
Rust

// SPDX-License-Identifier: MIT OR Apache-2.0
use cosmic_text::{
Action,
Attrs,
AttrsList,
Buffer,
BufferLine,
Color,
Editor,
Family,
FontSystem,
Metrics,
Style,
SwashCache,
Weight,
};
use orbclient::{EventOption, Renderer, Window, WindowFlag};
use std::{process, thread, time::{Duration, Instant}};
fn main() {
env_logger::init();
let font_system = FontSystem::new();
let display_scale = match orbclient::get_display_size() {
Ok((w, h)) => {
log::info!("Display size: {}, {}", w, h);
(h as i32 / 1600) + 1
}
Err(err) => {
log::warn!("Failed to get display size: {}", err);
1
}
};
let mut window = Window::new_flags(
-1,
-1,
1024 * display_scale as u32,
768 * display_scale as u32,
&format!("COSMIC TEXT - {}", font_system.locale()),
&[WindowFlag::Resizable],
)
.unwrap();
let mut editor = Editor::new(Buffer::new(
&font_system,
Metrics::new(32, 44).scale(display_scale)
));
editor.buffer.set_size(
window.width() as i32,
window.height() as i32
);
let attrs = Attrs::new();
let serif_attrs = attrs.family(Family::Serif);
let mono_attrs = attrs.monospaced(true).family(Family::Monospace);
let comic_attrs = attrs.family(Family::Name("Comic Neue"));
editor.buffer.lines.clear();
let lines: &[&[(&str, Attrs)]] = &[
&[
("B", attrs.weight(Weight::BOLD)),
("old ", attrs),
("I", attrs.style(Style::Italic)),
("talic ", attrs),
("f", attrs),
("i ", attrs),
("f", attrs.weight(Weight::BOLD)),
("i ", attrs),
("f", attrs.style(Style::Italic)),
("i ", attrs),
],
&[
("Sans-Serif Normal ", attrs),
("Sans-Serif Bold ", attrs.weight(Weight::BOLD)),
("Sans-Serif Italic ", attrs.style(Style::Italic)),
("Sans-Serif Bold Italic", attrs.weight(Weight::BOLD).style(Style::Italic)),
],
&[
("Serif Normal ", serif_attrs),
("Serif Bold ", serif_attrs.weight(Weight::BOLD)),
("Serif Italic ", serif_attrs.style(Style::Italic)),
("Serif Bold Italic", serif_attrs.weight(Weight::BOLD).style(Style::Italic)),
],
&[
("Mono Normal ", mono_attrs),
("Mono Bold ", mono_attrs.weight(Weight::BOLD)),
("Mono Italic ", mono_attrs.style(Style::Italic)),
("Mono Bold Italic", mono_attrs.weight(Weight::BOLD).style(Style::Italic)),
],
&[
("Comic Normal ", comic_attrs),
("Comic Bold ", comic_attrs.weight(Weight::BOLD)),
("Comic Italic ", comic_attrs.style(Style::Italic)),
("Comic Bold Italic", comic_attrs.weight(Weight::BOLD).style(Style::Italic)),
],
&[
("R", attrs.color(Color::rgb(0xFF, 0x00, 0x00))),
("A", attrs.color(Color::rgb(0xFF, 0x7F, 0x00))),
("I", attrs.color(Color::rgb(0xFF, 0xFF, 0x00))),
("N", attrs.color(Color::rgb(0x00, 0xFF, 0x00))),
("B", attrs.color(Color::rgb(0x00, 0x00, 0xFF))),
("O", attrs.color(Color::rgb(0x4B, 0x00, 0x82))),
("W ", attrs.color(Color::rgb(0x94, 0x00, 0xD3))),
("Red ", attrs.color(Color::rgb(0xFF, 0x00, 0x00))),
("Orange ", attrs.color(Color::rgb(0xFF, 0x7F, 0x00))),
("Yellow ", attrs.color(Color::rgb(0xFF, 0xFF, 0x00))),
("Green ", attrs.color(Color::rgb(0x00, 0xFF, 0x00))),
("Blue ", attrs.color(Color::rgb(0x00, 0x00, 0xFF))),
("Indigo ", attrs.color(Color::rgb(0x4B, 0x00, 0x82))),
("Violet ", attrs.color(Color::rgb(0x94, 0x00, 0xD3))),
("U", attrs.color(Color::rgb(0x94, 0x00, 0xD3))),
("N", attrs.color(Color::rgb(0x4B, 0x00, 0x82))),
("I", attrs.color(Color::rgb(0x00, 0x00, 0xFF))),
("C", attrs.color(Color::rgb(0x00, 0xFF, 0x00))),
("O", attrs.color(Color::rgb(0xFF, 0xFF, 0x00))),
("R", attrs.color(Color::rgb(0xFF, 0x7F, 0x00))),
("N", attrs.color(Color::rgb(0xFF, 0x00, 0x00))),
]
];
for &line in lines {
let mut line_text = String::new();
let mut attrs_list = AttrsList::new(attrs);
for &(text, attrs) in line {
let start = line_text.len();
line_text.push_str(text);
let end = line_text.len();
attrs_list.add_span(start..end, attrs);
}
editor.buffer.lines.push(BufferLine::new(line_text, attrs_list));
}
let mut swash_cache = SwashCache::new(&font_system);
//TODO: make window not async?
let mut mouse_x = -1;
let mut mouse_y = -1;
let mut mouse_left = false;
loop {
let bg_color = orbclient::Color::rgb(0x34, 0x34, 0x34);
let font_color = Color::rgb(0xFF, 0xFF, 0xFF);
editor.shape_as_needed();
if editor.buffer.redraw {
let instant = Instant::now();
window.set(bg_color);
editor.draw(&mut swash_cache, font_color, |x, y, w, h, color| {
window.rect(x, y, w, h, orbclient::Color { data: color.0 });
});
window.sync();
editor.buffer.redraw = false;
let duration = instant.elapsed();
log::debug!("redraw: {:?}", duration);
}
for event in window.events() {
match event.to_option() {
EventOption::Key(event) => match event.scancode {
orbclient::K_LEFT if event.pressed => editor.action(Action::Left),
orbclient::K_RIGHT if event.pressed => editor.action(Action::Right),
orbclient::K_UP if event.pressed => editor.action(Action::Up),
orbclient::K_DOWN if event.pressed => editor.action(Action::Down),
orbclient::K_HOME if event.pressed => editor.action(Action::Home),
orbclient::K_END if event.pressed => editor.action(Action::End),
orbclient::K_PGUP if event.pressed => editor.action(Action::PageUp),
orbclient::K_PGDN if event.pressed => editor.action(Action::PageDown),
orbclient::K_ENTER if event.pressed => editor.action(Action::Enter),
orbclient::K_BKSP if event.pressed => editor.action(Action::Backspace),
orbclient::K_DEL if event.pressed => editor.action(Action::Delete),
_ => (),
},
EventOption::TextInput(event) => editor.action(Action::Insert(event.character)),
EventOption::Mouse(mouse) => {
mouse_x = mouse.x;
mouse_y = mouse.y;
if mouse_left {
editor.action(Action::Drag { x: mouse_x, y: mouse_y });
}
},
EventOption::Button(button) => {
mouse_left = button.left;
if mouse_left {
editor.action(Action::Click { x: mouse_x, y: mouse_y });
}
},
EventOption::Resize(resize) => {
editor.buffer.set_size(resize.width as i32, resize.height as i32);
},
EventOption::Quit(_) => process::exit(0),
_ => (),
}
}
thread::sleep(Duration::from_millis(1));
}
}