Preliminary actions
This commit is contained in:
parent
d67ea79994
commit
911bfcfba3
6 changed files with 111 additions and 12 deletions
73
src/main.rs
73
src/main.rs
|
@ -21,9 +21,9 @@ fn main() -> Result<(), Box<dyn Error>> {
|
||||||
debug!{"Set up roftl"};
|
debug!{"Set up roftl"};
|
||||||
let mut roftl = roftl::Roftl::new()
|
let mut roftl = roftl::Roftl::new()
|
||||||
.add_source(sources::TestSource::new("ts1"))
|
.add_source(sources::TestSource::new("ts1"))
|
||||||
.add_source(sources::Window::new())
|
// .add_source(sources::Window::new())
|
||||||
.add_source(sources::Apps::new())
|
// .add_source(sources::Apps::new())
|
||||||
.add_source(sources::ShellHost::new())
|
// .add_source(sources::ShellHost::new())
|
||||||
.with_matcher(FuseMatcher::new());
|
.with_matcher(FuseMatcher::new());
|
||||||
|
|
||||||
debug!{"Source roftl sources"}
|
debug!{"Source roftl sources"}
|
||||||
|
@ -47,10 +47,16 @@ fn main() -> Result<(), Box<dyn Error>> {
|
||||||
roftl_loop.run(event_loop);
|
roftl_loop.run(event_loop);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum Mode {
|
||||||
|
Selection,
|
||||||
|
Actions
|
||||||
|
}
|
||||||
|
|
||||||
struct RoftlLoop {
|
struct RoftlLoop {
|
||||||
input_buffer: String,
|
input_buffer: String,
|
||||||
input_changed: bool,
|
input_changed: bool,
|
||||||
selection: usize,
|
selection: usize,
|
||||||
|
mode: Mode,
|
||||||
roftl: Roftl,
|
roftl: Roftl,
|
||||||
window: Window,
|
window: Window,
|
||||||
}
|
}
|
||||||
|
@ -58,7 +64,9 @@ struct RoftlLoop {
|
||||||
impl RoftlLoop {
|
impl RoftlLoop {
|
||||||
fn new(roftl: Roftl, window: Window) -> Self
|
fn new(roftl: Roftl, window: Window) -> Self
|
||||||
{
|
{
|
||||||
RoftlLoop{input_buffer: String::default(), input_changed: true, selection: 0, roftl, window}
|
RoftlLoop{input_buffer: String::default(), input_changed: true, selection: 0,
|
||||||
|
mode: Mode::Selection,
|
||||||
|
roftl, window}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run<T>(mut self, event_loop: EventLoop<T>) -> !
|
fn run<T>(mut self, event_loop: EventLoop<T>) -> !
|
||||||
|
@ -74,11 +82,19 @@ impl RoftlLoop {
|
||||||
}
|
}
|
||||||
|
|
||||||
Event::WindowEvent{event: ReceivedCharacter(character), window_id}
|
Event::WindowEvent{event: ReceivedCharacter(character), window_id}
|
||||||
if window_id == self.window.id() =>
|
if window_id == self.window.id()
|
||||||
|
&& matches!(self.mode, Mode::Selection) =>
|
||||||
{
|
{
|
||||||
*flow = self.process_character(character);
|
*flow = self.process_character(character);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Event::WindowEvent{event: ReceivedCharacter(character), window_id}
|
||||||
|
if window_id == self.window.id()
|
||||||
|
&& matches!(self.mode, Mode::Actions) =>
|
||||||
|
{
|
||||||
|
*flow = self.process_action(character);
|
||||||
|
}
|
||||||
|
|
||||||
Event::WindowEvent{event: winit::event::WindowEvent::KeyboardInput{input, ..}, window_id}
|
Event::WindowEvent{event: winit::event::WindowEvent::KeyboardInput{input, ..}, window_id}
|
||||||
if window_id == self.window.id() =>
|
if window_id == self.window.id() =>
|
||||||
{
|
{
|
||||||
|
@ -86,7 +102,8 @@ impl RoftlLoop {
|
||||||
}
|
}
|
||||||
|
|
||||||
Event::RedrawRequested(window_id)
|
Event::RedrawRequested(window_id)
|
||||||
if window_id == self.window.id() =>
|
if window_id == self.window.id()
|
||||||
|
&& matches!{self.mode, Mode::Selection} =>
|
||||||
{
|
{
|
||||||
if self.input_changed {
|
if self.input_changed {
|
||||||
trace!{"Redrawing with input {}", self.input_buffer}
|
trace!{"Redrawing with input {}", self.input_buffer}
|
||||||
|
@ -115,6 +132,15 @@ impl RoftlLoop {
|
||||||
self.input_changed = false;
|
self.input_changed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Event::RedrawRequested(window_id)
|
||||||
|
if window_id == self.window.id()
|
||||||
|
&& matches!{self.mode, Mode::Actions} =>
|
||||||
|
{
|
||||||
|
let actions = self.roftl.actions(self.selection);
|
||||||
|
debug!{"Actions for current selection: {:?}", actions}
|
||||||
|
ui::draw_actions(&self.window, actions);
|
||||||
|
}
|
||||||
|
|
||||||
_ => ()
|
_ => ()
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -179,6 +205,17 @@ impl RoftlLoop {
|
||||||
ControlFlow::Wait
|
ControlFlow::Wait
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ctrl+a
|
||||||
|
c if c == char::from(0x01) => {
|
||||||
|
debug!{"Received actions"}
|
||||||
|
match self.mode {
|
||||||
|
Mode::Selection => { self.mode = Mode::Actions; self.input_changed = true },
|
||||||
|
Mode::Actions => { self.mode = Mode::Selection; self.input_changed = true }
|
||||||
|
}
|
||||||
|
self.window.request_redraw();
|
||||||
|
ControlFlow::Wait
|
||||||
|
}
|
||||||
|
|
||||||
c if c.is_control() => {
|
c if c.is_control() => {
|
||||||
debug!{"Got unknown control character {:#x}", u32::from(c)}
|
debug!{"Got unknown control character {:#x}", u32::from(c)}
|
||||||
ControlFlow::Wait
|
ControlFlow::Wait
|
||||||
|
@ -194,6 +231,30 @@ impl RoftlLoop {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn process_action(&mut self, character: char) -> ControlFlow {
|
||||||
|
match character {
|
||||||
|
'0' => {
|
||||||
|
trace!{"Retrieved action selection 0. Trigger primary action"}
|
||||||
|
self.roftl.action(self.selection, roftl::Action::Primary);
|
||||||
|
ControlFlow::Exit
|
||||||
|
},
|
||||||
|
'1' => {
|
||||||
|
trace!{"Retrieved action selection 1. Trigger secondary action"}
|
||||||
|
self.roftl.action(self.selection, roftl::Action::Secondary);
|
||||||
|
ControlFlow::Exit
|
||||||
|
},
|
||||||
|
'2' => {
|
||||||
|
trace!{"Retrieved action selection 2. Trigger ternary action"}
|
||||||
|
self.roftl.action(self.selection, roftl::Action::Ternary);
|
||||||
|
ControlFlow::Exit
|
||||||
|
},
|
||||||
|
_ => {
|
||||||
|
trace!{"Retrieved unknown action selection"}
|
||||||
|
ControlFlow::Wait
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
23
src/roftl.rs
23
src/roftl.rs
|
@ -17,14 +17,19 @@ pub struct Entry {
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Action {
|
pub enum Action {
|
||||||
Primary,
|
Primary,
|
||||||
|
Secondary,
|
||||||
|
Ternary
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Source: Send + Sync {
|
pub trait Source: Send + Sync {
|
||||||
fn name(&self) -> &'static str;
|
fn name(&self) -> &'static str;
|
||||||
fn entries(&mut self) -> Vec<Entry>;
|
fn entries(&mut self) -> Vec<Entry>;
|
||||||
fn action(&self, entry: &Entry, action: Action);
|
fn action(&self, entry: &Entry, action: Action);
|
||||||
|
fn actions(&self) -> Vec<String>
|
||||||
|
{ vec![] }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub trait Matcher: Send + Sync {
|
pub trait Matcher: Send + Sync {
|
||||||
fn try_match(&self, haystack: &str, needle: &str) -> Option<(f64, Vec<usize>)>;
|
fn try_match(&self, haystack: &str, needle: &str) -> Option<(f64, Vec<usize>)>;
|
||||||
}
|
}
|
||||||
|
@ -96,16 +101,26 @@ impl Roftl {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn action(&self, selection_id: usize, action: Action) {
|
pub fn action(&self, selection_id: usize, action: Action) {
|
||||||
|
let (entry, source) = self.find_selection(selection_id);
|
||||||
|
source.action(entry, action);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn actions(&self, selection_id: usize) -> Vec<String> {
|
||||||
|
let (_entry, source) = self.find_selection(selection_id);
|
||||||
|
source.actions()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn find_selection(&self, selection_id: usize) -> (&Entry, &Box<dyn Source>)
|
||||||
|
{
|
||||||
let entry_id = self.narrow_map[selection_id];
|
let entry_id = self.narrow_map[selection_id];
|
||||||
let entry = &self.entries[entry_id];
|
let entry = &self.entries[entry_id];
|
||||||
debug!{"Got entry {:?} for id {} ", entry, entry_id};
|
debug!{"Got entry {:?} for id {} ", entry, entry_id};
|
||||||
|
|
||||||
let source = self
|
let source = self.sources
|
||||||
.sources
|
|
||||||
.iter()
|
.iter()
|
||||||
.find(|&s| s.name().eq(entry.source))
|
.find(|s| s.name().eq(entry.source))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
source.action(&entry, action);
|
(entry, source)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@ impl TestSource {
|
||||||
pub fn new(s: &str) -> Box<TestSource> {
|
pub fn new(s: &str) -> Box<TestSource> {
|
||||||
let mut ts = Box::new(TestSource { entries: vec![] });
|
let mut ts = Box::new(TestSource { entries: vec![] });
|
||||||
|
|
||||||
(1..1).for_each(|i| {
|
(0..1).for_each(|i| {
|
||||||
ts.add_entry(
|
ts.add_entry(
|
||||||
format! {"Test {} {}", i, s},
|
format! {"Test {} {}", i, s},
|
||||||
format! {"Test {} description", i},
|
format! {"Test {} description", i},
|
||||||
|
@ -41,5 +41,10 @@ impl Source for TestSource {
|
||||||
fn action(&self, entry: &Entry, action: Action) {
|
fn action(&self, entry: &Entry, action: Action) {
|
||||||
println!("Doing action {:?} for entry {}", action, entry.name)
|
println!("Doing action {:?} for entry {}", action, entry.name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn actions(&self) -> Vec<String> {
|
||||||
|
["Primary", "Secondary", "Ternary"]
|
||||||
|
.iter().map(|s| (*s).into()).collect()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
mod ui;
|
mod ui;
|
||||||
pub use ui::draw;
|
pub use ui::draw;
|
||||||
pub use ui::redraw_quick;
|
pub use ui::redraw_quick;
|
||||||
|
pub use ui::draw_actions;
|
||||||
|
|
||||||
mod painter;
|
mod painter;
|
||||||
mod theme;
|
mod theme;
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
use log::debug;
|
|
||||||
use pangocairo::pango::{self, AttrList, Attribute, FontDescription};
|
use pangocairo::pango::{self, AttrList, Attribute, FontDescription};
|
||||||
|
|
||||||
// (r,g,b,a)
|
// (r,g,b,a)
|
||||||
|
|
18
src/ui/ui.rs
18
src/ui/ui.rs
|
@ -113,3 +113,21 @@ pub fn redraw_quick(window: &Window, result: Vec<(&Entry, Vec<usize>)>, selectio
|
||||||
if i == selection { painter.result_box(0, 1+(i as u32), &e.source, &e.name, &r.1, true) }
|
if i == selection { painter.result_box(0, 1+(i as u32), &e.source, &e.name, &r.1, true) }
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn draw_actions(window: &Window, actions: Vec<String>)
|
||||||
|
{
|
||||||
|
let context = make_context(&window);
|
||||||
|
|
||||||
|
context.scale(30.0, 30.0);
|
||||||
|
|
||||||
|
let painter = painter::Painter::new(&context);
|
||||||
|
|
||||||
|
painter.background();
|
||||||
|
painter.divider(0, 1);
|
||||||
|
|
||||||
|
actions.iter().enumerate()
|
||||||
|
.for_each(|(i, r)| {
|
||||||
|
painter.result_box(0, 1+(i as u32), &usize::to_string(&i), r, &[], false);
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue