         container.once "DataLoaded", ->
           if counter is 1 then do callback
           counter--
+
+  addContainer:(container, pos)->
+    pos ?= x: 40 + @containers.length * 300, y: 40
+    super container, pos
+
+    {name} = container.constructor
+    label  = containerMap[name] or name
+    @boxes[label] = container
+
+  parseItems = (source, target)->
+    items = {}
+    for item in [source, target]
+      items[itemMap[item.dia.constructor.name]] = item
+    return items
+
+  type = (item)->
+    itemMap[item.dia.constructor.name] or null
 
   viewAppended:->
     super


    slider.on 'ValueChanged', (value)=>
      do _.throttle =>
        @setScale (Math.floor value) / 100
class EnvironmentScene extends KDDiaScene

  containerMap =
    EnvironmentDomainContainer  : 'domains'
    EnvironmentMachineContainer : 'machines'
  itemMap      =
    EnvironmentDomainItem       : 'domain'
    EnvironmentMachineItem      : 'machine'

  constructor:->
    super
      cssClass  : 'environments-scene'
      lineWidth : 1
    @boxes = {}

  disconnect:(dia, joint)->

    removeConnection = => KDDiaScene::disconnect.call this, dia, joint
    targetConnection = @findTargetConnection dia, joint
    return unless targetConnection
    {source, target} = targetConnection

    items = parseItems source, target
    {domain, machine} = items
    return unless domain

    @askForApprove items, 'delete', (modal)=>
      if machine? # Remove a domain from a machine
        jDomain = domain.dia.data.domain # JDomain
        vmName  = machine.dia.data.title # JVM.hostnameAlias
        jDomain.unbindVM hostnameAlias: vmName, (err)=>
          modal.destroy()
          return KD.showError err  if err
          jDomain.hostnameAlias.splice jDomain.hostnameAlias.indexOf(vmName), 1
          removeConnection()

  connect:(source, target, internal = no)->

    createConnection = => KDDiaScene::connect.call this, source, target
    return createConnection()  if internal

    items = parseItems source, target
    {domain, machine} = items
    return unless domain

    if machine?
      if domain.dia.data.domain.hostnameAlias.length > 0
        return new KDNotificationView
          title : "A domain name can only be bound to one VM."

    @askForApprove items, 'create', (modal)=>
      if machine? # Assign a domain to a machine
        jDomain = domain.dia.data.domain # JDomain
        vmName  = machine.dia.data.title # JVM.hostnameAlias
        jDomain.bindVM hostnameAlias: vmName, (err)=>
          modal.destroy()
          return KD.showError err  if err
          jDomain.hostnameAlias.push vmName
          createConnection()

  updateConnections:->
    for _, machine of @boxes.machines.dias
      for _, domain of @boxes.domains.dias
        if domain.data.aliases and machine.data.title in domain.data.aliases
          @connect {dia : domain , joint : 'right'}, \
                   {dia : machine, joint : 'left' }, yes

  askForApprove:(items, action, callback)->
    modal = new EnvironmentApprovalModal {action}, items
    modal.once 'Approved', => callback modal

  whenItemsLoadedFor:do->
    # poor man's when/promise implementation ~ GG
