This allows ctrl-click on a type in a build-picker window to remember it
as a favourite. An new filter button to show only favourites makes it
simpler to use these types.
Favourite types are saved locally in favs.cfg, so are remembered between
games.
This filters the build-picker type lists to only show types that have
already been placed in the current game, making it simpler to get to
build matching features.
These windows now share a common code base for choosing and display class and types.
An additional text filter is added to search types by name instead of just classes.
After sorting and filter lists for GUI, we often shirnk them to reduce size. However this has very little benefit:
1) The memory has already been allocated, so it doesn't prevent that memory being required.
2) It causes a new allocation and copy when the vector is shrunk, actually using more memory.
3) The list is in window state, so the lifetime is only while the window is open.
4) When a filter is clearer, the original size will be needed again, which will cause another allocation.
In fact it is beneficial to reserve to the known maximum in most cases, so do that instead.
GUIList has a pointer only to the start of each sort/filter func list, which has the potential for UB as it is unable to validate that the selected sort or filter type is in range.
Use a std::span instead and check if the selected type is in range before using it.
NWidgetMatrix modifies its child widget's index to indicate which element
is to be drawn, which now causes issues with code that does not know about
stuffing extra data into the index.
Instead, let NWidgetMatrix store the currently processing element, and
retrieve this information from the matrix widget while child widgets are
being drawn.
This means only widgets that are children of NWidgetMatrix need to know
anything about their extra data.
This simplifies processing nwidget parts as, unlike the remaining length, the pointer to the end of the list never changes. This is the same principle as we use(d) for tracking end instead of length for C-style strings.
And this removes 160~ instances of the lengthof() macro.
Hotkeys are now initialized inline, and use std::vector instead of
separate static C-arrays and std::string instead of char *. The list end
marker is no longer required.
In many instances the clicked row position is 'manually' calculated
instead of using the GetScrolledRowFromWidget helper function, with
variations on checks. Replace with the two helpers where possible.
* Fix: Scale object gui margin by interface scale.
* Fix: Improve padding on object info text.
* Fix#10021: Resizing for 1/2/4 object views didn't account for interface scale.
As halving and doubling padding is problematic due to rounding, it is now
added on lower view counts instead of removing on higher view counts.