Skip to content

Conversation

@Fwirt
Copy link

@Fwirt Fwirt commented Dec 2, 2025

I had mentioned my intention to write this in the comments on #649, but it ended up being a lot more than the 20 LoC I had projected. I wanted to get this out there before 13 hits release since it seems like something that would be included in a major release. Since @orbitalquark likes to merge changes manually I wrote this so that it wouldn't touch or break any existing functionality, but I suspect in the future it may benefit from being combined with the existing view.size attribute or reimplemented in some other way.

This code extends the view metatable so that Lua code can now reference view.width and view.height to get the dimensions of any Scintilla view, or assign an integer value to view.width and view.height to set the size of any Scintilla view by adjusting the parent splits. These attributes will not resize the window and will raise an error if the resize cannot be completed due to insufficient splits.

It also adds a "resize" event that is emitted when GTK or Qt trigger a widget resize event for a Scintilla view. This can be connected to for the purpose of e.g. "pinning" a split view to a given size so that it doesn't grow when the window is resized or maximized, or for dynamically adjusting tab stops (currently unused function add_tab_stop) to center align or right align text in a buffer.

I can confirm that the changes are tested and working for Qt and curses, but I am unable to build the GTK version on MacOS again, this time due to it complaining about gtk-quartz-2.0 missing (which it isn't). I didn't want to spend time fiddling with CMake again so if someone wants to test the GTK build that would be great.

A snippet to see what the use of this is:

-- Create a single line view below the current one
view.split()
ui.goto_view(-1)
view.h_scroll_bar = false
view.height = view:text_height(1)

-- Add an event handler to "pin" the view to a given size
single_line_view = view
pin_height = view.height
function pin_size(view)
  if (view == single_line_view and view.height ~= pin_height) then
    view.height = pin_height
  end
end
events.connect("resize", pin_size)
-- try resizing the window after this

This is obviously less "correct" than setting a maximum size for the widget in the toolkit but it's more generalizable. You could also use it to do things like update font size based on view width. I actually think that since this implements the general case, it may be possible to eliminate the platform specific command entry handling, since the command entry view is just a Scintilla widget with a label pinned to the front. Just swap the label out for some margin text with the proper styling and it would be visually indistinguishable from what we have now, and you could probably move the focus handling and resizing over to the Lua side of the house so you wouldn't have to maintain separate logic for each platform.

Note that if you run the above snippet, there is some odd behavior (at least with Qt) where if you drag the split handle it will still move, even though the view stays the correct size. If you resize the window or any other splits it will snap back to the correct position. There is probably some update method that needs to be called at the end of set_view_dimension to notify the split to snap its handle to the correct position, but I'm not sure what that would be. It could be some kind of race condition.

Collin Skiles and others added 2 commits December 2, 2025 01:47
Previously it was not possible to set the size of a view that was the
second child of a split to a fixed size because it was not possible
to know the size of its parent. This commit amends the view metatable
to allow Lua to get and set the size of individual Scintilla widgets.
It also adds a "resize" event that is called whenever a Scintilla
widget changes sizes and passes a pointer to the associated view table
to the handler function. This allows Lua user scripts to "pin" a view
to a specific size regardless of window and parent split size changes
by defining a handler function that resets the size of a view on change.
@Fwirt Fwirt changed the title Enhance user code ability to resize views and add an event for view resizing. Enhance ability to resize views from Lua and add an event for view resizing. Dec 2, 2025
@Fwirt Fwirt changed the title Enhance ability to resize views from Lua and add an event for view resizing. Add ability to resize individual views from Lua and add an event for view resizing. Dec 2, 2025
@Fwirt
Copy link
Author

Fwirt commented Dec 2, 2025

I got the GTK build working on MacOS again (had to re-add the target_link_directories(textadept-gtk PRIVATE ${GTK_LIBRARY_DIRS}) directive so the linker would find gtk-quartz-2.0) so I could test it. It's working except for one small bug that I'm having trouble working around: the way that the GTK build handles the command window is to call gtk_widget_hide(command_entry_box), which interestingly makes it stop showing in the Hpaned widget, but does not move the split handle, so the sibling view thinks it's still there. That means that when you set view.height in the GTK build for the lower pane in the root pane, it still allocates space for a one-line command entry instead of taking up the whole window. After monkeying with this for a couple hours I think I've figured out that GTK allocations and panes work together differently than Qt QSplitters (in a worse way). GTK still "allocates" space for a box even when the pane is allowed to shrink and is shrunk down to the minimum size (and hidden). So getting the allocation of the top level pane still gets you a height that's one line short. To demonstrate the problem, try this:

keys['cmd+l'] = function ()
  ui.print(ui.command_entry.height)
end

And watch the output be a non-zero size even when the command entry is hidden. Even more strange, if you expand the command entry box before hiding it, the above print will show the expanded size even though focus_command_entry should set the size to 0 when it hides the box. So far I have tried setting the size request of all the widgets in the command entry box, and the box itself to be 0, I have tried removing the directive to hide the box (just in case for some reason that allowed the widgets to expand), I have changed the getters and setters for the command entry pane to reference the size of command_entry_box instead of command_entry, I've even tried manually setting the allocation for the box in set_command_entry_height, nothing is working to get GTK to shrink the allocation.

It occurs to me that since the view.width and view.height logic is working for views below the top one, refactoring the command window to be a standard view as I mentioned above would solve this issue. But maybe a more experienced set of eyes will figure out what I missed.

@orbitalquark
Copy link
Owner

Thanks for taking the time to put this together. I'll take a look when I have some time and get back to you.

@Fwirt
Copy link
Author

Fwirt commented Dec 3, 2025

Thanks. Right now I'm working on a couple Lua modules that demonstrate the usefulness of this functionality so it has a reason to exist (Scintilla statusbar, drop-in command entry replacement) but once I have a couple working PoCs I intend to circle back around to the UI quirks.

@Fwirt
Copy link
Author

Fwirt commented Dec 5, 2025

I just made a small revision to the way resize events are handled that I haven’t had time to test and commit yet, should be coming later today.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants