in src/app/stores/action_handlers/glyph.ts [15:250]
export default function (REG: ActionHandlerRegistry<AppStore, Actions.Action>) {
REG.add(Actions.AddGlyph, function (action) {
this.saveHistory();
const glyph = this.chartManager.addGlyph(
action.classID,
this.dataset.tables[0].name
);
this.currentSelection = new GlyphSelection(null, glyph);
this.currentGlyph = glyph;
this.solveConstraintsAndUpdateGraphics();
});
REG.add(Actions.RemoveGlyph, function (action) {
this.saveHistory();
this.chartManager.removeGlyph(action.glyph);
this.currentSelection = null;
this.currentGlyph = null;
this.solveConstraintsAndUpdateGraphics();
});
REG.add(Actions.SetGlyphAttribute, function (action) {
this.saveHistory();
if (action.mapping == null) {
delete action.glyph.mappings[action.attribute];
} else {
action.glyph.mappings[action.attribute] = action.mapping;
}
this.solveConstraintsAndUpdateGraphics();
});
REG.add(Actions.UpdateGlyphAttribute, function (action) {
this.saveHistory();
for (const key in action.updates) {
if (!Object.prototype.hasOwnProperty.call(action.updates, key)) {
continue;
}
delete action.glyph.mappings[key];
}
this.forAllGlyph(action.glyph, (glyphState) => {
for (const key in action.updates) {
if (!Object.prototype.hasOwnProperty.call(action.updates, key)) {
continue;
}
glyphState.attributes[key] = action.updates[key];
this.addPresolveValue(
Solver.ConstraintStrength.STRONG,
glyphState.attributes,
key,
action.updates[key] as number
);
}
});
this.solveConstraintsAndUpdateGraphics();
});
// eslint-disable-next-line
REG.add(Actions.AddMarkToGlyph, function (action) {
this.saveHistory();
const mark = this.chartManager.createObject(
action.classID
) as Specification.Element;
for (const key in action.properties) {
mark.properties[key] = action.properties[key];
}
// Make sure name don't duplicate
if (this.chartManager.isNameUsed(mark.properties.name)) {
mark.properties.name = this.chartManager.findUnusedName(
mark.properties.name
);
}
this.chartManager.addMarkToGlyph(mark, action.glyph);
let attributesSet = false;
for (const attr in action.mappings) {
if (Object.prototype.hasOwnProperty.call(action.mappings, attr)) {
const [value, mapping] = action.mappings[attr];
if (mapping != null) {
if (mapping.type == MappingType._element) {
const elementMapping = mapping as SnappingElementMapping;
action.glyph.constraints.push({
type: "snap",
attributes: {
element: mark._id,
attribute: attr,
targetElement: elementMapping.element,
targetAttribute: elementMapping.attribute,
gap: 0,
},
});
} else {
mark.mappings[attr] = mapping;
}
}
if (value != null) {
const idx = action.glyph.marks.indexOf(mark);
this.forAllGlyph(action.glyph, (glyphState) => {
glyphState.marks[idx].attributes[attr] = value;
this.addPresolveValue(
Solver.ConstraintStrength.STRONG,
glyphState.marks[idx].attributes,
attr,
value
);
});
}
attributesSet = true;
}
}
// Logic for first marks
if (!attributesSet) {
switch (action.classID) {
case "mark.rect":
case "mark.nested-chart":
case "mark.textbox":
case "mark.image":
{
mark.mappings.x1 = {
type: MappingType.parent,
parentAttribute: "ix1",
} as Specification.ParentMapping;
mark.mappings.y1 = {
type: MappingType.parent,
parentAttribute: "iy1",
} as Specification.ParentMapping;
mark.mappings.x2 = {
type: MappingType.parent,
parentAttribute: "ix2",
} as Specification.ParentMapping;
mark.mappings.y2 = {
type: MappingType.parent,
parentAttribute: "iy2",
} as Specification.ParentMapping;
// Move anchor to bottom
// action.glyph.marks[0].mappings["y"] = <Specification.ParentMapping>{ type: "parent", parentAttribute: "iy1" };
}
break;
case "mark.line":
{
mark.mappings.x1 = {
type: MappingType.parent,
parentAttribute: "ix1",
} as Specification.ParentMapping;
mark.mappings.y1 = {
type: MappingType.parent,
parentAttribute: "iy1",
} as Specification.ParentMapping;
mark.mappings.x2 = {
type: MappingType.parent,
parentAttribute: "ix2",
} as Specification.ParentMapping;
mark.mappings.y2 = {
type: MappingType.parent,
parentAttribute: "iy2",
} as Specification.ParentMapping;
}
break;
case "mark.symbol":
case "mark.text":
case "mark.icon":
{
mark.mappings.x = {
type: MappingType.parent,
parentAttribute: "icx",
} as Specification.ParentMapping;
mark.mappings.y = {
type: MappingType.parent,
parentAttribute: "icy",
} as Specification.ParentMapping;
}
break;
case "mark.data-axis":
{
mark.mappings.x1 = {
type: MappingType.parent,
parentAttribute: "ix1",
} as Specification.ParentMapping;
mark.mappings.y1 = {
type: MappingType.parent,
parentAttribute: "iy1",
} as Specification.ParentMapping;
mark.mappings.x2 = {
type: MappingType.parent,
parentAttribute: "ix1",
} as Specification.ParentMapping;
mark.mappings.y2 = {
type: MappingType.parent,
parentAttribute: "iy2",
} as Specification.ParentMapping;
}
break;
}
}
if (action.classID == "mark.nested-chart") {
// Add column names to the mark
const columnNameMap: { [name: string]: string } = {};
for (const column of this.getTable(action.glyph.table).columns) {
columnNameMap[column.name] = column.name;
}
mark.properties.columnNameMap = columnNameMap;
}
this.currentSelection = new MarkSelection(
this.findPlotSegmentForGlyph(action.glyph),
action.glyph,
action.glyph.marks[action.glyph.marks.length - 1]
);
this.currentGlyph = action.glyph;
this.solveConstraintsAndUpdateGraphics();
this.emit(AppStore.EVENT_SELECTION);
});
REG.add(Actions.RemoveMarkFromGlyph, function (action) {
this.saveHistory();
// We never delete the anchor
if (action.mark.classID == "mark.anchor") {
return;
}
this.chartManager.removeMarkFromGlyph(action.mark, action.glyph);
this.currentSelection = null;
this.emit(AppStore.EVENT_SELECTION);
this.solveConstraintsAndUpdateGraphics();
});
}