libglui / glui

GLUI is a GLUT-based C++ user interface library which provides controls such as buttons, checkboxes, radio buttons, and spinners to OpenGL applications. It is window-system independent, using GLUT or FreeGLUT.
Other
194 stars 82 forks source link

Extension: User layout control feature (PX?) #104

Open m-7761 opened 5 years ago

m-7761 commented 5 years ago

In addition to #101 Since I've cleaned up the layout engine I've turned to thinking how it can be more flexible, without being complicated. I'm actually very interested in systems that are not everything-and-the-kitchen-sink design.

I'm going to apply this work to wxWidgets, but I think I don't intend to use its layout engine at all when doing so. That means I will be using what I can come up with for GLUI. (I'm considering making a GLUI standard project that isn't GLUI but is a portable standard for UI configuration. I would call it GLUI Library User Interface if so. It woudn't describe the implementation details, but just the code used to construct the UI and then the rest is just implementation-defined. If your callbacks don't depend on the implementation that is enough. Or enough to implement your algorithms with some nonportable prolog/epilog code.)

Without further adieu I call this system PX that is short for pixel (px) or packing-extension system, or something like that.

It is simple. In GLUI the margin members are not really under the user's control. Although I think x_off so far is. I've modified this some by guaranteeing that Panel::NONE is under user control; or the derived class's control. By default it adds no padding around itself. This lets it be used to extend the layout by dropping in a shrink-wrapped column-based group. It effectively makes it another meta layout tool like Column.

The trouble with this is you quickly run into ITEMSPACING that is a metric set to 3. This is the built-in vertical spacing. When you start dropping unrelated controls in without the extra padding from panels the resulting horizontal rules are using 2px or 3px top. They are 2px because the controls typically draw on 1px wider/taller than their width.

I don't really want to change this. The new Rollout look I've developed actually works really well with this spacing, because it fills it in, so that back-to-back rollouts look like logical totem-poles.

I'm also not a big fan of putting spacing around buttons. Later versions of Windows shrunk the buttons so that side-by-side buttons have spacing around them under the later themes. GLUI's buttons have 2px spacing.

The "PX" system adds a user_px pointer to controls that's type is signed char. It could be char.

That's all there is to it. It can be a string or a pointer to 4 margins. Only values between 31 and -31 are margins. Recognized strings are "fixed", "space" and "block". The first disables the layout engine. That gives you a traditional Win32 style system. The second is the current system. The last (block) is to pack the controls together compactly, like a group of buttons with no space in between them.

If margins are provided they imply/augment the "space" system. With user-margins you can make micro-adjustments, or add padding. Negative margins reduce space between elements.

If the string is not margins, then it can be passed through a callback system to let the user do something custom based on its contents. Margins can have a user-note tacked on the end so you can find out what the margins are designed to do.

By using a pointer it works more like a "style" system. So a user sets up margins for certain purposes, and assigns them to multiple elements that way. End-users can get in on the action too if something about their software doesn't suit them. Being 32-bits or pointers they can be easily added to a lookup table to keep track of. They are transparent to the UI since they are only for the user system's use. 32-bit values can be encoded as numbers in a serialization system.

I've added an x_border member that adds to the x_off value on the sides. It makes the panels more spacious without making the columns wider. It's how the NONE system is able to work with the Panel element. It is equal to -x_off so that it cancels it out. These four margins could also be stored in char values for space, but that's not a large concern, nor why I chose signed char for margins. That has to do with being able to use strings also, so it can be more flexible and easier to trace the source of user margins.

I don't know if the Column element is necessary. What it does is pretty complicated. I've changed it to store both left and right margins in addition to its own width... which is the width of the column and not the divider graphic. I still think that the get_column_dims method could simply accumulate widths, and so not require objects to be added to the graph just to use a horizontal layout. I've simplified get_column_dims to just two values. (Both horizontal. It the other 4 values were trivial/unused.) I don't know if the same can be said for the invisible Panel. HTML defaults to inline layout.

Unrelated: I've added a backward ALIGN_BUDDY mode for the Spinner control to change how it works. It's a weird one though because a spinner is usually embedded in a text control, but how GLUI works is for the spinner to own its text box. That means the user (code) interacts with the spinner instead. It's an arrangement where the spinner is a child of the text box (now) but the text box isn't a container control. I'm thinking about adding a similar feature for scrollbars so that they will be embedded in their control's frame. In that case they wouldn't use the "BUDDY" mode. How it works is the text box draws its alignment from the spinner's, and the spinner assumes right-alignment inside the text box.

I've also worked on expanding rollouts for subwindows... not columns. It would probably be better expressed with an "ALIGN_EXPAND" mode that would fill in the space afforded by a column. When the rollout expands its contents can look funny afterward. So I worked on a system that basically centers the contents, but as-if the container is only as wide as it would be if not expanded. If the contents don't fit into this model then the rollout contents are realigned to make use of the newly available width. I'm thinking about extending panels vertically to fill in the bottom of their columns up to a limit. Little, intelligent embellishments like this can go a long way to making an automatically generated layout look like it was designed by hand.