Compare commits
No commits in common. "e3588f68361a410363926683c7026ac0fd5563fb" and "7301c68b7e9a9e1026b53e483ce1c511b03f68b2" have entirely different histories.
e3588f6836
...
7301c68b7e
326
src/app.zig
326
src/app.zig
@ -102,7 +102,7 @@ task_pool: TaskPool,
|
|||||||
shown_window: enum {
|
shown_window: enum {
|
||||||
channels,
|
channels,
|
||||||
add_from_device
|
add_from_device
|
||||||
} = .add_from_device,
|
} = .channels,
|
||||||
|
|
||||||
shown_modal: ?union(enum) {
|
shown_modal: ?union(enum) {
|
||||||
no_library_error,
|
no_library_error,
|
||||||
@ -111,13 +111,10 @@ shown_modal: ?union(enum) {
|
|||||||
} = null,
|
} = null,
|
||||||
|
|
||||||
device_filter: NIDaq.BoundedDeviceName = .{},
|
device_filter: NIDaq.BoundedDeviceName = .{},
|
||||||
channel_type_filter: ?NIDaq.ChannelType = null,
|
show_voltage_analog_inputs: bool = true,
|
||||||
|
show_voltage_analog_outputs: bool = true,
|
||||||
selected_channels: std.BoundedArray([:0]u8, max_channels) = .{},
|
selected_channels: std.BoundedArray([:0]u8, max_channels) = .{},
|
||||||
|
|
||||||
last_hot_channel: ?[:0]const u8 = null,
|
|
||||||
show_device_filter_dropdown: bool = false,
|
|
||||||
show_channel_type_filter_dropdown: bool = false,
|
|
||||||
|
|
||||||
pub fn init(self: *App, allocator: std.mem.Allocator) !void {
|
pub fn init(self: *App, allocator: std.mem.Allocator) !void {
|
||||||
self.* = App{
|
self.* = App{
|
||||||
.allocator = allocator,
|
.allocator = allocator,
|
||||||
@ -352,40 +349,6 @@ fn findChannelIndexByName(haystack: []const [:0]const u8, needle: [:0]const u8)
|
|||||||
|
|
||||||
// ------------------------------- GUI -------------------------------------------- //
|
// ------------------------------- GUI -------------------------------------------- //
|
||||||
|
|
||||||
const Row = struct {
|
|
||||||
name: []const u8,
|
|
||||||
value: []const u8
|
|
||||||
};
|
|
||||||
|
|
||||||
fn showLabelRows(self: *App, rows: []const Row) void {
|
|
||||||
{
|
|
||||||
const name_column = self.ui.newBoxFromString("Names");
|
|
||||||
name_column.layout_axis = .Y;
|
|
||||||
name_column.size.y = UI.Size.childrenSum(1);
|
|
||||||
name_column.size.x = UI.Size.childrenSum(1);
|
|
||||||
self.ui.pushParent(name_column);
|
|
||||||
defer self.ui.popParent();
|
|
||||||
|
|
||||||
for (rows) |row| {
|
|
||||||
_ = self.ui.label(.text, row.name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
const value_column = self.ui.newBoxFromString("Values");
|
|
||||||
value_column.layout_axis = .Y;
|
|
||||||
value_column.size.y = UI.Size.childrenSum(1);
|
|
||||||
value_column.size.x = UI.Size.percent(1, 0);
|
|
||||||
self.ui.pushParent(value_column);
|
|
||||||
defer self.ui.popParent();
|
|
||||||
|
|
||||||
for (rows) |row| {
|
|
||||||
const label = self.ui.label(.text, row.value);
|
|
||||||
label.flags.insert(.text_wrapping);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn showChannelViewSlider(self: *App, view_rect: *Graph.ViewOptions, sample_count: f32) void {
|
fn showChannelViewSlider(self: *App, view_rect: *Graph.ViewOptions, sample_count: f32) void {
|
||||||
const min_visible_samples = 1; // sample_count*0.02;
|
const min_visible_samples = 1; // sample_count*0.02;
|
||||||
|
|
||||||
@ -591,7 +554,7 @@ fn showChannelsWindow(self: *App) !void {
|
|||||||
{
|
{
|
||||||
const prompt_box = self.ui.newBoxFromString("Add prompt");
|
const prompt_box = self.ui.newBoxFromString("Add prompt");
|
||||||
prompt_box.size.x = UI.Size.percent(1, 0);
|
prompt_box.size.x = UI.Size.percent(1, 0);
|
||||||
prompt_box.size.y = UI.Size.pixels(200, 1);
|
prompt_box.size.y = UI.Size.percent(1, 1);
|
||||||
self.ui.pushParent(prompt_box);
|
self.ui.pushParent(prompt_box);
|
||||||
defer self.ui.popParent();
|
defer self.ui.popParent();
|
||||||
|
|
||||||
@ -609,102 +572,14 @@ fn showChannelsWindow(self: *App) !void {
|
|||||||
const from_device_button = self.ui.button(.text, "Add from device");
|
const from_device_button = self.ui.button(.text, "Add from device");
|
||||||
from_device_button.background = srcery.green;
|
from_device_button.background = srcery.green;
|
||||||
if (self.ui.signalFromBox(from_device_button).clicked()) {
|
if (self.ui.signalFromBox(from_device_button).clicked()) {
|
||||||
self.shown_window = .add_from_device;
|
log.debug("TODO: Not implemented", .{});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn showChannelInfoPanel(self: *App, hot_channel: ?[:0]const u8) !void {
|
|
||||||
const ni_daq = &(self.ni_daq orelse return);
|
|
||||||
|
|
||||||
var device_buff: NIDaq.BoundedDeviceName = .{};
|
|
||||||
var hot_device: ?[:0]const u8 = null;
|
|
||||||
if (hot_channel) |channel| {
|
|
||||||
if (NIDaq.getDeviceNameFromChannel(channel)) |device| {
|
|
||||||
device_buff.appendSliceAssumeCapacity(device);
|
|
||||||
device_buff.buffer[device_buff.len] = 0;
|
|
||||||
hot_device = device_buff.buffer[0..device_buff.len :0];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const info_box = self.ui.newBoxFromString("Info box");
|
|
||||||
info_box.layout_axis = .Y;
|
|
||||||
info_box.size.y = UI.Size.percent(1, 0);
|
|
||||||
info_box.size.x = UI.Size.percent(1, 0);
|
|
||||||
self.ui.pushParent(info_box);
|
|
||||||
defer self.ui.popParent();
|
|
||||||
|
|
||||||
if (hot_channel) |channel| {
|
|
||||||
_ = self.ui.label(.text, "Channel properties");
|
|
||||||
|
|
||||||
const channel_info = self.ui.newBoxFromString("Channel info");
|
|
||||||
channel_info.layout_axis = .X;
|
|
||||||
channel_info.size.y = UI.Size.childrenSum(1);
|
|
||||||
channel_info.size.x = UI.Size.percent(1, 0);
|
|
||||||
self.ui.pushParent(channel_info);
|
|
||||||
defer self.ui.popParent();
|
|
||||||
|
|
||||||
var rows: std.BoundedArray(Row, 16) = .{};
|
|
||||||
|
|
||||||
rows.appendAssumeCapacity(Row{
|
|
||||||
.name = "Name",
|
|
||||||
.value = channel
|
|
||||||
});
|
|
||||||
|
|
||||||
var channel_type_name: []const u8 = "unknown";
|
|
||||||
if (NIDaq.getChannelType(channel)) |channel_type| {
|
|
||||||
channel_type_name = channel_type.name();
|
|
||||||
// rows.appendAssumeCapacity(Row{
|
|
||||||
// .name = "Type",
|
|
||||||
// .value = channel_type_name
|
|
||||||
// });
|
|
||||||
}
|
|
||||||
|
|
||||||
rows.appendAssumeCapacity(Row{
|
|
||||||
.name = "Type",
|
|
||||||
.value = channel_type_name
|
|
||||||
});
|
|
||||||
|
|
||||||
self.showLabelRows(rows.constSlice());
|
|
||||||
}
|
|
||||||
|
|
||||||
self.ui.spacer(.{ .y = UI.Size.pixels(16, 0) });
|
|
||||||
|
|
||||||
if (hot_device) |device| {
|
|
||||||
_ = self.ui.label(.text, "Device properties");
|
|
||||||
|
|
||||||
const device_info = self.ui.newBoxFromString("Device info");
|
|
||||||
device_info.layout_axis = .X;
|
|
||||||
device_info.size.y = UI.Size.childrenSum(1);
|
|
||||||
device_info.size.x = UI.Size.percent(1, 0);
|
|
||||||
self.ui.pushParent(device_info);
|
|
||||||
defer self.ui.popParent();
|
|
||||||
|
|
||||||
var rows: std.BoundedArray(Row, 16) = .{};
|
|
||||||
|
|
||||||
if (ni_daq.listDeviceAIMeasurementTypes(device)) |measurement_types| {
|
|
||||||
rows.appendAssumeCapacity(Row{
|
|
||||||
.name = "Measurement types",
|
|
||||||
.value = try std.fmt.allocPrint(device_info.allocator, "{} types", .{measurement_types.len})
|
|
||||||
});
|
|
||||||
} else |e| {
|
|
||||||
log.err("ni_daq.listDeviceAIMeasurementTypes(): {}", .{ e });
|
|
||||||
}
|
|
||||||
|
|
||||||
rows.appendAssumeCapacity(Row{
|
|
||||||
.name = "Foo",
|
|
||||||
.value = "bar"
|
|
||||||
});
|
|
||||||
|
|
||||||
self.showLabelRows(rows.constSlice());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn showAddFromDeviceWindow(self: *App) !void {
|
fn showAddFromDeviceWindow(self: *App) !void {
|
||||||
const ni_daq = &(self.ni_daq orelse return);
|
const ni_daq = &(self.ni_daq orelse return);
|
||||||
|
|
||||||
const device_names = try ni_daq.listDeviceNames();
|
|
||||||
|
|
||||||
const window = self.ui.newBoxFromString("Device window");
|
const window = self.ui.newBoxFromString("Device window");
|
||||||
window.size.x = UI.Size.percent(1, 0);
|
window.size.x = UI.Size.percent(1, 0);
|
||||||
window.size.y = UI.Size.percent(1, 0);
|
window.size.y = UI.Size.percent(1, 0);
|
||||||
@ -714,151 +589,72 @@ fn showAddFromDeviceWindow(self: *App) !void {
|
|||||||
|
|
||||||
{
|
{
|
||||||
const filters_box = self.ui.newBoxFromString("Filters box");
|
const filters_box = self.ui.newBoxFromString("Filters box");
|
||||||
filters_box.size.x = UI.Size.percent(0.5, 0);
|
filters_box.size.x = UI.Size.percent(0.5, 1);
|
||||||
filters_box.size.y = UI.Size.percent(1, 0);
|
filters_box.size.y = UI.Size.percent(1, 0);
|
||||||
filters_box.layout_axis = .Y;
|
filters_box.layout_axis = .Y;
|
||||||
self.ui.pushParent(filters_box);
|
self.ui.pushParent(filters_box);
|
||||||
defer self.ui.popParent();
|
defer self.ui.popParent();
|
||||||
|
|
||||||
const device_name_filter = self.ui.clickableBox("Device name filter");
|
for (try ni_daq.listDeviceNames()) |device| {
|
||||||
const channel_type_filter = self.ui.clickableBox("Channel type filter");
|
const device_box = self.ui.button(.text, device);
|
||||||
|
device_box.size.x = UI.Size.text(2, 1);
|
||||||
if (self.show_device_filter_dropdown) {
|
device_box.size.y = UI.Size.text(2, 1);
|
||||||
const dropdown = self.ui.clickableBox("Device name dropdown");
|
|
||||||
dropdown.size.x = UI.Size.percent(1, 1);
|
|
||||||
dropdown.size.y = UI.Size.childrenSum(1);
|
|
||||||
dropdown.layout_axis = .Y;
|
|
||||||
dropdown.background = srcery.xgray2;
|
|
||||||
self.ui.pushParent(dropdown);
|
|
||||||
defer self.ui.popParent();
|
|
||||||
|
|
||||||
dropdown.setFixedPosition(
|
|
||||||
device_name_filter.persistent.position.add(.{ .x = 0, .y = device_name_filter.persistent.size.y })
|
|
||||||
);
|
|
||||||
|
|
||||||
{
|
|
||||||
const device_box = self.ui.button(.text, "All");
|
|
||||||
device_box.size.x = UI.Size.percent(1, 1);
|
|
||||||
device_box.size.y = UI.Size.text(0.5, 1);
|
|
||||||
device_box.flags.insert(.text_left_align);
|
|
||||||
|
|
||||||
if (self.ui.signalFromBox(device_box).clicked()) {
|
|
||||||
self.device_filter.len = 0;
|
|
||||||
self.show_device_filter_dropdown = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (device_names) |device_name| {
|
|
||||||
const device_box = self.ui.button(.text, device_name);
|
|
||||||
device_box.size.x = UI.Size.percent(1, 1);
|
|
||||||
device_box.size.y = UI.Size.text(0.5, 1);
|
|
||||||
device_box.flags.insert(.text_left_align);
|
|
||||||
|
|
||||||
const signal = self.ui.signalFromBox(device_box);
|
const signal = self.ui.signalFromBox(device_box);
|
||||||
if (signal.clicked()) {
|
if (signal.clicked()) {
|
||||||
self.device_filter = try NIDaq.BoundedDeviceName.fromSlice(device_name);
|
self.device_filter = try NIDaq.BoundedDeviceName.fromSlice(device);
|
||||||
self.show_device_filter_dropdown = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (self.show_channel_type_filter_dropdown) {
|
|
||||||
const dropdown = self.ui.clickableBox("Channel type dropdown");
|
|
||||||
dropdown.size.x = UI.Size.percent(1, 1);
|
|
||||||
dropdown.size.y = UI.Size.childrenSum(1);
|
|
||||||
dropdown.layout_axis = .Y;
|
|
||||||
dropdown.background = srcery.xgray2;
|
|
||||||
self.ui.pushParent(dropdown);
|
|
||||||
defer self.ui.popParent();
|
|
||||||
|
|
||||||
dropdown.setFixedPosition(
|
|
||||||
channel_type_filter.persistent.position.add(.{ .x = 0, .y = channel_type_filter.persistent.size.y })
|
|
||||||
);
|
|
||||||
|
|
||||||
{
|
|
||||||
const device_box = self.ui.button(.text, "All");
|
|
||||||
device_box.size.x = UI.Size.percent(1, 1);
|
|
||||||
device_box.size.y = UI.Size.text(0.5, 1);
|
|
||||||
device_box.flags.insert(.text_left_align);
|
|
||||||
|
|
||||||
if (self.ui.signalFromBox(device_box).clicked()) {
|
|
||||||
self.channel_type_filter = null;
|
|
||||||
self.show_channel_type_filter_dropdown = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (&[_]NIDaq.ChannelType{ NIDaq.ChannelType.analog_input, NIDaq.ChannelType.analog_output }) |channel_type| {
|
|
||||||
const device_box = self.ui.button(.text, channel_type.name());
|
|
||||||
device_box.size.x = UI.Size.percent(1, 1);
|
|
||||||
device_box.size.y = UI.Size.text(0.5, 1);
|
|
||||||
device_box.flags.insert(.text_left_align);
|
|
||||||
|
|
||||||
if (self.ui.signalFromBox(device_box).clicked()) {
|
|
||||||
self.channel_type_filter = channel_type;
|
|
||||||
self.show_channel_type_filter_dropdown = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
device_name_filter.size.x = UI.Size.percent(1, 1);
|
const toggle_inputs_box = self.ui.button(.text, "Toggle inputs");
|
||||||
device_name_filter.size.y = UI.Size.pixels(24, 1);
|
toggle_inputs_box.size.x = UI.Size.text(2, 1);
|
||||||
device_name_filter.layout_axis = .X;
|
toggle_inputs_box.size.y = UI.Size.text(2, 1);
|
||||||
self.ui.pushParent(device_name_filter);
|
toggle_inputs_box.setText(.text, if (self.show_voltage_analog_inputs) "Hide inputs" else "Show inputs");
|
||||||
defer self.ui.popParent();
|
|
||||||
|
|
||||||
{
|
if (self.ui.signalFromBox(toggle_inputs_box).clicked()) {
|
||||||
self.ui.pushVerticalAlign();
|
self.show_voltage_analog_inputs = !self.show_voltage_analog_inputs;
|
||||||
defer self.ui.popVerticalAlign();
|
|
||||||
_ = self.ui.textureBox(Assets.dropdown_arrow, 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (self.device_filter.len > 0) {
|
|
||||||
_ = self.ui.label(.text, self.device_filter.constSlice());
|
|
||||||
} else {
|
|
||||||
_ = self.ui.label(.text, "All");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (self.ui.signalFromBox(device_name_filter).clicked()) {
|
|
||||||
self.show_device_filter_dropdown = !self.show_device_filter_dropdown;
|
|
||||||
}
|
|
||||||
|
|
||||||
self.ui.spacer(.{ .x = UI.Size.percent(1, 0) });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
channel_type_filter.size.x = UI.Size.percent(1, 1);
|
const toggle_outputs_box = self.ui.button(.text, "Toggle outputs");
|
||||||
channel_type_filter.size.y = UI.Size.pixels(24, 1);
|
toggle_outputs_box.size.x = UI.Size.text(2, 1);
|
||||||
channel_type_filter.layout_axis = .X;
|
toggle_outputs_box.size.y = UI.Size.text(2, 1);
|
||||||
self.ui.pushParent(channel_type_filter);
|
toggle_outputs_box.setText(.text, if (self.show_voltage_analog_outputs) "Hide outputs" else "Show outputs");
|
||||||
defer self.ui.popParent();
|
|
||||||
|
if (self.ui.signalFromBox(toggle_outputs_box).clicked()) {
|
||||||
|
self.show_voltage_analog_outputs = !self.show_voltage_analog_outputs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
self.ui.pushVerticalAlign();
|
const add_button = self.ui.button(.text, "Add selected");
|
||||||
defer self.ui.popVerticalAlign();
|
add_button.size.x = UI.Size.text(2, 1);
|
||||||
_ = self.ui.textureBox(Assets.dropdown_arrow, 1);
|
add_button.size.y = UI.Size.text(2, 1);
|
||||||
|
|
||||||
|
if (self.ui.signalFromBox(add_button).clicked()) {
|
||||||
|
const selected_devices = self.selected_channels.constSlice();
|
||||||
|
|
||||||
|
for (selected_devices) |channel| {
|
||||||
|
try self.appendChannelFromDevice(channel);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (self.channel_type_filter) |channeL_type| {
|
for (selected_devices) |channel| {
|
||||||
_ = self.ui.label(.text, channeL_type.name());
|
self.allocator.free(channel);
|
||||||
} else {
|
|
||||||
_ = self.ui.label(.text, "All");
|
|
||||||
}
|
}
|
||||||
|
self.selected_channels.len = 0;
|
||||||
|
|
||||||
if (self.ui.signalFromBox(channel_type_filter).clicked()) {
|
self.shown_window = .channels;
|
||||||
self.show_channel_type_filter_dropdown = !self.show_channel_type_filter_dropdown;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var hot_channel: ?[:0]const u8 = self.last_hot_channel;
|
|
||||||
{
|
{
|
||||||
const channels_box = self.ui.pushScrollbar(self.ui.newKeyFromString("Channels list"));
|
const channels_box = self.ui.pushScrollbar(self.ui.newKeyFromString("Channels list"));
|
||||||
defer self.ui.popScrollbar();
|
defer self.ui.popScrollbar();
|
||||||
const channels_box_container = self.ui.getParentOf(channels_box).?;
|
|
||||||
channels_box.layout_axis = .Y;
|
channels_box.layout_axis = .Y;
|
||||||
//channels_box.size.x = UI.Size.childrenSum(1);
|
channels_box.size.x = UI.Size.percent(1, 0);
|
||||||
channels_box_container.size.x = UI.Size.percent(1, 0);
|
|
||||||
|
|
||||||
var devices: []const [:0]const u8 = &.{};
|
var devices: []const [:0]const u8 = &.{};
|
||||||
if (self.device_filter.len > 0) {
|
if (self.device_filter.len > 0) {
|
||||||
@ -871,25 +667,23 @@ fn showAddFromDeviceWindow(self: *App) !void {
|
|||||||
|
|
||||||
for (devices) |device| {
|
for (devices) |device| {
|
||||||
var ai_voltage_physical_channels: []const [:0]const u8 = &.{};
|
var ai_voltage_physical_channels: []const [:0]const u8 = &.{};
|
||||||
|
if (self.show_voltage_analog_inputs) {
|
||||||
if (try ni_daq.checkDeviceAIMeasurementType(device, .Voltage)) {
|
if (try ni_daq.checkDeviceAIMeasurementType(device, .Voltage)) {
|
||||||
ai_voltage_physical_channels = try ni_daq.listDeviceAIPhysicalChannels(device);
|
ai_voltage_physical_channels = try ni_daq.listDeviceAIPhysicalChannels(device);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var ao_physical_channels: []const [:0]const u8 = &.{};
|
var ao_physical_channels: []const [:0]const u8 = &.{};
|
||||||
|
if (self.show_voltage_analog_outputs) {
|
||||||
if (try ni_daq.checkDeviceAOOutputType(device, .Voltage)) {
|
if (try ni_daq.checkDeviceAOOutputType(device, .Voltage)) {
|
||||||
ao_physical_channels = try ni_daq.listDeviceAOPhysicalChannels(device);
|
ao_physical_channels = try ni_daq.listDeviceAOPhysicalChannels(device);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
inline for (.{ ai_voltage_physical_channels, ao_physical_channels }) |channels| {
|
inline for (.{ ai_voltage_physical_channels, ao_physical_channels }) |channels| {
|
||||||
for (channels) |channel| {
|
for (channels) |channel| {
|
||||||
const selected_channels_slice = self.selected_channels.constSlice();
|
const selected_channels_slice = self.selected_channels.constSlice();
|
||||||
|
|
||||||
if (self.channel_type_filter) |channel_type_filter| {
|
|
||||||
if (NIDaq.getChannelType(channel) != channel_type_filter) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const channel_box = self.ui.button(.text, channel);
|
const channel_box = self.ui.button(.text, channel);
|
||||||
|
|
||||||
if (findChannelIndexByName(selected_channels_slice, channel) != null) {
|
if (findChannelIndexByName(selected_channels_slice, channel) != null) {
|
||||||
@ -905,44 +699,12 @@ fn showAddFromDeviceWindow(self: *App) !void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (signal.hot) {
|
|
||||||
hot_channel = channel;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
|
||||||
const left_panel = self.ui.newBox(UI.Key.initNil());
|
|
||||||
left_panel.layout_axis = .Y;
|
|
||||||
left_panel.size.y = UI.Size.percent(1, 0);
|
|
||||||
left_panel.size.x = UI.Size.percent(1, 0);
|
|
||||||
self.ui.pushParent(left_panel);
|
|
||||||
defer self.ui.popParent();
|
|
||||||
|
|
||||||
try self.showChannelInfoPanel(hot_channel);
|
|
||||||
|
|
||||||
const add_button = self.ui.button(.text, "Add");
|
|
||||||
if (self.ui.signalFromBox(add_button).clicked()) {
|
|
||||||
for (self.selected_channels.constSlice()) |channel_name| {
|
|
||||||
try self.appendChannelFromDevice(channel_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
self.shown_window = .channels;
|
|
||||||
for (self.selected_channels.constSlice()) |channel| {
|
|
||||||
self.allocator.free(channel);
|
|
||||||
}
|
|
||||||
self.selected_channels.len = 0;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hot_channel != null) {
|
|
||||||
self.last_hot_channel = hot_channel;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn showToolbar(self: *App) void {
|
fn showToolbar(self: *App) void {
|
||||||
const toolbar = self.ui.newBoxFromString("Toolbar");
|
const toolbar = self.ui.newBoxFromString("Toolbar");
|
||||||
toolbar.background = rl.Color.green;
|
toolbar.background = rl.Color.green;
|
||||||
|
@ -21,8 +21,6 @@ pub var grab_texture: struct {
|
|||||||
active: rl.Texture2D,
|
active: rl.Texture2D,
|
||||||
} = undefined;
|
} = undefined;
|
||||||
|
|
||||||
pub var dropdown_arrow: rl.Texture2D = undefined;
|
|
||||||
|
|
||||||
pub fn font(font_id: FontId) FontFace {
|
pub fn font(font_id: FontId) FontFace {
|
||||||
return fonts.get(font_id);
|
return fonts.get(font_id);
|
||||||
}
|
}
|
||||||
@ -36,7 +34,6 @@ pub fn init(allocator: std.mem.Allocator) !void {
|
|||||||
.text = FontFace{ .font = default_font, .line_height = 1.2 }
|
.text = FontFace{ .font = default_font, .line_height = 1.2 }
|
||||||
});
|
});
|
||||||
|
|
||||||
{
|
|
||||||
const grab_ase = try Aseprite.init(allocator, @embedFile("./assets/grab-marker.ase"));
|
const grab_ase = try Aseprite.init(allocator, @embedFile("./assets/grab-marker.ase"));
|
||||||
defer grab_ase.deinit();
|
defer grab_ase.deinit();
|
||||||
|
|
||||||
@ -62,18 +59,6 @@ pub fn init(allocator: std.mem.Allocator) !void {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
|
||||||
const dropdown_arrow_ase = try Aseprite.init(allocator, @embedFile("./assets/dropdown-arrow.ase"));
|
|
||||||
defer dropdown_arrow_ase.deinit();
|
|
||||||
|
|
||||||
const dropdown_image = dropdown_arrow_ase.getFrameImage(0);
|
|
||||||
defer dropdown_image.unload();
|
|
||||||
|
|
||||||
dropdown_arrow = rl.loadTextureFromImage(dropdown_image);
|
|
||||||
assert(rl.isTextureReady(dropdown_arrow));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn loadFont(ttf_data: []const u8, font_size: u32) !rl.Font {
|
fn loadFont(ttf_data: []const u8, font_size: u32) !rl.Font {
|
||||||
var codepoints: std.BoundedArray(i32, 128) = .{};
|
var codepoints: std.BoundedArray(i32, 128) = .{};
|
||||||
for (0..95) |i| {
|
for (0..95) |i| {
|
||||||
|
Binary file not shown.
@ -225,46 +225,9 @@ pub const AIMeasurementType = enum(i32) {
|
|||||||
TEDS_Sensor = c.DAQmx_Val_TEDS_Sensor,
|
TEDS_Sensor = c.DAQmx_Val_TEDS_Sensor,
|
||||||
Charge = c.DAQmx_Val_Charge,
|
Charge = c.DAQmx_Val_Charge,
|
||||||
Power = c.DAQmx_Val_Power,
|
Power = c.DAQmx_Val_Power,
|
||||||
_,
|
_
|
||||||
|
|
||||||
pub fn name(self: AIMeasurementType) []const u8 {
|
|
||||||
return switch (self) {
|
|
||||||
.Voltage => "Voltage",
|
|
||||||
.VoltageRMS => "Voltage RMS",
|
|
||||||
.Current => "Current",
|
|
||||||
.CurrentRMS => "Current RMS",
|
|
||||||
.Voltage_CustomWithExcitation => "Voltage (custom excitation)",
|
|
||||||
.Bridge => "Bridge",
|
|
||||||
.Freq_Voltage => "Frequency (frequency to voltage converter)",
|
|
||||||
.Resistance => "Resistance",
|
|
||||||
.Temp_TC => "Temperature (thermocouple)",
|
|
||||||
.Temp_Thrmstr => "Temperature (thermistor)",
|
|
||||||
.Temp_RTD => "Temperature (RTD)",
|
|
||||||
.Temp_BuiltInSensor => "Temperature (built-in)",
|
|
||||||
.Strain_Gage => "Strain",
|
|
||||||
.Rosette_Strain_Gage => "Strain (Rosette strain gage)",
|
|
||||||
.Position_LVDT => "Position (LVDT)",
|
|
||||||
.Position_RVDT => "Position (RVDT)",
|
|
||||||
.Position_EddyCurrentProximityProbe => "Position (eddy current proximity probe)",
|
|
||||||
.Accelerometer => "Acceleration",
|
|
||||||
.Acceleration_Charge => "Acceleration (charge-based)",
|
|
||||||
.Acceleration_4WireDCVoltage => "Acceleration (4 wire DC voltage based)",
|
|
||||||
.Velocity_IEPESensor => "Velocity (IEPE Sensor)",
|
|
||||||
.Force_Bridge => "Force (bridge-based)",
|
|
||||||
.Force_IEPESensor => "Force (IEPE Sensor)",
|
|
||||||
.Pressure_Bridge => "Pressure (bridge-based)",
|
|
||||||
.SoundPressure_Microphone => "Sound pressure (microphone)",
|
|
||||||
.Torque_Bridge => "Torque (bridge-based)",
|
|
||||||
.TEDS_Sensor => "TEDS",
|
|
||||||
.Charge => "Charge",
|
|
||||||
.Power => "Power source",
|
|
||||||
_ => "Unknown"
|
|
||||||
};
|
};
|
||||||
}
|
const AIMeasurementTypeList = std.BoundedArray(AIMeasurementType, @typeInfo(AIMeasurementType).Enum.fields.len);
|
||||||
};
|
|
||||||
|
|
||||||
pub const max_ai_measurement_type_list_len = @typeInfo(AIMeasurementType).Enum.fields.len;
|
|
||||||
pub const AIMeasurementTypeList = std.BoundedArray(AIMeasurementType, max_ai_measurement_type_list_len);
|
|
||||||
|
|
||||||
pub const AOOutputType = enum(i32) {
|
pub const AOOutputType = enum(i32) {
|
||||||
Voltage = c.DAQmx_Val_Voltage,
|
Voltage = c.DAQmx_Val_Voltage,
|
||||||
@ -669,26 +632,17 @@ pub fn listDeviceCIPhysicalChannels(self: *NIDaq, device: [:0]const u8) ![]const
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const ChannelType = enum {
|
const ChannelType = enum {
|
||||||
analog_input,
|
analog_input,
|
||||||
analog_output,
|
analog_output,
|
||||||
counter_input,
|
counter_input,
|
||||||
counter_output,
|
counter_output,
|
||||||
|
|
||||||
pub fn name(self: ChannelType) []const u8 {
|
|
||||||
return switch (self) {
|
|
||||||
.analog_input => "Analog input",
|
|
||||||
.analog_output => "Analog output",
|
|
||||||
.counter_input => "Counter input",
|
|
||||||
.counter_output => "Counter output",
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn getChannelType(channel_name: []const u8) ?ChannelType {
|
fn getChannelType(device: [:0]const u8) ?ChannelType {
|
||||||
const slash = std.mem.indexOfScalar(u8, channel_name, '/') orelse return null;
|
const slash = std.mem.indexOfScalar(u8, device, '/') orelse return null;
|
||||||
|
|
||||||
const afterSlash = channel_name[(slash+1)..];
|
const afterSlash = device[(slash+1)..];
|
||||||
if (std.mem.startsWith(u8, afterSlash, "ai")) {
|
if (std.mem.startsWith(u8, afterSlash, "ai")) {
|
||||||
return ChannelType.analog_input;
|
return ChannelType.analog_input;
|
||||||
} else if (std.mem.startsWith(u8, afterSlash, "ao")) {
|
} else if (std.mem.startsWith(u8, afterSlash, "ao")) {
|
||||||
|
85
src/ui.zig
85
src/ui.zig
@ -60,7 +60,6 @@ pub const Size = struct {
|
|||||||
pixels: f32,
|
pixels: f32,
|
||||||
percent: f32,
|
percent: f32,
|
||||||
text: f32,
|
text: f32,
|
||||||
texture: f32,
|
|
||||||
children_sum,
|
children_sum,
|
||||||
},
|
},
|
||||||
strictness: f32 = 1,
|
strictness: f32 = 1,
|
||||||
@ -86,13 +85,6 @@ pub const Size = struct {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn texture(scale: f32, strictness: f32) Size {
|
|
||||||
return Size{
|
|
||||||
.kind = .{ .texture = scale },
|
|
||||||
.strictness = strictness
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn childrenSum(strictness: f32) Size {
|
pub fn childrenSum(strictness: f32) Size {
|
||||||
return Size{
|
return Size{
|
||||||
.kind = .children_sum,
|
.kind = .children_sum,
|
||||||
@ -191,7 +183,6 @@ pub const Signal = struct {
|
|||||||
flags: std.EnumSet(Flag) = .{},
|
flags: std.EnumSet(Flag) = .{},
|
||||||
drag: Vec2 = .{ .x = 0, .y = 0 },
|
drag: Vec2 = .{ .x = 0, .y = 0 },
|
||||||
scroll: Vec2 = .{ .x = 0, .y = 0 },
|
scroll: Vec2 = .{ .x = 0, .y = 0 },
|
||||||
hot: bool = false,
|
|
||||||
|
|
||||||
pub fn clicked(self: Signal) bool {
|
pub fn clicked(self: Signal) bool {
|
||||||
return self.flags.contains(.left_clicked) or self.flags.contains(.right_clicked);
|
return self.flags.contains(.left_clicked) or self.flags.contains(.right_clicked);
|
||||||
@ -422,7 +413,7 @@ pub const Box = struct {
|
|||||||
return self.flags.contains(flag);
|
return self.flags.contains(flag);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn hasClipping(self: *Box) bool {
|
fn hasClipping(self: *Box) bool {
|
||||||
return self.view_offset.equals(Vec2.zero()) == 0;
|
return self.view_offset.equals(Vec2.zero()) == 0;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -800,18 +791,6 @@ fn calcLayoutStandaloneSize(self: *UI, box: *Box, axis: Axis) void {
|
|||||||
computed_size.* = fixed_size;
|
computed_size.* = fixed_size;
|
||||||
} else if (size.kind == .pixels) {
|
} else if (size.kind == .pixels) {
|
||||||
computed_size.* = size.kind.pixels;
|
computed_size.* = size.kind.pixels;
|
||||||
} else if (size.kind == .texture) {
|
|
||||||
if (box.texture) |texture| {
|
|
||||||
var texture_size: f32 = 0;
|
|
||||||
if (axis == .X) {
|
|
||||||
texture_size = @floatFromInt(texture.width);
|
|
||||||
} else if (axis == .Y) {
|
|
||||||
texture_size = @floatFromInt(texture.height);
|
|
||||||
}
|
|
||||||
computed_size.* = size.kind.texture * texture_size;
|
|
||||||
} else {
|
|
||||||
computed_size.* = 0;
|
|
||||||
}
|
|
||||||
} else if (size.kind == .text) {
|
} else if (size.kind == .text) {
|
||||||
if (box.text) |text| {
|
if (box.text) |text| {
|
||||||
const font = Assets.font(text.font);
|
const font = Assets.font(text.font);
|
||||||
@ -921,8 +900,6 @@ fn calcLayoutEnforceConstraints(self: *UI, box: *Box, axis: Axis) void {
|
|||||||
|
|
||||||
var child_iter = self.iterChildrenByParent(box);
|
var child_iter = self.iterChildrenByParent(box);
|
||||||
while (child_iter.next()) |child| {
|
while (child_iter.next()) |child| {
|
||||||
if (child.isPositionFixed(axis)) continue;
|
|
||||||
|
|
||||||
const child_size = getVec2Axis(&child.persistent.size, axis);
|
const child_size = getVec2Axis(&child.persistent.size, axis);
|
||||||
|
|
||||||
if (child_size.* > max_child_size) {
|
if (child_size.* > max_child_size) {
|
||||||
@ -1289,8 +1266,6 @@ pub fn signalFromBox(self: *UI, box: *Box) Signal {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
result.hot = self.isKeyHot(box.key);
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1330,14 +1305,6 @@ fn getParentIndex(self: *UI) ?BoxIndex {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getParentOf(self: *UI, box: *Box) ?*Box {
|
|
||||||
if (box.parent_index) |index| {
|
|
||||||
return &self.boxes.buffer[index];
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn getParent(self: *UI) ?*Box {
|
pub fn getParent(self: *UI) ?*Box {
|
||||||
if (self.getParentIndex()) |parent_index| {
|
if (self.getParentIndex()) |parent_index| {
|
||||||
return &self.boxes.buffer[parent_index];
|
return &self.boxes.buffer[parent_index];
|
||||||
@ -1481,27 +1448,18 @@ pub fn spacer(self: *UI, size: Vec2Size) void {
|
|||||||
box.size = size;
|
box.size = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn label(self: *UI, font: Assets.FontId, text: []const u8) *Box {
|
|
||||||
const box = self.newBoxFromString(text);
|
|
||||||
box.size.x = UI.Size.text(1, 1);
|
|
||||||
box.size.y = UI.Size.text(0.5, 1);
|
|
||||||
box.setText(font, text);
|
|
||||||
|
|
||||||
return box;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn textureBox(self: *UI, texture: rl.Texture2D, scale: f32) *Box {
|
|
||||||
const box = self.newBox(Key.initNil());
|
|
||||||
box.size.x = UI.Size.texture(scale, 1);
|
|
||||||
box.size.y = UI.Size.texture(scale, 1);
|
|
||||||
box.texture = texture;
|
|
||||||
|
|
||||||
return box;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn pushCenterBox(self: *UI) *Box {
|
pub fn pushCenterBox(self: *UI) *Box {
|
||||||
self.pushHorizontalAlign();
|
self.pushHorizontalAlign();
|
||||||
self.pushVerticalAlign();
|
|
||||||
|
const vertical_align = self.newBox(UI.Key.initNil());
|
||||||
|
vertical_align.layout_axis = .Y;
|
||||||
|
vertical_align.size = .{
|
||||||
|
.x = UI.Size.childrenSum(1),
|
||||||
|
.y = UI.Size.percent(1, 0),
|
||||||
|
};
|
||||||
|
self.pushParent(vertical_align);
|
||||||
|
|
||||||
|
self.spacer(.{ .y = UI.Size.percent(1, 0) });
|
||||||
|
|
||||||
const container = self.newBox(UI.Key.initNil());
|
const container = self.newBox(UI.Key.initNil());
|
||||||
container.size.x = UI.Size.childrenSum(1);
|
container.size.x = UI.Size.childrenSum(1);
|
||||||
@ -1514,7 +1472,9 @@ pub fn pushCenterBox(self: *UI) *Box {
|
|||||||
pub fn popCenterBox(self: *UI) void {
|
pub fn popCenterBox(self: *UI) void {
|
||||||
self.popParent();
|
self.popParent();
|
||||||
|
|
||||||
self.popVerticalAlign();
|
self.spacer(.{ .y = UI.Size.percent(1, 0) });
|
||||||
|
self.popParent();
|
||||||
|
|
||||||
self.popHorizontalAlign();
|
self.popHorizontalAlign();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1534,20 +1494,3 @@ pub fn popHorizontalAlign(self: *UI) void {
|
|||||||
self.spacer(.{ .x = UI.Size.percent(1, 0) });
|
self.spacer(.{ .x = UI.Size.percent(1, 0) });
|
||||||
self.popParent();
|
self.popParent();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pushVerticalAlign(self: *UI) void {
|
|
||||||
const vertical_align = self.newBox(UI.Key.initNil());
|
|
||||||
vertical_align.layout_axis = .Y;
|
|
||||||
vertical_align.size = .{
|
|
||||||
.x = UI.Size.childrenSum(1),
|
|
||||||
.y = UI.Size.percent(1, 0),
|
|
||||||
};
|
|
||||||
self.pushParent(vertical_align);
|
|
||||||
|
|
||||||
self.spacer(.{ .y = UI.Size.percent(1, 0) });
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn popVerticalAlign(self: *UI) void {
|
|
||||||
self.spacer(.{ .y = UI.Size.percent(1, 0) });
|
|
||||||
self.popParent();
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user