How to use CheckBoxListCell in ScalaFX? - scala

I am trying to make a list of checkBox with scalaFX.
With some research i found the CheckBoxListCell Component to resolve this problem.
But i didn't find a a good example with scalaFX ( there is only with javaFX).
Please any help ? Thanx

Here is a complete ScalaFX example:
package scalafx.controls
import scala.language.implicitConversions
import scalafx.Includes._
import scalafx.application.JFXApp
import scalafx.application.JFXApp.PrimaryStage
import scalafx.beans.property.BooleanProperty
import scalafx.collections.ObservableBuffer
import scalafx.scene.Scene
import scalafx.scene.control.cell.CheckBoxListCell
import scalafx.scene.control.{Button, ListView}
import scalafx.scene.layout.VBox
object CheckBoxListCellDemo extends JFXApp {
class Item(initialSelection: Boolean, val name: String) {
val selected = BooleanProperty(initialSelection)
override def toString = name
}
val data = ObservableBuffer[Item](
(1 to 10).map { i => new Item(i % 2 == 0, s"Item $i") }
)
stage = new PrimaryStage {
scene = new Scene {
title = "CheckBoxListCell Demo"
root = new VBox {
children = Seq(
new ListView[Item] {
prefHeight=250
items = data
cellFactory = CheckBoxListCell.forListView(_.selected)
},
new Button("Print State ") {
onAction = handle {
println("-------------")
println(data.map(d => d.name + ": " + d.selected()).mkString("\n"))
}
}
)
}
}
}
}

Related

not found value ~ in Scala

I am defining some paths but then i run into this error for the tilde ~ right before " pathPrefix(start)" . I am a bit new in Scala and so something do not click right away. thanks
not found:value ~
Is it because i need to define a function? If so why?
import
akka.http.scaladsl.marshallers.xml.ScalaXmlSupport.defaultNodeSeqMarshaller
import akka.http.scaladsl.server.{ HttpApp, Route }
import akka.http.scaladsl.model.StatusCodes
import akka.actor.ActorSystem
import akka.stream.ActorMaterializer
import com.typesafe.config.ConfigFactory
import akka.event.Logging
import akka.http.scaladsl.model._
object ABC extends HttpApp with App {
implicit val actorSystem = ActorSystem()
implicit val matter = ActorMaterializer()
val start = "hello"
val Routing= {
path(start) {
redirect( Uri(start+ "/index.html"), StatusCodes.PermanentRedirect )
}
~
pathPrefix(start) {
content
}
}
val content =
{
get
{
path("html") {
getFromResource("src/html") }
}
}
}
Make sure you have the following import:
import akka.http.scaladsl.server.Directives._
Once you added the import as per #chunjef answer, also note that ~ is an infix operator, so it comes with all the "quirks" of it.
To sort out your routes, you can avoid placing the ~ in a new line
val Routing= {
path(start) {
redirect( Uri(start+ "/index.html"), StatusCodes.PermanentRedirect )
} ~
pathPrefix(start) {
content
}
}
or you can wrap the concatenated routes in brackets
val Routing= {
(path(start) {
redirect( Uri(start+ "/index.html"), StatusCodes.PermanentRedirect )
}
~
pathPrefix(start) {
content
})
}

Unbound placeholder parameter when initializing with default value

