1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264
|
## -*- tcl -*-
# # ## ### ##### ######## ############# ######################
## (c) 2022 Andreas Kupries
##
## Originally developed within the AKIS project (c) Andreas Kupries
# @@ Meta Begin
# Package map::area::table-table-display 0.1
# Meta author {Andreas Kupries}
# Meta location https://core.tcl.tk/tklib
# Meta platform tcl
# Meta summary Widget to display a table of area definitions
# Meta description Widget to display the information of many area definitions
# Meta description in a table
# Meta subject {area display, tabular}
# Meta subject {tabular, area display}
# Meta require {Tcl 8.6-}
# Meta require {Tk 8.6-}
# Meta require debug
# Meta require debug::caller
# Meta require {map::slippy 0.8}
# Meta require scrollutil
# Meta require snit
# Meta require tablelist
# @@ Meta End
package provide map::area::table-display 0.1
# # ## ### ##### ######## ############# ######################
## API
#
## <class> OBJ store ...
#
## OBJ focus ID
#
## -on-selection Command prefix to report selection changes
#
# # ## ### ##### ######## ############# ######################
## Requirements
package require Tcl 8.6-
package require Tk 8.6-
# ;# Tcllib
package require debug ;# - Narrative Tracing
package require debug::caller ;#
package require map::slippy 0.8 ;# - Map utilities
package require snit ;# - OO system
# ;# Tklib
package require scrollutil ;# - Scroll framework
package require tablelist ;# - Tabular table-display
# # ## ### ##### ######## ############# ######################
## Ensemble setup.
namespace eval map { namespace export area ; namespace ensemble create }
namespace eval map::area { namespace export table-display ; namespace ensemble create }
debug level tklib/map/area/table-display
debug prefix tklib/map/area/table-display {<[pid]> [debug caller] | }
# # ## ### ##### ######## ############# ######################
snit::widget ::map::area::table-display {
# . . .. ... ..... ........ ............. .....................
## User configuration
option -on-selection -default {}
# . . .. ... ..... ........ ............. .....................
## State
#
# - List of shown area definitions
# (per row: id, name, center (lat/lon separate), parts, diameter, perimeter)
# => 7 columns
# id identifies the row, and is mapped back to the AREA id.
#
# - Backward map from row ids to AREA ids
# NOTE: multiple row ids can map to the same area (multiple names!)
#
# - Forward map from area id to the set of rows showing that area
# (set because multiple names)
#
# - Command to access backing store.
variable myspec {} ;# Table data derived from the area specifications
variable myrows {} ;# dict (row-id -> area-id)
variable myareas {} ;# dict (area-id -> row-id -> ".")
variable mystore {} ;# Store backing the display
# FUTURE: event: add/remove/change
# . . .. ... ..... ........ ............. .....................
## Lifecycle
constructor {store args} {
debug.tklib/map/area/table-display {}
$self configurelist $args
set mystore $store
scrollutil::scrollarea $win.sa
tablelist::tablelist $win.sa.table -width 90 \
-columntitles {\# Name Lat Lon Parts Diameter Perimeter}
$win.sa setwidget $win.sa.table
pack $win.sa -in $win -fill both -expand 1
$win.sa.table configure \
-listvariable [myvar myspec] \
-labelcommand tablelist::sortByColumn \
-labelcommand2 tablelist::addToSortColumns
bind $win.sa.table <<TablelistSelect>> [mymethod SelectionChanged]
#DO watch [mymethod StoreChanged] ;# FUTURE: react to edits and
after 100 [mymethod StoreChanged] ;# resulting store changes
return
}
destructor {
debug.tklib/map/area/table-display {}
#DO unwatch [mymethod StoreChanged]
return
}
# . . .. ... ..... ........ ............. .....................
## API
method focus {areaid} {
debug.tklib/map/area/table-display {}
set rowids [dict keys [dict get $myareas $areaid]]
# Locate the rows in the table bearing the rowids for the area
# Search is required because the table may not be sorted in order
set rows [lsort -integer [lmap rowid $rowids {
set pos [lsearch -exact -index 0 $myspec $rowid]
if {$pos < 0} continue
set pos
}]]
# Select all rows, show the highest (by dint of sorting above)
$win.sa.table selection clear 0 end
foreach row $rows {
$win.sa.table selection set $row
$win.sa.table see $row
}
return
}
# . . .. ... ..... ........ ............. .....................
## Internals
proc DO {args} {
debug.tklib/map/area/table-display {}
upvar 1 mystore mystore
return [uplevel #0 [list {*}$mystore {*}$args]]
}
method StoreChanged {args} {
debug.tklib/map/area/table-display {}
# Local storage to assemble the display information in.
set specs {}
set map {}
set areas {}
# Note: Areas with multiple names generate multiple entries in the table, one per name.
# Each such row maps to the same area, and the area will know about all its rows.
foreach areaid [DO ids] {
set spec [DO get $areaid]
# names, geo, center, diameter, perimeter, parts
dict with spec {}
#puts |$areaid|$spec|
# Formatting for display - Ignores geo
set diameter [map slippy pretty-distance $diameter]
set perimeter [map slippy pretty-distance $perimeter]
lassign [map slippy geo limit $center] lat lon
if {![llength $names]} {
# No names, single row with empty name column.
lappend row [incr rowid]
lappend row {}
lappend row $lat
lappend row $lon
lappend row $parts
lappend row $diameter
lappend row $perimeter
lappend specs $row
unset row
dict set map $rowid $areaid
dict set areas $areaid $rowid .
} else {
# One or more names, one row per name
foreach name $names {
lappend row [incr rowid]
lappend row $name
lappend row $lat
lappend row $lon
lappend row $parts
lappend row $diameter
lappend row $perimeter
lappend specs $row
unset row
dict set map $rowid $areaid
dict set areas $areaid $rowid .
}
}
}
# ... and commit
set myrows $map
set myareas $areas
set myspec $specs
return
}
method SelectionChanged {} {
debug.tklib/map/area/table-display {}
after idle [mymethod ReportSelectionChange]
return
}
method ReportSelectionChange {} {
debug.tklib/map/area/table-display {}
if {![llength $options(-on-selection)]} return
# row - index of entry in table, influenced by sorting
# rowid - internal row id as pulled out of entry
# areaid - area id associated to the row id
set row [$win.sa.table curselection]
if {$row eq {}} return
#puts row//[lindex $myspec $row]//
set rowid [lindex $myspec $row 0]
set areaid [dict get $myrows $rowid]
uplevel #0 [list {*}$options(-on-selection) $areaid]
return
}
# . . .. ... ..... ........ ............. .....................
}
# # ## ### ##### ######## ############# ######################
return
|