apprt/gtk: switch to has-x and optional internals for search counts

pull/9756/head
Mitchell Hashimoto 2025-11-30 07:06:44 -08:00
parent b8393fd4aa
commit c67bcf969c
No known key found for this signature in database
GPG Key ID: 523D5DC389D273BC
2 changed files with 97 additions and 25 deletions

View File

@ -53,12 +53,33 @@ pub const SearchOverlay = extern struct {
const impl = gobject.ext.defineProperty( const impl = gobject.ext.defineProperty(
name, name,
Self, Self,
i64, u64,
.{ .{
.default = -1, .default = 0,
.minimum = -1, .minimum = 0,
.maximum = std.math.maxInt(i64), .maximum = std.math.maxInt(u64),
.accessor = C.privateShallowFieldAccessor("search_total"), .accessor = gobject.ext.typedAccessor(
Self,
u64,
.{ .getter = getSearchTotal },
),
},
);
};
pub const @"has-search-total" = struct {
pub const name = "has-search-total";
const impl = gobject.ext.defineProperty(
name,
Self,
bool,
.{
.default = false,
.accessor = gobject.ext.typedAccessor(
Self,
bool,
.{ .getter = getHasSearchTotal },
),
}, },
); );
}; };
@ -68,12 +89,33 @@ pub const SearchOverlay = extern struct {
const impl = gobject.ext.defineProperty( const impl = gobject.ext.defineProperty(
name, name,
Self, Self,
i64, u64,
.{ .{
.default = -1, .default = 0,
.minimum = -1, .minimum = 0,
.maximum = std.math.maxInt(i64), .maximum = std.math.maxInt(u64),
.accessor = C.privateShallowFieldAccessor("search_selected"), .accessor = gobject.ext.typedAccessor(
Self,
u64,
.{ .getter = getSearchSelected },
),
},
);
};
pub const @"has-search-selected" = struct {
pub const name = "has-search-selected";
const impl = gobject.ext.defineProperty(
name,
Self,
bool,
.{
.default = false,
.accessor = gobject.ext.typedAccessor(
Self,
bool,
.{ .getter = getHasSearchSelected },
),
}, },
); );
}; };
@ -162,11 +204,11 @@ pub const SearchOverlay = extern struct {
/// True when a search is active, meaning we should show the overlay. /// True when a search is active, meaning we should show the overlay.
active: bool = false, active: bool = false,
/// Total number of search matches (-1 means unknown/none). /// Total number of search matches (null means unknown/none).
search_total: i64 = -1, search_total: ?usize = null,
/// Currently selected match index (-1 means none selected). /// Currently selected match index (null means none selected).
search_selected: i64 = -1, search_selected: ?usize = null,
/// Target horizontal alignment for the overlay. /// Target horizontal alignment for the overlay.
halign_target: gtk.Align = .end, halign_target: gtk.Align = .end,
@ -194,27 +236,55 @@ pub const SearchOverlay = extern struct {
/// Set the total number of search matches. /// Set the total number of search matches.
pub fn setSearchTotal(self: *Self, total: ?usize) void { pub fn setSearchTotal(self: *Self, total: ?usize) void {
const priv = self.private(); const priv = self.private();
const value: i64 = if (total) |t| @intCast(t) else -1; const had_total = priv.search_total != null;
if (priv.search_total == value) return; if (priv.search_total == total) return;
priv.search_total = value; priv.search_total = total;
self.as(gobject.Object).notifyByPspec(properties.@"search-total".impl.param_spec); self.as(gobject.Object).notifyByPspec(properties.@"search-total".impl.param_spec);
if (had_total != (total != null)) {
self.as(gobject.Object).notifyByPspec(properties.@"has-search-total".impl.param_spec);
}
} }
/// Set the currently selected match index. /// Set the currently selected match index.
pub fn setSearchSelected(self: *Self, selected: ?usize) void { pub fn setSearchSelected(self: *Self, selected: ?usize) void {
const priv = self.private(); const priv = self.private();
const value: i64 = if (selected) |s| @intCast(s) else -1; const had_selected = priv.search_selected != null;
if (priv.search_selected == value) return; if (priv.search_selected == selected) return;
priv.search_selected = value; priv.search_selected = selected;
self.as(gobject.Object).notifyByPspec(properties.@"search-selected".impl.param_spec); self.as(gobject.Object).notifyByPspec(properties.@"search-selected".impl.param_spec);
if (had_selected != (selected != null)) {
self.as(gobject.Object).notifyByPspec(properties.@"has-search-selected".impl.param_spec);
}
} }
fn closureMatchLabel(_: *Self, selected: i64, total: i64) callconv(.c) ?[*:0]const u8 { fn getSearchTotal(self: *Self) u64 {
if (total <= 0) return glib.ext.dupeZ(u8, "0/0"); return self.private().search_total orelse 0;
}
fn getHasSearchTotal(self: *Self) bool {
return self.private().search_total != null;
}
fn getSearchSelected(self: *Self) u64 {
return self.private().search_selected orelse 0;
}
fn getHasSearchSelected(self: *Self) bool {
return self.private().search_selected != null;
}
fn closureMatchLabel(
_: *Self,
has_selected: bool,
selected: u64,
has_total: bool,
total: u64,
) callconv(.c) ?[*:0]const u8 {
if (!has_total or total == 0) return glib.ext.dupeZ(u8, "0/0");
var buf: [32]u8 = undefined; var buf: [32]u8 = undefined;
const label = std.fmt.bufPrintZ(&buf, "{}/{}", .{ const label = std.fmt.bufPrintZ(&buf, "{}/{}", .{
if (selected >= 0) selected + 1 else 0, if (has_selected) selected + 1 else 0,
if (total >= 0) total else 0, total,
}) catch return null; }) catch return null;
return glib.ext.dupeZ(u8, label); return glib.ext.dupeZ(u8, label);
} }
@ -370,7 +440,9 @@ pub const SearchOverlay = extern struct {
gobject.ext.registerProperties(class, &.{ gobject.ext.registerProperties(class, &.{
properties.active.impl, properties.active.impl,
properties.@"search-total".impl, properties.@"search-total".impl,
properties.@"has-search-total".impl,
properties.@"search-selected".impl, properties.@"search-selected".impl,
properties.@"has-search-selected".impl,
properties.@"halign-target".impl, properties.@"halign-target".impl,
properties.@"valign-target".impl, properties.@"valign-target".impl,
}); });

View File

@ -46,7 +46,7 @@ template $GhosttySearchOverlay: Adw.Bin {
"dim-label", "dim-label",
] ]
label: bind $match_label_closure(template.search-selected, template.search-total) as <string>; label: bind $match_label_closure(template.has-search-selected, template.search-selected, template.has-search-total, template.search-total) as <string>;
width-chars: 6; width-chars: 6;
xalign: 1.0; xalign: 1.0;
} }