Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature Request] Seed id hash with parent's id #26

Open
bullno1 opened this issue Sep 24, 2024 · 4 comments
Open

[Feature Request] Seed id hash with parent's id #26

bullno1 opened this issue Sep 24, 2024 · 4 comments
Assignees
Labels
Complete - Needs Documentation The issue or feature has been addressed but documentation still needs to be updated.

Comments

@bullno1
Copy link
Contributor

bullno1 commented Sep 24, 2024

Currently, element id needs to be globally unique.
Copy&paste or refactoring reusable components into functions would be a bit of a pain since you'd need to parameterize all the ids.

What if the id only has to be unique among siblings?
Clay__Rehash already exists but it is only used for debugger.
The fact that it exists mean that kind of id is useful.

CLAY_ID_AUTO on the other hand, does not allow providing a string and counter which are needed to identify elements independent of orders.
e.g: In a list of items.

There are 2 ways of doing this:

  • Make CLAY_ID and CLAY_IDI context-dependent.
    This might break some existing code.

    Floating attachment may be a bit harder but there are workarounds like saving the id into a variable first.

  • Alternatively, provide CLAY_LOCAL_ID and CLAY_LOCAL_IDI which takes the parent id as seed.
    Alternate names:

    • CLAY_CTX_ID[I]: context dependent id
    • CLAY_SCOPED_ID[I]

I can make PR for either of these.

@nicbarker
Copy link
Owner

Hello! Firstly, I completely agree with your assertion that we need a local context-aware way to auto generate IDs. At present it's quite painful to have to uniquely everything in the hierarchy, even for immediate mode renderers where it's almost entirely unnecessary. I'll merge your PR in the short term to address that particular problem.

Secondly given that you've dug in here already, I'd like to get your opinion on an API change I'm working on at the moment. It replaces all the type-specific element macros with a single generic CLAY() macro, and allows you to configure this element by attaching whichever configs you want:

carbon(88)

I specifically started this change to address the painful ergonomics of working on an interface where most elements needed a border and a rectangle.

The main idea is that in the new api, all configs are optional, including ID and Layout, e.g:

// Create an empty layout element with no children and the default layout config
CLAY()

// Create a scrolling element with a border and background
CLAY(CLAY_SCROLL(...etc), CLAY_BORDER(...etc), CLAY_RECTANGLE(...etc)) {
    // ...children
}

// Tag a rectangle with a specific ID for mouse interactions, etc
CLAY(CLAY_ID("Button"), CLAY_RECTANGLE(...etc)) {
    // ...children
}

With the refactor being relevant to this situation because I'm planning to attach generated ids to each element if the user chooses not to provide one. It makes sense for the auto generated ID to be derived from the parent ID, and positional based on the sibling index.

@nicbarker
Copy link
Owner

This was addressed in #27 but I will leave it open until I've updated the README to include documentation of the new feature.

@nicbarker nicbarker added the Complete - Needs Documentation The issue or feature has been addressed but documentation still needs to be updated. label Sep 25, 2024
@bullno1
Copy link
Contributor Author

bullno1 commented Sep 25, 2024

It replaces all the type-specific element macros with a single generic CLAY() macro, and allows you to configure this element by attaching whichever configs you want

Since the user can pick a combination of features, how about having just one type: Clay_Element?
Then features can be turned on by initializing it.

CLAY(
    CLAY_SCROLL(...), // Enable scrolls
    CLAY_BORDER(...), // Enable border
) {
}

The API is essentially the same but the implementation is different.
There is only Clay_Element.
The renderer just have to check whether a feature is enabled like:

if (cmd.has_border) {
    // draw border
}

if (cmd.has_background) {
    // draw solid background
}

The macro CLAY_SCROLL(...) for example expands to something like: .scroll = { .enabled = true, __VA_ARGS__}.
With 0 initialization by default, if a feature is not included, it will be disabled.

There would be fewer elements to name or inspect.

Maybe scroll is somewhat special but image, rect, border and (plain) container are just decorations and styles.

Another radical idea about id: Given that local id seems to be more prevalent, how about make it the default (CLAY_ID is local)? And have CLAY_ID_GLOBAL to create global id instead?

@nicbarker
Copy link
Owner

nicbarker commented Sep 25, 2024

Yep, you're describing pretty much my exact line of thinking - a single macro that can be configured with whichever features. There is a little internal work to do to support this but it shouldn't take too long.

Another radical idea about id: Given that local id seems to be more prevalent, how about make it the default (CLAY_ID is local)? And have CLAY_ID_GLOBAL to create global id instead?

Yes, I'm very much thinking along the same lines. I want it to be obvious when an element is tagged with a global ID for a reason - it's used for click handling etc.

I actually would prefer if the IDs were local internally, but mostly auto generated. e.g. if you don't specify an ID at all:

CLAY_ELEMENT(CLAY_SCROLL(), CLAY_RECTANGLE()) { // Automatically assigned CLAY_ID_LOCAL("0")
    CLAY_ELEMENT() // Automatically assigned CLAY_ID_LOCAL("0")
    CLAY_ELEMENT() // Automatically assigned CLAY_ID_LOCAL("1")
    CLAY_ELEMENT() // Automatically assigned CLAY_ID_LOCAL("2")
    CLAY_ELEMENT() // Automatically assigned CLAY_ID_LOCAL("3")
    CLAY_ELEMENT(CLAY_TAG("ClickableButton")) {} // ID is already specified with a global so no local ID is attached
}

This way IDs would be internally be represented by trees of parent -> sibling index, i.e. a local id might end up being equivalent to CLAY_ID("0214"), which would mean 0th sibling -> children(2nd sibling) -> children(1st sibling) -> children(4th sibling)

@nicbarker nicbarker self-assigned this Sep 28, 2024
@nicbarker nicbarker changed the title Seed id hash with parent's id [Feature Request] Seed id hash with parent's id Sep 29, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Complete - Needs Documentation The issue or feature has been addressed but documentation still needs to be updated.
Projects
None yet
Development

No branches or pull requests

2 participants