impl PivotTable {
fn builder(title: impl Into<Value>, dimensions: Vec<DimensionBuilder>) -> PivotTableBuilder {
- PivotTableBuilder::new(title, dimensions)
+ PivotTableBuilder::from_builders(title, dimensions)
}
fn axis_values(&self, axis: Axis3) -> AxisIterator {
AxisIterator {
}
impl Dimension {
+ pub fn new(root: Group) -> Self {
+ Dimension {
+ presentation_order: (0..root.len()).collect(),
+ root,
+ hide_all_labels: false,
+ }
+ }
+
pub fn is_empty(&self) -> bool {
self.len() == 0
}
}
impl Group {
+ pub fn new(name: impl Into<Value>) -> Group {
+ Self {
+ len: 0,
+ name: Box::new(name.into()),
+ children: Vec::new(),
+ show_label: false,
+ }
+ }
+
+ pub fn push(&mut self, child: impl Into<Category>) {
+ let mut child = child.into();
+ if let Category::Group(group) = &mut child {
+ group.show_label = true;
+ }
+ self.len += child.len();
+ self.children.push(child);
+ }
+
+ pub fn with(mut self, child: impl Into<Category>) -> Self {
+ self.push(child);
+ self
+ }
+
+ pub fn with_label_shown(self) -> Self {
+ self.with_show_label(true)
+ }
+
+ pub fn with_show_label(mut self, show_label: bool) -> Self {
+ self.show_label = show_label;
+ self
+ }
+
pub fn builder(name: impl Into<Value>) -> GroupBuilder {
GroupBuilder::new(name)
}
}
impl PivotTableBuilder {
- pub fn new(title: impl Into<Value>, dimension_builders: Vec<DimensionBuilder>) -> Self {
+ pub fn new(title: impl Into<Value>, dimensions_and_axes: Vec<(Axis3, Dimension)>) -> Self {
+ let mut dimensions = Vec::new();
+ let mut axes = EnumMap::<Axis3, Axis>::default();
+ for (axis, dimension) in dimensions_and_axes {
+ axes[axis].dimensions.push(dimensions.len());
+ dimensions.push(dimension);
+ }
+ Self {
+ look: Settings::global().look.clone(),
+ title: Box::new(title.into()),
+ axes,
+ dimensions,
+ cells: HashMap::new(),
+ footnotes: Footnotes::new(),
+ }
+ }
+ pub fn from_builders(
+ title: impl Into<Value>,
+ dimension_builders: Vec<DimensionBuilder>,
+ ) -> Self {
let mut dimensions = Vec::with_capacity(dimension_builders.len());
let mut axes = EnumMap::from_fn(|_axis| Axis {
dimensions: Vec::with_capacity(dimension_builders.len()),
}
}
+impl From<Group> for Category {
+ fn from(group: Group) -> Self {
+ Self::Group(group)
+ }
+}
+
+impl From<Value> for Category {
+ fn from(name: Value) -> Self {
+ Self::Leaf(Leaf::new(name))
+ }
+}
+
+impl From<&str> for Category {
+ fn from(name: &str) -> Self {
+ Self::Leaf(Leaf::new(Value::new_text(name)))
+ }
+}
+
trait CategoryTrait {
fn name(&self) -> &Value;
}
}
fn d1(title: &str, axis: Axis3) -> PivotTable {
- let mut group = GroupBuilder::new(Value::new_text("a")).with_label_shown();
- for name in ["a1", "a2", "a3"] {
- group.push(Value::new_text(name));
- }
- let dimension = DimensionBuilder::new(axis, group);
- let mut pt = PivotTableBuilder::new(Value::new_text(title), vec![dimension]);
+ let dimension = Dimension::new(
+ Group::new("a")
+ .with_label_shown()
+ .with("a1")
+ .with("a2")
+ .with("a3"),
+ );
+ let mut pt = PivotTableBuilder::new(Value::new_text(title), vec![(axis, dimension)]);
for i in 0..3 {
pt.insert(&[i], Value::new_integer(Some(i as f64)));
}
}
fn d2(title: &str, axes: [Axis3; 2], dimension_labels: Option<LabelPosition>) -> PivotTable {
- let mut a = GroupBuilder::new(Value::new_text("a")).with_show_label(dimension_labels.is_some());
- for name in ["a1", "a2", "a3"] {
- a.push(Value::new_text(name));
- }
- let d1 = DimensionBuilder::new(axes[0], a);
+ let d1 = Dimension::new(
+ Group::new("a")
+ .with_show_label(dimension_labels.is_some())
+ .with("a1")
+ .with("a2")
+ .with("a3"),
+ );
- let mut b = GroupBuilder::new(Value::new_text("b")).with_show_label(dimension_labels.is_some());
- for name in ["b1", "b2", "b3"] {
- b.push(Value::new_text(name));
- }
- let d2 = DimensionBuilder::new(axes[1], b);
+ let d2 = Dimension::new(
+ Group::new("b")
+ .with_show_label(dimension_labels.is_some())
+ .with("b1")
+ .with("b2")
+ .with("b3"),
+ );
- let mut pt = PivotTableBuilder::new(Value::new_text(title), vec![d1, d2]);
+ let mut pt = PivotTableBuilder::new(Value::new_text(title), vec![(axes[0], d1), (axes[1], d2)]);
let mut i = 0;
for b in 0..3 {
for a in 0..3 {
let mut footnotes = Footnotes::new();
let f0 = footnotes.push(Footnote::new("First footnote").with_marker("*"));
let f1 = footnotes.push(Footnote::new("Second footnote"));
- let a = Dimension::builder(
+ let a = (
Axis3::X,
- Group::builder(Value::new_text("A").with_footnote(&f0))
- .with_label_shown()
- .with(Value::new_text("B").with_footnote(&f1))
- .with(Value::new_text("C").with_footnote(&f0).with_footnote(&f1)),
+ Dimension::new(
+ Group::new(Value::new_text("A").with_footnote(&f0))
+ .with_label_shown()
+ .with(Value::new_text("B").with_footnote(&f1))
+ .with(Value::new_text("C").with_footnote(&f0).with_footnote(&f1)),
+ ),
);
- let d = Dimension::builder(
+ let d = (
Axis3::Y,
- Group::builder(Value::new_text("D").with_footnote(&f1))
- .with_label_shown()
- .with(Value::new_text("E").with_footnote(&f0))
- .with(Value::new_text("F").with_footnote(&f1).with_footnote(&f0)),
+ Dimension::new(
+ Group::new(Value::new_text("D").with_footnote(&f1))
+ .with_label_shown()
+ .with(Value::new_text("E").with_footnote(&f0))
+ .with(Value::new_text("F").with_footnote(&f1).with_footnote(&f0)),
+ ),
);
let look = test_look().with_row_label_position(LabelPosition::Nested);
- let mut pt = PivotTable::builder(
+ let mut pt = PivotTableBuilder::new(
Value::new_text("Pivot Table with Alphabetic Subscript Footnotes").with_footnote(&f0),
vec![a, d],
);
#[test]
fn no_dimension() {
- let pivot_table = PivotTableBuilder::new(Value::new_text("No Dimensions"), vec![])
+ let pivot_table = PivotTableBuilder::new("No Dimensions", vec![])
.with_look(Arc::new(test_look()))
.build();
assert_rendering(
fn empty_dimensions() {
let look = Arc::new(test_look().with_omit_empty(false));
- let d1 = DimensionBuilder::new(Axis3::X, GroupBuilder::new(Value::new_text("a")));
- let pivot_table = PivotTableBuilder::new(Value::new_text("One Empty Dimension"), vec![d1])
+ let d1 = (Axis3::X, Dimension::new(Group::new("a")));
+ let pivot_table = PivotTableBuilder::new("One Empty Dimension", vec![d1])
.with_look(look.clone())
.build();
assert_rendering(&pivot_table, "One Empty Dimension\n");
- let d1 = DimensionBuilder::new(Axis3::X, GroupBuilder::new(Value::new_text("a")));
- let d2 = DimensionBuilder::new(
- Axis3::X,
- GroupBuilder::new(Value::new_text("b")).with_label_shown(),
- );
+ let d1 = (Axis3::X, Dimension::new(Group::new("a")));
+ let d2 = (Axis3::X, Dimension::new(Group::new("b").with_label_shown()));
let pivot_table = PivotTableBuilder::new(Value::new_text("Two Empty Dimensions"), vec![d1, d2])
.with_look(look.clone())
.build();
assert_rendering(&pivot_table, "Two Empty Dimensions\n");
- let d1 = DimensionBuilder::new(Axis3::X, GroupBuilder::new(Value::new_text("a")));
- let d2 = DimensionBuilder::new(
+ let d1 = (Axis3::X, Dimension::new(Group::new("a")));
+ let d2 = (Axis3::X, Dimension::new(Group::new("b").with_label_shown()));
+ let d3 = (
Axis3::X,
- GroupBuilder::new(Value::new_text("b")).with_label_shown(),
+ Dimension::new(Group::new("c").with("c1").with("c2")),
);
- let d3 = DimensionBuilder::new(
- Axis3::X,
- GroupBuilder::new(Value::new_text("c"))
- .with(Value::new_text("c1"))
- .with(Value::new_text("c2")),
- );
- let pivot_table = PivotTableBuilder::new(
- Value::new_text("Three Dimensions, Two Empty"),
- vec![d1, d2, d3],
- )
- .with_look(look.clone())
- .build();
+ let pivot_table = PivotTableBuilder::new("Three Dimensions, Two Empty", vec![d1, d2, d3])
+ .with_look(look.clone())
+ .build();
assert_rendering(&pivot_table, "Three Dimensions, Two Empty\n");
}
#[test]
fn empty_groups() {
- let a = GroupBuilder::new(Value::new_text("a"))
- .with(Value::new_text("a1"))
- .with(GroupBuilder::new(Value::new_text("a2")))
- .with(Value::new_text("a3"));
- let d1 = DimensionBuilder::new(Axis3::X, a);
+ let d1 = (
+ Axis3::X,
+ Dimension::new(Group::new("a").with("a1").with(Group::new("a2")).with("a3")),
+ );
- let b = GroupBuilder::new(Value::new_text("b"))
- .with(GroupBuilder::new(Value::new_text("b1")))
- .with(Value::new_text("b2"))
- .with(Value::new_text("b3"));
- let d2 = DimensionBuilder::new(Axis3::Y, b);
+ let d2 = (
+ Axis3::Y,
+ Dimension::new(Group::new("b").with(Group::new("b1")).with("b2").with("b3")),
+ );
- let mut pt = PivotTableBuilder::new(Value::new_text("Empty Groups"), vec![d1, d2]);
+ let mut pt = PivotTableBuilder::new("Empty Groups", vec![d1, d2]);
let mut i = 0;
for b in 0..2 {
for a in 0..2 {
borders: EnumMap<Border, BorderStyle>,
show_dimension_labels: bool,
) -> PivotTable {
- let a = Dimension::builder(
+ let a = (
Axis3::X,
- Group::builder("a")
- .with_show_label(show_dimension_labels)
- .with("a1")
- .with(Group::builder("ag1").with("a2").with("a3")),
+ Dimension::new(
+ Group::new("a")
+ .with_show_label(show_dimension_labels)
+ .with("a1")
+ .with(Group::new("ag1").with("a2").with("a3")),
+ ),
);
- let b = Dimension::builder(
+ let b = (
Axis3::X,
- Group::builder("b")
- .with_show_label(show_dimension_labels)
- .with(Group::builder("bg1").with("b1").with("b2"))
- .with("b3"),
+ Dimension::new(
+ Group::new("b")
+ .with_show_label(show_dimension_labels)
+ .with(Group::new("bg1").with("b1").with("b2"))
+ .with("b3"),
+ ),
);
- let c = Dimension::builder(
+ let c = (
Axis3::Y,
- Group::builder("c")
- .with_show_label(show_dimension_labels)
- .with("c1")
- .with(Group::builder("cg1").with("c2").with("c3")),
+ Dimension::new(
+ Group::new("c")
+ .with_show_label(show_dimension_labels)
+ .with("c1")
+ .with(Group::new("cg1").with("c2").with("c3")),
+ ),
);
- let d = Dimension::builder(
+ let d = (
Axis3::Y,
- Group::builder("d")
- .with_show_label(show_dimension_labels)
- .with(Group::builder("dg1").with("d1").with("d2"))
- .with("d3"),
+ Dimension::new(
+ Group::new("d")
+ .with_show_label(show_dimension_labels)
+ .with(Group::new("dg1").with("d1").with("d2"))
+ .with("d3"),
+ ),
);
- let mut pivot_table = PivotTable::builder(title, vec![a, b, c, d])
+ let mut pivot_table = PivotTableBuilder::new(title, vec![a, b, c, d])
.with_look(Arc::new(test_look().with_borders(borders)));
let mut i = 0;
for d in 0..3 {
#[test]
fn small_numbers() {
- let exponent = Dimension::builder(
+ let exponent = (
Axis3::Y,
- Group::builder("exponent")
- .with("0")
- .with("-1")
- .with("-2")
- .with("-3")
- .with("-4")
- .with("-5")
- .with("-6")
- .with("-7")
- .with("-8")
- .with("-9")
- .with_label_shown(),
+ Dimension::new(
+ Group::new("exponent")
+ .with("0")
+ .with("-1")
+ .with("-2")
+ .with("-3")
+ .with("-4")
+ .with("-5")
+ .with("-6")
+ .with("-7")
+ .with("-8")
+ .with("-9")
+ .with_label_shown(),
+ ),
);
- let sign = Dimension::builder(
+ let sign = (
Axis3::X,
- Group::builder("sign")
- .with("positive")
- .with("negative")
- .with_label_shown(),
+ Dimension::new(
+ Group::new("sign")
+ .with("positive")
+ .with("negative")
+ .with_label_shown(),
+ ),
);
- let rc = Dimension::builder(
+ let rc = (
Axis3::X,
- Group::builder("result class")
- .with((Value::new_text("general"), Class::Other))
- .with((Value::new_text("specific"), Class::Residual))
- .with_label_shown(),
+ Dimension::new(
+ Group::new("result class")
+ .with("general")
+ .with("specific")
+ .with_label_shown(),
+ ),
);
- let mut pt = PivotTable::builder("small numbers", vec![exponent, sign, rc]);
+ let mut pt = PivotTableBuilder::new("small numbers", vec![exponent, sign, rc]);
pt.insert_number(&[0, 0, 0], Some(1.0), Class::Other);
pt.insert_number(&[1, 0, 0], Some(0.1), Class::Other);
pt.insert_number(&[2, 0, 0], Some(0.01), Class::Other);