Add Parent and Child types for tracking splits; Add methods for

adding start and end children in `Paned` widget;
This commit is contained in:
Nathan Fisher
2023-09-30 00:43:17 -04:00
committed by Mitchell Hashimoto
parent 5b5c2c9ab2
commit aba1b85503
4 changed files with 121 additions and 11 deletions

View File

@ -2,33 +2,40 @@ const Paned = @This();
const std = @import("std"); const std = @import("std");
const Allocator = std.mem.Allocator; const Allocator = std.mem.Allocator;
const assert = std.debug.assert;
const font = @import("../../font/main.zig"); const font = @import("../../font/main.zig");
const CoreSurface = @import("../../Surface.zig"); const CoreSurface = @import("../../Surface.zig");
const Window = @import("Window.zig"); const Window = @import("Window.zig");
const Surface = @import("Surface.zig"); const Surface = @import("Surface.zig");
const Tab = @import("Tab.zig"); const Tab = @import("Tab.zig");
const Position = @import("parent.zig").Position;
const Parent = @import("parent.zig").Parent;
const c = @import("c.zig"); const c = @import("c.zig");
const Child = union(enum) { const Child = union(enum) {
surface: *Surface, surface: *Surface,
paned: *Paned, paned: *Paned,
empty: void, empty: void,
const Self = @This();
fn is_empty(self: Self) bool {
switch (self) {
Child.empty => return true,
else => return false,
}
}
}; };
const Parent = union(enum) { /// We'll need to keep a reference to the Window this belongs to for various reasons
tab: *Tab, Window: *c.GtkWindow,
paned: *Paned,
};
// We'll need to keep a reference to the Window this belongs to for various reasons
window: *c.GtkWindow,
// We keep track of the tab label's text so that if a child widget of this pane // We keep track of the tab label's text so that if a child widget of this pane
// gets focus (and is a Surface) we can reset the tab label appropriately // gets focus (and is a Surface) we can reset the tab label appropriately
label_text: *c.GtkWidget, label_text: *c.GtkWidget,
// Our actual GtkPaned widget /// Our actual GtkPaned widget
paned: *c.GtkPaned, paned: *c.GtkPaned,
// We have two children, each of which can be either a Surface, another pane, // We have two children, each of which can be either a Surface, another pane,
@ -96,3 +103,73 @@ pub fn newSurface(self: *Paned, parent_: ?*CoreSurface) !*Surface {
}); });
return surface; return surface;
} }
fn addChild1Surface(self: *Paned, surface: *Surface) void {
assert(self.child1.is_empty());
self.child1 = Child{ .surface = surface };
surface.parent = Surface.Parent{ .paned = .{ self, Position.start } };
c.gtk_paned_pack1(@ptrCast(self.paned), @ptrCast(surface.gl_area), 1, 0);
if (self.child2.is_empty()) {
c.gtk_paned_set_position(self.paned, 100);
} else {
c.gtk_paned_set_position(self.paned, 50);
}
}
fn addChild2Surface(self: *Paned, surface: *Surface) void {
assert(self.child1.is_empty());
self.child2 = Child{ .surface = surface };
surface.parent = Surface.Parent{ .paned = .{ self, Position.end } };
c.gtk_paned_pack2(@ptrCast(self.paned), @ptrCast(surface.gl_area), 1, 0);
if (self.child2.is_empty()) {
c.gtk_paned_set_position(self.paned, 0);
} else {
c.gtk_paned_set_position(self.paned, 50);
}
}
fn addChild1Paned(self: *Paned, child: *Paned) void {
assert(self.child1.is_empty());
self.child1 = Child{ .paned = child };
child.parent = Parent{ .paned = .{ self, Position.start } };
c.gtk_paned_pack1(@ptrCast(self.paned), @ptrCast(child.paned), 1, 0);
if (self.child2.is_empty()) {
c.gtk_paned_set_position(self.paned, 100);
} else {
c.gtk_paned_set_position(self.paned, 50);
}
}
fn addChild2Paned(self: *Paned, child: *Paned) void {
assert(self.child1.is_empty());
self.child2 = Child{ .paned = child };
child.parent = Parent{ .paned = .{ self, Position.end } };
c.gtk_paned_pack2(@ptrCast(self.paned), @ptrCast(child.paned), 1, 0);
if (self.child2.is_empty()) {
c.gtk_paned_set_position(self.paned, 0);
} else {
c.gtk_paned_set_position(self.paned, 50);
}
}
fn removeChild1(self: *Paned) void {
assert(!self.child1.is_empty());
// todo
}
fn removeChild2(self: *Paned) void {
assert(!self.child1.is_empty());
// todo
}
pub fn splitStartPosition(self: *Paned, orientation: c.GtkOrientation) !void {
_ = orientation;
_ = self;
// todo
}
pub fn splitEndPosition(self: *Paned, orientation: c.GtkOrientation) !void {
_ = orientation;
_ = self;
// todo
}

View File

