Skip to content

Commit

Permalink
refactor(tree): use click/rendered_at
Browse files Browse the repository at this point in the history
  • Loading branch information
EdJoPaTo committed May 16, 2024
1 parent 25ea7ab commit 3f6f4eb
Show file tree
Hide file tree
Showing 7 changed files with 35 additions and 75 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ rustls-pemfile = "2"
rustls-pki-types = "1"
serde = { version = "1", features = ["derive"] }
serde_json = "1"
tui-tree-widget = { git = "https://github.com/EdJoPaTo/tui-rs-tree-widget" }
tui-tree-widget = { git = "https://github.com/EdJoPaTo/tui-rs-tree-widget", branch = "select_item_at" }
url = "2"

# https://crates.io/crates/cargo-deb
Expand Down
12 changes: 6 additions & 6 deletions src/interactive/details/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,20 +24,20 @@ impl Details {
.min(topic_history_length.saturating_sub(1))
}

const fn table_index_of_click(&self, column: u16, row: u16) -> Option<usize> {
const fn table_index_of_click(&self, position: Position) -> Option<usize> {
let area = self.last_table_area;
if !area.contains(Position { x: column, y: row }) {
if !area.contains(position) {
return None;
}
let visible = row.saturating_sub(area.top()).saturating_sub(2); // subtract block & header
let visible_index = position.y.saturating_sub(area.top()).saturating_sub(2); // subtract block & header
let offset = self.table_state.offset();
let index = (visible as usize) + offset;
let index = (visible_index as usize) + offset;
Some(index)
}

/// Handles a click. Checks if its on the table. When it is the index get selected and true is returned.
pub fn table_click(&mut self, column: u16, row: u16) -> bool {
let Some(index) = self.table_index_of_click(column, row) else {
pub fn table_click(&mut self, position: Position) -> bool {
let Some(index) = self.table_index_of_click(position) else {
return false;
};
self.table_state.select(Some(index));
Expand Down
11 changes: 1 addition & 10 deletions src/interactive/details/payload_view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,7 @@ use ratatui::Frame;
use ratatui_binary_data_widget::{BinaryDataWidget, BinaryDataWidgetState};
use tui_tree_widget::{Tree, TreeState};

use crate::interactive::ui::{
focus_color, get_row_inside, split_area_vertically, BORDERS_TOP_RIGHT,
};
use crate::interactive::ui::{focus_color, split_area_vertically, BORDERS_TOP_RIGHT};
use crate::mqtt::HistoryEntry;
use crate::payload::{tree_items_from_json, tree_items_from_messagepack, JsonSelector, Payload};

Expand Down Expand Up @@ -40,13 +38,6 @@ impl PayloadView {
}
}

pub fn json_index_of_click(&self, column: u16, row: u16) -> Option<usize> {
get_row_inside(self.last_area, column, row).map(|index| {
let offset = self.json_state.get_offset();
(index as usize) + offset
})
}

fn areas(&mut self, area: Rect, has_focus: bool, content_height: usize) -> (Rect, Rect) {
let max_payload_height = if has_focus {
area.height.saturating_mul(2) / 3
Expand Down
37 changes: 24 additions & 13 deletions src/interactive/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::time::{Duration, Instant};

use crossterm::event::{Event, KeyCode, KeyEvent, KeyModifiers, MouseButton, MouseEventKind};
use ratatui::backend::{Backend, CrosstermBackend};
use ratatui::layout::{Alignment, Rect};
use ratatui::layout::{Alignment, Position, Rect};
use ratatui::text::Span;
use ratatui::widgets::Paragraph;
use ratatui::{Frame, Terminal};
Expand Down Expand Up @@ -496,16 +496,30 @@ impl App {
}

fn on_click(&mut self, column: u16, row: u16) -> Refresh {
if let Some(index) = self.topic_overview.index_of_click(column, row) {
let changed = self.topic_overview.state.select_visible_index(index);
if !changed {
self.topic_overview.state.toggle_selected();
let position = Position::new(column, row);

if let Some(identifier) = self.topic_overview.state.rendered_at(position) {
let is_already_selected = identifier == self.topic_overview.state.get_selected();
if is_already_selected {
// change focus or toggle, don't do both
if matches!(self.focus, ElementInFocus::TopicOverview) {
self.topic_overview.state.toggle_selected();
} else {
self.focus = ElementInFocus::TopicOverview;
}
} else {
self.focus = ElementInFocus::TopicOverview;
self.topic_overview.state.select(identifier.to_vec());
}

return Refresh::Update;
}
if self.topic_overview.state.click_at(position) {
self.focus = ElementInFocus::TopicOverview;
return Refresh::Update;
}

if let Some(index) = self.details.payload.json_index_of_click(column, row) {
if self.details.payload.last_area.contains(position) {
match self.get_selected_payload() {
None => return Refresh::Update, // No payload but click into payload area -> redraw
Some(Payload::Binary(_)) => {
Expand All @@ -519,23 +533,20 @@ impl App {
.payload
.binary_state
.select_address(Some(address));
self.focus = ElementInFocus::Payload;
return Refresh::Update;
}
self.focus = ElementInFocus::Payload;
return Refresh::Update;
}
Some(Payload::Json(_) | Payload::MessagePack(_)) => {
let changed = self.details.payload.json_state.select_visible_index(index);
if !changed {
self.details.payload.json_state.toggle_selected();
}
self.details.payload.json_state.click_at(position);
self.focus = ElementInFocus::Payload;
return Refresh::Update;
}
Some(Payload::String(_)) => return Refresh::Skip,
}
}

if self.details.table_click(column, row) {
if self.details.table_click(position) {
self.focus = ElementInFocus::HistoryTable;
return Refresh::Update;
}
Expand Down
12 changes: 1 addition & 11 deletions src/interactive/topic_overview.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use ratatui::Frame;
use tui_tree_widget::{Tree, TreeState};

use super::mqtt_history::MqttHistory;
use super::ui::{focus_color, get_row_inside, BORDERS_TOP_RIGHT};
use super::ui::{focus_color, BORDERS_TOP_RIGHT};

#[derive(Default)]
pub struct TopicOverview {
Expand Down Expand Up @@ -47,14 +47,4 @@ impl TopicOverview {
frame.render_stateful_widget(widget, area, &mut self.state);
self.last_area = area;
}

pub const fn index_of_click(&self, column: u16, row: u16) -> Option<usize> {
if let Some(index) = get_row_inside(self.last_area, column, row) {
let offset = self.state.get_offset();
let new_index = (index as usize) + offset;
Some(new_index)
} else {
None
}
}
}
34 changes: 1 addition & 33 deletions src/interactive/ui.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use ratatui::layout::{Position, Rect};
use ratatui::layout::Rect;
use ratatui::style::{Color, Modifier, Style};
use ratatui::widgets::Borders;

Expand All @@ -21,38 +21,6 @@ pub const fn focus_color(has_focus: bool) -> Color {
}
}

/// When the column/row is inside the area, return the row relative to the area.
/// Otherwise `None` is returned.
pub const fn get_row_inside(area: Rect, column: u16, row: u16) -> Option<u16> {
#[allow(clippy::if_then_some_else_none)]
if area.contains(Position { x: column, y: row }) {
Some(row.saturating_sub(area.top()).saturating_sub(1))
} else {
None
}
}

#[test]
fn row_outside() {
let area = Rect::new(5, 5, 5, 10);
let result = get_row_inside(area, 7, 1);
assert_eq!(result, None);
}

#[test]
fn column_outside() {
let area = Rect::new(5, 5, 5, 10);
let result = get_row_inside(area, 1, 7);
assert_eq!(result, None);
}

#[test]
fn is_inside() {
let area = Rect::new(5, 5, 5, 10);
let result = get_row_inside(area, 7, 10);
assert_eq!(result, Some(4));
}

pub const fn split_area_vertically(area: Rect, height_first: u16) -> (Rect, Rect) {
let first = Rect {
height: height_first,
Expand Down

0 comments on commit 3f6f4eb

Please sign in to comment.