Skip to content

Commit

Permalink
chart-lib.js: Expand barChart() to produce the related dot chart if t…
Browse files Browse the repository at this point in the history
…he dot-chart option set brownplt#469

chart.arr: Added dot-chart-from-list()
dot-chart-test.arr added
  • Loading branch information
ds26gte committed Oct 9, 2024
1 parent 867325c commit 8dd3c21
Show file tree
Hide file tree
Showing 4 changed files with 100 additions and 4 deletions.
38 changes: 38 additions & 0 deletions src/web/arr/trove/chart.arr
Original file line number Diff line number Diff line change
Expand Up @@ -1067,6 +1067,7 @@ default-bar-chart-series = {
pointer-color: none,
axisdata: none,
horizontal: false,
dot-chart: false,
default-interval-color: none
}

Expand Down Expand Up @@ -1917,6 +1918,42 @@ fun bar-chart-from-list(labels :: P.LoS, values :: P.LoN) -> DataSeries block:
data-series.make-axis(max-positive-height, max-negative-height)
end

fun dot-chart-from-list(labels :: P.LoS, values :: P.LoN) -> DataSeries block:
doc: ```
Consume labels, a list of string, and values, a list of numbers
and construct a dot chart
```
# Type Checking
values.each(check-num)
labels.each(check-string)

# Constants
label-length = labels.length()
value-length = values.length()
rational-values = map(num-to-rational, values)

# Edge Case Error Checking
when value-length == 0:
raise("dot-chart: can't have empty data")
end
when label-length <> value-length:
raise('dot-chart: labels and values should have the same length')
end

{max-positive-height; max-negative-height} = prep-axis(rational-values)

data-series = default-bar-chart-series.{
tab: to-table2-n(labels, rational-values),
dot-chart: true,
axis-top: max-positive-height,
axis-bottom: max-negative-height,
annotations: values.map({(_): [list: none]}) ^ list-to-table2,
intervals: values.map({(_): [list: [raw-array: ]]}) ^ list-to-table2,
} ^ bar-chart-series

data-series.make-axis(max-positive-height, max-negative-height)
end

fun grouped-bar-chart-from-list(
labels :: P.LoS,
value-lists :: P.LoLoN,
Expand Down Expand Up @@ -2613,6 +2650,7 @@ from-list = {
exploding-pie-chart: exploding-pie-chart-from-list,
image-pie-chart: image-pie-chart-from-list,
bar-chart: bar-chart-from-list,
dot-chart: dot-chart-from-list,
image-bar-chart: image-bar-chart-from-list,
grouped-bar-chart: grouped-bar-chart-from-list,
stacked-bar-chart: stacked-bar-chart-from-list,
Expand Down
43 changes: 41 additions & 2 deletions src/web/js/trove/chart-lib.js
Original file line number Diff line number Diff line change
Expand Up @@ -700,6 +700,7 @@

// ASSERT: if we're using custom images, there will be a 4th column
const hasImage = table[0].length == 4;
const dotChartP = get(rawData, 'dot-chart');

// Adds each row of bar data and bar_color data
table.forEach(function (row) {
Expand All @@ -717,7 +718,7 @@
color : interval_color,
},
series : {
0 : { dataOpacity : hasImage? 0 : 1.0 }
0 : { dataOpacity : (hasImage || dotChartP)? 0 : 1.0 }
}
};

Expand Down Expand Up @@ -761,17 +762,21 @@
onExit: defaultImageReturn,
mutators: [backgroundMutator, axesNameMutator, yAxisRangeMutator],
overlay: (overlay, restarter, chart, container) => {
if(!hasImage) return;

if (!hasImage && !dotChartP) return;

// if custom images are defined, use the image at that location
// and overlay it atop each dot


google.visualization.events.addListener(chart, 'ready', function () {
// HACK(Emmanuel):
// If Google changes the DOM for charts, these lines will likely break
const svgRoot = chart.container.querySelector('svg');
const rects = svgRoot.children[1].children[1].children[1].children;
$('.__img_labels').each((idx, n) => $(n).remove());

if (hasImage) {
// Render each rect above the old ones, using the image as a pattern
table.forEach(function (row, i) {
const rect = rects[i];
Expand All @@ -790,7 +795,41 @@
Object.assign(imageElt, rects[i]); // we should probably not steal *everything*...
svgRoot.appendChild(imageElt);
});
}

if (dotChartP) {
table.forEach(function (row, i) {
// console.log('row', i, '=', row);
const rect = rects[i];
// console.log('rect', i, '=', rect);
const num_elts = row[1];
const rect_x = Number(rect.getAttribute('x'));
const rect_y = Number(rect.getAttribute('y'));
const rect_height = Number(rect.getAttribute('height'));
const unit_height = rect_height/num_elts;
const rect_width = Number(rect.getAttribute('width'));
const rect_fill = rect.getAttribute('fill');
const rect_fill_opacity = Number(rect.getAttribute('fill-opacity'));
const rect_stroke = rect.getAttribute('stroke');
const rect_stroke_width = Number(rect.getAttribute('stroke-width'));
for (let j = 0; j < num_elts; j++) {
const circle = document.createElementNS('http://www.w3.org/2000/svg', 'circle');
circle.classList.add('__img_labels');
circle.setAttribute('r', rect_width/8);
circle.setAttribute('cx', rect_x + rect_width/2);
circle.setAttribute('cy', rect_y + (num_elts - j - 0.5)*unit_height);
circle.setAttribute('fill', rect_fill);
// circle.setAttribute('fill-opacity', rect_fill_opacity);
// circle.setAttribute('stroke', rect_stroke);
// circle.setAttribute('stroke-width', rect_stroke_width);
// console.log('adding circle elt', i, j, '=', circle);
svgRoot.appendChild(circle);
}
});
}

});

}
};
}
Expand Down
18 changes: 18 additions & 0 deletions test-util/pyret-programs/charts/dot-chart-test.arr
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
include chart
include image
import color as C
# include image-structs
include math

labels = [list: "cats", "dogs", "ants", "elephants"]
count = [list: 3, 7, 4, 9]

series = from-list.dot-chart(
labels,
count)

img = render-chart(series).get-image()

check:
img satisfies is-image
end
5 changes: 3 additions & 2 deletions test-util/pyret-programs/charts/image-bar-chart-test.arr
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
include chart
include image
include image-structs
import color as C
# include image-structs # color tan clashes with starter2024's trig tan
include math

fun f(r): star(50, "solid", "red") end
Expand All @@ -19,5 +20,5 @@ img = render-chart(series)

check:
img satisfies is-image
color-at-position(img, 504, 258) is red
color-at-position(img, 504, 258) is C.red
end

0 comments on commit 8dd3c21

Please sign in to comment.