function Controller(title, panel, nester, parent) {

    if (!arguments.length)
        return
    this.title = title || "Unnamed Board"
    if (panel instanceof Panel)
        this.panel = panel
    else
        this.panel = new Panel(html_node(panel))
    this.parent = parent || null
    this.nester = nester
    this.canvas_view = {}
    this.board = new Board(this, this.title, this.get_parent_html_node(), {
        id: this.title.underscore()
    })
    this.item = this.board.views
}

Controller.prototype.get_canvas_views = function (prefix) {
    prefix = prefix || ""
    var result = []
    Object.keys(this.canvas_view).forEach( (nam, i) => {
        result.push( [prefix + this.title.underscore() + "_" + nam, this.canvas_view[nam]])
    })
    return result
}

Controller.prototype.get_parent_html_node = function() {
    if (!this.parent)
        return document.getElementById("specimen_tree")
    return this.parent.board.node
}

Controller.prototype.add_view = function(control, par_view, name) {
    this.cont[name] = control
    this.panel.add_control(control.dom(), par_view)
}

Controller.prototype.add_curve = function(name, data, actions) {
    var item = new ItemCurve(this, data, name, actions)
    this.register(name, item)
    this.panel.add(item)
}

Controller.prototype.register = function(name, item) {
    this.item[name] = item.owner
    return this
}

Controller.prototype.get_active_data = function() {
    alert("Virtual method get_active_data. Please redefine.")
}

Controller.prototype.cast = function(action, result) {
    alert("Virtula method cast. You must redefine your event handler.")
}

Controller.prototype.total_active_points = function() {
    alert("Virtual method active_points. You must redifine a point counter.")
}

Controller.prototype.refresh = function() {
    if (this.board && this.board.update_info && this.info) {
        this.board.update_info(this.info())
        if (this.parent)
            this.parent.cast("update_info")
    }

    this.nester.cast("panel_change")
    this.nester.cast("canvas_update")
}