Here is the code:
package scalafx.ensemble.example.charts
import javafx.scene.chart.PieChart.Data
import scala.util.Random
import scalafx.application.JFXApp
import scalafx.scene.Scene
import scalafx.Includes._
import scalafx.collections.ObservableBuffer
import scalafx.scene.chart.PieChart
import scalafx.scene.input.MouseEvent
object BasicPie extends JFXApp {
// data level 1
val pieChartDataBuffer: ObservableBuffer[Data] = ObservableBuffer(
PieChart.Data("A", 20),
PieChart.Data("B", 30),
PieChart.Data("C", 10),
PieChart.Data("D", 40)
)
pieChartDataBuffer.foreach(
(data: Data) => data.node().onMouseClicked = {
(_: MouseEvent) => pieChart.data = pieChartDataSubBuffer(data.name())
}
)
val pieChart = new PieChart {
data = pieChartDataBuffer
title = "DrillDown Pie Chart"
}
// data level 2
val pieChartDataSubBuffer: Map[String, ObservableBuffer[Data]] = _
Array("A", "B", "C", "D").foreach(
(letter: String) => {
val subData: ObservableBuffer[Data] = _
(1 to 10).foreach(
i => {
val subName = letter + "-" + i
subData.add(PieChart.Data(subName, Random.nextInt(100)))
}
)
pieChartDataSubBuffer.updated(letter, subData)
}
)
pieChartDataSubBuffer.foreach(
(nameDataBufferTuple) => {
nameDataBufferTuple._2.foreach(
(data: Data) => {
data.node().onMouseClicked = {
(_: MouseEvent) => pieChart.data = pieChartDataBuffer
}
}
)
}
)
// set listener for one data node
def drillDownData = (pieData: Data, pie: PieChart) => {
pieData.node().onMouseClicked = (_: MouseEvent) => pie.data = pieChartDataSubBuffer(pieData.name())
}
stage = new JFXApp.PrimaryStage {
title = "Drilldown Pie Chart Example"
scene = new Scene {
root = pieChart
}
}
}
One would expect subData to be initialized with null, but instead of that I get an error: Unbound placeholder parameter. Why?
You cannot create an uninitialized val, because you can never assign anything useful to it afterwards.
Say you make that explicit:
val subData: ObservableBuffer[Data] = null
subData = ObservableBuffer.empty -> error: reassignment to val!
subData.add(data) -> NullPointerException
You either initialize it as a var
var subData: ObservableBuffer[Data] = _
or (especially in case of mutable collections) as empty buffer
val subData: ObservableBuffer[Data] = ObservableBuffer.empty // comes to mind
Your code would suggest that you would want to do the latter.
Just for the record, here is the modified version that compiles:
package scalafx.ensemble.example.charts
import javafx.scene.chart.PieChart.Data
import scala.util.Random
import scalafx.application.JFXApp
import scalafx.scene.Scene
import scalafx.Includes._
import scalafx.collections.ObservableBuffer
import scalafx.scene.chart.PieChart
import scalafx.scene.input.MouseEvent
import scala.collection.mutable.{HashMap => MMap}
object BasicPie extends JFXApp {
stage = new JFXApp.PrimaryStage {
title = "Drilldown Pie Chart Example"
scene = new Scene {
root = {
val pieChartDataBuffer = ObservableBuffer(
PieChart.Data("A", 20),
PieChart.Data("B", 30),
PieChart.Data("C", 10),
PieChart.Data("D", 40)
)
val pieChart = new PieChart {
data = pieChartDataBuffer
title = "DrillDown Pie Chart"
}
def subPieChartData: MMap[String, ObservableBuffer[Data]] = {
val subDataMap: MMap[String, ObservableBuffer[Data]] = MMap.empty
for(letter <- Array("A", "B", "C", "D")) {
val dataBuffer: ObservableBuffer[Data] = ObservableBuffer.empty
for(i <- 1 to 10) {
val subLabel = letter + i
dataBuffer.add(PieChart.Data(subLabel, Random.nextInt(100)))
}
subDataMap.update(letter, dataBuffer)
}
subDataMap
}
def drillDownData = (pie: PieChart, pieData: PieChart.Data) => {
val labelPrefix = pieData.name()
val subData = subPieChartData(pieData.name())
pieData.node().onMouseClicked = (_: MouseEvent) => pie.data = subData
subData.foreach(
(data) => climbUpData(pie, data)
)
}
def climbUpData = (pie: PieChart, pieData: PieChart.Data) => {
val node = pieData.node()
if(node != null) {
node.onMouseClicked = (_: MouseEvent) => pie.data = pieChartDataBuffer
}
}
pieChartDataBuffer.foreach((data: Data) => drillDownData(pieChart, data))
pieChart
}
}
}
}

How do you set the viewport, width, with phantomjs with play 2 framework

