in packages/sanddance-specs/src/layouts/cross.ts [88:265]
public build(): InnerScope {
const { binX, binY, names, prefix, props } = this;
const { axisTextColor, colRowTitles, globalScope, parentScope } = props;
const titles: Titles = { x: { dataName: null, quantitative: null }, y: { dataName: null, quantitative: null } };
const dx: Dimension = {
dim: 'x',
bin: binX,
sortOrder: <SortOrder>'ascending',
size: parentScope.sizeSignals.layoutWidth,
layout: parentScope.sizeSignals.layoutWidth,
min: globalScope.signals.minCellWidth.name,
out: globalScope.signals.plotWidthOut,
offset: SignalNames.FacetPaddingLeft,
padding: SignalNames.FacetPaddingLeft,
dataOut: <Data>null,
scaleName: <string>null,
position: null
};
const dy: Dimension = {
dim: 'y',
bin: binY,
sortOrder: <SortOrder>'ascending',
size: parentScope.sizeSignals.layoutHeight,
layout: parentScope.sizeSignals.layoutHeight,
min: globalScope.signals.minCellHeight.name,
out: globalScope.signals.plotHeightOut,
offset: SignalNames.FacetPaddingTop,
padding: `(${SignalNames.FacetPaddingTop} + ${SignalNames.FacetPaddingBottom})`,
dataOut: <Data>null,
scaleName: <string>null,
position: null
};
const dimensions = [dx, dy];
dimensions.forEach(d => {
const { bin, dim, padding, sortOrder } = d;
let data: Data;
let dataName: string;
let countSignal: string;
let scale: OrdinalScale;
const titleSource: TitleSource = titles[dim];
if (bin.native === false) {
addSignals(globalScope.scope, ...bin.signals);
addTransforms(globalScope.data, ...bin.transforms);
addData(globalScope.scope, bin.dataSequence);
addTransforms(bin.dataSequence,
{
type: 'formula',
expr: `indata(${JSON.stringify(globalScope.markDataName)}, ${JSON.stringify(bin.fields[0])}, datum[${JSON.stringify(bin.fields[0])}])`,
as: FieldNames.Contains
}
);
data = bin.dataSequence;
dataName = bin.dataSequence.name;
countSignal = `length(data(${JSON.stringify(dataName)}))`;
scale = ordinalScale(dataName, `${names.dimScale}_${dim}`, bin.fields);
titleSource.dataName = bin.dataSequence.name;
} else {
dataName = globalScope.markDataName;
const ord = createOrdinals(dataName, `${prefix}_${dim}`, bin.fields, sortOrder);
data = ord.data;
addData(globalScope.scope, ord.data);
countSignal = `length(data(${JSON.stringify(ord.data.name)}))`;
scale = ord.scale;
titleSource.dataName = ord.data.name;
}
titleSource.quantitative = bin.discreteColumn.column.quantitative;
d.dataOut = data;
d.scaleName = scale.name;
addTransforms(data,
{
type: 'formula',
expr: serializeAsVegaExpression(bin, FieldNames.First, FieldNames.Last),
as: FieldNames.FacetSearch
},
{
type: 'formula',
expr: displayBin(bin),
as: FieldNames.FacetTitle
}
);
addScales(globalScope.scope, scale);
const count = `${names.dimCount}_${dim}`;
const calc = `${names.dimCellSizeCalc}_${dim}`;
const size = `${names.dimCellSize}_${dim}`;
addSignals(globalScope.scope, { name: count, update: countSignal });
addSignals(globalScope.scope,
{
name: calc,
update: `${d.layout} / ${count}`
},
{
name: size,
update: `max(${d.min}, (${calc} - ${padding}))`
}
);
modifySignal(d.out, 'max', `((${size} + ${padding}) * ${count})`);
d.position = this.dimensionOffset(d);
});
const groupRow: GroupMark = {
type: 'group',
encode: {
update: {
y: {
signal: dy.position
}
}
},
from: {
data: dy.dataOut.name
},
data: [
{
name: names.searchUnion,
source: dx.dataOut.name,
transform: [
{
type: 'formula',
expr: `[datum[${JSON.stringify(FieldNames.FacetSearch)}], merge(parent[${JSON.stringify(FieldNames.FacetSearch)}], { clause: '&&'})]`,
as: FieldNames.FacetSearch
}
]
}
]
};
const groupCol: GroupMark = {
style: 'cell',
name: prefix,
type: 'group',
encode: {
update: {
height: {
signal: `${names.dimCellSize}_y`
},
width: {
signal: `${names.dimCellSize}_x`
},
x: {
signal: dx.position
}
}
},
from: {
data: names.searchUnion
}
};
addMarks(globalScope.markGroup, groupRow);
addMarks(groupRow, groupCol);
const offsets: LayoutOffsets = {
x: this.dimensionOffset(dx),
y: this.dimensionOffset(dy),
h: `${names.dimCellSize}_y`,
w: `${names.dimCellSize}_x`
};
const sizeSignals: SizeSignals = {
layoutHeight: `${names.dimCellSize}_y`,
layoutWidth: `${names.dimCellSize}_x`,
colCount: `${names.dimCount}_x`,
rowCount: `${names.dimCount}_y`
};
if (colRowTitles) {
addFacetColRowTitles(globalScope.scope, titles.x, titles.y, sizeSignals, axisTextColor);
}
return {
facetScope: groupCol,
offsets,
sizeSignals,
titles
};
}