draw
Parameters
- self:*LabelWidget
- *LabelWidget
Source
Implementation
pub fn draw(self: *LabelWidget) void {
const rot = self.data().options.rotationGet();
const label_gravity = self.init_options.gravityGet();
const rect = dvui.placeIn(self.data().contentRect(), self.data().options.min_size_contentGet(), .none, label_gravity);
const rs = self.data().parent.screenRectScale(rect);
const sel_start = self.init_options.sel_start;
const sel_end = self.init_options.sel_end;
const sel_color = self.init_options.sel_color;
const oldclip = if (rot == 0.0) dvui.clip(rs.r) else dvui.clipGet();
var iter = std.mem.splitScalar(u8, self.label_str, '\n');
var line_height_adj: ?f32 = null;
var first: bool = true;
var r = rs.r;
var line_start: usize = 0;
while (iter.next()) |line_slice| {
r.x = rs.r.x;
if (first) {
first = false;
} else {
if (line_height_adj == null) {
line_height_adj = self.data().options.fontGet().textHeight() * (self.data().options.fontGet().line_height_factor - 1.0);
}
r.y += rs.s * line_height_adj.?;
}
var line = line_slice;
var tsize = if (line.len == self.label_str.len) self.label_size else self.data().options.fontGet().textSize(line);
// this is only about horizontal direction
var lineRect = dvui.placeIn(self.data().contentRect(), tsize, .none, label_gravity);
const ellip = "...";
// give ourselves a fraction of a pixel extra for floating point innacurracies:
// - a lot of times the content Rect is sized based on the text width
if (rot == 0.0 and self.init_options.ellipsize and tsize.w > (self.data().contentRect().w + 0.001)) {
self.ellipsized = true;
const esize = self.data().options.fontGet().textSize(ellip);
var endi: usize = 0;
tsize = self.data().options.fontGet().textSizeEx(line, .{ .max_width = self.data().contentRect().w - esize.w, .end_idx = &endi });
line = line[0..endi];
lineRect = dvui.placeIn(self.data().contentRect(), tsize, .none, .{ .x = 0, .y = 0 });
}
const liners = self.data().parent.screenRectScale(lineRect);
r.x = liners.r.x;
var render_p = r.topLeft();
if (rot != 0.0) {
const cos = @cos(rot);
const sin = @sin(rot);
// place label size in center and rotate
const origin = self.data().parent.screenRectScale(rect).r.center();
//origin.stroke(.{ .after = true, .thickness = 3.0, .color = .blue });
//const label_size_rect: Rect.Physical = .{ .x = origin.x, .y = origin.y, .w = self.label_size.w * rs.s, .h = self.label_size.h * rs.s };
//label_size_rect.stroke(.all(0), .{ .after = true, .thickness = 1.0, .color = .green });
var d = (dvui.Point{ .x = -self.label_size.w / 2, .y = -self.label_size.h / 2 }).scale(rs.s, dvui.Point);
d.x += (self.label_size.w - tsize.w) * label_gravity.x * rs.s;
d.y += r.y - rs.r.y;
// rotate vector
const rotated: dvui.Point.Physical = .{
.x = d.x * cos - d.y * sin,
.y = d.x * sin + d.y * cos,
};
const xy = origin.plus(rotated);
render_p.x = xy.x;
render_p.y = xy.y;
//r.stroke(.all(0), .{ .after = true, .thickness = 1.0, .color = .red });
}
dvui.renderText(.{
.font = self.data().options.fontGet(),
.text = line,
.p = render_p,
.rs = rs,
.color = self.data().options.color(.text),
.rotation = rot,
.sel_start = if (sel_start) |ss| ss -| line_start else null,
.sel_end = if (sel_end) |se| se -| line_start else null,
.sel_color = sel_color,
}) catch |err| {
dvui.logError(@src(), err, "Failed to render text: {s}", .{line});
};
if (self.ellipsized) {
r.x += liners.r.w;
dvui.renderText(.{
.font = self.data().options.fontGet(),
.text = ellip,
.rs = .{ .r = r, .s = rs.s },
.color = self.data().options.color(.text),
}) catch |err| {
dvui.logError(@src(), err, "Failed to render ellipses after text: {s}", .{line});
};
}
r.y += rs.s * tsize.h;
line_start += line_slice.len + 1; // account for newline
}
dvui.clipSet(oldclip);
}