A simple/fast stacking box layout library. It's useful for calculating layouts for things like 2D user interfaces.

Overview

Layout

A simple/fast stacking box layout library. It's useful for calculating layouts for things like 2D user interfaces. It compiles as C99 or C++. It's tested with gcc (mingw64), VS2015, and clang/LLVM. You only need one file to use it in your own project: layout.h.

Use Layout in Your Project

To use Layout in your own project, copy layout.h into your project's source tree and define LAY_IMPLEMENTATION in exactly one .c or .cpp file that includes layout.h.

The includes in your one special file should look like this:

#include ...
#include ...
#define LAY_IMPLEMENTATION
#include "layout.h"

All other files in your project should not define LAY_IMPLEMENTATION, and can include layout.h like normal.

Requirements and Extras

Layout has no external dependencies, but by default it does use assert.h, stdlib.h and string.h for assert, realloc and memset. If your own project does not or cannot use these, you can easily exchange them for something else by using preprocessor definitions. See the section below about the available customizations.

Layout can be built as C99 or C++ if you are using GCC or Clang, but must be built as C++ if you are using MSVC. This requirement exists because the Layout implementation code uses the vector_size extension in GCC and Clang, which does not exist in MSVC. C++ operator overloading is used to simulate this feature in MSVC. The code generated by all three compilers is not too different -- the vector_size extension is used mostly to keep the syntax of the implementation easier to read.

Layout is based on the nice library oui by duangle. Unlike oui, Layout does not handle anything related to user input, focus, or UI state.

Building the tests and benchmarks is handled by the tool.bash script, or by GENie. See the section below about building the tests and benchmarks. There's also an example of using Layout as a Lua .dll module. However, you don't need any of that to use Layout in your own project.

Options

You can choose to build Layout to use either integer (int16) or floating point (float) coordinates. Integer is the default, because UI and other 2D layouts do not often use units smaller than a single point when aligning and positioning elements. You can choose to use floating point instead of integer by defining LAY_FLOAT.

  • LAY_FLOAT, when defined, will use float instead of int16 for coordinates.

In addition to the LAY_FLOAT preprocessor option, other behavior in Layout can be customized by setting preprocessor definitions. Default behavior will be used for undefined customizations.

  • LAY_ASSERT will replace the use of assert.h's assert

  • LAY_REALLOC will replace the use of stdlib.h's realloc

  • LAY_MEMSET will replace the use of string.h's memset

If you define LAY_REALLOC, you will also need to define LAY_FREE.

Example

// LAY_IMPLEMENTATION needs to be defined in exactly one .c or .cpp file that
// includes layout.h. All other files should not define it.

#define LAY_IMPLEMENTATION
#include "layout.h"

// Let's pretend we're creating some kind of GUI with a master list on the
// left, and the content view on the right.

// We first need one of these
lay_context ctx;

// And we need to initialize it
lay_init_context(&ctx);

// The context will automatically resize its heap buffer to grow as needed
// during use. But we can avoid multiple reallocations by reserving as much
// space as we'll need up-front. Don't worry, lay_init_context doesn't do any
// allocations, so this is our first and only alloc.
lay_reserve_items_capacity(&ctx, 1024);

// Create our root item. Items are just 2D boxes.
lay_id root = lay_item(&ctx);

// Let's pretend we have a window in our game or OS of some known dimension.
// We'll want to explicitly set our root item to be that size.
lay_set_size_xy(&ctx, root, 1280, 720);

// Set our root item to arrange its children in a row, left-to-right, in the
// order they are inserted.
lay_set_contain(&ctx, root, LAY_ROW);

// Create the item for our master list.
lay_id master_list = lay_item(&ctx);
lay_insert(&ctx, root, master_list);
// Our master list has a specific fixed width, but we want it to fill all
// available vertical space.
lay_set_size_xy(&ctx, master_list, 400, 0);
// We set our item's behavior within its parent to desire filling up available
// vertical space.
lay_set_behave(&ctx, master_list, LAY_VFILL);
// And we set it so that it will lay out its children in a column,
// top-to-bottom, in the order they are inserted.
lay_set_contain(&ctx, master_list, LAY_COLUMN);

