       @emitter.emit 'did-update-progress', global
 
     span
+
+  # UI logic
+  showOnHover: ->
+    timer = null
+    @view.onmouseover = =>
+      clearTimeout timer
+      @overlay.style.display = 'block' unless @hasNoDeterminateBars()
+    @view.onmouseout  = => timer = setTimeout (=> @overlay.style.display = 'none' ), 150
+    @overlay.onmouseover = => clearTimeout timer
+    @overlay.onmouseout  = => timer = setTimeout (=> @overlay.style.display = 'none' ), 150
+
+  positionOverlay: ->
+    bounding = @view.getBoundingClientRect()
+    @overlay.style.bottom   = bounding.height + 'px'
+    @overlay.style.left     = bounding.left + 'px'
+    @overlay.style.minWidth = bounding.width + 'px'


    div

  showOnHover: ->
    timer = null
    @view.onmouseover = =>
      clearTimeout timer
      @overlay.style.display = 'block' unless @hasNoDeterminateBars()
    @view.onmouseout  = => timer = setTimeout (=> @overlay.style.display = 'none' ), 150
    @overlay.onmouseover = => clearTimeout timer
    @overlay.onmouseout  = => timer = setTimeout (=> @overlay.style.display = 'none' ), 150

  positionOverlay: ->
    bounding = @view.getBoundingClientRect()
    @overlay.style.bottom   = bounding.height + 'px'
    @overlay.style.left     = bounding.left + 'px'
    @overlay.style.minWidth = bounding.width + 'px'

  emptyProgress: (id = 'empty') ->
    id: id
    determinate: true
    progress: 0

  indeterminateProgress: (id = 'indeterminate') ->
    id: id
    determinate: false

  tileView: ->
    span = document.createElement 'span'
    span.classList.add 'inline-block'

    @activate()
    i = @stack.findIndex (e) -> e.id is p.id
    return if i < 0
    oldp = @stack[i]
    @stack[i] = p
    @emitter.emit 'did-update-progress', p
    # if p.determinate changes, update the stack display
    @emitter.emit 'did-update-stack' unless oldp.determinate is p.determinate

  emptyStack: () ->
    @stack = []
    @emitter.emit 'did-update-stack'

  emptyProgress: (id = 'empty') ->
    id: id
    determinate: true
    progress: 0

  indeterminateProgress: (id = 'indeterminate') ->
    id: id
    determinate: false

  # update logic
  hasNoDeterminateBars: ->
    @stack.filter((p) => p.determinate).length is 0

