reyman64
reyman64

Reputation: 553

How to add listeners to javafx UI component with scala

I'm using Scala and Publisher trait to listen the change on my data component and publish/update display to swing UI component (like this)

I recently rewrite my program to use Javafx2 and Scala, and i cannot use the recent binding project Scalafx, because only some of part of my program switch to javafx (which is embedded into swing JFrame).

What is the best syntax i can use in scala to have the same (or similar) behaviour based on scala.swing Publisher trait ?

Do you have some link or simple example to illustrate this method ?

Upvotes: 2

Views: 600

Answers (1)

pagoda_5b
pagoda_5b

Reputation: 7373

What I can suggest at the moment is reusing the patterns from scala.swing that implemented the Publish/React system. An example can be taken from the scala.swing.Component in the old scala.swing repository.

The idea is to create the possibly most generic wrapper for all javafx classes that need to publish events, and implicitly convert these classes to this wrapper.

The wrapper would define the logic for bridging events from javafx listeners to the publish/react system.

An example code would look like this, and is based on the aforementioned scala.swing code

  package scala.fx.react

  object ScalaFxReactive {
      /*
       * Can't say if Node is the best and only class that should be converted.
       * You should make implicit publishers from any fx class that supports the
       * addEventHandler(someEventType)
       */
      implicit def toPublisher(peer: Node): ScalaFxComponentPublisher = new ScalaFxComponentPublisher(peer)

  class ScalaFxComponentPublisher(peer: Component) {

    /**
     * Contains publishers for various mouse events. They are separated for
     * efficiency reasons.
     */
    object mouse {
       /**
        * Publishes clicks, presses and releases.
        */
        val clicks: Publisher = new LazyPublisher {

          lazy val clicked = new EventHandler[MouseEvent] {
            def handle(e: MouseEvent) {
               /*
                *This is the most critical part: you need
                * to check if it's possible to create the swing 
                * event from an fx event, eventually through an
                * implicit conversion
                */
               publish(new MouseClicked(e))
            }
          }

          def onFirstSubscribe() = peer.setOnMouseClicked(clicked)
          def onLastUnsubscribe() = peer.setOnMouseClicked(null)
          /*
           * probably better:
           * def onLastUnsubscribe() = peer.removeEventHandler(MouseEvent.MOUSE_CLICKED)
           */
        }
        /**
         * Publishes enters, exits, moves, and drags.
         */
        val moves: Publisher = new LazyPublisher {
           lazy val entered = new EventHandler[MouseEvent] {
             def handle(e: MouseEvent) {
               publish(new MouseEntered(e))
             }
           }
           lazy val exited = new EventHandler[MouseEvent] {
             def handle(e: MouseEvent) {
               publish(new MouseExited(e))
             }
           }

           /*
            * Need implementation
            */
           lazy val moved = new EventHandler[MouseEvent] {
             ...
           }
           def onFirstSubscribe() {
             peer.setOnMouseEntered(entered)
             peer.setOnMouseExited(exited)
             ...
           }
           def onLastUnsubscribe() {
             peer.setOnMouseEntered(null)
             peer.setOnMouseExited(null)
             ...
           }
         }
       }
     }

Then you can support reacting in your components as you do with scala.swing

class MyComponent {
    import scala.fx.react.ScalaFxReactive._

    listenTo(node)

    reactions += {
      ...   
    }

}

The code is to be taken as a rough sketch and will not compile as it is. It points in a possible direction, but the complete solution could be an interesting enough library for people that, like you, need to progressively bridge legacy scala.swing application to the javafx library.

Upvotes: 1

Related Questions