All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.barrybecker4.ui.sliders.SliderGroup.scala Maven / Gradle / Ivy

/* Copyright by Barry G. Becker, 2017. Licensed under MIT License: http://www.opensource.org/licenses/MIT */
package com.barrybecker4.ui.sliders

import com.barrybecker4.common.format.FormatUtil
import javax.swing._
import javax.swing.border.EtchedBorder
import javax.swing.event.ChangeEvent
import javax.swing.event.ChangeListener
import java.awt._
import SliderGroup._


object SliderGroup {
  private val DEFAULT_MIN = 0
  private val DEFAULT_MAX = 100
  private val DEFAULT_INITIAL = 50

  def sliderPropsFromNames(sliderNames: Array[String]): Array[SliderProperties] = {
    val numSliders = sliderNames.length
    val sliderProps = new Array[SliderProperties](numSliders)

    for (i <- 0 until numSliders) {
      sliderProps(i) = new SliderProperties(sliderNames(i), DEFAULT_MIN, DEFAULT_MAX, DEFAULT_INITIAL)
    }
    sliderProps
  }
}

/**
  * A group of horizontal sliders arranged vertically.
  * @author Barry Becker
  */
class SliderGroup(sliderProps: Array[SliderProperties]) extends JPanel with ChangeListener {
  private var sliderListener: SliderGroupChangeListener = _
  private var labels: Array[JLabel] = _
  private var sliders: Array[JSlider] = _
  commonInit(sliderProps)

  /** @param sliderNames used for both identification and labels */
  def this(sliderNames: Array[String]) = {
    this(sliderPropsFromNames(sliderNames))
  }

  protected def getSliderProperties: Array[SliderProperties] = sliderProps

  /** Initialize sliders with floating point values. */
  protected def commonInit(sliderProps: Array[SliderProperties]): Unit = {
    val numSliders = this.sliderProps.length
    labels = new Array[JLabel](numSliders)
    sliders = new Array[JSlider](numSliders)

    for (i <- 0 until numSliders) {
      val scale = this.sliderProps(i).getScale
      val intInitial = (this.sliderProps(i).getInitialValue * scale).toInt
      val intMin = (this.sliderProps(i).getMinValue * scale).toInt
      val intMax = (this.sliderProps(i).getMaxValue * scale).toInt
      labels(i) = new JLabel(getSliderTitle(i, intInitial))
      sliders(i) = new JSlider(SwingConstants.HORIZONTAL, intMin, intMax, intInitial)
      sliders(i).addChangeListener(this)
    }
    buildUI()
  }

  /** return all the sliders to their initial value. */
  def reset(): Unit = {
    for (i <- sliderProps.indices) {
      val initial = (sliderProps(i).getInitialValue * sliderProps(i).getScale).toInt
      sliders(i).setValue(initial)
    }
  }

  def getSliderValueAsInt(sliderIndex: Int): Int = getSliderValue(sliderIndex).toInt

  def getSliderValue(sliderIndex: Int): Double =
    sliderProps(sliderIndex).getScale * sliders(sliderIndex).getValue.toDouble

  def setSliderValue(sliderIndex: Int, value: Double): Unit = {
    val v = value * sliderProps(sliderIndex).getScale
    sliders(sliderIndex).setValue(v.toInt)
    labels(sliderIndex).setText(sliderProps(sliderIndex).getName + " " + FormatUtil.formatNumber(value))
  }

  def setSliderValue(sliderIndex: Int, value: Int): Unit = {
    assert(sliderProps(sliderIndex).getScale == 1.0,
      "you should call setSliderValue(int, double) if you have a slider with real values")
    sliders(sliderIndex).setValue(value)
    labels(sliderIndex).setText(getSliderTitle(sliderIndex, value))
  }

  def setSliderMinimum(sliderIndex: Int, min: Int): Unit = {
    assert(sliderProps(sliderIndex).getScale == 1.0,
      "you should call setSliderMinimum(int, double) if you have a slider with real values")
    sliders(sliderIndex).setMinimum(min)
  }

  def setSliderMinimum(sliderIndex: Int, min: Double): Unit = {
    val mn = min * sliderProps(sliderIndex).getScale
    sliders(sliderIndex).setMinimum(mn.toInt)
  }

  def addSliderChangeListener(listener: SliderGroupChangeListener): Unit = {
    sliderListener = listener
  }

  private def getSliderTitle(index: Int, value: Int) = {
    val title = sliderProps(index).getName + " : "
    if (sliderProps(index).getScale == 1.0) title + FormatUtil.formatNumber(value)
    else title + FormatUtil.formatNumber(value.toDouble / sliderProps(index).getScale)
  }

  private def buildUI(): Unit = {
    setLayout(new BoxLayout(this, BoxLayout.Y_AXIS))
    setBorder(BorderFactory.createEtchedBorder(EtchedBorder.LOWERED))

    for (i <- sliderProps.indices) {
      add(createLabelPanel(labels(i)))
      add(sliders(i))
    }
  }

  private def createLabelPanel(label: JLabel) = {
    val p = new JPanel(new BorderLayout)
    p.add(label, BorderLayout.WEST)
    p.add(new JPanel, BorderLayout.CENTER)
    p
  }

  def setSliderListener(listener: SliderGroupChangeListener): Unit = {
    sliderListener = listener
  }

  /** @param name of the slider to enable or disable.*/
  def setEnabled(name: String, enable: Boolean): Unit = {
    var slider: JSlider = null

    for (i <- sliderProps.indices) {
      if (name == sliderProps(i).getName) slider = sliders(i)
    }
    assert(slider != null, "no slider by the name of " + name)
    slider.setEnabled(enable)
  }

  /**
    * One of the sliders has moved.
    * @param e change event.
    */
  override def stateChanged(e: ChangeEvent): Unit = {
    val src = e.getSource.asInstanceOf[JSlider]

    for (i <- sliderProps.indices) {
      val slider = sliders(i)
      if (src eq slider) {
        val value = slider.getValue
        labels(i).setText(getSliderTitle(i, value))
        if (sliderListener != null) {
          val v = value.toDouble / sliderProps(i).getScale
          sliderListener.sliderChanged(i, sliderProps(i).getName, v)
        }
      }
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy