Nuklear
This is a minimal-state, immediate-mode graphical user interface toolkit written in ANSI C and licensed under public domain. It was designed as a simple embeddable user interface for application and does not have any dependencies, a default render backend or OS window/input handling but instead provides a highly modular, library-based approach, with simple input state for input and draw commands describing primitive shapes as output. So instead of providing a layered library that tries to abstract over a number of platform and render backends, it focuses only on the actual UI.
 
Loading...
Searching...
No Matches
Layouting

Layouting in general describes placing widget inside a window with position and size.

While in this particular implementation there are five different APIs for layouting each with different trade offs between control and ease of use.

All layouting methods in this library are based around the concept of a row. A row has a height the window content grows by and a number of columns and each layouting method specifies how each widget is placed inside the row. After a row has been allocated by calling a layouting functions and then filled with widgets will advance an internal pointer over the allocated row.

To actually define a layout you just call the appropriate layouting function and each subsequent widget call will place the widget as specified. Important here is that if you define more widgets then columns defined inside the layout functions it will allocate the next row without you having to make another layouting

call.

Biggest limitation with using all these APIs outside the nk_layout_space_xxx API is that you have to define the row height for each. However the row height often depends on the height of the font.

To fix that internally nuklear uses a minimum row height that is set to the height plus padding of currently active font and overwrites the row height value if zero.

If you manually want to change the minimum row height then use nk_layout_set_min_row_height, and use nk_layout_reset_min_row_height to reset it back to be derived from font height.

Also if you change the font in nuklear it will automatically change the minimum row height for you and. This means if you change the font but still want a minimum row height smaller than the font you have to repush your value.

For actually more advanced UI I would even recommend using the nk_layout_space_xxx layouting method in combination with a cassowary constraint solver (there are some versions on github with permissive license model) to take over all control over widget layouting yourself. However for quick and dirty layouting using all the other layouting functions should be fine.

Usage

  1. nk_layout_row_dynamic

    The easiest layouting function is nk_layout_row_dynamic. It provides each widgets with same horizontal space inside the row and dynamically grows if the owning window grows in width. So the number of columns dictates the size of each widget dynamically by formula:

    c widget_width = (window_width - padding - spacing) * (1/column_count)

    Just like all other layouting APIs if you define more widget than columns this library will allocate a new row and keep all layouting parameters previously defined.

    c if (nk_begin_xxx(...) { // first row with height: 30 composed of two widgets nk_layout_row_dynamic(&ctx, 30, 2); nk_widget(...); nk_widget(...); // // second row with same parameter as defined above nk_widget(...); nk_widget(...); // // third row uses 0 for height which will use auto layouting nk_layout_row_dynamic(&ctx, 0, 2); nk_widget(...); nk_widget(...); } nk_end(...);

  2. nk_layout_row_static

    Another easy layouting function is nk_layout_row_static. It provides each widget with same horizontal pixel width inside the row and does not grow if the owning window scales smaller or bigger.

    c if (nk_begin_xxx(...) { // first row with height: 30 composed of two widgets with width: 80 nk_layout_row_static(&ctx, 30, 80, 2); nk_widget(...); nk_widget(...); // // second row with same parameter as defined above nk_widget(...); nk_widget(...); // // third row uses 0 for height which will use auto layouting nk_layout_row_static(&ctx, 0, 80, 2); nk_widget(...); nk_widget(...); } nk_end(...);

  3. nk_layout_row_xxx

    A little bit more advanced layouting API are functions nk_layout_row_begin, nk_layout_row_push and nk_layout_row_end. They allow to directly specify each column pixel or window ratio in a row. It supports either directly setting per column pixel width or widget window ratio but not both. Furthermore it is a immediate mode API so each value is directly pushed before calling a widget. Therefore the layout is not automatically repeating like the last two layouting functions.

    c if (nk_begin_xxx(...) { // first row with height: 25 composed of two widgets with width 60 and 40 nk_layout_row_begin(ctx, NK_STATIC, 25, 2); nk_layout_row_push(ctx, 60); nk_widget(...); nk_layout_row_push(ctx, 40); nk_widget(...); nk_layout_row_end(ctx); // // second row with height: 25 composed of two widgets with window ratio 0.25 and 0.75 nk_layout_row_begin(ctx, NK_DYNAMIC, 25, 2); nk_layout_row_push(ctx, 0.25f); nk_widget(...); nk_layout_row_push(ctx, 0.75f); nk_widget(...); nk_layout_row_end(ctx); // // third row with auto generated height: composed of two widgets with window ratio 0.25 and 0.75 nk_layout_row_begin(ctx, NK_DYNAMIC, 0, 2); nk_layout_row_push(ctx, 0.25f); nk_widget(...); nk_layout_row_push(ctx, 0.75f); nk_widget(...); nk_layout_row_end(ctx); } nk_end(...);

  4. nk_layout_row

    The array counterpart to API nk_layout_row_xxx is the single nk_layout_row functions. Instead of pushing either pixel or window ratio for every widget it allows to define it by array. The trade of for less control is that nk_layout_row is automatically repeating. Otherwise the behavior is the same.

    c if (nk_begin_xxx(...) { // two rows with height: 30 composed of two widgets with width 60 and 40 const float ratio[] = {60,40}; nk_layout_row(ctx, NK_STATIC, 30, 2, ratio); nk_widget(...); nk_widget(...); nk_widget(...); nk_widget(...); // // two rows with height: 30 composed of two widgets with window ratio 0.25 and 0.75 const float ratio[] = {0.25, 0.75}; nk_layout_row(ctx, NK_DYNAMIC, 30, 2, ratio); nk_widget(...); nk_widget(...); nk_widget(...); nk_widget(...); // // two rows with auto generated height composed of two widgets with window ratio 0.25 and 0.75 const float ratio[] = {0.25, 0.75}; nk_layout_row(ctx, NK_DYNAMIC, 30, 2, ratio); nk_widget(...); nk_widget(...); nk_widget(...); nk_widget(...); } nk_end(...);

  5. nk_layout_row_template_xxx

    The most complex and second most flexible API is a simplified flexbox version without line wrapping and weights for dynamic widgets. It is an immediate mode API but unlike nk_layout_row_xxx it has auto repeat behavior and needs to be called before calling the templated widgets. The row template layout has three different per widget size specifier. The first one is the nk_layout_row_template_push_static with fixed widget pixel width. They do not grow if the row grows and will always stay the same. The second size specifier is nk_layout_row_template_push_variable which defines a minimum widget size but it also can grow if more space is available not taken by other widgets. Finally there are dynamic widgets with nk_layout_row_template_push_dynamic which are completely flexible and unlike variable widgets can even shrink to zero if not enough space is provided.

    c if (nk_begin_xxx(...) { // two rows with height: 30 composed of three widgets nk_layout_row_template_begin(ctx, 30); nk_layout_row_template_push_dynamic(ctx); nk_layout_row_template_push_variable(ctx, 80); nk_layout_row_template_push_static(ctx, 80); nk_layout_row_template_end(ctx); // // first row nk_widget(...); // dynamic widget can go to zero if not enough space nk_widget(...); // variable widget with min 80 pixel but can grow bigger if enough space nk_widget(...); // static widget with fixed 80 pixel width // // second row same layout nk_widget(...); nk_widget(...); nk_widget(...); } nk_end(...);

  6. nk_layout_space_xxx

    Finally the most flexible API directly allows you to place widgets inside the window. The space layout API is an immediate mode API which does not support row auto repeat and directly sets position and size of a widget. Position and size hereby can be either specified as ratio of allocated space or allocated space local position and pixel size. Since this API is quite powerful there are a number of utility functions to get the available space and convert between local allocated space and screen space.

    c if (nk_begin_xxx(...) { // static row with height: 500 (you can set column count to INT_MAX if you don't want to be bothered) nk_layout_space_begin(ctx, NK_STATIC, 500, INT_MAX); nk_layout_space_push(ctx, nk_rect(0,0,150,200)); nk_widget(...); nk_layout_space_push(ctx, nk_rect(200,200,100,200)); nk_widget(...); nk_layout_space_end(ctx); // // dynamic row with height: 500 (you can set column count to INT_MAX if you don't want to be bothered) nk_layout_space_begin(ctx, NK_DYNAMIC, 500, INT_MAX); nk_layout_space_push(ctx, nk_rect(0.5,0.5,0.1,0.1)); nk_widget(...); nk_layout_space_push(ctx, nk_rect(0.7,0.6,0.1,0.1)); nk_widget(...); } nk_end(...);

Reference

Function Description
nk_layout_set_min_row_height Set the currently used minimum row height to a specified value
nk_layout_reset_min_row_height Resets the currently used minimum row height to font height
nk_layout_widget_bounds Calculates current width a static layout row can fit inside a window
nk_layout_ratio_from_pixel Utility functions to calculate window ratio from pixel size
nk_layout_row_dynamic Current layout is divided into n same sized growing columns
nk_layout_row_static Current layout is divided into n same fixed sized columns
nk_layout_row_begin Starts a new row with given height and number of columns
nk_layout_row_push Pushes another column with given size or window ratio
nk_layout_row_end Finished previously started row
nk_layout_row Specifies row columns in array as either window ratio or size
nk_layout_row_template_begin Begins the row template declaration
nk_layout_row_template_push_dynamic Adds a dynamic column that dynamically grows and can go to zero if not enough space
nk_layout_row_template_push_variable Adds a variable column that dynamically grows but does not shrink below specified pixel width
nk_layout_row_template_push_static Adds a static column that does not grow and will always have the same size
nk_layout_row_template_end Marks the end of the row template
nk_layout_space_begin Begins a new layouting space that allows to specify each widgets position and size
nk_layout_space_push Pushes position and size of the next widget in own coordinate space either as pixel or ratio
nk_layout_space_end Marks the end of the layouting space
nk_layout_space_bounds Callable after nk_layout_space_begin and returns total space allocated
nk_layout_space_to_screen Converts vector from nk_layout_space coordinate space into screen space
nk_layout_space_to_local Converts vector from screen space into nk_layout_space coordinates
nk_layout_space_rect_to_screen Converts rectangle from nk_layout_space coordinate space into screen space
nk_layout_space_rect_to_local Converts rectangle from screen space into nk_layout_space coordinates