Structure tree widget state around cursors

This commit is contained in:
Joscha 2022-07-19 09:51:50 +02:00
parent 4f4cae070a
commit 2beb44a17c

View file

@ -18,34 +18,10 @@ use crate::ui::widgets::Widget;
// State // // State //
/////////// ///////////
/// The anchor specifies a specific line in a room's history. /// Position of a cursor that is displayed as the last child of its parent
enum Anchor<I> { /// message, or last thread if it has no parent.
/// The bottom of the room's history stays fixed. struct LastChild<I> {
Bottom,
/// The top of a message stays fixed.
Msg(I),
/// The line after a message's subtree stays fixed.
After(I),
}
struct Compose<I> {
/// The message that the cursor was on when composing began, or `None` if it
/// was [`Cursor::Bottom`].
///
/// Used to jump back to the original position when composing is aborted
/// because the editor may be moved during composing.
coming_from: Option<I>, coming_from: Option<I>,
/// The parent message of this reply, or `None` if it will be a new
/// top-level message.
parent: Option<I>,
// TODO Editor state
// TODO Whether currently editing or moving cursor
}
struct Placeholder<I> {
/// See [`Composing::coming_from`].
coming_from: Option<I>,
/// See [`Composing::parent`].
after: Option<I>, after: Option<I>,
} }
@ -55,38 +31,34 @@ enum Cursor<I> {
/// See also [`Anchor::Bottom`]. /// See also [`Anchor::Bottom`].
Bottom, Bottom,
/// The cursor points to a message. /// The cursor points to a message.
///
/// See also [`Anchor::Msg`].
Msg(I), Msg(I),
/// The cursor has turned into an editor because we're composing a new /// The cursor has turned into an editor because we're composing a new
/// message. /// message.
/// Compose(LastChild<I>),
/// See also [`Anchor::After`].
Compose(Compose<I>),
/// A placeholder message is being displayed for a message that was just /// A placeholder message is being displayed for a message that was just
/// sent by the user. /// sent by the user.
/// ///
/// Will be replaced by a [`Cursor::Msg`] as soon as the server replies to /// Will be replaced by a [`Cursor::Msg`] as soon as the server replies to
/// the send command with the sent message. Otherwise, it will /// the send command with the sent message.
/// Placeholder(LastChild<I>),
/// See also [`Anchor::After`].
Placeholder(Placeholder<I>),
} }
struct InnerTreeViewState<M: Msg, S: MsgStore<M>> { struct InnerTreeViewState<M: Msg, S: MsgStore<M>> {
store: S, store: S,
anchor: Anchor<M::Id>, last_blocks: (), // TODO
anchor_line: i32, last_cursor: Cursor<M::Id>,
cursor: Cursor<M::Id>, cursor: Cursor<M::Id>,
editor: (), // TODO
} }
impl<M: Msg, S: MsgStore<M>> InnerTreeViewState<M, S> { impl<M: Msg, S: MsgStore<M>> InnerTreeViewState<M, S> {
fn new(store: S) -> Self { fn new(store: S) -> Self {
Self { Self {
store, store,
anchor: Anchor::Bottom, last_blocks: (),
anchor_line: 0, last_cursor: Cursor::Bottom,
cursor: Cursor::Bottom, cursor: Cursor::Bottom,
editor: (),
} }
} }
} }
@ -121,6 +93,17 @@ where
} }
async fn render(self: Box<Self>, frame: &mut Frame) { async fn render(self: Box<Self>, frame: &mut Frame) {
// Determine current cursor position
// If cursor in last blocks, use that
// If cursor below last cursor, use last line
// Otherwise, use first line
// Layout starting from cursor tree
// Make cursor visible
// If cursor was moved last, scroll so it is fully visible
// Otherwise, move cursor so it is barely visible
// Clamp scrolling and fill screen again
// Update last layout and last cursor position
// Draw layout to screen
todo!() todo!()
} }
} }