Skip to content
This repository has been archived by the owner on May 27, 2021. It is now read-only.

Access object field in a loop #87

Open
Namek opened this issue Aug 19, 2018 · 4 comments
Open

Access object field in a loop #87

Namek opened this issue Aug 19, 2018 · 4 comments

Comments

@Namek
Copy link

Namek commented Aug 19, 2018

Current state

I have a collection of objects, this is working:

@LmlAction("blocks")
public Array<Block> getBlocks() {
    return level.blocks;
}
<:foreach element="$blocks">
    <textbutton color="red">{element}</textbutton>
</:foreach>
public class Block {
    public boolean isWritten = false;

    @Override
    public String toString() {
        return isWritten ? "x" : " ";
    }
}

image

Goal

I'd like to colorize "x" blocks to red based on isWritten field.

Problem

Accessing the isWritten field is the unknown to me. How do I do that?

I thought about 2 ways:

  1. pass the element (or index) to a method to evaluate it
  2. access the field directly from the template which doesn't work for me:
<:foreach element="$blocks">
    <textbutton color="red">{element.isWritten}</textbutton>
</:foreach>
@czyzby
Copy link
Owner

czyzby commented Aug 19, 2018

Try using the condition syntax. It should work similarly to this:

<textbutton color="{? '{element}' = 'x' ? red : default}">{element}</textbutton>

You'd have to check if conditions support executing methods, but I'm positive that they just might.

@czyzby
Copy link
Owner

czyzby commented Aug 19, 2018

Also, loops support going through multiple collections at once. While it isn't an ideal solution, you can also do something like this:

// Java 8-ish pseudo-code:
@LmlAction("blocksWritten")
public Array<Boolean> getBlocksWrittenStatus() {
    return level.blocks.map(Block::isWritten);
}
<:foreach element="$blocks" isWritten="$blocksWritten">
    <textbutton color="{? {isWritten} ? red : white}">{element}</textbutton>
</:foreach>

@Namek
Copy link
Author

Namek commented Aug 19, 2018

Thank you for your kind response.

1. Workaround but not a solution

This 'x' comparison would be a workaround, I know that. But, there are going to be more booleans than just isWritten. So, neither is a solution for me.

2. Obfuscation?

I've seen between threads that obfuscation matters so Java things should be named with LmlAction annotation to be accessible from a template. However, actor macro doesn't seem to fit this rule:

  1. https://github.com/czyzby/gdx-lml/blob/master/examples/gdx-lml-tests/assets/templates/examples/actorMacro.lml
  2. https://github.com/czyzby/gdx-lml/blob/master/examples/gdx-lml-tests/core/src/main/java/com/github/czyzby/tests/reflected/MainView.java#L232

Thus, I think either the macro should be "fixed" (please don't) or field access from a template (stated in this thread) should be supported :)

3. Redraw

However, the worst thing is I realized all of this probably won't automatically update since there is no change detection. What would be the way to properly redraw some elements (taking fresh data from Java part), then?

I'm sorry for asking so many things but it's all related and I'd like to keep the same context.

@czyzby
Copy link
Owner

czyzby commented Aug 20, 2018

This 'x' comparison would be a workaround, I know that. But, there are going to be more booleans than just isWritten. So, neither is a solution for me.

I'm sorry to hear that. If field access does not work, I'm afraid you're stuck with the workarounds or doing part of the job in Java, as LML is in maintenance mode.

I've seen between threads that obfuscation matters so Java things should be named with LmlAction annotation to be accessible from a template. However, actor macro doesn't seem to fit this rule:

@LmlAction is encouraged, but not necessary. If no annotated method is found, the parser looks for methods by name from any registered action containers.

Field access is somewhat supported, as I recall, in a sense that you can access a field similarly to how you would invoke a method: with $ operator. I don't think nested fields are supported though.

What would be the way to properly redraw some elements (taking fresh data from Java part), then?

You should implement your listeners in Java. All properties that are available in LML, are simple Java methods that you can call in your views. Look into @LmlActor and getting references to the widgets from LML templates.

I'm sorry for asking so many things but it's all related and I'd like to keep the same context.

It's OK, I'm happy to help.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

2 participants