File: area-table-display.tcl

package info (click to toggle)
tklib 0.9-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 23,156 kB
  • sloc: tcl: 105,088; sh: 2,573; ansic: 792; pascal: 359; makefile: 69; sed: 53; exp: 21
file content (264 lines) | stat: -rw-r--r-- 7,318 bytes parent folder | download
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