DVUI

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);
}