pivot-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Bojan Vučinić <bojan.vuci...@ma-cad.com>
Subject Re: Scala
Date Tue, 23 Nov 2010 20:30:06 GMT
Clint, Greg,
Thanks for taking the time to look into this.
Here is the code that works:

...
import org.apache.pivot.wtk.PushButton
import org.apache.pivot.wtk.Button
...

class EnBalSP extends Application {
   var window: Window = null
...
  @BXML private var printButton: PushButton = null
...

...
   override def startup(display:Display, ns:Map[String, String]) = {
     val enBalSer: BXMLSerializer = new BXMLSerializer
...

     window = enBalSer.readObject(classOf[EnBalSP], "enbal.bxml").asInstanceOf[Window]
...
  enBalSer.bind(this, classOf[EnBalSP])

...
     initButtons
...
  window.open(display)
   }

...
  def initButtons = {
...
    printButton.getButtonPressListeners.add(new ButtonPressListener {
      override def buttonPressed(b: Button) {
      print
      }
      })
...
  }

...
  override def suspend() {}

   override def resume() {}

   override def shutdown(optional:Boolean):Boolean = {
     if (window != null) window.close()
     return false
   }
}

So, in the above the Application is launched, the buttons are binded 
with @BXML, the bxml file is deserialized in startup,
which calls initButtons where the listeners are registered. The above is 
working. Now if I change the initButtons as shown below:

...
import org.apache.pivot.wtk.PushButton
import org.apache.pivot.wtk.Button
...

class EnBalSP extends Application {
   var window: Window = null
...
  @BXML private var printButton: PushButton = null
...

...
   override def startup(display:Display, ns:Map[String, String]) = {
     val enBalSer: BXMLSerializer = new BXMLSerializer
...

     window = enBalSer.readObject(classOf[EnBalSP], "enbal.bxml").asInstanceOf[Window]
...
  enBalSer.bind(this, classOf[EnBalSP])

...
     initButtons
...
  window.open(display)
   }

...
  def initButtons = {
...
     pressedDo(printButton, print)
...
  }

