scaloid
scaloid copied to clipboard
Support `TextView#setTextAppearance` in layout DSL
Currently we don't have any shortcut for [void setTextAppearance(Context, Int)](https://developer.android.com/reference/android/widget/TextView.html#setTextAppearance(android.content.Context, int)) as it takes Context
as one of args. Is there any way to support this by Scaloid DSL?
Because it refers to another attr, it's hard to be automatically converted from XML.
Does the word 'support' you used means that providing DSL-style setter with implicit Context?
i.e. STextView.textAppearance_=(resid: Int)(implicit context:Context)
Unless the implicit parameter doesn't break a following method chain. I said a bit vaguely because I haven't tried it yet.
Method chaining works fine with an implicit parameter:
class Foo {}
class Bar {
def something(a: Int)(implicit context: Foo): Bar = {
println("a==" + a)
this
}
def bar() = println("bar()")
}
implicit val foo = new Foo
new Bar().something(3).bar()
Based on this issue, I imagined something like this:
If a setter has just two parameter and the type of the first parameter is Context, it is automatically converted to DSL-style setter with implicit context.
Could you try this?
The last line does not be compiled.
class Foo {}
class Bar {
def something(a: Int)(implicit context: Foo): Bar = {
println("a==" + a)
this
}
def something_=(a: Int)(implicit context: Foo) = something(a)
def bar() = {
println("bar()")
this
}
}
implicit val foo = new Foo
val b = new Bar().something(3).bar()
b.something = 9
yields the error value something is not a member of Bar
Anyway, method chaining new Bar().something(3).bar()
is proven to be valid. Could you manage to the automatic conversion issue above?
I'll look into it after first draft of new layout converter is done.
If you really want to use something_=
as well, here's a solution:
class ValueWithContext[A] private (val value: A, val context: Context)
object ValueWithContext {
implicit def apply[A](value: A)(implicit context: Context) =
new ValueWithContext(value, context)
}
// ...
class Bar {
// ..
def something_=(vwc: ValueWithContext[Int]) = something(vwc.value)(vwc.context)
//..
A brief confirmation in REPL:
scala> :paste
// Entering paste mode (ctrl-D to finish)
class C
class V[A](val v: A, val c: C)
object V {
implicit def apply[A](v: A)(implicit c: C) = new V(v, c)
}
// Exiting paste mode, now interpreting.
warning: there were 1 feature warning(s); re-run with -feature for details
defined class C
defined class V
defined module V
scala> class B {
| var _a: Int = _
| def a = _a
| def a(v: Int)(implicit c: C) = { this._a = v; this }
| def a_=(v: V[Int]) = this.a(v.v)(v.c)
| }
defined class B
scala> val b = new B
b: B = B@1ddf7713
scala> b.a = 1
<console>:14: error: value V is not a member of object $iw
b.a = 1
^
scala> b.a(1)
<console>:15: error: could not find implicit value for parameter c: C
b.a(1)
^
scala> implicit val c = new C
c: C = C@494a8227
scala> b.a(1)
res5: B = B@1ddf7713
scala> b.a
res6: Int = 1
scala> b.a = 2
b.a: Int = 2
scala> b.a
res7: Int = 2
The error message in line 14 looks somewhat ugly though.
Good, looking forward the integration into Scaloid!