scaloid icon indicating copy to clipboard operation
scaloid copied to clipboard

Support `TextView#setTextAppearance` in layout DSL

Open guersam opened this issue 11 years ago • 9 comments

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.

guersam avatar Sep 19 '13 00:09 guersam

Does the word 'support' you used means that providing DSL-style setter with implicit Context?

i.e. STextView.textAppearance_=(resid: Int)(implicit context:Context)

pocorall avatar Sep 19 '13 12:09 pocorall

Unless the implicit parameter doesn't break a following method chain. I said a bit vaguely because I haven't tried it yet.

guersam avatar Sep 19 '13 12:09 guersam

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?

pocorall avatar Sep 19 '13 14:09 pocorall

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

pocorall avatar Sep 19 '13 14:09 pocorall

Anyway, method chaining new Bar().something(3).bar() is proven to be valid. Could you manage to the automatic conversion issue above?

pocorall avatar Sep 19 '13 21:09 pocorall

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)
//..

guersam avatar Sep 20 '13 17:09 guersam

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 

guersam avatar Sep 20 '13 17:09 guersam

The error message in line 14 looks somewhat ugly though.

guersam avatar Sep 20 '13 17:09 guersam

Good, looking forward the integration into Scaloid!

pocorall avatar Sep 20 '13 19:09 pocorall