Giter Site home page Giter Site logo

Comments (6)

czyzby avatar czyzby commented on September 18, 2024

I'm afraid there isn't a simple way to do this without either ditching the ActorConsumer altogether and relying only on reflection-based methods or ugly non-generic solutions. I'm well aware there are some use cases where you could use a few extra parameters (or be able to invoke any Java method with any custom parameters), but for now you're stuck with plain Java. A while back I thought about some DSL that allows you to invoke any method via LML, but I don't think its worth the effort after all - LML should contain as little logic as possible and refactoring would be a hell. (Think about JSP...)

Suggested workaround: use onCreate or onClose attributes to invoke your Java method that adds the ClickListener manually.

Anyway, commonly invoked methods should be written as pure Java (ActorConsumer or just plain old listeners), as reflection is not as fast on mobile devices as it is on desktop.

So yeah, for now I'm closing this issue. If you have any suggestions or want to dive into the code, I'm willing to help and accept any pull requests.

from gdx-lml.

metaphore avatar metaphore commented on September 18, 2024

I agree, such a flexible and generic solution mostly will just overcomplicate the idea of ActorConsumer and LML in general. But I'm thinking of something simple like non generic tuple that could be just Object array as extra parameter for ActorConsumer. So you always know how to work with your own custom actions, you can pass anything you like through this object array and you can achieve any depth of flexibility that way. Default actions can still just keep that array empty. It doesn't look so ugly to me and should not add much complexity to old code.

What do you think?

from gdx-lml.

czyzby avatar czyzby commented on September 18, 2024

Sure, Triple<Actor, Float, Float> would be easy to pass, but it still suffers from some issues. Unless you create a separate class for each use case, you create unnecessary garbage (primitives boxing, wrapping parameters in tuple objects), lose the parameter names (which was the X one again? Is this even a position?) and force the user to use a particular API that he might or might not need. After all, the exact local click position is rarely needed in most cases.

When I (re)designed LML, I went for extensibility. The API might be rusty here and there, but creating custom attributes should be easy enough. Based on current OnClickLmlAttribute, here's a quick class using Triple tuple from gdx-kiwi that might help:

package com.github.czyzby.lml.parser.impl.attribute;

import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.InputEvent;
import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;
import com.github.czyzby.kiwi.util.tuple.immutable.Triple;
import com.github.czyzby.lml.parser.LmlParser;
import com.github.czyzby.lml.parser.action.ActorConsumer;
import com.github.czyzby.lml.parser.tag.LmlAttribute;
import com.github.czyzby.lml.parser.tag.LmlTag;

public class OnClickWithPositionLmlAttribute implements LmlAttribute<Actor> {
    private static final Triple<Actor, Float, Float> MOCK = Triple.of(null, 0f, 0f);

    @Override
    public Class<Actor> getHandledType() {
        return Actor.class;
    }

    @Override
    public void process(final LmlParser parser, final LmlTag tag, final Actor actor, final String rawAttributeData) {
        final ActorConsumer<?, Triple<Actor, Float, Float>> action = parser.parseAction(rawAttributeData, MOCK);
        if (action == null) {
            parser.throwError("Could not find action for: " + rawAttributeData + " with actor: " + actor);
        }
        actor.addListener(new ClickListener() {
            @Override
            public void clicked(final InputEvent event, final float x, final float y) {
                action.consume(Triple.of(actor, x, y));
            }
        });
    }
}

Note that gdx-lml library already depends on gdx-kiwi, so you can easily access the existing tuple classes.

Your typical handler method would look like this:

    @LmlAction("onClickWithPos")
    public void handleClickEvent(Triple<Button, Float, Float> actorWithClickPosition) {
        Button myClickedButton = actorWithClickPosition.getFirst();
        float x = actorWithClickPosition.getSecond();
        float y = actorWithClickPosition.getThird();
        // TODO Do something with the actor.
    }

You can register new attributes during parser building, as well as by accessing LmlSyntax object of an existing LmlParser instance:

Lml.parser().attribute(new OnClickWithPositionLmlAttribute(), "onClickPos").build();
lmlParser.getSyntax().addAttributeProcessor(new OnClickWithPositionLmlAttribute(), "onClickPos");

from gdx-lml.

metaphore avatar metaphore commented on September 18, 2024

Oh, that's already there. I'm so sorry for confusion.
I mix up generic parameter called Widget in ActorConsumer<ReturnType, Widget> and by some reason was start thinking that ActorConsumer is limited to use only widgets for consume(Widget actor) parameters.

Thanks a lot for that detailed message and sorry again that I've stole your time for my silly mistake.

from gdx-lml.

czyzby avatar czyzby commented on September 18, 2024

OnClickWithPositionLmlAttribute I posted above is not (and will not be) a part of LML library and most ActorConsumers consume, well, actors - so your confusion is understandable. I actually wanted to refactor ActorConsumer name to something more generic when I was rewriting from so-called LML 0 to LML 1, but I guess that could break even more code than it already did.

from gdx-lml.

metaphore avatar metaphore commented on September 18, 2024

Sure, I'm not about OnClickWithPositionLmlAttribute, but generic Widget parameter that can be used like a tuple.

from gdx-lml.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.