randrew / layout Goto Github PK
View Code? Open in Web Editor NEWSingle-file library for calculating 2D UI layouts using stacking boxes. Compiles as C99 or C++.
License: Other
Single-file library for calculating 2D UI layouts using stacking boxes. Compiles as C99 or C++.
License: Other
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.
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)
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;
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.
While reading through your code, I found something that may be an error.
Lines 783 to 784 in b0c0282
From your comment, here should be pchild->margins[dim] + rect[2 + dim] + pchild->margins[wdim]
?
Also, about the layout algorithm itself, margins are not allowed to overlap with other margins. Did I understand it correctly?
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οΌ
Hi! As a little weekend project, I've ported Layout to C#/.Net. π
Figured I'd make an issue and let anyone who may be looking for something like this know.
You can find the code here: https://github.com/codecat/Nimble.Layout
(The performance isn't as good as I want it to be, but it's at least functional and passes all tests.)
Of course, huge thanks to @randrew for this super solid library. I'm using it in a lot of different projects at this point! π
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.
We should have the ability to do this.
I would think what might sometimes be good to have is the mode for preset (fixed) item ID numbers, you will specify how many they are and then you will call the function to allocate that many, instead of calling lay_item
for each one.
This could be done to check first if ctx->count
is zero; if not, then it is an error, but if it is zero then it will set its capacity and count to the specified number, allocate them, and then initialize each item in a loop, similarly than lay_item
already does.
(My own "smallxrm" library, which is an implementation of the X resource manager, has a xrm_init_quarks
function with a similar use. You will allocate many items with fixed preset ID numbers from the beginning, which can be compile-time constants, rather than having to pass strings always or allocating them and assigning them to variables. (You can still add additional quarks afterward which do not have fixed numbers.))
how do i remove an item without having to rebuild the entire context list?
how can custom layouts be achieved?
for example, a grid with AxB columns/rows
or a LinearLayout https://developer.android.com/guide/topics/ui/layout/linear.html
or even ConstraintLayout https://developer.android.com/develop/ui/views/layout/constraint-layout
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.
We should use a separate mutable break flag bit instead of re-purposing the input flag bit.
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)
Is there a way to mark a node such that it will fill the available space while keeping its original aspect ratio?
While using layout library in my project I've come across somewhat unexpected layouting behaviour.
Minimal reproducible example follows:
Equivalent code:
lay_id root = lay_item(ctx);
lay_set_size_xy(ctx, root, 1, 100);
lay_id row = lay_item(ctx);
lay_set_contain(ctx, row, LAY_ROW);
lay_insert(ctx, root, row);
lay_id child = lay_item(ctx);
lay_set_size_xy(ctx, child, 1, 50);
lay_set_margins_ltrb(ctx, child, 0, 0, 0, 10);
lay_insert(ctx, row, child);
In a case like that I would expect the following
It can be validated by a test:
lay_run_context(ctx);
lay_vec4 root_rect = lay_get_rect(ctx, root);
lay_vec4 row_rect = lay_get_rect(ctx, row);
lay_vec4 child_rect = lay_get_rect(ctx, child);
LTEST_VEC4EQ(root_rect, 0, 0, 1, 100);
LTEST_VEC4EQ(row_rect, 0, 20, 1, 60);
LTEST_VEC4EQ(child_rect, 0, 20, 1, 50);
It is consistent with like other layout engines implement margins (like yoga layout or flexboxes in basically all modern browsers).
However, in current version of the library:
From my understanding, the culprit is the lay_arrange_overlay_squeezed_range
function, specifically line 1104:
// in LAY_HCENTER case
rect[dim] += (space - rect[2 + dim]) / 2 - margins[wdim];
The following change seems to be fixing the problem, and doesn't break any of the tests
--- a/layout.h
+++ b/layout.h
@@ -1101,7 +1101,7 @@ void lay_arrange_overlay_squeezed_range(
switch (b_flags & LAY_HFILL) {
case LAY_HCENTER:
rect[2 + dim] = lay_scalar_min(rect[2 + dim], min_size);
- rect[dim] += (space - rect[2 + dim]) / 2 - margins[wdim];
+ rect[dim] += (space - rect[2 + dim] - margins[wdim]) / 2;
break;
case LAY_RIGHT:
rect[2 + dim] = lay_scalar_min(rect[2 + dim], min_size);
Before submitting an actual pull request I would like to ask:
A declarative, efficient, and flexible JavaScript library for building user interfaces.
π Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. πππ
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google β€οΈ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.