     initPhase2()
   }
   
-  required public init?(coder aDecoder: NSCoder) {
+  required init?(coder aDecoder: NSCoder) {
     super.init(coder: aDecoder)
     initPhase2()
   }
   
-  fileprivate func initPhase2() {
-    backgroundColor = .white
-    layer.addSublayer(trackLine)
-    trackLine.masksToBounds = true
-    trackLine.backgroundColor = UIColor.clear.cgColor
-    
-    trackLine.addSublayer(maxLine)
-    trackLine.addSublayer(minLine)
-    maxLine.backgroundColor  = maximumTrackTintColor.cgColor
-    minLine.backgroundColor = minimumTrackTintColor.cgColor
-    layer.addSublayer(selector)
-    
-    isMultipleTouchEnabled = false
-    layoutTrackLine()
-    
-    guard let font = getFont(bold: true) else {
+  private func initPhase2() {
+    nameLabel.translatesAutoresizingMaskIntoConstraints = false
+    slider.translatesAutoresizingMaskIntoConstraints = false
+    
+    addSubview(nameLabel)
+    addSubview(slider)
+    
+    guard let font = getAdaptiveFont(bold: true) else {
       return
     }
     
-    let nsString = NSString(string: "text String")
+    let nsString = NSString(string: "text string")
     let textSize = nsString.size(attributes: [NSFontAttributeName : font])
     textHeight = textSize.height
-  }
-  
-  override public var intrinsicContentSize: CGSize {
-    var height = selectorSize.height + (Constants.vertPad * 2)
-    height += textHeight + Constants.vertPad
-    
-    guard let font = getFont(bold: true) else {
+    
+    NSLayoutConstraint.activate([
+      nameLabel.topAnchor.constraint(equalTo: topAnchor),
+      nameLabel.leadingAnchor.constraint(equalTo: leadingAnchor),
+      
+      slider.topAnchor.constraint(equalTo: nameLabel.bottomAnchor, constant: Constants.vertPad),
+      slider.leadingAnchor.constraint(equalTo: leadingAnchor),
+      slider.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -Constants.sliderHorzInsets),
+      slider.heightAnchor.constraint(equalToConstant: Constants.sliderHeight),
+      ])
+    
+    slider.addTarget(self, action: #selector(DiscreteSlider.sliderTouchedUpInside(_:)),
+                     for: .touchUpInside)
+    
+    slider.addTarget(self, action: #selector(DiscreteSlider.sliderValueChanged(_:)),
+                     for: .valueChanged)
+  }
+  
+  override var intrinsicContentSize: CGSize {
+    var height =  nameLabel.intrinsicContentSize.height + Constants.vertPad
+    height += slider.intrinsicContentSize.height
+    height += textHeight
+    
+    guard let font = getAdaptiveFont(bold: true) else {
       return CGSize(width: 100.0, height: height)
     }
     

    return CGSize(width: width, height: height)
  }
  
  override public func layoutSubviews() {
    super.layoutSubviews()
    layoutTrackLine()
    calculateLittleBallRects()
    recalculateThumbX()
    setNeedsDisplay()
  }
  
  fileprivate func recalculateThumbX() {
    guard trackRect.width > 0, values.count > 1 else {
      return
    }
  
    thumbX = trackRect.width / CGFloat(values.count - 1) * CGFloat(discreteValue)
  }
  
  fileprivate func layoutTrackLine() {
    let trackSize : CGSize = CGSize(width: frame.width, height: trackHeight)
    
    trackRect = CGRect(x: 0, y: (frame.height - trackSize.height) / 2,
      width: trackSize.width, height: trackSize.height)
    
    setNeedsDisplay()
  }
  
  fileprivate func calculateLittleBallRects() {
    ballRects.removeAll()
    let width : CGFloat = bounds.width
    let extra = ceil(bounds.height / 2.0)
    let y = bounds.origin.y + extra
    let cx = width / CGFloat(values.count - 1)
    maxTextWidthAllowed = cx
    
    for i in 0..<self.values.count {
      let px : CGFloat = CGFloat(i) * cx + self.ballRadius
      let center : CGPoint = CGPoint(x: px, y: y)
      var rect = CGRect(x: center.x - self.ballRadius,
        y: center.y - self.ballRadius, width: self.ballRadius * 2.0,
        height: self.ballRadius * 2.0)
      
      if i == self.values.count - 1 {
        let rectOriginX = rect.origin.x
        let newRectOriginX = self.bounds.width - (self.ballRadius * 2)
        let offsetX = newRectOriginX - rectOriginX
        rect = rect.offsetBy(dx: offsetX, dy: 0.0)
      }
      
      ballRects.append(rect)
    }
  }
  
  override public func touchesBegan(_ touches: Set<UITouch>,
    with event: UIEvent?) {
    
    guard let location = locationOfFirstTouch(inTouches: touches) else {
      return
    }
    let thumbcenter = thumbX + ballRadius
    touchOffsetX = location.x - thumbcenter
  }
  
  override public func touchesMoved(_ touches: Set<UITouch>,
    with event: UIEvent?) {
    
    guard let location = locationOfFirstTouch(inTouches: touches) else {
      return
    }
    
    let desiredX = desiredThumbX(touchX: location.x)
    moveThumbTo(x: desiredX, animationDuration: 0.0)
  }
  
  override public func touchesEnded(_ touches: Set<UITouch>,
    with event: UIEvent?) {
    
    guard let location = locationOfFirstTouch(inTouches: touches) else {
      return
    }
    
    let desiredX = desiredThumbX(touchX: location.x)
    moveThumbTo(x: desiredX, animationDuration: 0.0, discrete: true)
    touchOffsetX = 0.0
  }
  
  fileprivate func desiredThumbX(touchX : CGFloat) -> CGFloat {
    return touchX - touchOffsetX
  }
  
  fileprivate func locationOfFirstTouch(inTouches touches : Set<UITouch>)
    -> CGPoint? {
      
    guard let touch = touches.first else {
      return nil
    }
    return touch.location(in: touch.view)
  }
  
  fileprivate func showDiscretion(value : CGFloat) -> Int {
    guard values.count > 1, value >= 0.0, trackRect.width > 0 else {
      return 0
    }
    
    let scaledToValueSetValue = value / trackRect.width *
      CGFloat(values.count - 1)
    
    var intValue = Int(scaledToValueSetValue)
    if scaledToValueSetValue - CGFloat(intValue) > 0.5 {
      intValue += 1
    }
    return intValue
  }

  
  override public func draw(_ rect: CGRect) {
    super.draw(rect)
    
    drawTrackLine()
    guard let context = UIGraphicsGetCurrentContext() else {
      return
    }
    
    let currentThumbCenter = thumbX + selectorRadius
    
    for i in 0..<ballRects.count {
      let ballRect = ballRects[i]
      context.saveGState()
      let ball = UIBezierPath(ovalIn: ballRect)
      // The zeroth ball is always painted the max color
      if ballRect.origin.x < currentThumbCenter  || i == 0 {
        maximumTrackTintColor.setFill()
        ball.fill()
      } else {
        minimumTrackTintColor.setFill()
        ball.fill()
      }
      context.restoreGState()
    }
    
    drawThumb()
    drawLabels()
  }
  
  fileprivate func drawLabels() {
    let tuple = getTextRectFontsAndCollisionInfo()
    let textRectFonts = tuple.0
    let collision = tuple.1

      }
      
      let textRect = CGRect(x: x,
                            y: sliderBottom + Constants.vertPad, width: textSize.width,
                            height: textSize.height)
      
      if i > 0 {
        // pad things out a bit, and chec for collision.
        let prevRect = rectFonts[i - 1].rect.insetBy(dx: -Constants.horzPad, dy: 0.0)
        let curRect = textRect.insetBy(dx: -Constants.horzPad, dy: 0.0)
        