lay_id content_view = lay_item(&ctx);
lay_insert(&ctx, root, content_view);
// The content view just wants to fill up all of the remaining space, so we
// don't need to set any size on it.
//
// We could just set LAY_FILL here instead of bitwise-or'ing LAY_HFILL and
// LAY_VFILL, but I want to demonstrate that this is how you combine flags.
lay_set_behave(&ctx, content_view, LAY_HFILL | LAY_VFILL);

// Normally at this point, we would probably want to create items for our
// master list and our content view and insert them. This is just a dumb fake
// example, so let's move on to finishing up.

// Run the context -- this does all of the actual calculations.
lay_run_context(&ctx);

// Now we can get the calculated size of our items as 2D rectangles. The four
// components of the vector represent x and y of the top left corner, and then
// the width and height.
lay_vec4 master_list_rect = lay_get_rect(&ctx, master_list);
lay_vec4 content_view_rect = lay_get_rect(&ctx, content_view);

// master_list_rect  == {  0, 0, 400, 720}
// content_view_rect == {400, 0, 880, 720}

// If we're using an immediate-mode graphics library, we could draw our boxes
// with it now.
my_ui_library_draw_box_x_y_width_height(
    master_list_rect[0],
    master_list_rect[1],
    master_list_rect[2],
    master_list_rect[3]);

// You could also recursively go through the entire item hierarchy using
// lay_first_child and lay_next_sibling, or something like that.

// After you've used lay_run_context, the results should remain valid unless a
// reallocation occurs.
//
// However, while it's true that you could manually update the existing items
// in the context by using lay_set_size{_xy}, and then calling lay_run_context
// again, you might want to consider just rebuilding everything from scratch
// every frame. This is a lot easier to program than tedious fine-grained
// invalidation, and a context with thousands of items will probably still only
// take a handful of microseconds.
//
// There's no way to remove items -- once you create them and insert them,
// that's it. If we want to reset our context so that we can rebuild our layout
// tree from scratch, we use lay_reset_context:

lay_reset_context(&ctx);

// And now we could start over with creating the root item, inserting more
// items, etc. The reason we don't create a new context from scratch is that we
// want to reuse the buffer that was already allocated.

// But let's pretend we're shutting down our program -- we need to destroy our
// context.
lay_destroy_context(&ctx);

// The heap-allocated buffer is now freed. The context is now invalid for use
// until lay_init_context is called on it again.

Building the Tests and Benchmarks

None of this is necessary to use in your own project. These directions are only for building the tests and benchmarks programs, which you probably don't care about.

If you have bash and are on a POSIX system, you can use the tool.bash script to build Layout's standalone tests and benchmarks programs. Run tool.bash to see the options.

Using GENie

Instead of using the tool.bash script, you can use GENie to generate a Visual Studio project file, or any of the other project and build system output types it supports. The GENie generator also lets you build the example Lua module.

Directions for acquiring and using GENie

The genie.lua script is mostly tested on Windows, so if you use it on another platform, you might need to tweak it.

You will first need to get (or make) a GENie binary and place it in your path or at the root of this repository.

Download GENie

Linux:
https://github.com/bkaradzic/bx/raw/master/tools/bin/linux/genie

OSX:
https://github.com/bkaradzic/bx/raw/master/tools/bin/darwin/genie

Windows:
https://github.com/bkaradzic/bx/raw/master/tools/bin/windows/genie.exe

Visual Studio 2015/2017

genie.exe vs2015
start build/vs2015/layout.sln

Replace vs2015 with vs2017 if you want to use Visual Studio 2017.

GCC/MinGW/Clang

./genie gmake