   def pressedDo (aB: PushButton, action: Unit) = {
     aB.getButtonPressListeners.add(new ButtonPressListener {
         override def buttonPressed(b: Button): Unit = action })

...
  override def suspend() {}

   override def resume() {}

   override def shutdown(optional:Boolean):Boolean = {
     if (window != null) window.close()
     return false
   }
}

I get the error that display is null??

It is really strange.



Clint Gilbert said the following on 23/11/2010 20:37:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
>
> Actually, the type of b is the problem:
>
> override def buttonPressed(b: Button): Unit = action
>
> or even
>
> override def buttonPressed(b: Button) = action
>
> instead of
>
> override def buttonPressed(b: PushButton): Unit = action
>
> is what you want.
>
> Clint Gilbert wrote:
>> This is getting off-topic, but it's something I actually know a tiny bit
>> about.
>>
>> The compiler is complaining (I think) because you're not actually
>> overriding buttonPressed.  This can happen when type inference goes a
>> little astray, especially with methods that return Unit.  Naming
>> buttonPressed's param 'b' shouldn't be a problem.  I'd try explicitly
>> specifying the return type, like
>>
>> def pressedDo (aB: PushButton, action: Unit) = {
>>    aB.getButtonPressListeners.add(new ButtonPressListener {
>>      override def buttonPressed(b: PushButton): Unit = action
>>    })
>> }
>>
>> There are also inference rule that take effect regarding the = in
>>
>> def foo(...) = { }
>>
>> vs def foo(...) { }
>>
>> The latter (I believe) is assumed to return Unit, but I always add the =
>> just to be sure.  (/Programming Scala/ by Odersky, Venners, and Spoon
>> explains things like this very, very well.)
>>
>> Additionally, you probably want something like this:
>>
>> def pressedDo (aB: PushButton, action: =>  Unit) = {
>>    aB.getButtonPressListeners.add(new ButtonPressListener {
>>      override def buttonPressed(b: PushButton) = action
>>    })
>> }
>>
>> Note the new type of the 'action' param.  It's now "a function that
>> takes no params and returns Unit", instead of an actual value of type
>> Unit.  This is an easy way to have lazily-evaluated parameters.
>>
>> Due to some neat syntactic sugar for writing anonymous functions of this
>> type, if you split the parameter list for pressedDo, like
>>
>> def pressedDo (aB: PushButton)(action: =>  Unit) = {
>>    aB.getButtonPressListeners.add(new ButtonPressListener {
>>      override def buttonPressed(b: PushButton) = action
>>    })
>> }
>>
>> You could call it like:
>>
>> pressedDo(someButton) {
>>    val foo = new Foo
>>
>>    someOtherThing.doStuff(foo)
>>
>>    //etc
>> }
>>
>> Here the stuff in the braces becomes an anonymous function that gets
>> passed to pressedDo.
>>
>> It's also possible to use implicit conversions (the perhaps
>> tastelessly-named "Pimp-My-Library" pattern[1]) to "add" the pressedDo
>> method to the Button class.  Well, kind of, not really to the Button
>> class, but combined with the above technique, you could make a call like
>>
>> val someButton: Button = ...
>>
>> someButton pressed {
>>    val foo = new Foo
>>
>>    someOtherThing.doStuff(foo)
>> }
>>
>> which is starting to look smooth.  Implicits can get pretty black-magic
>> though, so use them with care and restraint if you do.
>>
>> [1]: http://scala.sygneca.com/patterns/pimp-my-library
>>
>> Bojan Vu ini wrote:
>>> Hi All,
>>> If you are using Scala for your code then you are obliged to write listeners
in the following way:
>>
>>> printButton.getButtonPressListeners.add(new ButtonPressListener {
>>>       override def buttonPressed(b: Button) {
>>>          print
>>>       }
>>>    })
>>
>>> I've tried to simplify this by defining the following method:
>>>    def pressedDo (aB: PushButton, action: Unit) = {
>>>      aB.getButtonPressListeners.add(new ButtonPressListener {
>>>          override def buttonPressed(b: PushButton) { action }})
>>>    }
>>
>>> and than invoking the method in this way (example)
>>>      pressedDo(printButton, print)
>>
>>> however, this results in a compiler error:
>>
>>> error: object creation impossible, since method buttonPressed in trait ButtonPressListener
of type (x$1: org.apache.pivot.wtk.Button)Unit is not defined
>>>      aB.getButtonPressListeners.add(new ButtonPressListener {
>>
>>> I'm not a programming language specialist, and in addition a Scala novice, but
I'm puzzled why putting boilerplate code in a separate method is not working??
>>> Best regards,
>>> Bojan
>>
>>> Dr. Bojan Vu ini
>>> President, Ma-CAD<http://www.ma-cad.com/>
>>> bojan.vucinic@ma-cad.com<mailto:bojan.vucinic@ma-cad.com>
>>> IM: bvucinic (Skype)
>>> http://fr.linkedin.com/in/bvucinic
>>> Maintenance Concept Adjustment&  Design 31, rue Chanzy
>>> Paris, Ile de France 75011 France
>>> Work: +33 (6) 14 15 36 70
>>> Mobile: +33 (6) 14 15 36 70
>>> Fax: +33 (1) 53 01 38 28
>>> See who we know in common<http://www.linkedin.com/e/wwk/4839994/>     
  Want a signature like this?<http://www.linkedin.com/e/sig/4839994/>
>>
> -----BEGIN PGP SIGNATURE-----
> Version: GnuPG v1.4.9 (GNU/Linux)
> Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org
>
> iEYEARECAAYFAkzsGBIACgkQ5IyIbnMUeTtlkwCZAUsW/ssyCxJ95PaxTbW0ap0a
> RBwAn1ttMyvrnr/iLAZ8gAIPFy/g5obf
> =axhA
> -----END PGP SIGNATURE-----
>
>

Mime
View raw message