Highlight the current node and make all nodes a bit larger

Savanni D'Gerinel 2024-04-09 21:28:34 -04:00
parent c702ffcfab
commit cff6739d56
2 changed files with 64 additions and 15 deletions

View File

@ -267,6 +267,14 @@ impl<T> Tree<T> {
&self.nodes[idx].content
}
pub fn parent(&self, node: &Node<T>) -> Option<&Node<T>> {
if let Some(parent_idx) = node.parent {
self.nodes.get(parent_idx)
} else {
None
}
}
// Add a node to the parent specified by parent_idx. Return the new index. This cannot be used
// to add the root node, but the constructor should handle that, anyway.
fn add_node(&mut self, parent_idx: usize, node: T) -> usize {

View File

@ -21,6 +21,10 @@ use otg_core::GameReviewViewModel;
const WIDTH: i32 = 200;
const HEIGHT: i32 = 800;
const RADIUS: f64 = 7.5;
const HIGHLIGHT_WIDTH: f64 = 4.;
const SPACING: f64 = 30.;
#[derive(Clone)]
pub struct ReviewTree {
widget: gtk::ScrolledWindow,
@ -32,16 +36,19 @@ pub struct ReviewTree {
impl ReviewTree {
pub fn new(view: GameReviewViewModel) -> ReviewTree {
let drawing_area = gtk::DrawingArea::new();
let widget = gtk::ScrolledWindow::builder()
.child(&drawing_area)
.build();
let widget = gtk::ScrolledWindow::builder().child(&drawing_area).build();
widget.set_width_request(WIDTH);
widget.set_height_request(HEIGHT);
drawing_area.set_height_request(view.tree_max_depth() as i32 * 20 + 40);
// TODO: figure out the maximum width of the tree so that we can also set a width request
drawing_area.set_height_request(view.tree_max_depth() as i32 * SPACING as i32);
let s = Self { widget, drawing_area, view };
let s = Self {
widget,
drawing_area,
view,
};
s.drawing_area.set_draw_func({
let s = s.clone();
@ -55,20 +62,54 @@ impl ReviewTree {
fn redraw(&self, ctx: &Context, _width: i32, _height: i32) {
println!("redraw: {} {}", _width, _height);
self.view.map_tree(move |tree, node, current| {
ctx.set_source_rgb(0.7, 0.7, 0.7);
let (row, column) = tree.position(node.id);
let y = (row as f64) * 20. + 10.;
let x = (column as f64) * 20. + 10.;
ctx.arc(x, y, 5., 0., 2. * std::f64::consts::PI);
if current == Some(node.content) {
ctx.set_line_width(3.);
} else {
#[allow(deprecated)]
let context = WidgetExt::style_context(&self.widget);
#[allow(deprecated)]
let foreground_color = context.lookup_color("sidebar_fg_color").unwrap();
#[allow(deprecated)]
let accent_color = context.lookup_color("accent_color").unwrap();
self.view.map_tree(move |tree, node, current| {
let parent = tree.parent(node);
ctx.set_source_rgb(
foreground_color.red().into(),
foreground_color.green().into(),
foreground_color.blue().into(),
);
let (row, column) = tree.position(node.id);
let y = (row as f64) * SPACING + RADIUS * 2.;
let x = (column as f64) * SPACING + RADIUS * 2.;
ctx.arc(x, y, RADIUS, 0., 2. * std::f64::consts::PI);
let _ = ctx.fill();
if let Some(parent) = parent {
ctx.set_line_width(1.);
let (row, column) = tree.position(parent.id);
let py = (row as f64) * SPACING + RADIUS * 2.;
let px = (column as f64) * SPACING + RADIUS * 2.;
ctx.move_to(px, py);
ctx.line_to(x, y);
let _ = ctx.stroke();
}
let _ = ctx.stroke();
if current == Some(node.content) {
ctx.set_line_width(HIGHLIGHT_WIDTH);
ctx.set_source_rgb(
accent_color.red().into(),
accent_color.green().into(),
accent_color.blue().into(),
);
ctx.arc(
x,
y,
RADIUS + HIGHLIGHT_WIDTH / 2.,
0.,
2. * std::f64::consts::PI,
);
let _ = ctx.stroke();
ctx.set_line_width(2.);
}
});
}