Sunday, October 18, 2015

Drilling down and climbing up a piechart in Scala

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
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) => {
              //////////////////////////////////////////
              // important: the climbUpData listener only makes sense when the subData is attached to the piechart
              //////////////////////////////////////////
              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
      }
    }
  }

}

object Test {
  BasicPie.main(Array("a"))
}

0 comments: