mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-19 10:16:12 +03:00
apprt/gtk-ng: hook up all the bindings for the config errors dialog
This commit is contained in:
@ -21,6 +21,7 @@ const adw_version = @import("../adw_version.zig");
|
|||||||
const gtk_version = @import("../gtk_version.zig");
|
const gtk_version = @import("../gtk_version.zig");
|
||||||
const GhosttyConfig = @import("config.zig").GhosttyConfig;
|
const GhosttyConfig = @import("config.zig").GhosttyConfig;
|
||||||
const GhosttyWindow = @import("window.zig").GhosttyWindow;
|
const GhosttyWindow = @import("window.zig").GhosttyWindow;
|
||||||
|
const ConfigErrorsDialog = @import("config_errors_dialog.zig").ConfigErrorsDialog;
|
||||||
|
|
||||||
const log = std.log.scoped(.gtk_ghostty_application);
|
const log = std.log.scoped(.gtk_ghostty_application);
|
||||||
|
|
||||||
@ -320,6 +321,11 @@ pub const GhosttyApplication = extern struct {
|
|||||||
fn startup(self: *GhosttyApplication) callconv(.C) void {
|
fn startup(self: *GhosttyApplication) callconv(.C) void {
|
||||||
log.debug("startup", .{});
|
log.debug("startup", .{});
|
||||||
|
|
||||||
|
gio.Application.virtual_methods.startup.call(
|
||||||
|
Class.parent,
|
||||||
|
self.as(Parent),
|
||||||
|
);
|
||||||
|
|
||||||
// Setup our event loop
|
// Setup our event loop
|
||||||
self.startupXev();
|
self.startupXev();
|
||||||
|
|
||||||
@ -331,10 +337,15 @@ pub const GhosttyApplication = extern struct {
|
|||||||
log.warn("TODO", .{});
|
log.warn("TODO", .{});
|
||||||
};
|
};
|
||||||
|
|
||||||
gio.Application.virtual_methods.startup.call(
|
// If we have any config diagnostics from loading, then we
|
||||||
Class.parent,
|
// show the diagnostics dialog. We show this one as a general
|
||||||
self.as(Parent),
|
// modal (not to any specific window) because we don't even
|
||||||
);
|
// know if the window will load.
|
||||||
|
const priv = self.private();
|
||||||
|
if (priv.config.hasDiagnostics()) {
|
||||||
|
const dialog: *ConfigErrorsDialog = .new(priv.config);
|
||||||
|
dialog.present(null);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Configure libxev to use a specific backend.
|
/// Configure libxev to use a specific backend.
|
||||||
@ -474,8 +485,8 @@ pub const GhosttyApplication = extern struct {
|
|||||||
self.as(Parent),
|
self.as(Parent),
|
||||||
);
|
);
|
||||||
|
|
||||||
const win = GhosttyWindow.new(self);
|
// const win = GhosttyWindow.new(self);
|
||||||
gtk.Window.present(win.as(gtk.Window));
|
// gtk.Window.present(win.as(gtk.Window));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn finalize(self: *GhosttyApplication) callconv(.C) void {
|
fn finalize(self: *GhosttyApplication) callconv(.C) void {
|
||||||
|
@ -29,6 +29,36 @@ pub const GhosttyConfig = extern struct {
|
|||||||
.private = .{ .Type = Private, .offset = &Private.offset },
|
.private = .{ .Type = Private, .offset = &Private.offset },
|
||||||
});
|
});
|
||||||
|
|
||||||
|
pub const properties = struct {
|
||||||
|
pub const @"diagnostics-buffer" = gobject.ext.defineProperty(
|
||||||
|
"diagnostics-buffer",
|
||||||
|
Self,
|
||||||
|
?*gtk.TextBuffer,
|
||||||
|
.{
|
||||||
|
.nick = "Dignostics Buffer",
|
||||||
|
.blurb = "A TextBuffer that contains the diagnostics.",
|
||||||
|
.default = null,
|
||||||
|
.accessor = .{
|
||||||
|
.getter = Self.diagnosticsBuffer,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
pub const @"has-diagnostics" = gobject.ext.defineProperty(
|
||||||
|
"has-diagnostics",
|
||||||
|
Self,
|
||||||
|
bool,
|
||||||
|
.{
|
||||||
|
.nick = "has-diagnostics",
|
||||||
|
.blurb = "Whether the configuration has diagnostics.",
|
||||||
|
.default = false,
|
||||||
|
.accessor = .{
|
||||||
|
.getter = Self.hasDiagnostics,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
const Private = struct {
|
const Private = struct {
|
||||||
config: Config,
|
config: Config,
|
||||||
|
|
||||||
@ -55,6 +85,48 @@ pub const GhosttyConfig = extern struct {
|
|||||||
return &self.private().config;
|
return &self.private().config;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the mutable configuration. This is usually NOT recommended
|
||||||
|
/// because any changes to the config won't be propagated to anyone
|
||||||
|
/// with a reference to this object. If you know what you're doing, then
|
||||||
|
/// you can use this.
|
||||||
|
pub fn getMut(self: *Self) *Config {
|
||||||
|
return &self.private().config;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns whether this configuration has any diagnostics.
|
||||||
|
pub fn hasDiagnostics(self: *Self) bool {
|
||||||
|
const config = self.get();
|
||||||
|
return !config._diagnostics.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Reads the diagnostics of this configuration as a TextBuffer,
|
||||||
|
/// or returns null if there are no diagnostics.
|
||||||
|
pub fn diagnosticsBuffer(self: *Self) ?*gtk.TextBuffer {
|
||||||
|
const config = self.get();
|
||||||
|
if (config._diagnostics.empty()) return null;
|
||||||
|
|
||||||
|
const text_buf: *gtk.TextBuffer = .new(null);
|
||||||
|
errdefer text_buf.unref();
|
||||||
|
|
||||||
|
var buf: [4095:0]u8 = undefined;
|
||||||
|
var fbs = std.io.fixedBufferStream(&buf);
|
||||||
|
for (config._diagnostics.items()) |diag| {
|
||||||
|
fbs.reset();
|
||||||
|
diag.write(fbs.writer()) catch |err| {
|
||||||
|
log.warn(
|
||||||
|
"error writing diagnostic to buffer err={}",
|
||||||
|
.{err},
|
||||||
|
);
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
|
||||||
|
text_buf.insertAtCursor(&buf, @intCast(fbs.pos));
|
||||||
|
text_buf.insertAtCursor("\n", 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return text_buf;
|
||||||
|
}
|
||||||
|
|
||||||
fn finalize(self: *Self) callconv(.C) void {
|
fn finalize(self: *Self) callconv(.C) void {
|
||||||
self.private().config.deinit();
|
self.private().config.deinit();
|
||||||
|
|
||||||
@ -91,6 +163,10 @@ pub const GhosttyConfig = extern struct {
|
|||||||
|
|
||||||
fn init(class: *Class) callconv(.C) void {
|
fn init(class: *Class) callconv(.C) void {
|
||||||
gobject.Object.virtual_methods.finalize.implement(class, &finalize);
|
gobject.Object.virtual_methods.finalize.implement(class, &finalize);
|
||||||
|
gobject.ext.registerProperties(class, &.{
|
||||||
|
properties.@"diagnostics-buffer",
|
||||||
|
properties.@"has-diagnostics",
|
||||||
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -5,11 +5,11 @@ const gtk = @import("gtk");
|
|||||||
|
|
||||||
const gresource = @import("../build/gresource.zig");
|
const gresource = @import("../build/gresource.zig");
|
||||||
const adw_version = @import("../adw_version.zig");
|
const adw_version = @import("../adw_version.zig");
|
||||||
const GhosttyConfig = @import("config.zig").GhosttyConfig;
|
const Config = @import("config.zig").GhosttyConfig;
|
||||||
|
|
||||||
const log = std.log.scoped(.gtk_ghostty_window);
|
const log = std.log.scoped(.gtk_ghostty_window);
|
||||||
|
|
||||||
pub const GhosttyConfigErrors = extern struct {
|
pub const ConfigErrorsDialog = extern struct {
|
||||||
const Self = @This();
|
const Self = @This();
|
||||||
parent_instance: Parent,
|
parent_instance: Parent,
|
||||||
|
|
||||||
@ -19,18 +19,38 @@ pub const GhosttyConfigErrors = extern struct {
|
|||||||
adw.MessageDialog;
|
adw.MessageDialog;
|
||||||
|
|
||||||
pub const getGObjectType = gobject.ext.defineClass(Self, .{
|
pub const getGObjectType = gobject.ext.defineClass(Self, .{
|
||||||
|
.name = "GhosttyConfigErrorsDialog",
|
||||||
.instanceInit = &init,
|
.instanceInit = &init,
|
||||||
.classInit = &Class.init,
|
.classInit = &Class.init,
|
||||||
.parent_class = &Class.parent,
|
.parent_class = &Class.parent,
|
||||||
.private = .{ .Type = Private, .offset = &Private.offset },
|
.private = .{ .Type = Private, .offset = &Private.offset },
|
||||||
});
|
});
|
||||||
|
|
||||||
|
pub const properties = struct {
|
||||||
|
pub const config = gobject.ext.defineProperty(
|
||||||
|
"config",
|
||||||
|
Self,
|
||||||
|
?*Config,
|
||||||
|
.{
|
||||||
|
.nick = "config",
|
||||||
|
.blurb = "The configuration that this dialog is showing errors for.",
|
||||||
|
.default = null,
|
||||||
|
.accessor = gobject.ext.privateFieldAccessor(
|
||||||
|
Self,
|
||||||
|
Private,
|
||||||
|
&Private.offset,
|
||||||
|
"config",
|
||||||
|
),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
const Private = struct {
|
const Private = struct {
|
||||||
_todo: u8 = 0,
|
config: ?*Config,
|
||||||
var offset: c_int = 0;
|
var offset: c_int = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn new(config: *GhosttyConfig) *Self {
|
pub fn new(config: *Config) *Self {
|
||||||
return gobject.ext.newInstance(Self, .{
|
return gobject.ext.newInstance(Self, .{
|
||||||
.config = config,
|
.config = config,
|
||||||
});
|
});
|
||||||
@ -40,6 +60,13 @@ pub const GhosttyConfigErrors = extern struct {
|
|||||||
gtk.Widget.initTemplate(self.as(gtk.Widget));
|
gtk.Widget.initTemplate(self.as(gtk.Widget));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn present(self: *Self, parent: ?*gtk.Widget) void {
|
||||||
|
switch (Parent) {
|
||||||
|
adw.AlertDialog => self.as(adw.Dialog).present(parent),
|
||||||
|
else => unreachable,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn as(win: *Self, comptime T: type) *T {
|
pub fn as(win: *Self, comptime T: type) *T {
|
||||||
return gobject.ext.as(T, win);
|
return gobject.ext.as(T, win);
|
||||||
}
|
}
|
||||||
@ -58,9 +85,14 @@ pub const GhosttyConfigErrors = extern struct {
|
|||||||
.minor = 5,
|
.minor = 5,
|
||||||
.name = "config-errors-dialog",
|
.name = "config-errors-dialog",
|
||||||
}),
|
}),
|
||||||
|
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
gobject.ext.registerProperties(class, &.{
|
||||||
|
properties.config,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn as(class: *Class, comptime T: type) *T {
|
pub fn as(class: *Class, comptime T: type) *T {
|
@ -20,7 +20,7 @@ pub const GhosttyWindow = extern struct {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const Private = struct {
|
const Private = struct {
|
||||||
_todo: u8 = 0,
|
_todo: u8,
|
||||||
var offset: c_int = 0;
|
var offset: c_int = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -28,12 +28,20 @@ pub const GhosttyWindow = extern struct {
|
|||||||
return gobject.ext.newInstance(Self, .{ .application = app });
|
return gobject.ext.newInstance(Self, .{ .application = app });
|
||||||
}
|
}
|
||||||
|
|
||||||
fn init(win: *GhosttyWindow, _: *Class) callconv(.C) void {
|
fn init(self: *GhosttyWindow, _: *Class) callconv(.C) void {
|
||||||
gtk.Widget.initTemplate(win.as(gtk.Widget));
|
gtk.Widget.initTemplate(self.as(gtk.Widget));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn as(win: *Self, comptime T: type) *T {
|
pub fn as(self: *Self, comptime T: type) *T {
|
||||||
return gobject.ext.as(T, win);
|
return gobject.ext.as(T, self);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn private(self: *Self) *Private {
|
||||||
|
return gobject.ext.impl_helpers.getPrivate(
|
||||||
|
self,
|
||||||
|
Private,
|
||||||
|
Private.offset,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const Class = extern struct {
|
pub const Class = extern struct {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
using Gtk 4.0;
|
using Gtk 4.0;
|
||||||
using Adw 1;
|
using Adw 1;
|
||||||
|
|
||||||
Adw.AlertDialog config_errors_dialog {
|
template $GhosttyConfigErrorsDialog: Adw.AlertDialog {
|
||||||
heading: _("Configuration Errors");
|
heading: _("Configuration Errors");
|
||||||
body: _("One or more configuration errors were found. Please review the errors below, and either reload your configuration or ignore these errors.");
|
body: _("One or more configuration errors were found. Please review the errors below, and either reload your configuration or ignore these errors.");
|
||||||
|
|
||||||
@ -21,6 +21,7 @@ Adw.AlertDialog config_errors_dialog {
|
|||||||
bottom-margin: 8;
|
bottom-margin: 8;
|
||||||
left-margin: 8;
|
left-margin: 8;
|
||||||
right-margin: 8;
|
right-margin: 8;
|
||||||
|
buffer: bind (template.config as <$GhosttyConfig>).diagnostics-buffer;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user