@ -12,8 +12,12 @@ const terminal = @import("../../terminal/main.zig");
const CoreSurface = @import("../../Surface.zig"); const CoreSurface = @import("../../Surface.zig");
const App = @import("App.zig"); const App = @import("App.zig");
const Paned = @import("Paned.zig");
const Tab = @import("Tab.zig");
const Window = @import("Window.zig"); const Window = @import("Window.zig");
const ClipboardConfirmationWindow = @import("ClipboardConfirmationWindow.zig"); const ClipboardConfirmationWindow = @import("ClipboardConfirmationWindow.zig");
const Position = @import("parent.zig").Position;
const Parent = @import("parent.zig").Parent;
const inspector = @import("inspector.zig"); const inspector = @import("inspector.zig");
const gtk_key = @import("key.zig"); const gtk_key = @import("key.zig");
const c = @import("c.zig"); const c = @import("c.zig");
@ -66,6 +70,9 @@ app: *App,
/// The window we're part of /// The window we're part of
window: *Window, window: *Window,
/// Our parent widget
parent: Parent,
/// Our GTK area /// Our GTK area
gl_area: *c.GtkGLArea, gl_area: *c.GtkGLArea,
@ -154,6 +161,7 @@ pub fn init(self: *Surface, app: *App, opts: Options) !void {
self.* = .{ self.* = .{
.app = app, .app = app,
.window = opts.window, .window = opts.window,
.parent = Parent.none,
.gl_area = opts.gl_area, .gl_area = opts.gl_area,
.title = if (opts.title_label) |label| .{ .title = if (opts.title_label) |label| .{
.label = label, .label = label,

View File

@ -9,6 +9,10 @@ const Surface = @import("Surface.zig");
const Window = @import("Window.zig"); const Window = @import("Window.zig");
const c = @import("c.zig"); const c = @import("c.zig");
const log = std.log.scoped(.gtk);
const GHOSTTY_TAB = "ghostty_tab";
const Child = union(enum) { const Child = union(enum) {
surface: *Surface, surface: *Surface,
paned: *Paned, paned: *Paned,
@ -30,7 +34,7 @@ focus_child: *Surface,
pub fn create(alloc: Allocator, window: *Window, parent_: ?*CoreSurface) !*Tab { pub fn create(alloc: Allocator, window: *Window, parent_: ?*CoreSurface) !*Tab {
var tab = try alloc.create(Tab); var tab = try alloc.create(Tab);
errdefer alloc.destroy(tab); errdefer alloc.destroy(tab);
try tab.init(window, _parent); try tab.init(window, parent_);
} }
pub fn init(self: *Tab, window: *Window, parent_: ?*CoreSurface) !void { pub fn init(self: *Tab, window: *Window, parent_: ?*CoreSurface) !void {
@ -80,7 +84,7 @@ pub fn init(self: *Tab, window: *Window, parent_: ?*CoreSurface) !void {
const box_widget = c.gtk_box_new(c.GTK_ORIENTATION_VERTICAL, 0); const box_widget = c.gtk_box_new(c.GTK_ORIENTATION_VERTICAL, 0);
c.gtk_widget_set_hexpand(box_widget, 1); c.gtk_widget_set_hexpand(box_widget, 1);
c.gtk_widget_set_vexpand(box_widget, 1); c.gtk_widget_set_vexpand(box_widget, 1);
self.box = ptrCast(box_widget); self.box = @ptrCast(box_widget);
// Initialize the GtkGLArea and attach it to our surface. // Initialize the GtkGLArea and attach it to our surface.
// The surface starts in the "unrealized" state because we have to // The surface starts in the "unrealized" state because we have to
@ -114,7 +118,7 @@ pub fn init(self: *Tab, window: *Window, parent_: ?*CoreSurface) !void {
} }
// Set the userdata of the close button so it points to this page. // Set the userdata of the close button so it points to this page.
c.g_object_set_data(@ptrCast(box), GHOSTTY_TAB, self); c.g_object_set_data(@ptrCast(box_widget), GHOSTTY_TAB, self);
// Switch to the new tab // Switch to the new tab
c.gtk_notebook_set_current_page(self.notebook, page_idx); c.gtk_notebook_set_current_page(self.notebook, page_idx);
@ -123,3 +127,8 @@ pub fn init(self: *Tab, window: *Window, parent_: ?*CoreSurface) !void {
// creating a window we want to always focus on the widget. // creating a window we want to always focus on the widget.
_ = c.gtk_widget_grab_focus(box_widget); _ = c.gtk_widget_grab_focus(box_widget);
} }
fn gtkTabCloseClick(_: *c.GtkButton, ud: ?*anyopaque) callconv(.C) void {
_ = ud;
// todo
}

16
src/apprt/gtk/parent.zig Normal file
View File

@ -0,0 +1,16 @@
const Paned = @import("Paned.zig");
const Tab = @import("Tab.zig");
pub const Position = enum {
start,
end,
};
pub const Parent = union(enum) {
none: void,
tab: *Tab,
paned: struct {
*Paned,
Position,
},
};