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

Support library difficulties and ugliness #66

Closed
graknol opened this issue Apr 25, 2016 · 10 comments
Closed

Support library difficulties and ugliness #66

graknol opened this issue Apr 25, 2016 · 10 comments

Comments

@graknol
Copy link

graknol commented Apr 25, 2016

Hi, I love this library so far, it's so refreshing! But, there is one thing holding me back and making me wanna go back to XML, which is that the appcompat-v7 and support-v4 DSLs have conflicting methods with the core DSL. Also, it kills me that we have to write appCompatButton instead of just button and have it automatically use the appropriate version.

I would gladly work with someone on the issue (I'm not too good at making APIs on my own, hehe).

Thanks in advance,
Graknol

@zserge
Copy link
Collaborator

zserge commented Apr 25, 2016

@graknol I tried to make a discussion about it some time ago - #29

There are a few constraints:

  • Support library DSL could extend the base DSL and it would fix the methods duplicated in both, but will not prevent from method conflicts in two different support libraries.
  • Support library may not extend the base DSL, but then you will have method conflicts as you have now.
  • The only way to resolve method conflicts as I see it is to use full name for one of the DSLs.

Of course, this is an easy option to leave it all to the end user, who is always welcome to wrap layouts into friendlier function names, e.g. you can always make an alias for your button as:

public void btn(Renderable r) {
  appCompatButton(() -> {
    size(FILL, FILL);
    // other common styles here
    r.view();
  });
}

btn(() -> {
  text(....);
  onClick(v -> ....);
});

@graknol
Copy link
Author

graknol commented Apr 25, 2016

@zserge hmm, it's not an easy feat. I'll see if I can write a kotlin (as that's what I'm using) wrapper for the DSL (kinda a DSL for a DSL lol), handwritten to route the calls to the correct library depending on the view type. It will take some time, but I'd rather write this library than having to write AppCompatv7DSL.orientation() ;)

@zserge
Copy link
Collaborator

zserge commented Apr 25, 2016

That would be awesome! I'm sure there is no generic solution to this in Java which lacks traits so much. There is a number of name conflicts between base DSL and support DSL - in both, view names and property setters. And I'm strongly reluctant to giving custom (unpredictable) names to views, because the benefit of Anvil is that you already know the DSL - just use property or view names from the SDK in camel-case and without "set" prefix. The only exception so far has been "switchView", because "switch" is a keyword in both Java and Kotlin.

Again, I'm pretty happy with writing DSL class names in Java, because Java is verbose anyway, so excplicit is better than implicit. I tend to wrap common repeatitive parts into small functions, so I don't notice that I type it too often. Kotlin is different in its style, so a good-looking wrapper is more than welcome.

@graknol
Copy link
Author

graknol commented Apr 27, 2016

@zserge Care to explain what the return type ViewClassResult is used for? If it's only used internally, I'd rather avoid implementing those methods as they should not be visible to the user.

@zserge
Copy link
Collaborator

zserge commented Apr 27, 2016

@graknol Sure, each view has two types of "builder" functions.

When lambdas are available (Java 8, Kotlin) the lambda function should be used, e.g. button(() -> ....) or button { ... }.

When lambdas are not available one can still use Anvil like:

o (frameLayout(),
    size(FILL, FLL),
  o (button(),
      text("Click me")));

For Kotlin-only it's safe to wrap lambda methods only.

Answering your question, ViewClassResult is used to get some kind of type safety so that o (frameLayout(), ....) would be correct, but o (text("hello"), ...) will fail to compile because view functions return ViewClassResult while attribute setters seem to return Void.

@graknol
Copy link
Author

graknol commented Apr 27, 2016

Ahhh I see, that's really clever :) Well, I've completed the BaseDSL class, modified your generator (ugly as h***, but works for manual work, haha). And am currently in the process of writing a converter in python, crossing fingers I'll be able to do it :)

@graknol
Copy link
Author

graknol commented Apr 27, 2016

Also, the DSL functions aren't supposed to be used outside of a RenderableView right? As I've restricted the root functions like button(), v(), etc to those classes who inherit from it.

@zserge
Copy link
Collaborator

zserge commented Apr 27, 2016

@graknol Exactly, all DSL functions must be called only within Anvil.render() scope, which means inside the view() method of the Renderable or RenderableView.

@graknol
Copy link
Author

graknol commented Apr 30, 2016

So I finished the core wrapper (the support libraries can be done the same way, but I want to have some better form for automation in place, will probably have to write a javapoet kinda library for kotlin files, yuck). I don't want to mess with your directory structure, so I'll just post it here and you can mention it on the front page or something. Later on I would like to post it as a separate project and have it available as a repo, but for the time being it'll stay like this, until I get everything set up the way I want :)

graknol.anvil.kotlin.zip

@graknol
Copy link
Author

graknol commented May 3, 2016

@graknol graknol closed this as completed May 3, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants