PEAT Online Course -
How To Improve Your Personal Performance in Java work Technology

  • YOU + CONTROL
  • Focus
  • Autonomy
  • Proficiency
  • Purpose
  • Covid-19!!!
  • Deep Hidden Meaning
  • FREE updates
GET 75% OFF NOW
Your Promo code: TECHLAYOFF
Exclusively on
VIMEO ON-DEMAND

Scala Swing REPL: Resolved

23 March 2011 Comments off

4 minutes

836

Well after a night’s sleep and a good rest, which always sorts out the best engineers among us, I realised that the issue is my lack of brain cells on Scala’s Uniform Access Principle. If you noticed in yesterday’s program, the editor panes were created like this:-

    def outputPane = new EditorPane { text="?" }
    def inputPane = new EditorPane { text="List(1,2,3,4,5)" }
    def splitPane = new SplitPane( 
         Orientation.Horizontal, inputPane, outputPane ) 

So I am sorry to say, there is no pint of beer for you, because I resolved my own issue. However the definitions are actual method declarations. That is every time I referenced outputPane or inputPane in the older program I was calling a method that instantiated a EditorPane wrapper and for good measure a real JEditorPane. Of course in a real program that could disasterous if the underlying peer was a expensive resource to create. The solution is to change the def to a val declaration and therefore the Swing wrapper is created only once in the program.

    val outputPane = new EditorPane { text="?" }
    val inputPane = new EditorPane { text="List(1,2,3,4,5)" }
    def splitPane = new SplitPane( 
            Orientation.Horizontal, inputPane, outputPane ) 

In the end, there was no problem with Swing Scala or asynchronous concurrency threading in Java Swing bar the usual caveat emptor on the Event Dispatch Thread. The correct behaviour is shown in the program towards the end of this blog entry. Suffice to say, I would strongly recommend investing in the e-Book edition of Programming in Scala 2nd Edition, 2010 of Martin Odersky, Lex Spoon and Bill Venners from Artima press. I can particularly that the Kindle edition of book is worthwhile, it really formats well and it works out well. There are two chapter in the book that discuss the Scala Swing library in depth and, indeed, more than complement the free PDF in the Scala docs.

Now here is the working program. You need to add the program’s classpath the scala-compiler-2.8.1.jar and jline-0.9.91.jar from the Maven and Scala-Tools repos. I also changed EditorPane to TextArea from yesterday’s code extract:

package swingrepl

import java.io._
import scala.swing._
import scala.swing.event._

import javax.swing.SwingUtilities

import scala.tools.nsc._
import scala.tools.nsc.interpreter._

/**
 * Swing version of the REPL
 * User: Peter
 * Date: 22/03/11
 * Time: 14:34
 */
 class SwingRepl {
   def create(): MainFrame = {
      new MainFrame {
        title = "Swing REPL (cc) XeNoNiQUe Peter Pilgrim - Very Basic Console"
        preferredSize = new Dimension(900, 900 )
        contents = splitPane
     }
   }

   def debug( x: AnyRef ): String = {
    x match {
      case Nil => "nil"
      case null => "null"
      case _ => x.getClass().getName() +"@"+Integer.toHexString( java.lang.System.identityHashCode(x) )
    }
   }

   val outputPane  = new TextArea {
     editable = false
     text = "Text output"
   }
   System.out.println("outputPane="+debug( outputPane) )
   System.out.println("outputPane.peer="+debug( outputPane.peer) )


   val inputPane: TextArea = new TextArea {
     text = "List(1,2,3,4,5) map ( n => n * n )"
     editable = true
     listenTo(keys)

     reactions += {
       case e: KeyPressed => {
         // println("keyCode =" +e.peer.getKeyCode+", keyChar = "+e.peer.getKeyChar)
         if ( e.peer.isControlDown && e.key == Key.Enter ) {
           interpret( text )
         }
       }

       case _ =>
     }
   }
   System.out.println("inputPane="+debug( inputPane) )


   def scrollInputPane = new ScrollPane( inputPane )
   def scrollOutputPane = new ScrollPane( outputPane )

   def splitPane = new SplitPane( Orientation.Horizontal, scrollInputPane, scrollOutputPane )  {
     dividerLocation =  100
   }

   protected val swriter = new StringWriter()
   protected val pwriter = new PrintWriter( swriter ) {
     override def print( line: String ) {
       super.print( line )
       System.out.println("print line=``"+line+"''")
       System.out.println("swriter.toString=<<"+swriter.toString+">>" )

       SwingUtilities.invokeLater( new Runnable() {
         override def run(): Unit = {
           // outputPane.text = outputPane.text +"\n"+ line +"\n"
           System.out.println("3) outputPane="+debug( outputPane) )
           System.out.println("4) outputPane.peer="+debug( outputPane.peer) )
           System.out.println("BEFORE outputPane.text = "+outputPane.text)
           outputPane.text = swriter.toString
           System.out.println(" AFTER outputPane.text = "+outputPane.text)
           outputPane.peer.revalidate
           outputPane.peer.repaint()
         }
       })
     }
   }

   protected val cmd = new InterpreterCommand(Nil, println )
   System.out.println("cmd="+cmd)
   protected val settings = cmd.settings
   System.out.println("settings="+settings)

   settings.usejavacp.value = true

   protected val interpreter = new Interpreter(settings, pwriter ) {
     override def reset() = { super.reset; unleash() }
     override def unleash() = { super.unleash;  }
   }
   System.out.println("interpreter="+interpreter)
   protected val completion = new Completion(interpreter)
   System.out.println("completion="+completion)


   def interpret(cmd: String): Unit = {
     System.out.println("replInvoker.interpret cmd="+cmd )
     System.out.println("interpreter="+interpreter)
     interpreter.interpret(cmd)
   }
 }

object SwingRepl extends SimpleSwingApplication {
  def top = new SwingRepl().create()
}

No free beer 😉

PS: You will notice that I put in a simple debug() method to dump out the object reference. It helped me track down the issue and then eureka. As they say: everything appears obvious after the invention.

PS PS: I would love to repeat the exercise for JavaFX 2.0 Beta and all I need is the multi-line TextInput and the equivalent JTextArea output components.

Hey all! Thanks for visiting. I provide fringe benefits to interested readers: checkout consultancy, training or mentorship Please make enquiries by email or
call +44 (0)7397 067 658.

Due to the Off-Payroll Working plan for the UK government, I am enforcing stricter measures on contracts. All potential public sector GOV.UK contracts engagements must be approved by QDOS and/or SJD Accounting. Please enquire for further information.