textadept icon indicating copy to clipboard operation
textadept copied to clipboard

Add ability to resize individual views from Lua and add an event for view resizing.

Open Fwirt opened this issue 3 weeks ago • 11 comments

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.

Fwirt avatar Dec 02 '25 10:12 Fwirt