feat: selected's children
This commit is contained in:
@@ -1,25 +1,30 @@
|
||||
pub const UnknownTabError = error.UnknownTab;
|
||||
|
||||
pub const AppState = struct {
|
||||
allocator: std.mem.Allocator,
|
||||
currentTab: *Tab = undefined,
|
||||
tabs: std.ArrayList(*Tab),
|
||||
currentTabChanged: Observable(*Tab),
|
||||
tabPreCurrentItemsUnload: Observable(*Tab),
|
||||
tabChildrenLoaded: Observable(*Tab),
|
||||
|
||||
pub fn init(allocator: std.mem.Allocator) AppState {
|
||||
return .{
|
||||
.allocator = allocator,
|
||||
.tabs = std.ArrayList(*Tab).init(allocator),
|
||||
.currentTabChanged = Observable(*Tab).init(allocator),
|
||||
.tabPreCurrentItemsUnload = Observable(*Tab).init(allocator),
|
||||
.tabChildrenLoaded = Observable(*Tab).init(allocator),
|
||||
};
|
||||
}
|
||||
|
||||
pub fn addTab(self: *AppState, tab: *Tab) !void {
|
||||
try self.tabs.append(tab);
|
||||
// tab.preCurrentItemsUnload.attach(.{
|
||||
// .ctx = @ptrCast(@alignCast(self)),
|
||||
// .update = preCurrentItemsUnload,
|
||||
// });
|
||||
const tabChildrenLoadedHandlerObserver = try tab.childrenLoaded.allocator.create(Observer(*Tab));
|
||||
tabChildrenLoadedHandlerObserver.* = Observer(*Tab){
|
||||
.ctx = @ptrCast(@alignCast(self)),
|
||||
.update = tabChildrenLoadedHandler,
|
||||
};
|
||||
|
||||
try tab.childrenLoaded.attach(tabChildrenLoadedHandlerObserver);
|
||||
}
|
||||
|
||||
pub fn setCurrentTab(self: *AppState, newTab: *Tab) !void {
|
||||
@@ -34,8 +39,20 @@ pub const AppState = struct {
|
||||
self.currentTabChanged.notify(newTab);
|
||||
}
|
||||
|
||||
pub fn removeTab(self: *AppState, tab: *Tab) void {
|
||||
const index = for (tab.childrenLoaded.observers, 0..) |observer, i| {
|
||||
if (observer.ctx == self) break i;
|
||||
} else null;
|
||||
|
||||
if (index) |i| {
|
||||
tab.childrenLoaded.observers.swapRemove(i);
|
||||
}
|
||||
|
||||
//TODO: remove from tabs
|
||||
}
|
||||
|
||||
pub fn deinit(self: *AppState) void {
|
||||
self.tabPreCurrentItemsUnload.deinit();
|
||||
self.tabChildrenLoaded.deinit();
|
||||
self.currentTabChanged.deinit();
|
||||
for (self.tabs.items) |tab| {
|
||||
tab.deinit();
|
||||
@@ -43,12 +60,13 @@ pub const AppState = struct {
|
||||
self.tabs.deinit();
|
||||
}
|
||||
|
||||
fn preCurrentItemsUnload(ctx: *anyopaque, tab: *Tab) void {
|
||||
const self: AppState = @ptrCast(@alignCast(ctx));
|
||||
self.tabPreCurrentItemsUnload.notify(tab);
|
||||
fn tabChildrenLoadedHandler(ctx: *anyopaque, tab: *Tab) void {
|
||||
const self: *AppState = @ptrCast(@alignCast(ctx));
|
||||
self.tabChildrenLoaded.notify(tab);
|
||||
}
|
||||
};
|
||||
|
||||
const std = @import("std");
|
||||
const Tab = @import("tab/tab.zig").Tab;
|
||||
const Observable = @import("observable.zig").Observable;
|
||||
const Observer = @import("observable.zig").Observer;
|
||||
|
||||
@@ -1,15 +1,20 @@
|
||||
pub fn Observable(T: type) type {
|
||||
return struct {
|
||||
allocator: std.mem.Allocator,
|
||||
observers: std.ArrayList(*const Observer(T)),
|
||||
|
||||
const Self = @This();
|
||||
pub fn init(allocator: std.mem.Allocator) Self {
|
||||
return .{
|
||||
.allocator = allocator,
|
||||
.observers = std.ArrayList(*const Observer(T)).init(allocator),
|
||||
};
|
||||
}
|
||||
|
||||
pub fn deinit(self: *Self) void {
|
||||
for(self.observers)|o| {
|
||||
self.allocator.destroy(o);
|
||||
}
|
||||
self.observers.deinit();
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,8 @@ pub const Tab = struct {
|
||||
currentLocation: ?*Container,
|
||||
currentItems: locked(?std.ArrayList(Arc(*Item))),
|
||||
currentParentItems: locked(?std.ArrayList(Arc(*Item))),
|
||||
currentChildren: locked(?std.ArrayList(Arc(*Item))),
|
||||
childrenLoaded: Observable(*Tab),
|
||||
currentLocationChanged: Observable(?*Container),
|
||||
currentItemFullName: ?models.FullName,
|
||||
currentItem: ?Arc(*models.Item),
|
||||
@@ -21,7 +23,9 @@ pub const Tab = struct {
|
||||
.allocator = allocator,
|
||||
.currentItems = .{ .data = null },
|
||||
.currentParentItems = .{ .data = null },
|
||||
.currentChildren = .{ .data = null },
|
||||
.currentLocationChanged = Observable(?*Container).init(allocator),
|
||||
.childrenLoaded = Observable(*Tab).init(allocator),
|
||||
.currentLocation = null,
|
||||
.currentRequested = null,
|
||||
.currentItem = null,
|
||||
@@ -169,6 +173,13 @@ pub const Tab = struct {
|
||||
self.currentItemFullName = models.FullName{
|
||||
.path = try self.allocator.dupe(u8, arc.value.*.fullName.path),
|
||||
};
|
||||
|
||||
switch (arc.value.*.item) {
|
||||
.container => {
|
||||
std.Thread.Pool.spawn(self.threadPool, loadChildrenWrapper, .{ self, arc.retain() }) catch unreachable;
|
||||
},
|
||||
else => {},
|
||||
}
|
||||
}
|
||||
|
||||
fn loadItemsWrapper(self: *Tab, location: *Container) void {
|
||||
@@ -180,6 +191,7 @@ pub const Tab = struct {
|
||||
|
||||
fn loadParentItemsWrapper(self: *Tab, location: *Container) void {
|
||||
const parentAbsolutePath = location.item.parent orelse return;
|
||||
|
||||
var arena = std.heap.ArenaAllocator.init(self.allocator);
|
||||
defer arena.deinit();
|
||||
const allocator = arena.allocator();
|
||||
@@ -188,7 +200,7 @@ pub const Tab = struct {
|
||||
.path = allocator.dupe(u8, parentAbsolutePath.path.path) catch return,
|
||||
};
|
||||
|
||||
const resolvedParent = location.item.provider.getItemByFullName(parentFullName, &.{ .skipChildInit = true }, allocator) catch |e| {
|
||||
const resolvedParent = location.item.provider.getItemByFullName(parentFullName, &.{}, allocator) catch |e| {
|
||||
std.debug.print("error {} {s}\r\n", .{ e, parentFullName.path });
|
||||
return;
|
||||
};
|
||||
@@ -196,9 +208,47 @@ pub const Tab = struct {
|
||||
.container => |c| c,
|
||||
else => return,
|
||||
};
|
||||
loadItems(*Tab, self, parentContainer, &self.currentParentItems, (struct {
|
||||
fn a(_: *Tab) void {}
|
||||
}).a, self.allocator) catch {};
|
||||
loadItems(
|
||||
void,
|
||||
{},
|
||||
parentContainer,
|
||||
&self.currentParentItems,
|
||||
(struct {
|
||||
fn a(_: void) void {}
|
||||
}).a,
|
||||
self.allocator,
|
||||
) catch {};
|
||||
}
|
||||
|
||||
fn loadChildrenWrapper(self: *Tab, newSelectedItemArc: Arc(*models.Item)) void {
|
||||
defer if (newSelectedItemArc.releaseUnwrap()) |item| item.deinit();
|
||||
|
||||
var arena = std.heap.ArenaAllocator.init(self.allocator);
|
||||
defer arena.deinit();
|
||||
|
||||
const allocator = arena.allocator();
|
||||
|
||||
const resolvedChild = newSelectedItemArc.value.*.provider.getItemByFullName(newSelectedItemArc.value.*.fullName, &.{}, allocator) catch |e| {
|
||||
std.debug.print("error {} {s}\r\n", .{ e, newSelectedItemArc.value.*.fullName.path });
|
||||
return;
|
||||
};
|
||||
const childContainer = switch (resolvedChild.item) {
|
||||
.container => |c| c,
|
||||
else => return,
|
||||
};
|
||||
|
||||
loadItems(
|
||||
void,
|
||||
{},
|
||||
childContainer,
|
||||
&self.currentChildren,
|
||||
(struct {
|
||||
fn a(_: void) void {}
|
||||
}).a,
|
||||
self.allocator,
|
||||
) catch {};
|
||||
|
||||
self.childrenLoaded.notify(self);
|
||||
}
|
||||
|
||||
pub fn deinit(self: *Tab) void {
|
||||
@@ -217,10 +267,35 @@ pub const Tab = struct {
|
||||
currentItems.deinit();
|
||||
}
|
||||
|
||||
const data2 = self.currentParentItems.data;
|
||||
self.currentParentItems.data = null;
|
||||
if (data2) |currentItems| {
|
||||
for (currentItems.items) |arc_item| {
|
||||
if (arc_item.releaseUnwrap()) |item| {
|
||||
item.deinit();
|
||||
}
|
||||
}
|
||||
currentItems.deinit();
|
||||
}
|
||||
|
||||
const data3 = self.currentChildren.data;
|
||||
self.currentChildren.data = null;
|
||||
if (data3) |currentItems| {
|
||||
for (currentItems.items) |arc_item| {
|
||||
if (arc_item.releaseUnwrap()) |item| {
|
||||
item.deinit();
|
||||
}
|
||||
}
|
||||
currentItems.deinit();
|
||||
}
|
||||
|
||||
self.cleanCurrentItem();
|
||||
|
||||
self.cleanCurrentRequested();
|
||||
|
||||
self.currentLocationChanged.deinit();
|
||||
self.childrenLoaded.deinit();
|
||||
|
||||
self.allocator.destroy(self);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user