# copyright (C) 1997-2006 Jean-Luc Fontaine (mailto:jfontain@free.fr)
# this program is free software: please read the COPYRIGHT file enclosed in this package or use the Help Copyright menu

# $Id: viewtab.tcl,v 1.22 2006/01/28 19:16:59 jfontain Exp $


class viewTable {

if {$global::withGUI} { ;# >8
    set (monitorInstanceCellsMessage) [mc {in database history mode, can only monitor cells from a module instance data table}]
} ;# >8

    proc viewTable {this args} {
        set ($this,nextRow) 0
    }

    proc ~viewTable {this} {
        variable ${this}cellRow

        catch {unset ${this}cellRow}
if {$global::withGUI} { ;# >8
        delete $($this,dataTable)
} ;# >8
        set dataName $($this,dataName)
        incr ${dataName}(updates)                                              ;# so related viewers can show cells have disappeared
        unset $dataName
    }

if {$global::withGUI} { ;# >8

    proc createTable {this dataName dragDataCommand} {
        if {[info exists ($this,dataTable)]} {                                                             ;# useful in history mode
            delete $($this,dataTable)
            unset ($this,dataTable)
        }
        # wait till after completion before creating table since some options are not dynamically settable
        set table [new dataTable $widget::($this,path)\
            -data $dataName -draggable $composite::($this,-draggable) -background $viewer::(background)\
        ]
        ### hack: drag and drop code should be separated from dataTable which should provide a selected member procedure ###
        # allow dropping of data cells ### use same path as drag path to avoid drops in table from table ###
        viewer::setupDropSite $this $dataTable::($table,tablePath)
        if {$composite::($this,-draggable)} {
            # extend data table drag capabilities ### hack ### also eventually allow row selection only instead of cells ###
            dragSite::provide $dataTable::($table,drag) OBJECTS $dragDataCommand
            # intercept original data cells dragging
            dragSite::provide $dataTable::($table,drag) DATACELLS $dragDataCommand
        }
        pack $widget::($table,path) -fill both -expand 1
        set ($this,dataTable) $table
        set ($this,dataName) $dataName
    }

} else { ;# >8

    proc setDataName {this name} {
        set ($this,dataName) $name
    }

} ;# >8

    proc cells {this} {                                                           ;# return cells in creation (increasing row) order
        variable ${this}cellRow

        set lists {}
        foreach {cell row} [array get ${this}cellRow] {
            lappend lists [list $row $cell]
        }
        set cells {}
        foreach list [lsort -integer -index 0 $lists] {
            lappend cells [lindex $list end]
        }
        return $cells
    }

    proc setCellRows {this rows} {                                                   ;# restore cell to row mapping from a save file
        set ($this,cellRows) $rows
        set ($this,cellRowIndex) 0                                                      ;# initialize cell row index in list of rows
    }

    proc row {this cell} {
        variable ${this}cellRow

        set row {}
        catch {set row [set ${this}cellRow($cell)]}
        return $row
    }

    proc register {this cell array} {
        variable ${this}cellRow

        viewer::registerTrace $this $array
        if {[info exists ($this,cellRowIndex)]} {                                    ;# restore cell row from recorded configuration
            set row [lindex $($this,cellRows) $($this,cellRowIndex)]
            if {$row eq ""} {                                    ;# rows list exhausted: we are done initializing from recorded data
                unset ($this,cellRowIndex) ($this,cellRows)
                set row $($this,nextRow)
            } else {
                incr ($this,cellRowIndex)                                                             ;# get ready for upcoming cell
                if {$($this,nextRow) < $row} {set ($this,nextRow) $row}                ;# make sure to eliminate potential conflicts
            }
        } else {
            set row $($this,nextRow)                                                                 ;# next row for this data table
        }
        set ${this}cellRow($cell) $row                                                                          ;# remember cell row
        incr ($this,nextRow)
        return $row
    }

    proc cellsAndRows {this} {
        variable ${this}cellRow

        return [array get ${this}cellRow]
    }

if {$global::withGUI} { ;# >8

    proc dragCells {this} {
        variable ${this}cellRow

        foreach {cell row} [array get ${this}cellRow] {                                          ;# revert original cell/row mapping
            set original($row) $cell
        }
        set cells {}
        foreach cell [dataTable::dragData $($this,dataTable) DATACELLS] {
            viewer::parse $cell array row column type
            if {$column == 1} {                         ;# current value: replace with original cell to propagate color, for example
                lappend cells $original($row)
            } else {
                lappend cells $cell
            }
        }
        return $cells
    }

    proc deleteRow {this cell} {
        variable ${this}cellRow

        viewer::parse $cell array ignore ignore ignore
        viewer::unregisterTrace $this $array
        set row [set ${this}cellRow($cell)]
        unset ${this}cellRow($cell)
        return $row
    }

    # data index is needed so that data array that other eventual data viewers depend on is reused when initializing from save file
    proc initializationConfiguration {this} {
        variable ${this}cellRow

        scan [namespace tail $($this,dataName)] %u index                                            ;# retrieve index from data name
        set list [list -dataindex $index]
        foreach cell [cells $this] {                                                                            ;# in creation order
            lappend rows [set ${this}cellRow($cell)]
        }
        if {[info exists rows]} {
            lappend list -cellrows $rows
        }
        return $list
    }

    proc numberOfRows {this} {
        variable ${this}cellRow

        return [array size ${this}cellRow]
    }

    proc monitored {this cell} {
        variable ${this}cellRow

        # either a current value cell or an internally generated cell:
        return [expr {[info exists ${this}cellRow($cell)] || [dataTable::monitored $($this,dataTable) $cell]}]
    }

    proc setCellColor {this source color} {         ;# useful for current value cell only, others are handled directly by data table
        variable ${this}cellRow

        foreach {cell row} [array get ${this}cellRow] {
            if {$cell eq $source} {
                dataTable::setCellColor $($this,dataTable) $row 1 $color
                return
            }
        }
    }

    proc selectedRows {this format} {                                                   ;# gather rows with at least 1 selected cell
        foreach cell [dataTable::dragData $($this,dataTable) $format] {
            regexp {\(([^,]+)} $cell dummy row
            set selected($row) {}
        }
        return [array names selected]
    }

    proc update {this} {
        dataTable::update $($this,dataTable)
    }

    proc updateLabels {this} {
        variable ${this}cellRow

        set dataName $($this,dataName)
        foreach {cell row} [array get ${this}cellRow] {
            viewer::parse $cell array cellRow cellColumn ignore
            set ${dataName}($row,0) [lindex [viewer::label $array $cellRow $cellColumn] 0]
        }
        incr ${dataName}(updates)                                                                    ;# let data table update itself
    }

    proc updateTitleLabels {this} {
        dataTable::updateTitleLabels $($this,dataTable)
    }

} ;# >8

}
