Skip to content

Instantly share code, notes, and snippets.

@r4zzz4k
Created October 15, 2019 18:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save r4zzz4k/06054b99876c173b581e962ef683970e to your computer and use it in GitHub Desktop.
Save r4zzz4k/06054b99876c173b581e962ef683970e to your computer and use it in GitHub Desktop.
inkremental/anvil DSL
package trikita.anvil.dsl
import android.view.*
import android.widget.LinearLayout
import trikita.anvil.Anvil
import trikita.anvil.attr
// weight constants
const val FILL = ViewGroup.LayoutParams.MATCH_PARENT
const val MATCH = ViewGroup.LayoutParams.MATCH_PARENT
const val WRAP = ViewGroup.LayoutParams.WRAP_CONTENT
// gravity constants
const val TOP = Gravity.TOP
const val BOTTOM = Gravity.BOTTOM
const val LEFT = Gravity.LEFT
const val RIGHT = Gravity.RIGHT
const val CENTER_VERTICAL = Gravity.CENTER_VERTICAL
const val GROW_VERTICAL = Gravity.FILL_VERTICAL
const val CENTER_HORIZONTAL = Gravity.CENTER_HORIZONTAL
const val GROW_HORIZONTAL = Gravity.FILL_HORIZONTAL
const val CENTER = CENTER_VERTICAL or CENTER_HORIZONTAL
const val GROW = GROW_VERTICAL or GROW_HORIZONTAL
const val CLIP_VERTICAL = Gravity.CLIP_VERTICAL
const val CLIP_HORIZONTAL = Gravity.CLIP_HORIZONTAL
const val START = Gravity.START
const val END = Gravity.END
fun ViewCfg.padding(p: Int) = padding(p, p, p, p)
fun ViewCfg.padding(h: Int, v: Int) = padding(h, v, h, v)
fun ViewCfg.margin(m: Int) = margin(m, m, m, m)
fun ViewCfg.margin(h: Int, v: Int) = margin(h, v, h, v)
package trikita.anvil.dsl
import android.view.*
import android.widget.LinearLayout
import trikita.anvil.Anvil
import trikita.anvil.attr
open class ViewCfg : WidgetCfg() {
fun init(action: (View) -> Unit) = attr("init", action)
fun tag(key: Int, value: Any?) = attr("tag", key to value)
fun size(w: Int, h: Int) = attr("size", w to h)
fun padding(l: Int, t: Int, r: Int, b: Int) = attr("padding", listOf(l, t, r, b))
fun margin(l: Int, t: Int, r: Int, b: Int) = attr("margin", listOf(l, t, r, b))
companion object : ViewCfg()
}
object ViewSetter : Anvil.AttributeSetter<Any?> {
init {
Anvil.registerAttributeSetter(this)
}
override fun set(v: View, name: String, value: Any?, prevValue: Any?): Boolean = when(name) {
"init" -> when {
value is Function1<*, *> -> {
if (Anvil.get(v, "_initialized") == null) {
Anvil.set(v, "_initialized", true)
(value as (View) -> Any?)(v)
}
true
}
else -> false
}
"tag" -> when {
value is Pair<*, *> -> {
v.setTag(value.first as Int, value.second)
true
}
else -> false
}
"size" -> when {
value is Pair<*, *> -> {
val p = v.layoutParams
p.width = value.first as Int
p.height = value.second as Int
v.layoutParams = p
true
}
else -> false
}
"padding" -> when {
value is List<*> -> {
val (l, t, r, b) = value as List<Int>
v.setPadding(l, t, r, b)
true
}
else -> false
}
"margin" -> when {
v.layoutParams is ViewGroup.MarginLayoutParams && value is List<*> -> {
val p = v.layoutParams as ViewGroup.MarginLayoutParams
val (l, t, r, b) = value as List<Int>
p.leftMargin = l
p.topMargin = t
p.rightMargin = r
p.bottomMargin = b
v.layoutParams = p
true
}
else -> false
}
else -> false
}
}
package trikita.anvil.dsl
fun <T, U> ((T) -> U).bind(value: T): () -> U = { this(value) }
@DslMarker
annotation class WidgetDslMarker
@WidgetDslMarker
open class WidgetCfg
package trikita.anvil.dsl
import android.view.View
import android.widget.*
import trikita.anvil.*
abstract class LinearLayoutCfg : ViewCfg() {
companion object : LinearLayoutCfg()
fun weight(w: Float) = attr("weight", w)
fun layoutGravity(g: Int) = attr("layoutGravity", g)
fun orientation(arg: Int) = attr("orientation", arg)
}
abstract class TextViewCfg : ViewCfg() {
companion object : TextViewCfg()
}
fun linearLayout(r: LinearLayoutCfg.() -> Unit = {}) = v<LinearLayout>(r.bind(LinearLayoutCfg))
fun textView(r: TextViewCfg.() -> Unit = {}) = v<TextView>(r.bind(TextViewCfg))
object SdkSetter : Anvil.AttributeSetter<Any?> {
init {
Anvil.registerAttributeSetter(this)
}
override fun set(v: View, name: String, value: Any?, prevValue: Any?): Boolean = when(name) {
"weight" -> when {
v.layoutParams is LinearLayout.LayoutParams && value is Float -> {
(v.layoutParams as LinearLayout.LayoutParams).weight = value
true
}
else -> false
}
"layoutGravity" -> when {
v.layoutParams is LinearLayout.LayoutParams && value is Int -> {
(v.layoutParams as LinearLayout.LayoutParams).gravity = value
true
}
v.layoutParams is FrameLayout.LayoutParams && value is Int -> {
(v.layoutParams as FrameLayout.LayoutParams).gravity = value
true
}
else -> false
}
"orientation" -> when {
v is LinearLayout && value is Int -> {
v.orientation = value
true
}
else -> false
}
else -> false
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment