2010-04-13 16 views
7

soy no un experto Groovy, pero sí leí el libro "Groovy en acción". En Groovy, cada cierre viene con un "contexto", donde los elementos dentro del cierre pueden tener acceso a pseudovariables como "este", "propietario" y "delegado", que permiten a los elementos saber quién llamó al cierre. Esto permite escribir DSL como este (de maravilloso en Acción):contexto de cierre de Scala

swing = new SwingBuilder() 
frame = swing.frame(title:'Demo') { 
    menuBar { 
    menu('File') { 
     menuItem 'New' 
     menuItem 'Open' 
    } 
    } 
    panel { 
    // ... 
    } 
} 

Tenga en cuenta que 'barra de menú' "sabe" que pertenece al 'marco', ya que puede obtener información de contexto sobre el propietario y el delegado de la cierre.

¿Esto es posible hacer en Scala? ¿Si es así, cómo?

+0

Una vez vanamente con algunos enfoques para emular el constructor HTML (no el propietario/delegado de un cierre). http://gist.github.com/260426 http://gist.github.com/260446 – retronym

+0

Estaba buscando más el patrón que una aplicación específica con Swing. Como ejercicio de aprendizaje, estoy considerando intentar esto con SWT. – Ralph

Respuesta

16

Una forma es utilizar scala.util.DynamicVariable para rastrear el contexto. Algo así como el SwingBuilder podría ser implementado como

import scala.util.DynamicVariable 
import javax.swing._ 

object SwingBuilder { 
    case class Context(frame: Option[JFrame], parent: Option[JComponent]) 
} 

class SwingBuilder { 
    import SwingBuilder._ 
    val context = new DynamicVariable[Context](Context(None,None)) 

    def frame(title: String)(f: =>Unit) = { 
    val res = new JFrame(title) 
    res.add(new JPanel()) 
    context.withValue(Context(Some(res),context.value.parent)){f;res} 
    } 

    def menuBar(f: =>Unit) = { 
    val mb = new JMenuBar() 
    context.value.frame.foreach(_.setJMenuBar(mb)) 
    context.withValue(Context(context.value.frame,Some(mb))){f;mb} 
    } 

    def menu(title: String)(f: =>Unit) = { 
    val m = new JMenu(title) 
    context.value.parent.foreach(_.asInstanceOf[JMenuBar].add(m)) 
    context.withValue(Context(context.value.frame,Some(m))){f;m} 
    } 

    def menuItem(title: String) = { 
    val mi = new JMenuItem(title) 
    context.value.parent.foreach(_.asInstanceOf[JMenu].add(mi)) 
    } 
} 

object Test { 
    def main(args: Array[String]) { 
    val builder = new SwingBuilder() 
    import builder._ 

    val f = frame("Demo") { 
     val mb = menuBar { 
     menu("File") { 
      menuItem("New") 
      menuItem("Open") 
     } 
     } 
    } 
    f.setVisible(true) 
    } 
} 
+3

Scala nunca deja de sorprenderme:) ... Gracias. – Ralph

Cuestiones relacionadas