feat: requested selected item+
This commit is contained in:
@@ -121,6 +121,9 @@ const Model = struct {
|
|||||||
{
|
{
|
||||||
const currentTab = vm.app_common_model.appState.currentTab;
|
const currentTab = vm.app_common_model.appState.currentTab;
|
||||||
if (currentTab.currentItem) |currentItem| {
|
if (currentTab.currentItem) |currentItem| {
|
||||||
|
const currentItemArcCopy = currentItem.retain();
|
||||||
|
defer if (currentItemArcCopy.releaseUnwrap()) |item| item.deinit();
|
||||||
|
|
||||||
currentTab.currentItems.mutex.lock();
|
currentTab.currentItems.mutex.lock();
|
||||||
defer currentTab.currentItems.mutex.unlock();
|
defer currentTab.currentItems.mutex.unlock();
|
||||||
|
|
||||||
@@ -130,7 +133,7 @@ const Model = struct {
|
|||||||
const arc_item = item.retain();
|
const arc_item = item.retain();
|
||||||
defer if (arc_item.releaseUnwrap()) |i| i.deinit();
|
defer if (arc_item.releaseUnwrap()) |i| i.deinit();
|
||||||
|
|
||||||
if (models.FullName.eql(&arc_item.value.*.fullName, ¤tItem)) {
|
if (models.FullName.eql(&arc_item.value.*.fullName, ¤tItemArcCopy.value.*.fullName)) {
|
||||||
break try std.fmt.allocPrint(ctx.arena, "{s} ", .{arc_item.value.*.displayName});
|
break try std.fmt.allocPrint(ctx.arena, "{s} ", .{arc_item.value.*.displayName});
|
||||||
}
|
}
|
||||||
} else "";
|
} else "";
|
||||||
@@ -183,10 +186,11 @@ const Model = struct {
|
|||||||
|
|
||||||
const text_items = blk2: {
|
const text_items = blk2: {
|
||||||
const currentTab = vm.app_common_model.appState.currentTab;
|
const currentTab = vm.app_common_model.appState.currentTab;
|
||||||
const current_full_name = if (currentTab.currentItem) |currentItem|
|
const current_full_name = if (currentTab.currentItem) |currentItem| blk: {
|
||||||
models.FullName{ .path = try ctx.arena.dupe(u8, currentItem.path) }
|
const arc_copy = currentItem.retain();
|
||||||
else
|
defer if (arc_copy.releaseUnwrap()) |item| item.deinit();
|
||||||
null;
|
break :blk models.FullName{ .path = try ctx.arena.dupe(u8, currentItem.value.*.fullName.path) };
|
||||||
|
} else null;
|
||||||
|
|
||||||
currentTab.currentItems.mutex.lock();
|
currentTab.currentItems.mutex.lock();
|
||||||
defer currentTab.currentItems.mutex.unlock();
|
defer currentTab.currentItems.mutex.unlock();
|
||||||
|
|||||||
@@ -11,8 +11,11 @@ pub fn handle(action: Action, appState: *AppState, arena: std.mem.Allocator) !Ac
|
|||||||
} else return error.NoCurrentLocation;
|
} else return error.NoCurrentLocation;
|
||||||
},
|
},
|
||||||
.Enter => {
|
.Enter => {
|
||||||
if (appState.currentTab.currentItem) |currentItem| {
|
if (appState.currentTab.currentItem) |*currentItem| {
|
||||||
const path = try arena.dupe(u8, currentItem.path);
|
const arc_copy = currentItem.retain();
|
||||||
|
defer if (arc_copy.releaseUnwrap()) |item| item.deinit();
|
||||||
|
|
||||||
|
const path = try arena.dupe(u8, arc_copy.value.*.fullName.path);
|
||||||
try appState.currentTab.setCurrentLocation(.{ .path = path });
|
try appState.currentTab.setCurrentLocation(.{ .path = path });
|
||||||
return ActionResult.Handled;
|
return ActionResult.Handled;
|
||||||
} else return error.NoCurrentLocation;
|
} else return error.NoCurrentLocation;
|
||||||
@@ -43,7 +46,10 @@ fn selectNextIndex(currentTab: *Tab, step: SelectStep, arena: std.mem.Allocator)
|
|||||||
|
|
||||||
const index = blk: {
|
const index = blk: {
|
||||||
if (currentTab.currentItem) |*currentItem| {
|
if (currentTab.currentItem) |*currentItem| {
|
||||||
const index = indexOf(Arc(*models.Item), models.FullName, currentItems.items, currentItem, arcFullNameEql);
|
const arc_copy = currentItem.retain();
|
||||||
|
defer if (arc_copy.releaseUnwrap()) |item| item.deinit();
|
||||||
|
|
||||||
|
const index = indexOf(Arc(*models.Item), models.FullName, currentItems.items, &arc_copy.value.*.fullName, arcFullNameEql);
|
||||||
if (index) |i| {
|
if (index) |i| {
|
||||||
break :blk switch (step) {
|
break :blk switch (step) {
|
||||||
.Next => i +| 1,
|
.Next => i +| 1,
|
||||||
@@ -57,6 +63,8 @@ fn selectNextIndex(currentTab: *Tab, step: SelectStep, arena: std.mem.Allocator)
|
|||||||
break :blk 0;
|
break :blk 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (index >= currentItems.items.len) return ActionResult.None;
|
||||||
|
|
||||||
const arc = currentItems.items[index];
|
const arc = currentItems.items[index];
|
||||||
const arc_copy = arc.retain();
|
const arc_copy = arc.retain();
|
||||||
defer if (arc_copy.releaseUnwrap()) |item| item.deinit();
|
defer if (arc_copy.releaseUnwrap()) |item| item.deinit();
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ fn loadChildren(container: *Container) void {
|
|||||||
container.childrenLoading = false;
|
container.childrenLoading = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
std.debug.print("load children {s}", .{container.item.nativePath.path});
|
|
||||||
var dir = std.fs.cwd().openDir(container.item.nativePath.path, .{ .iterate = true }) catch {
|
var dir = std.fs.cwd().openDir(container.item.nativePath.path, .{ .iterate = true }) catch {
|
||||||
// const errorContent = std.fmt.allocPrint(container.item.allocator, "Could not open directory '{s}'.", .{container.item.nativePath.path}) catch return;
|
// const errorContent = std.fmt.allocPrint(container.item.allocator, "Could not open directory '{s}'.", .{container.item.nativePath.path}) catch return;
|
||||||
// container.item.errors.append(.{ .content = errorContent }) catch return;
|
// container.item.errors.append(.{ .content = errorContent }) catch return;
|
||||||
|
|||||||
8
src/core/tab/order.zig
Normal file
8
src/core/tab/order.zig
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
pub fn orderByDisplayName(lhs: *const models.Item, rhs: *const models.Item) std.math.Order {
|
||||||
|
if (lhs.item == .container and rhs.item == .element) return .lt;
|
||||||
|
if (lhs.item == .element and rhs.item == .container) return .gt;
|
||||||
|
return std.mem.order(u8, lhs.displayName, rhs.displayName);
|
||||||
|
}
|
||||||
|
|
||||||
|
const std = @import("std");
|
||||||
|
const models = @import("../models.zig");
|
||||||
@@ -3,8 +3,10 @@ pub const Tab = struct {
|
|||||||
currentLocation: ?*Container,
|
currentLocation: ?*Container,
|
||||||
currentItems: locked(?std.ArrayList(Arc(*Item))),
|
currentItems: locked(?std.ArrayList(Arc(*Item))),
|
||||||
currentLocationChanged: Observable(?*Container),
|
currentLocationChanged: Observable(?*Container),
|
||||||
currentItem: ?models.FullName,
|
currentItemFullName: ?models.FullName,
|
||||||
currentRequestedItem: ?models.FullName,
|
currentItem: ?Arc(*models.Item),
|
||||||
|
currentRequested: ?union(enum) { item: Arc(*models.Item), name: models.FullName },
|
||||||
|
itemComparer: *const fn (item1: *const models.Item, item2: *const models.Item) std.math.Order,
|
||||||
threadPool: *std.Thread.Pool,
|
threadPool: *std.Thread.Pool,
|
||||||
rootProvider: *RootProvider,
|
rootProvider: *RootProvider,
|
||||||
|
|
||||||
@@ -19,8 +21,10 @@ pub const Tab = struct {
|
|||||||
.currentItems = .{ .data = null },
|
.currentItems = .{ .data = null },
|
||||||
.currentLocationChanged = Observable(?*Container).init(allocator),
|
.currentLocationChanged = Observable(?*Container).init(allocator),
|
||||||
.currentLocation = null,
|
.currentLocation = null,
|
||||||
.currentRequestedItem = null,
|
.currentRequested = null,
|
||||||
.currentItem = null,
|
.currentItem = null,
|
||||||
|
.currentItemFullName = null,
|
||||||
|
.itemComparer = order.orderByDisplayName,
|
||||||
.threadPool = threadPool,
|
.threadPool = threadPool,
|
||||||
.rootProvider = rootProvider,
|
.rootProvider = rootProvider,
|
||||||
};
|
};
|
||||||
@@ -31,10 +35,7 @@ pub const Tab = struct {
|
|||||||
c.item.deinit();
|
c.item.deinit();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (self.currentItem) |i| {
|
self.cleanCurrentItem();
|
||||||
self.allocator.free(i.path);
|
|
||||||
self.currentItem = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const newLocationContainer = blk: {
|
const newLocationContainer = blk: {
|
||||||
const newLocation = try self.rootProvider.getItemByFullName(newLocationFullName, &.{}, self.allocator);
|
const newLocation = try self.rootProvider.getItemByFullName(newLocationFullName, &.{}, self.allocator);
|
||||||
@@ -55,6 +56,7 @@ pub const Tab = struct {
|
|||||||
self.currentLocationChanged.notify(newLocationContainer);
|
self.currentLocationChanged.notify(newLocationContainer);
|
||||||
|
|
||||||
self.updateCurrentItem() catch {
|
self.updateCurrentItem() catch {
|
||||||
|
self.currentItemFullName = null;
|
||||||
self.currentItem = null;
|
self.currentItem = null;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -66,47 +68,80 @@ pub const Tab = struct {
|
|||||||
self.currentItems.mutex.lock();
|
self.currentItems.mutex.lock();
|
||||||
defer self.currentItems.mutex.unlock();
|
defer self.currentItems.mutex.unlock();
|
||||||
|
|
||||||
self.currentRequestedItem = models.FullName{
|
self.cleanCurrentRequested();
|
||||||
.path = try self.allocator.dupe(u8, requested_selected.path),
|
|
||||||
|
self.currentRequested = .{
|
||||||
|
.name = models.FullName{
|
||||||
|
.path = try self.allocator.dupe(u8, requested_selected.path),
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
return self.updateCurrentItem();
|
return self.updateCurrentItem();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn updateCurrentItem(self: *Tab) !void {
|
fn cleanCurrentRequested(self: *Tab) void {
|
||||||
const currentRequestedItem = self.currentRequestedItem orelse return;
|
const requested = self.currentRequested orelse return;
|
||||||
|
|
||||||
|
switch (requested) {
|
||||||
|
.item => |item| {
|
||||||
|
if (item.releaseUnwrap()) |i| i.deinit();
|
||||||
|
},
|
||||||
|
.name => |fullName| self.allocator.free(fullName.path),
|
||||||
|
}
|
||||||
|
|
||||||
|
self.currentRequested = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn updateCurrentItem(self: *Tab) !void {
|
||||||
|
const currentRequested = self.currentRequested orelse return;
|
||||||
|
|
||||||
|
const requestedFullName = switch (currentRequested) {
|
||||||
|
.item => |*item| item.value.*.fullName,
|
||||||
|
.name => |fullName| fullName,
|
||||||
|
};
|
||||||
// The requested is already selected
|
// The requested is already selected
|
||||||
if (self.currentItem) |currentItem| {
|
if (self.currentItemFullName) |currentItem| {
|
||||||
if (std.mem.order(u8, currentRequestedItem.path, currentItem.path) == .eq) return;
|
if (std.mem.order(u8, requestedFullName.path, currentItem.path) == .eq) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const currentItems = self.currentItems.data orelse return error.Error;
|
const currentItems = self.currentItems.data orelse return error.Error;
|
||||||
if (currentItems.items.len == 0) return error.Error;
|
if (currentItems.items.len == 0) return error.Error;
|
||||||
|
|
||||||
// Looking for the requested
|
// Looking for the requested
|
||||||
const foundIndex = for (0..currentItems.items.len) |i| {
|
const foundIndex = index: for (0..currentItems.items.len) |i| {
|
||||||
const arc_item = currentItems.items[i];
|
const arc_item = currentItems.items[i];
|
||||||
const arc_copy = arc_item.retain();
|
const arc_copy = arc_item.retain();
|
||||||
defer if (arc_copy.releaseUnwrap()) |item| item.deinit();
|
defer if (arc_copy.releaseUnwrap()) |item| item.deinit();
|
||||||
|
|
||||||
const comp = std.mem.order(u8, arc_copy.value.*.fullName.path, currentRequestedItem.path);
|
switch (currentRequested) {
|
||||||
if (comp == .eq) {
|
.item => |*itemArc| {
|
||||||
break i;
|
const comp = self.itemComparer(itemArc.value.*, arc_copy.value.*);
|
||||||
}
|
if (comp == .eq) {
|
||||||
if (comp == .lt) {
|
break :index i;
|
||||||
break i -| 1;
|
}
|
||||||
|
if (comp == .lt) {
|
||||||
|
break :index i -| 1;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
.name => |fullName| {
|
||||||
|
if (std.mem.order(u8, fullName.path, arc_copy.value.*.fullName.path) == .eq) {
|
||||||
|
break :index i;
|
||||||
|
}
|
||||||
|
},
|
||||||
}
|
}
|
||||||
} else null;
|
} else null;
|
||||||
|
|
||||||
if (foundIndex) |i| {
|
if (foundIndex) |i| {
|
||||||
const arc_item = currentItems.items[i];
|
const arc_item = currentItems.items[i];
|
||||||
const arc_copy = arc_item.retain();
|
|
||||||
defer if (arc_copy.releaseUnwrap()) |item| item.deinit();
|
|
||||||
|
|
||||||
self.setSelectedItemInner(models.FullName{
|
self.cleanCurrentRequested();
|
||||||
.path = try self.allocator.dupe(u8, arc_copy.value.*.fullName.path),
|
self.currentRequested = .{
|
||||||
});
|
.item = arc_item.retain(),
|
||||||
|
};
|
||||||
|
|
||||||
|
try self.setSelectedItemInner(arc_item.retain());
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -116,21 +151,21 @@ pub const Tab = struct {
|
|||||||
// Fallback to first item
|
// Fallback to first item
|
||||||
{
|
{
|
||||||
const arc_item = currentItems.items[0];
|
const arc_item = currentItems.items[0];
|
||||||
const arc_copy = arc_item.retain();
|
|
||||||
defer if (arc_copy.releaseUnwrap()) |item| item.deinit();
|
|
||||||
|
|
||||||
self.setSelectedItemInner(models.FullName{
|
try self.setSelectedItemInner(arc_item.retain());
|
||||||
.path = try self.allocator.dupe(u8, arc_copy.value.*.fullName.path),
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setSelectedItemInner(self: *Tab, newSelectedItem: models.FullName) void {
|
fn setSelectedItemInner(self: *Tab, newSelectedItemArc: Arc(*models.Item)) !void {
|
||||||
if (self.currentItem) |current| {
|
const arc = newSelectedItemArc.retain();
|
||||||
self.allocator.free(current.path);
|
defer if (arc.releaseUnwrap()) |item| item.deinit();
|
||||||
}
|
|
||||||
|
|
||||||
self.currentItem = newSelectedItem;
|
self.cleanCurrentItem();
|
||||||
|
|
||||||
|
self.currentItem = newSelectedItemArc;
|
||||||
|
self.currentItemFullName = models.FullName{
|
||||||
|
.path = try self.allocator.dupe(u8, arc.value.*.fullName.path),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn loadItemsWrapper(self: *Tab, location: *Container) void {
|
fn loadItemsWrapper(self: *Tab, location: *Container) void {
|
||||||
@@ -177,8 +212,8 @@ pub const Tab = struct {
|
|||||||
self.currentItems.mutex.lock();
|
self.currentItems.mutex.lock();
|
||||||
defer self.currentItems.mutex.unlock();
|
defer self.currentItems.mutex.unlock();
|
||||||
|
|
||||||
const insertIndex = for (self.currentItems.data.?.items, 0..) |item, i| {
|
const insertIndex = for (self.currentItems.data.?.items, 0..) |*item, i| {
|
||||||
if (compareByDisplayName(resolvedItem, item.value.*)) break i;
|
if (order.orderByDisplayName(resolvedItem, item.value.*) == .lt) break i;
|
||||||
} else null;
|
} else null;
|
||||||
|
|
||||||
const arc = try Arc(*Item).init(self.allocator, resolvedItem);
|
const arc = try Arc(*Item).init(self.allocator, resolvedItem);
|
||||||
@@ -208,17 +243,23 @@ pub const Tab = struct {
|
|||||||
currentItems.deinit();
|
currentItems.deinit();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (self.currentItem) |currentItem| {
|
self.cleanCurrentItem();
|
||||||
self.allocator.free(currentItem.path);
|
|
||||||
}
|
self.cleanCurrentRequested();
|
||||||
|
|
||||||
self.allocator.destroy(self);
|
self.allocator.destroy(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compareByDisplayName(lhs: *models.Item, rhs: *models.Item) bool {
|
fn cleanCurrentItem(self: *Tab) void {
|
||||||
if (lhs.item == .container and rhs.item == .element) return true;
|
if (self.currentItemFullName) |currentItem| {
|
||||||
if (lhs.item == .element and rhs.item == .container) return false;
|
self.allocator.free(currentItem.path);
|
||||||
return std.mem.order(u8, lhs.displayName, rhs.displayName) == .lt;
|
self.currentItemFullName = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (self.currentItem) |currentItem| {
|
||||||
|
if (currentItem.releaseUnwrap()) |item| item.deinit();
|
||||||
|
self.currentItem = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -226,6 +267,8 @@ const std = @import("std");
|
|||||||
const assert = std.debug.assert;
|
const assert = std.debug.assert;
|
||||||
const Mutex = std.Thread.Mutex;
|
const Mutex = std.Thread.Mutex;
|
||||||
|
|
||||||
|
const order = @import("./order.zig");
|
||||||
|
|
||||||
const models = @import("../models.zig");
|
const models = @import("../models.zig");
|
||||||
const Container = models.Container;
|
const Container = models.Container;
|
||||||
const Item = models.Item;
|
const Item = models.Item;
|
||||||
|
|||||||
Reference in New Issue
Block a user