init
It's expected to call this when self is undefined
Parameters
- self:*PlotWidget
- *PlotWidget
- src:std.builtin.SourceLocation
- std.builtin.SourceLocation
- init_opts:InitOptions
- InitOptions
- opts:Options
- Options
Source
Implementation
pub fn init(self: *PlotWidget, src: std.builtin.SourceLocation, init_opts: InitOptions, opts: Options) void {
self.* = .{
.src = src,
.opts = opts,
.init_options = init_opts,
};
self.box.init(self.src, .{ .dir = .vertical }, defaults.override(self.opts));
if (self.init_options.x_axis) |xa| {
self.x_axis = xa;
} else {
if (dvui.dataGet(null, self.box.data().id, "_x_axis", Axis)) |xaxis| {
self.x_axis_store = xaxis;
}
self.x_axis = &self.x_axis_store;
}
if (self.init_options.y_axis) |ya| {
self.y_axis = ya;
} else {
if (dvui.dataGet(null, self.box.data().id, "_y_axis", Axis)) |yaxis| {
self.y_axis_store = yaxis;
}
self.y_axis = &self.y_axis_store;
}
self.box.drawBackground();
if (self.init_options.title) |title| {
dvui.label(@src(), "{s}", .{title}, .{ .gravity_x = 0.5, .font = opts.themeGet().font_title });
}
const tick_font = opts.themeGet().font_body.larger(-3);
var yticks = self.y_axis.getTicks(dvui.currentWindow().lifo()) catch Axis.Ticks.empty;
defer yticks.deinit(dvui.currentWindow().lifo());
var xticks = self.x_axis.getTicks(dvui.currentWindow().lifo()) catch Axis.Ticks.empty;
defer xticks.deinit(dvui.currentWindow().lifo());
const y_axis_tick_width: f32 = blk: {
if (self.y_axis.name == null) break :blk 0;
var max_width: f32 = 0;
for (yticks.values) |ytick| {
const tick_str = self.y_axis.formatTick(dvui.currentWindow().lifo(), ytick) catch "";
defer dvui.currentWindow().lifo().free(tick_str);
max_width = @max(max_width, tick_font.textSize(tick_str).w);
}
break :blk max_width;
};
const x_axis_last_tick_width: f32 = blk: {
if (xticks.values.len == 0) break :blk 0;
const str = self.x_axis.formatTick(
dvui.currentWindow().lifo(),
xticks.values[xticks.values.len - 1],
) catch "";
defer dvui.currentWindow().lifo().free(str);
break :blk tick_font.sizeM(@as(f32, @floatFromInt(str.len)), 1).w;
};
var hbox1 = dvui.box(@src(), .{ .dir = .horizontal }, .{ .expand = .both });
// y axis label
var yaxis = dvui.box(@src(), .{ .dir = .horizontal }, .{
.expand = .vertical,
.min_size_content = .{ .w = y_axis_tick_width },
.padding = dvui.Rect{ .w = y_axis_tick_width },
});
var yaxis_rect = yaxis.data().rect;
if (self.y_axis.name) |yname| {
if (yname.len > 0) {
dvui.label(@src(), "{s}", .{yname}, .{ .gravity_y = 0.5, .rotation = std.math.pi * 1.5 });
}
}
yaxis.deinit();
// x axis padding
if (self.x_axis.name) |_| {
var xaxis_padding = dvui.box(@src(), .{ .dir = .horizontal }, .{
.gravity_x = 1.0,
.expand = .vertical,
.min_size_content = .{ .w = x_axis_last_tick_width / 2 },
});
xaxis_padding.deinit();
}
// data area
var data_box = dvui.box(@src(), .{ .dir = .horizontal }, .{
.expand = .both,
.role = .image,
.label = .{ .text = self.init_options.title orelse "" },
});
// mouse hover
if (self.init_options.mouse_hover) {
const evts = dvui.events();
for (evts) |*e| {
if (!dvui.eventMatchSimple(e, data_box.data()))
continue;
switch (e.evt) {
.mouse => |me| {
if (me.action == .position) {
dvui.cursorSet(.arrow);
self.mouse_point = me.p;
}
},
else => {},
}
}
}
yaxis_rect.h = data_box.data().rect.h;
self.data_rs = data_box.data().contentRectScale();
data_box.deinit();
const bt: f32 = self.init_options.border_thick orelse 0.0;
const bc: dvui.Color = self.init_options.spine_color orelse self.box.data().options.color(.text);
const pad = 2 * self.data_rs.s;
hbox1.deinit();
var hbox2 = dvui.box(@src(), .{ .dir = .horizontal }, .{ .expand = .horizontal });
// bottom left corner under y axis
_ = dvui.spacer(@src(), .{ .min_size_content = .width(yaxis_rect.w), .expand = .vertical });
var x_tick_height: f32 = 0;
if (self.x_axis.name) |_| {
if (self.x_axis.min != null or self.x_axis.max != null) {
x_tick_height = tick_font.sizeM(1, 1).h;
}
}
// x axis label
var xaxis = dvui.box(@src(), .{}, .{
.gravity_y = 1.0,
.expand = .horizontal,
.min_size_content = .{ .h = x_tick_height * 3 },
});
if (self.x_axis.name) |xname| {
if (xname.len > 0) {
dvui.label(@src(), "{s}", .{xname}, .{ .gravity_x = 0.5, .gravity_y = 1.0 });
}
}
xaxis.deinit();
_ = dvui.spacer(@src(), .{
.min_size_content = .width(x_axis_last_tick_width / 2),
.expand = .vertical,
});
hbox2.deinit();
const tick_line_len = 5;
const subtick_line_len = 3;
// y axis ticks
if (self.y_axis.name) |_| {
for (yticks.values) |ytick| {
const tick: Data = .{ .x = self.x_axis.min orelse 0, .y = ytick };
const tick_str = self.y_axis.formatTick(dvui.currentWindow().lifo(), ytick) catch "";
defer dvui.currentWindow().lifo().free(tick_str);
const tick_str_size = tick_font.textSize(tick_str).scale(self.data_rs.s, Size.Physical);
const tick_p = self.dataToScreen(tick);
self.drawTickline(
.vertical,
tick_p,
tick_line_len,
self.y_axis.ticks.side,
bc,
self.y_axis.gridline_color,
);
var tick_label_p = tick_p;
tick_label_p.x -= tick_str_size.w + pad;
tick_label_p.y -= tick_str_size.h / 2;
const tick_rs: RectScale = .{ .r = Rect.Physical.fromPoint(tick_label_p).toSize(tick_str_size), .s = self.data_rs.s };
dvui.renderText(.{
.font = tick_font,
.text = tick_str,
.rs = tick_rs,
.color = self.box.data().options.color(.text),
}) catch |err| {
dvui.logError(@src(), err, "y axis tick text for {d}", .{ytick});
};
}
for (yticks.subticks) |ytick| {
const tick: Data = .{ .x = self.x_axis.min orelse 0, .y = ytick };
const tick_p = self.dataToScreen(tick);
self.drawTickline(
.vertical,
tick_p,
subtick_line_len,
self.y_axis.ticks.side,
bc,
self.y_axis.subtick_gridline_color,
);
}
}
// x axis ticks
if (self.x_axis.name) |_| {
for (xticks.values) |xtick| {
const tick: Data = .{ .x = xtick, .y = self.y_axis.min orelse 0 };
const tick_str = self.x_axis.formatTick(dvui.currentWindow().lifo(), xtick) catch "";
defer dvui.currentWindow().lifo().free(tick_str);
const tick_str_size = tick_font.textSize(tick_str).scale(self.data_rs.s, Size.Physical);
const tick_p = self.dataToScreen(tick);
self.drawTickline(
.horizontal,
tick_p,
tick_line_len,
self.x_axis.ticks.side,
bc,
self.x_axis.gridline_color,
);
var tick_label_p = tick_p;
tick_label_p.x -= tick_str_size.w / 2;
tick_label_p.y += pad;
const tick_rs: RectScale = .{ .r = Rect.Physical.fromPoint(tick_label_p).toSize(tick_str_size), .s = self.data_rs.s };
dvui.renderText(.{
.font = tick_font,
.text = tick_str,
.rs = tick_rs,
.color = self.box.data().options.color(.text),
}) catch |err| {
dvui.logError(@src(), err, "x axis tick text for {d}", .{xtick});
};
}
for (xticks.subticks) |xtick| {
const tick: Data = .{ .x = xtick, .y = self.y_axis.min orelse 0 };
const tick_p = self.dataToScreen(tick);
self.drawTickline(
.horizontal,
tick_p,
subtick_line_len,
self.x_axis.ticks.side,
bc,
self.x_axis.subtick_gridline_color,
);
}
}
if (bt > 0) {
self.data_rs.r.stroke(.{}, .{ .thickness = bt * self.data_rs.s, .color = bc });
}
self.old_clip = dvui.clip(self.data_rs.r);
}