and then run your make in the directory build/gmake. You will need to specify a target and config. Here is an example for building the tests target in Windows with the 64-bit release configuration using mingw64 in a bash-like shell (for example, git bash):

./genie.exe gmake && mingw32-make.exe -C build/gmake tests config=release64

If you want to use float coordinates instead of integer, you can use an option in the build script which will define LAY_FLOAT for you:

./genie gmake --coords=float

or if you want to specify integer (the default):

./genie gmake --coords=integer
Issues
  • LAY_RIGHT position doesn't add left margins

    LAY_RIGHT position doesn't add left margins

    When using LAY_BOTTOM or LAY_RIGHT anchors for an item's behavior, it doens't subtract the "left" margin, leaving you with an invalid offset: (yellow rectangles are the margins)

    image

    Changing the code to the following fixes the problem:

    case LAY_RIGHT:
        child_rect[dim] += space - child_rect[2 + dim] - child_margins[wdim] - child_margins[dim];
        break;
    

    image

    This might possibly be an issue in lay_arrange_overlay_squeezed_range as well, but I have not tested it.

    I can do a pull request if you want.

    opened by codecat 12
  • help: how to deal with layout for lay_top or lay_down ?

    help: how to deal with layout for lay_top or lay_down ?

    this ui layout is very good,but I do not understand how tp deal with layout for lay_top or lay_down? I had read codes, do not found case lay_top: some code; break; case lay_down: some code; break; and so on I don't know if you can understand what I mean?

    opened by zhouxs1023 2
  • LAY_RESTRICT in g++

    LAY_RESTRICT in g++

    Layout defines it like this if __GNUC__ is defined:

    #define LAY_RESTRICT restrict
    

    However, this is not valid on g++. Changing this to __restrict makes it compile on g++ 6.3.0.

    opened by codecat 2
  • Help:how to understand this codes for LAY_HCENTER

    Help:how to understand this codes for LAY_HCENTER

    in layout.h 360-1642103179134111 in oui.h switch(flags & UI_HFILL) { case UI_HCENTER: { pkid->margins[dim] += (space-pkid->size[dim])/2 - pkid->margins[wdim]; } break; .............. }

    but I calculated pkid->margins[dim] by OUI.H code, but I found it was not in the middle.

    opened by zhouxs1023 1
  • Naming is dumb

    Naming is dumb

    Using names like lay_context_reset instead of lay_reset_context made sense when matching the style of the original project I wrote this for, but in hindsight it's pretty annoying. The functions will be renamed to lay_verb_noun where appropriate in an upcoming commit, and a regex to update existing code will be supplied.

    opened by randrew 0
  • Add tests for checking both C99 and C++ compilation in GCC/Clang automatically

    Add tests for checking both C99 and C++ compilation in GCC/Clang automatically

    The GENie file currently only builds as C99 for GCC and Clang by default. We should have some command we can run to test both C99 and C++ in one go, which should make it easier to catch incompatible differences (like the restrict/__restrict mistake)

    opened by randrew 0
  • Use pre/post condition checks before attempting to allocate

    Use pre/post condition checks before attempting to allocate

    I originally didn't expect to have so many users of layout, so I didn't put in security checks for overflows on the allocation math. I'll add some before too long.

    opened by randrew 0
Owner
Andrew Richards
Andrew Richards
A small C library for building user interfaces with C, XML and CSS

LCUI A small C library for building user interfaces with C, XML and CSS. Table of contents Table of contents Introduction Features Screenshots Related

Liu 3.8k Jun 27, 2022
Arcan is a powerful development framework for creating virtually anything from user interfaces

Arcan is a powerful development framework for creating virtually anything from user interfaces for specialized embedded applications all the way to full-blown standalone desktop environments.

Bjorn Stahl 1.1k Jun 20, 2022
GTK is a multi-platform toolkit for creating graphical user interfaces.

GTK — The GTK toolkit General information GTK is a multi-platform toolkit for creating graphical user interfaces. Offering a complete set of widgets,

GNOME Github Mirror 1k Jun 25, 2022
Taitank is a cross platform lightweight flex layout engine implemented in C++.

Taitank is a cross platform lightweight flex layout engine implemented in C++.

Tencent 414 Jun 16, 2022
lite android layout for chromium

layout lite android layout for chromium include linear layout and relative layout If you are familiar with android, it is easy to get started However,

null 1 Oct 15, 2021
Real-time GUI layout creator/editor for Dear ImGui

ImStudio Real-time GUI layout creator/editor for Dear ImGui Inspired by Code-Building/ImGuiBuilder Features Drag edit Property edit Covers most of the

null 215 Jun 19, 2022
Yoga is a cross-platform layout engine which implements Flexbox

Yoga Building Yoga builds with buck. Make sure you install buck before contributing to Yoga. Yoga's main implementation is in C++, with bindings to su

Meta 15.3k Jun 26, 2022
Nice things to use along dear imgui

Mini hexadecimal editor! Right-click for option menu. Features: Keyboard controls. Read-only mode. Optional Ascii display. Optional HexII display. Goto address. Highlight range/function. Read/Write handlers.

omar 617 Jun 24, 2022
ZIAPI repository which contains the interfaces and concrete implementations that make up our Epitech Zia project API proposal.

ZIAPI Welcome to the ZIAPI repository which contains the interfaces and concrete implementations that make up our Epitech Zia project API proposal. ZI

Martin Olivier 29 Mar 17, 2022
RmlUi - The HTML/CSS User Interface library evolved

RmlUi - The HTML/CSS User Interface Library Evolved RmlUi - now with added boosters taking control of the rocket, targeting your games and application

Michael R. P. Ragazzon 1.3k Jun 23, 2022
ImTui: Immediate Mode Text-based User Interface C++ Library

ImTui is an immediate mode text-based user interface library. Supports 256 ANSI colors and mouse/keyboard input.

Georgi Gerganov 1.9k Jun 24, 2022
GPU Accelerated C++ User Interface, with WYSIWYG developing tools, XML supports, built-in data binding and MVVM features.

GacUI GPU Accelerated C++ User Interface, with WYSIWYG developing tools, XML supports, built-in data binding and MVVM features. Read the LICENSE first

Vczh Libraries 2.1k Jun 21, 2022
Dear ImGui: Bloat-free Graphical User interface for C++ with minimal dependencies

Dear ImGui (This library is available under a free and permissive license, but needs financial support to sustain its continued improvements. In addit

omar 39.3k Jun 24, 2022
AirPods desktop user experience enhancement program

AirPodsDesktop AirPods desktop user experience enhancement program

Sprite 193 Jun 27, 2022
ROS_Melodic_Qt_GUI_Template is a Graphical User Interface programmed with Qt framework.

This is a GUI template for ros to control your robot and read data from sensors.

null 25 Jun 15, 2022
AnUI is a powerful Graphical User Interface framework made for people that actually care about design!

What's AuUI ** Project is not finished ** AuUI, an abbreviation for "Actual Understandable User Interface" is a graphical user interface framework to

Goat 4 Jun 17, 2022
This is a minimal state immediate mode graphical user interface toolkit written in ANSI C and licensed under public domain

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 and input handling but instead provides a very modular library approach by using simple input state for input and draw commands describing primitive shapes as output.

Micha Mettke 13.4k Jun 22, 2022
LicenseValidationDialog is a class designed to validate license keys on the user's side.

QT-LicenseValidationDialog Basic LicenseValidationDialog is a class designed to validate license keys on the user's side. The class is designed to ver

Piotr Napierała 1 Jun 10, 2022
WMBar is a window manager agnostic status bar that aims to be lightweight, simple, extensible/modular and fast.

WMBar is a window manager agnostic status bar that aims to be lightweight, simple, extensible/modular and fast.

WMBar 1 Nov 27, 2021