Files
FileTime3/src/core/tab/tab.zig

141 lines
4.4 KiB
Zig

pub const Tab = struct {
allocator: std.mem.Allocator,
currentLocation: ?*Container,
currentItems: locked(?std.ArrayList(Arc(*Item))),
currentLocationChanged: Observable(?*Container),
currentItemsChanged: bool = false,
threadPool: *std.Thread.Pool,
rootProvider: *RootProvider,
pub fn init(
self: *Tab,
threadPool: *std.Thread.Pool,
rootProvider: *RootProvider,
allocator: std.mem.Allocator,
) void {
self.* = Tab{
.allocator = allocator,
.currentItems = .{ .data = null },
.currentLocationChanged = Observable(?*Container).init(allocator),
.currentLocation = null,
.threadPool = threadPool,
.rootProvider = rootProvider,
};
}
pub fn setCurrentLocation(self: *Tab, newLocationFullName: models.FullName) !void {
if (self.currentLocation) |c| {
c.item.deinit();
}
errdefer {
self.currentLocation = null;
self.currentLocationChanged.notify(null);
}
const newLocation = try self.rootProvider.getItemByFullName(newLocationFullName, &.{}, self.allocator);
errdefer {
newLocation.deinit();
}
const newLocationContainer = switch (newLocation.item) {
.container => |c| c,
.element => return error.NotContainer,
};
self.currentLocation = newLocationContainer;
self.currentLocationChanged.notify(newLocationContainer);
//TODO: Proper error handling
std.Thread.Pool.spawn(self.threadPool, loadItemsWrapper, .{ self, newLocationContainer }) catch unreachable;
}
fn loadItemsWrapper(self: *Tab, location: *Container) void {
loadItems(self, location) catch return;
}
fn loadItems(self: *Tab, location: *Container) !void {
{
self.currentItems.mutex.lock();
defer self.currentItems.mutex.unlock();
const data = self.currentItems.data;
self.currentItems.data = null;
if (data) |currentItems| {
for (currentItems.items) |*item| {
if (item.releaseUnwrap()) |i| i.deinit();
}
currentItems.deinit();
}
}
{
self.currentItems.mutex.lock();
defer self.currentItems.mutex.unlock();
self.currentItems.data = std.ArrayList(Arc(*Item)).init(self.allocator);
}
errdefer {
self.currentItems.data.?.deinit();
self.currentItems.data = null;
}
//TODO: add async
while (location.childrenLoading) {
std.Thread.sleep(1 * std.time.ns_per_ms);
}
for (location.children.items) |item| {
const resolvedItem = location.item.provider.getItemByFullName(item, &.{ .skipChildInit = true }, self.allocator) catch |e| {
//TODO: save error to container errors
std.debug.print("error {} {s}\r\n", .{ e, item.path });
continue;
};
self.currentItems.mutex.lock();
defer self.currentItems.mutex.unlock();
// const arc = try Arc(*Item).init(self.allocator, resolvedItem);
// try self.currentItems.data.?.append(arc);
try self.currentItems.data.?.append(try Arc(*Item).init(self.allocator, resolvedItem));
}
{
self.currentItems.mutex.lock();
defer self.currentItems.mutex.unlock();
self.currentItemsChanged = true;
}
}
pub fn deinit(self: *Tab) void {
if (self.currentLocation) |c| {
c.item.deinit();
}
const data = self.currentItems.data;
self.currentItems.data = null;
if (data) |currentItems| {
for (currentItems.items) |arc_item| {
if (arc_item.releaseUnwrap()) |item| {
item.deinit();
}
}
currentItems.deinit();
}
self.allocator.destroy(self);
}
};
const std = @import("std");
const assert = std.debug.assert;
const Mutex = std.Thread.Mutex;
const models = @import("../models.zig");
const Container = models.Container;
const Item = models.Item;
const locked = @import("../sync.zig").locked;
const Observable = @import("../observable.zig").Observable;
const RootProvider = @import("../provider/root.zig").RootProvider;
const Arc = @import("zigrc").Arc;