2024-09-04 21:37:35 +02:00
|
|
|
//! ### Cursor Controller
|
2024-09-18 16:11:12 +02:00
|
|
|
//! A [Controller] implementation for [crate::api::Cursor] actions in a [crate::Workspace]
|
2024-09-04 21:37:35 +02:00
|
|
|
|
2024-08-05 19:13:48 +02:00
|
|
|
use std::sync::Arc;
|
|
|
|
|
2024-09-01 03:08:43 +02:00
|
|
|
use tokio::sync::{mpsc, oneshot, watch};
|
2023-08-16 23:09:47 +02:00
|
|
|
|
2024-09-19 21:32:46 +02:00
|
|
|
use crate::{
|
2024-10-03 04:05:58 +02:00
|
|
|
api::{
|
2024-10-10 12:14:44 +02:00
|
|
|
controller::{AsyncReceiver, AsyncSender, ControllerCallback},
|
2024-10-10 12:46:56 +02:00
|
|
|
Controller, Cursor, Selection,
|
2024-10-03 04:05:58 +02:00
|
|
|
},
|
2024-09-19 21:32:46 +02:00
|
|
|
errors::ControllerResult,
|
|
|
|
};
|
|
|
|
use codemp_proto::{
|
|
|
|
cursor::{CursorPosition, RowCol},
|
|
|
|
files::BufferNode,
|
|
|
|
};
|
2024-09-04 21:37:35 +02:00
|
|
|
|
2024-09-05 01:45:48 +02:00
|
|
|
/// A [Controller] for asynchronously sending and receiving [Cursor] event.
|
2023-08-20 00:46:55 +02:00
|
|
|
///
|
2024-09-04 21:37:35 +02:00
|
|
|
/// An unique [CursorController] exists for each active [crate::Workspace].
|
2024-08-05 19:13:48 +02:00
|
|
|
#[derive(Debug, Clone)]
|
2024-09-19 21:32:46 +02:00
|
|
|
#[cfg_attr(any(feature = "py", feature = "py-noabi"), pyo3::pyclass)]
|
2024-08-07 23:06:33 +02:00
|
|
|
#[cfg_attr(feature = "js", napi_derive::napi)]
|
2024-08-08 02:27:06 +02:00
|
|
|
pub struct CursorController(pub(crate) Arc<CursorControllerInner>);
|
2024-08-05 19:13:48 +02:00
|
|
|
|
2023-08-21 02:47:52 +02:00
|
|
|
#[derive(Debug)]
|
2024-08-08 02:27:06 +02:00
|
|
|
pub(crate) struct CursorControllerInner {
|
2024-10-03 02:30:46 +02:00
|
|
|
pub(crate) op: mpsc::UnboundedSender<CursorPosition>,
|
2024-09-01 03:08:43 +02:00
|
|
|
pub(crate) stream: mpsc::Sender<oneshot::Sender<Option<Cursor>>>,
|
|
|
|
pub(crate) poll: mpsc::UnboundedSender<oneshot::Sender<()>>,
|
2024-08-15 20:41:53 +02:00
|
|
|
pub(crate) callback: watch::Sender<Option<ControllerCallback<CursorController>>>,
|
2023-08-17 00:04:37 +02:00
|
|
|
}
|
|
|
|
|
2024-09-05 23:26:56 +02:00
|
|
|
#[cfg_attr(feature = "async-trait", async_trait::async_trait)]
|
2024-10-10 02:10:02 +02:00
|
|
|
impl Controller<Selection, Cursor> for CursorController {}
|
2024-09-28 03:33:13 +02:00
|
|
|
|
|
|
|
#[cfg_attr(feature = "async-trait", async_trait::async_trait)]
|
2024-10-10 02:10:02 +02:00
|
|
|
impl AsyncSender<Selection> for CursorController {
|
|
|
|
fn send(&self, mut cursor: Selection) -> ControllerResult<()> {
|
2024-10-10 12:46:56 +02:00
|
|
|
if cursor.start_row > cursor.end_row
|
|
|
|
|| (cursor.start_row == cursor.end_row && cursor.start_col > cursor.end_col)
|
|
|
|
{
|
2024-10-10 02:10:02 +02:00
|
|
|
std::mem::swap(&mut cursor.start_row, &mut cursor.end_row);
|
|
|
|
std::mem::swap(&mut cursor.start_col, &mut cursor.end_col);
|
2023-09-10 23:20:07 +02:00
|
|
|
}
|
2024-10-10 02:10:02 +02:00
|
|
|
|
2024-10-03 03:17:30 +02:00
|
|
|
Ok(self.0.op.send(CursorPosition {
|
|
|
|
buffer: BufferNode {
|
|
|
|
path: cursor.buffer,
|
|
|
|
},
|
|
|
|
start: RowCol {
|
2024-10-10 02:10:02 +02:00
|
|
|
row: cursor.start_row,
|
|
|
|
col: cursor.start_col,
|
2024-10-03 03:17:30 +02:00
|
|
|
},
|
|
|
|
end: RowCol {
|
2024-10-10 02:10:02 +02:00
|
|
|
row: cursor.end_row,
|
|
|
|
col: cursor.end_col,
|
2024-10-03 03:17:30 +02:00
|
|
|
},
|
|
|
|
})?)
|
2023-08-16 23:09:47 +02:00
|
|
|
}
|
2024-09-28 03:33:13 +02:00
|
|
|
}
|
2023-08-16 23:09:47 +02:00
|
|
|
|
2024-09-28 03:33:13 +02:00
|
|
|
#[cfg_attr(feature = "async-trait", async_trait::async_trait)]
|
|
|
|
impl AsyncReceiver<Cursor> for CursorController {
|
2024-09-01 02:46:03 +02:00
|
|
|
async fn try_recv(&self) -> ControllerResult<Option<Cursor>> {
|
2024-09-01 03:08:43 +02:00
|
|
|
let (tx, rx) = oneshot::channel();
|
|
|
|
self.0.stream.send(tx).await?;
|
|
|
|
Ok(rx.await?)
|
2023-08-16 23:09:47 +02:00
|
|
|
}
|
2023-08-21 02:35:56 +02:00
|
|
|
|
2024-09-01 02:46:03 +02:00
|
|
|
async fn poll(&self) -> ControllerResult<()> {
|
2024-09-01 03:08:43 +02:00
|
|
|
let (tx, rx) = oneshot::channel();
|
|
|
|
self.0.poll.send(tx)?;
|
|
|
|
rx.await?;
|
|
|
|
Ok(())
|
2023-08-21 02:35:56 +02:00
|
|
|
}
|
2024-08-08 00:28:15 +02:00
|
|
|
|
2024-08-15 22:47:49 +02:00
|
|
|
fn callback(&self, cb: impl Into<ControllerCallback<CursorController>>) {
|
|
|
|
if self.0.callback.send(Some(cb.into())).is_err() {
|
2024-08-15 19:32:01 +02:00
|
|
|
// TODO should we panic? we failed what we were supposed to do
|
|
|
|
tracing::error!("no active cursor worker to run registered callback!");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn clear_callback(&self) {
|
|
|
|
if self.0.callback.send(None).is_err() {
|
|
|
|
tracing::warn!("no active cursor worker to clear callback");
|
|
|
|
}
|
|
|
|
}
|
2023-08-16 23:09:47 +02:00
|
|
|
}
|