1
0
Fork 0
fgdata/Nasal/canvas/draw/scales.nas
2020-03-08 21:02:44 +01:00

129 lines
4.4 KiB
Text

#
# canvas.draw library - scale module for speed tape etc.
# created 12/2018 by jsb
#
# The Scale class combines draw.marks* with text labels to create scales/gauges
# to build speed tape, compass etc.
var Scale = {
# see also canvas.draw.marksStyle
Style: {
new: func() {
var obj = {
parents: [Scale.Style, canvas.draw.marksStyle.new()],
orientation: "u",
spacing: 20, # spacing in pixel
label_interval: 1, # one txt every n marks
label_distance_abs: 0, # distance between ticks and text labels in px
label_distance_rel: 1.1, # distance in %mark_length
mark_color: [255,255,255,1],
label_color: [255,255,255,1],
fontsize: 16, # fontsize for labels
};
return obj;
},
# the 'draw direction' for a linear scale (up, down, left, right)
setOrientation: func(value) {
me.orientation = chr(string.tolower(value[0]));
if (me.orientation == "v") me.orientation = "d";
if (me.orientation == "h") me.orientation = "r";
return me;
},
setFontSize: func(value) {
me.fontsize = num(value) or 16;
return me;
},
setSpacing: func(value) {
me.spacing = num(value) or 10;
return me;
},
# draw one text label every <value> marks
setLabelInterval: func(value) {
me.label_interval = num(value) or 1;
return me;
},
# Distance of text label to mark in pixel (be careful when resizing).
# See also setLabelDistanceRel()
setLabelDistanceAbs: func(value) {
me.label_distance_abs = num(value) or 0;
return me;
},
# Distance of text label to mark in %mark_length (easy scaling).
setLabelDistanceRel: func(value) {
me.label_distance_rel = num(value) or 1.1;
return me;
},
# get alignment of text label for linear scales based on style params
getAlignmentString: func() {
if (me.orientation == "d") {
return (me.mark_offset < 0 ? "right" : "left")~"-center";
}
elsif (me.orientation == "u") {
return (me.mark_offset < 0 ? "right" : "left")~"-center";
}
elsif (me.orientation == "r") {
return "center-"~(me.mark_offset > 0 ? "top" : "bottom");
}
elsif (me.orientation == "l") {
return "center-"~(me.mark_offset > 0 ? "top" : "bottom");
}
else {
return "center-center";
}
},
},
};
# draw a scale on canvas group
# start first value of scale
# count number of values to draw
# increment value to add (can be negative)
Scale.draw = func(cgroup, start, count, increment, style=nil) {
if (style == nil) {
style = me.Style.new();
}
var label_count = count; #math.floor(math.abs(stop - start) / increment);
if (label_count < 2) {
return false;
}
var marks = canvas.draw.marksLinear(cgroup, style.orientation, label_count * style.label_interval, style.spacing, style);
marks.setStrokeLineWidth(style.mark_width);
var labels = cgroup.createChild("group", "labels")
.createChildren("text", label_count);
var length = style.spacing * style.mark_length;
var offset = style.mark_offset * length * style.label_distance_rel;
offset += (offset > 0) ? style.label_distance_abs : -style.label_distance_abs;
var alignment = style.getAlignmentString();
forindex (i; labels) {
var txt = sprintf("%d", start + i * increment);
var translation = i * style.spacing * style.label_interval;
labels[i]
.setText(txt)
.setAlignment(alignment)
.setFontSize(style.fontsize)
.setColor(style.label_color);
if (style.orientation == "d") {
labels[i].setTranslation(offset, translation);
}
elsif (style.orientation == "u") {
labels[i].setTranslation(offset, -translation);
}
elsif (style.orientation == "r") {
labels[i].setTranslation(translation, offset);
}
elsif (style.orientation == "l") {
labels[i].setTranslation(-translation, offset);
}
}
return cgroup;
};