parent
784f3f2c10
commit
c9d71b0bec
@ -0,0 +1,124 @@
|
|||||||
|
use super::*;
|
||||||
|
use treemap::{
|
||||||
|
Rect,
|
||||||
|
Mappable,
|
||||||
|
TreemapLayout
|
||||||
|
};
|
||||||
|
use data::{FsInfo, INodeInfoGraph, INodeInfoGraphEntry};
|
||||||
|
|
||||||
|
/// A treemap of all **files** in the graph.
|
||||||
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
pub struct Treemap
|
||||||
|
{
|
||||||
|
//layout: TreemapLayout,
|
||||||
|
nodes: Vec<MapNode>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Treemap
|
||||||
|
{
|
||||||
|
/// All nodes of the map.
|
||||||
|
#[inline] pub fn nodes(&self) -> &[MapNode]
|
||||||
|
{
|
||||||
|
&self.nodes[..]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
pub struct MapNode
|
||||||
|
{
|
||||||
|
name: String,
|
||||||
|
|
||||||
|
vw_size: f64, // Should be halved each iteration
|
||||||
|
vw_bounds: Rect, // should be Rect::new() before aligntment
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MapNode
|
||||||
|
{
|
||||||
|
/// The calculated bounds of the node
|
||||||
|
#[inline] pub fn bounds(&self) -> &Rect
|
||||||
|
{
|
||||||
|
&self.vw_bounds
|
||||||
|
}
|
||||||
|
/// The name of the node
|
||||||
|
#[inline] pub fn name(&self) -> &str
|
||||||
|
{
|
||||||
|
&self.name[..]
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline] fn size(&self) -> f64 //Is this useful for consumer?
|
||||||
|
{
|
||||||
|
self.vw_size
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline] fn new(name: String) -> Self
|
||||||
|
{
|
||||||
|
Self {
|
||||||
|
vw_size: 1.0,
|
||||||
|
vw_bounds: Rect::new(),
|
||||||
|
name,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a treemap from this graph.
|
||||||
|
pub fn treemap(_cfg: &Config, graph: &INodeInfoGraph, (w, h): (f64, f64)) -> Treemap
|
||||||
|
{
|
||||||
|
let layout = TreemapLayout::new();
|
||||||
|
let mut nodes = Vec::with_capacity(graph.len());
|
||||||
|
//TODO: Recursively walk the graph, halving size with each iteration. (Maybe we need `INodeInfoGraph` here, not `Hierarchicalinodegraph`?)
|
||||||
|
let total_size = graph.total_size();
|
||||||
|
|
||||||
|
let size = 1.0;
|
||||||
|
|
||||||
|
fn calc_path<'a, I: IntoIterator<Item = INodeInfoGraphEntry<'a>>>(insert: &'a mut Vec<MapNode>, from: I, total_size: u64, size: f64, scale: f64)
|
||||||
|
{
|
||||||
|
for top in from {
|
||||||
|
let path = top.path();
|
||||||
|
match top.info() {
|
||||||
|
FsInfo::Directory(_) => {
|
||||||
|
//TODO: Do we add dir itself? I think not?
|
||||||
|
// Add children
|
||||||
|
let size = size * 0.5;
|
||||||
|
calc_path(insert, top.level().unwrap(), total_size, size, scale);
|
||||||
|
},
|
||||||
|
&FsInfo::File(sz, _) => {
|
||||||
|
let fract = (sz as f64) / (total_size as f64);
|
||||||
|
insert.push(MapNode {
|
||||||
|
name: path.to_string_lossy().into_owned(),
|
||||||
|
vw_size: fract * scale,
|
||||||
|
vw_bounds: Rect::new(),
|
||||||
|
})
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
calc_path(&mut nodes, graph.top_level(), total_size, size, 1.0);
|
||||||
|
|
||||||
|
layout.layout_items(&mut nodes[..], Rect {
|
||||||
|
x: 0.0,
|
||||||
|
y: 0.0,
|
||||||
|
w, h,
|
||||||
|
});
|
||||||
|
|
||||||
|
Treemap {
|
||||||
|
//layout,
|
||||||
|
nodes
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Mappable for MapNode
|
||||||
|
{
|
||||||
|
fn size(&self) -> f64
|
||||||
|
{
|
||||||
|
self.vw_size
|
||||||
|
}
|
||||||
|
fn bounds(&self) -> &Rect
|
||||||
|
{
|
||||||
|
&self.vw_bounds
|
||||||
|
}
|
||||||
|
fn set_bounds(&mut self, bounds: Rect)
|
||||||
|
{
|
||||||
|
self.vw_bounds = bounds;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in new issue