I have been struggling with this for a while, I can't find a way to instruct phantomjs about the viewport. I am using play 2.2 (code is based on: Set Accept-Language on PhantomJSDriver in a Play Framework Specification )
package selenium
import org.specs2.mutable.Around
import org.specs2.specification.Scope
import play.api.test.{TestServer, TestBrowser, FakeApplication}
import org.openqa.selenium.remote.DesiredCapabilities
import org.specs2.execute.{Result, AsResult}
import play.api.test.Helpers._
import scala.Some
import org.openqa.selenium.phantomjs.PhantomJSDriver
import org.openqa.selenium.NoSuchElementException
import java.io.File
import java.io.PrintWriter
import java.util.concurrent.TimeUnit
import collection.JavaConversions._
abstract class WithPhantomJS(val additionalOptions: Map[String, String] = Map()) extends Around with Scope {
implicit def app = FakeApplication()
implicit def port = play.api.test.Helpers.testServerPort
// for phantomjs
lazy val browser: TestBrowser = {
val defaultCapabilities = DesiredCapabilities.phantomjs
print(defaultCapabilities.toString)
val additionalCapabilities = new DesiredCapabilities(mapAsJavaMap(additionalOptions))
val capabilities = new DesiredCapabilities(defaultCapabilities, additionalCapabilities)
val driver = new PhantomJSDriver(capabilities)
val br = TestBrowser(driver, Some("http://localhost:" + port))
br.webDriver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS)
br
}
override def around[T: AsResult](body: => T):Result = {
try {
running(TestServer(port, FakeApplication()))(AsResult.effectively(body))
} catch {
case e: Exception => {
val fn: String = "/tmp/test_" + e.getClass.getCanonicalName;
browser.takeScreenShot(fn + ".png")
val out = new PrintWriter(new File(fn + ".html"), "UTF-8");
try {
out.print(browser.pageSource())
} finally {
out.close
}
throw e;
}
} finally {
browser.quit()
}
}
}
and the actual test looks like this:
class ChangeName extends Specification {
"User" should {
"be able to change his name in account settings" in new WithPhantomJS() {
// ... this throws
I'd like the exception handler to render the site, which works, however, i can see the with matching a mobile device (narrow).
How can I change the width?
This seems to work:
import org.openqa.selenium.Dimension
...
browser.webDriver.manage().window().setSize(new Dimension(1280, 800))

i am trying to write a text file using scala in play

i have attached my codes
Application (controller)
package controllers
import play.api._
import play.api.mvc._
import play.api.data._
import play.api.data.Forms._
import models.Task
import java.io._
object Application extends Controller {
val taskForm = Form(
tuple(
"id" -> number,
"label" -> nonEmptyText(minLength = 4),
"add" -> nonEmptyText
)
)
def index = Action {
Redirect(routes.Application.tasks)
}
def tasks = Action {
Ok(views.html.index(Task.all(),taskForm))
}
def showTask= Action {
Ok(views.html.test(Task.all(), taskForm))
}
def newTask = Action { implicit request =>
taskForm.bindFromRequest.fold(
errors => BadRequest(views.html.index(Task.all(), errors)),
{
case(id,label,add) => {
Task.create(id,label,add)
Redirect(routes.Application.showTask)
}
}
)
}
def deleteTask(id: Int) = Action {
Task.delete(id)
Redirect(routes.Application.showTask)
}
}
Task(model)
package models
import anorm._
import anorm.SqlParser._
import play.api.db._
import play.api.Play.current
case class Task(id: Int, label: String,add:String)
object Task {
val task = {
get[Int]("id") ~
get[String]("label") ~
get[String]("add") map {
case id~label~add => Task(id, label,add)
}
}
def all(): List[Task] = DB.withConnection { implicit c =>
SQL("select * from task").as(task *)
}
def create(id:Int , label: String, add:String) {
DB.withConnection { implicit c =>
SQL("insert into task (id,label,add) values ({id},{label},{add})").on(
'id -> id ,
'label -> label ,
'add -> add
).executeUpdate()
}
}
def delete(id:Int) {
DB.withConnection { implicit c =>
SQL("delete from task where id = {id}").on(
'id -> id
).executeUpdate()
}
}
}
I have no idea where to declare the writer function .please help me with the syntax also, I need to write the form elements into a text file .. Thankx in advance
Assuming that you want to append the text whenever a new task is added (i.e. newTask is invoked by Play).
You can define a helper function in object Application and use this helper method in your newTask method.
object Application extends Controller {
//...
import java.io.FileWriter
val filePath = """ path to file """
def writingToFile(str: String) = {
val fw = new FileWriter(filePath, true)
try {
fw.write(str)
} finally {
fw.close()
}
}
def newTask = Action { implicit request =>
taskForm.bindFromRequest.fold(
errors => BadRequest(views.html.index(Task.all(), errors)),
{
case(id,label,add) => {
/* Call the helper function to append to the file */
writingToFile(s"id : $id, label : $label, add : $add \n")
Task.create(id,label,add)
Redirect(routes.Application.showTask)
}
}
)
}
//..
}
Likewise when other methods are invoked you may append to the file in similar fashion.
Hope it helps :)

Creating a time-based chunking Enumeratee

I want to create a Play 2 Enumeratee that takes in values and outputs them, chunked together, every x seconds/milliseconds. That way, in a multi-user websocket environment with lots of user input, one could limit the number of received frames per second.
I know that it's possible to group a set number of items together like this:
val chunker = Enumeratee.grouped(
Traversable.take[Array[Double]](5000) &>> Iteratee.consume()
)
Is there a built-in way to do this based on time rather than based on the number of items?
I was thinking about doing this somehow with a scheduled Akka job, but on first sight this seems inefficient, and I'm not sure if concurency issues would arise.
How about like this? I hope this is helpful for you.
package controllers
import play.api._
import play.api.Play.current
import play.api.mvc._
import play.api.libs.iteratee._
import play.api.libs.concurrent.Akka
import play.api.libs.concurrent.Promise
object Application extends Controller {
def index = Action {
val queue = new scala.collection.mutable.Queue[String]
Akka.future {
while( true ){
Logger.info("hogehogehoge")
queue += System.currentTimeMillis.toString
Thread.sleep(100)
}
}
val timeStream = Enumerator.fromCallback { () =>
Promise.timeout(Some(queue), 200)
}
Ok.stream(timeStream.through(Enumeratee.map[scala.collection.mutable.Queue[String]]({ queue =>
var str = ""
while(queue.nonEmpty){
str += queue.dequeue + ", "
}
str
})))
}
}
And this document is also helpful for you.
http://www.playframework.com/documentation/2.0/Enumerators
UPDATE
This is for play2.1 version.
package controllers
import play.api._
import play.api.Play.current
import play.api.mvc._
import play.api.libs.iteratee._
import play.api.libs.concurrent.Akka
import play.api.libs.concurrent.Promise
import scala.concurrent._
import ExecutionContext.Implicits.global
object Application extends Controller {
def index = Action {
val queue = new scala.collection.mutable.Queue[String]
Akka.future {
while( true ){
Logger.info("hogehogehoge")
queue += System.currentTimeMillis.toString
Thread.sleep(100)
}
}
val timeStream = Enumerator.repeatM{
Promise.timeout(queue, 200)
}
Ok.stream(timeStream.through(Enumeratee.map[scala.collection.mutable.Queue[String]]({ queue =>
var str = ""
while(queue.nonEmpty){
str += queue.dequeue + ", "
}
str
})))
}
}
Here I've quickly defined an iteratee that will take values from an input for a fixed time length t measured in milliseconds and an enumeratee that will allow you to group and further process an input stream divided into segments constructed within such length t. It relies on JodaTime to keep track of how much time has passed since the iteratee began.
def throttledTakeIteratee[E](timeInMillis: Long): Iteratee[E, List[E]] = {
var startTime = new Instant()
def step(state: List[E])(input: Input[E]): Iteratee[E, List[E]] = {
val timePassed = new Interval(startTime, new Instant()).toDurationMillis
input match {
case Input.EOF => { startTime = new Instant; Done(state, Input.EOF) }
case Input.Empty => Cont[E, List[E]](i => step(state)(i))
case Input.El(e) =>
if (timePassed >= timeInMillis) { startTime = new Instant; Done(e::state, Input.Empty) }
else Cont[E, List[E]](i => step(e::state)(i))
}
}
Cont(step(List[E]()))
}
def throttledTake[T](timeInMillis: Long) = Enumeratee.grouped(throttledTakeIteratee[T](timeInMillis))