legend.tcl 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515
  1. ##########################################################################
  2. # legend.tcl - raster legend layer options file for GRASS GIS Manager
  3. # March 2006 Michael Barton, Arizona State University
  4. # COPYRIGHT: (C) 1999 - 2006 by the GRASS Development Team
  5. #
  6. # This program is free software under the GNU General Public
  7. # License (>=v2). Read the file COPYING that comes with GRASS
  8. # for details.
  9. #
  10. ##########################################################################
  11. namespace eval GmLegend {
  12. variable array opt ;# legend current options
  13. variable count 1
  14. variable array lfile ;# raster
  15. variable array lfilemask ;# raster
  16. variable optlist
  17. variable array dup ;# vector
  18. variable llcorner
  19. }
  20. ###############################################################################
  21. # create new legend layer
  22. proc GmLegend::create { tree parent } {
  23. variable opt
  24. variable count
  25. variable lfile
  26. variable lfilemask
  27. variable optlist
  28. variable first
  29. variable dup
  30. set node "legend:$count"
  31. set dup($count) 1
  32. set frm [ frame .legendicon$count]
  33. set check [checkbutton $frm.check \
  34. -variable GmLegend::opt($count,1,_check) \
  35. -height 1 -padx 0 -width 0]
  36. set ico [label $frm.ico -bd 1 -relief raised -text "Leg"]
  37. icon_configure $ico module d.legend
  38. bind $ico <ButtonPress-1> "GmTree::selectn $tree $node"
  39. pack $check $ico -side left
  40. #insert new layer
  41. if {[$tree selection get] != "" } {
  42. set sellayer [$tree index [$tree selection get]]
  43. } else {
  44. set sellayer "end"
  45. }
  46. $tree insert $sellayer $parent $node \
  47. -text "legend $count"\
  48. -window $frm \
  49. -drawcross auto
  50. set opt($count,1,_check) 1
  51. set dup($count) 0
  52. set opt($count,1,map) ""
  53. set opt($count,1,opacity) 1.0
  54. set opt($count,1,color) "black"
  55. set opt($count,1,lines) 0
  56. set opt($count,1,thin) 1
  57. set opt($count,1,font) ""
  58. set opt($count,1,mouseset) 0
  59. set opt($count,1,labelnum) 5
  60. set opt($count,1,at) "5,90"
  61. set opt($count,1,height) 80
  62. set opt($count,1,width) 5
  63. set opt($count,1,use) ""
  64. set opt($count,1,range) ""
  65. set opt($count,1,nolbl) 0
  66. set opt($count,1,noval) 0
  67. set opt($count,1,skip) 0
  68. set opt($count,1,smooth) 0
  69. set opt($count,1,flip) 0
  70. set opt($count,1,mod) 1
  71. set optlist { _check map opacity color lines thin labelnum at height width \
  72. font mouseset use range nolbl noval skip smooth flip}
  73. foreach key $optlist {
  74. set opt($count,0,$key) $opt($count,1,$key)
  75. }
  76. # create files in tmp diretory for layer output
  77. set mappid [pid]
  78. if {[catch {set lfile($count) [exec g.tempfile pid=$mappid]} error]} {
  79. GmLib::errmsg $error [G_msg "Error creating tempfile"]
  80. }
  81. set lfilemask($count) $lfile($count)
  82. append lfile($count) ".ppm"
  83. append lfilemask($count) ".pgm"
  84. incr count
  85. return $node
  86. }
  87. ###############################################################################
  88. proc GmLegend::set_option { node key value } {
  89. variable opt
  90. set id [GmTree::node_id $node]
  91. set opt($id,1,$key) $value
  92. }
  93. ##########################################################################
  94. proc GmLegend::set_font { id } {
  95. variable opt
  96. if {$GmLegend::opt($id,1,font) != "" } {
  97. set Gm::dfont $GmLegend::opt($id,1,font)
  98. }
  99. Gm::defaultfont dlegend
  100. tkwait variable Gm::dfont
  101. set GmLegend::opt($id,1,font) $Gm::dfont
  102. set Gm::dfont ""
  103. }
  104. ##########################################################################
  105. proc GmLegend::mouseset { id } {
  106. # use mouse to set scalebar placement coordinates
  107. global mon pctentry
  108. variable llcorner
  109. variable opt
  110. if { $GmLegend::opt($id,1,mouseset) == 1 } {
  111. set pctentry $GmLegend::llcorner
  112. } else {
  113. set pctentry ""
  114. }
  115. }
  116. ###############################################################################
  117. # select raster map
  118. proc GmLegend::select_map { id } {
  119. variable tree
  120. variable node
  121. set m [GSelect cell title [G_msg "Raster map for legend"] parent "."]
  122. if { $m != "" } {
  123. set GmLegend::opt($id,1,map) $m
  124. GmTree::autonamel [format [G_msg "legend for %s"] $m]
  125. }
  126. }
  127. # Calculate optimal legend height for CELL maps
  128. proc GmLegend::getoptimalvsize { varname key op } {
  129. upvar #0 $varname var
  130. set numclass 0
  131. if {[string length $var($key)] > 0} {
  132. if {![catch {open "|r.info -t map=$var($key)" r} iinput]} {
  133. while {[gets $iinput iline] >= 0} {
  134. if {[string equal "datatype=CELL" "$iline"]} {
  135. if {![catch {open "|r.describe -1 -n --q map=$var($key)" r} dinput]} {
  136. while {[gets $dinput dline] >= 0} {
  137. incr numclass
  138. }
  139. }
  140. }
  141. }
  142. }
  143. if {$numclass > 0} {
  144. set hg [expr {$numclass * 7}]
  145. if {$hg > 80} {
  146. set GmLegend::opt([string index $key 0],1,height) 80
  147. } else {
  148. set GmLegend::opt([string index $key 0],1,height) $hg
  149. }
  150. }
  151. }
  152. }
  153. ###############################################################################
  154. # legend options
  155. proc GmLegend::options { id frm } {
  156. variable opt
  157. variable llcorner
  158. global bgcolor
  159. # Panel heading
  160. set row [ frame $frm.heading1 ]
  161. Label $row.a -text [G_msg "Display legend for raster map using cat values and labels"] \
  162. -fg MediumBlue
  163. pack $row.a -side left
  164. pack $row -side top -fill both -expand yes
  165. #opacity
  166. set row [ frame $frm.opc]
  167. Label $row.a -text [G_msg "Opaque "]
  168. scale $row.b -from 1.0 -to 0.0 -showvalue 1 \
  169. -orient horizontal -length 300 -resolution 0.01 -fg "#656565"\
  170. -variable GmLegend::opt($id,1,opacity)
  171. Label $row.c -text [G_msg " Transparent"]
  172. pack $row.a $row.b $row.c -side left
  173. pack $row -side top -fill both -expand yes
  174. # raster name
  175. set row [ frame $frm.map ]
  176. Label $row.a -text [G_msg "Raster map: "]
  177. Button $row.b -highlightthickness 0 -takefocus 0 -relief raised -borderwidth 1 \
  178. -command "GmLegend::select_map $id"
  179. icon_configure $row.b element cell
  180. Entry $row.c -width 35 -text " $opt($id,1,map)" \
  181. -textvariable GmLegend::opt($id,1,map)
  182. trace add variable GmLegend::opt($id,1,map) write GmLegend::getoptimalvsize
  183. Label $row.d -text " "
  184. Button $row.e -text [G_msg "Help"] \
  185. -command "spawn g.manual --q d.legend" \
  186. -background $bgcolor \
  187. -helptext [G_msg "Help"]
  188. icon_configure $row.e gui help
  189. pack $row.a $row.b $row.c $row.d $row.e -side left
  190. pack $row -side top -fill both -expand yes
  191. # size and location
  192. set row [ frame $frm.at1 ]
  193. Label $row.a -text [G_msg "Legend placement and size as 0-100% of display"]
  194. pack $row.a -side left
  195. pack $row -side top -fill both -expand yes
  196. # at
  197. set row [ frame $frm.at2 ]
  198. Label $row.a -text [G_msg " x,y of lower left corner (in % from display top left)"]
  199. set llcorner [LabelEntry $row.b -width 8 \
  200. -textvariable GmLegend::opt($id,1,at)]
  201. checkbutton $row.c -text [G_msg "place with mouse"] \
  202. -variable GmLegend::opt($id,1,mouseset) \
  203. -command "GmLegend::mouseset $id"
  204. pack $row.a $row.b $row.c -side left
  205. pack $row -side top -fill both -expand yes
  206. # size
  207. set row [ frame $frm.size ]
  208. Label $row.a -text [G_msg " legend height "]
  209. SpinBox $row.b -range {0 100 1} -textvariable GmLegend::opt($id,1,height) \
  210. -width 5 -helptext [G_msg "Legend height (% of display)"]
  211. Label $row.c -text [G_msg "% width"]
  212. SpinBox $row.d -range {0 100 1} -textvariable GmLegend::opt($id,1,width) \
  213. -width 5 -helptext [G_msg "Legend width (% of display)"]
  214. Label $row.e -text "%"
  215. pack $row.a $row.b $row.c $row.d $row.e -side left
  216. pack $row -side top -fill both -expand yes
  217. # text
  218. set row [ frame $frm.color ]
  219. Label $row.a -text [G_msg "Legend appearance: text color"]
  220. ComboBox $row.b -padx 0 -width 10 -textvariable GmLegend::opt($id,1,color) \
  221. -values {"white" "grey" "gray" "black" "brown" "red" "orange" \
  222. "yellow" "green" "aqua" "cyan" "indigo" "blue" "purple" "violet" "magenta"}
  223. Label $row.c -text [G_msg " legend text font "]
  224. Button $row.d -highlightthickness 0 -takefocus 0 -relief raised -borderwidth 1 \
  225. -helptext [G_msg "select font for text"] \
  226. -command "GmLegend::set_font $id"
  227. icon_configure $row.d gui font
  228. pack $row.a $row.b $row.c $row.d -side left
  229. pack $row -side top -fill both -expand yes
  230. # no category labels or numbers
  231. set row [ frame $frm.cats ]
  232. Label $row.a -text " "
  233. checkbutton $row.b -text [G_msg "do not display labels"] -variable \
  234. GmLegend::opt($id,1,nolbl)
  235. checkbutton $row.c -text [G_msg "do not display values"] -variable \
  236. GmLegend::opt($id,1,noval)
  237. pack $row.a $row.b $row.c -side left
  238. pack $row -side top -fill both -expand yes
  239. # display lines
  240. set row [ frame $frm.lines ]
  241. Label $row.a -text [G_msg " number of lines (0=display all):"]
  242. SpinBox $row.b -range {0 1000 1} -textvariable GmLegend::opt($id,1,lines) \
  243. -width 5 -helptext [G_msg "Lines to display"]
  244. Label $row.c -text " "
  245. checkbutton $row.d -text [G_msg "invert legend"] -variable \
  246. GmLegend::opt($id,1,flip)
  247. pack $row.a $row.b $row.c $row.d -side left
  248. pack $row -side top -fill both -expand yes
  249. # thin
  250. set row [ frame $frm.thin ]
  251. Label $row.a -text [G_msg " interval between categories (integer maps)"]
  252. SpinBox $row.b -range {1 1000 1} -textvariable GmLegend::opt($id,1,thin) \
  253. -width 5 -helptext [G_msg "Thinning interval"]
  254. pack $row.a $row.b -side left
  255. pack $row -side top -fill both -expand yes
  256. # labelnum
  257. set row [ frame $frm.labelnum ]
  258. Label $row.a -text " "
  259. checkbutton $row.b -text [G_msg "draw smooth gradient (fp maps)"] -variable \
  260. GmLegend::opt($id,1,smooth)
  261. Label $row.c -text [G_msg "with maximum of"]
  262. SpinBox $row.d -range {2 100 1} -textvariable GmLegend::opt($id,1,labelnum) \
  263. -width 4 -helptext [G_msg "Maximum lines to display for gradient"]
  264. Label $row.e -text [G_msg "lines"]
  265. pack $row.a $row.b $row.c $row.d $row.e -side left
  266. pack $row -side top -fill both -expand yes
  267. # display subset of values
  268. set row [ frame $frm.subset ]
  269. Label $row.a -text [G_msg "Display legend for subset of raster values"]
  270. pack $row.a -side left
  271. pack $row -side top -fill both -expand yes
  272. # skip
  273. set row [ frame $frm.opts ]
  274. Label $row.a -text " "
  275. checkbutton $row.b -text [G_msg "skip categories with no labels"] -variable \
  276. GmLegend::opt($id,1,skip)
  277. pack $row.a $row.b -side left
  278. pack $row -side top -fill both -expand yes
  279. # use cats
  280. set row [ frame $frm.use ]
  281. Label $row.a -text [G_msg " legend for only these categories "]
  282. LabelEntry $row.b -textvariable GmLegend::opt($id,1,use) -width 28
  283. pack $row.a $row.b -side left
  284. pack $row -side top -fill both -expand yes
  285. # range
  286. set row [ frame $frm.range ]
  287. Label $row.a -text [G_msg " legend for only this range of values"]
  288. LabelEntry $row.b -textvariable GmLegend::opt($id,1,range) -width 28
  289. pack $row.a $row.b -side left
  290. pack $row -side top -fill both -expand yes
  291. set opt($id,1,mod) "1"
  292. }
  293. ###############################################################################
  294. #save legend layer to grc file
  295. proc GmLegend::save { tree depth node } {
  296. variable opt
  297. variable optlist
  298. set id [GmTree::node_id $node]
  299. foreach key $optlist {
  300. GmTree::rc_write $depth "$key $opt($id,1,$key)"
  301. }
  302. }
  303. ###############################################################################
  304. # render and composite legend layer
  305. proc GmLegend::display { node mod } {
  306. global mon
  307. global env
  308. variable optlist
  309. variable lfile
  310. variable lfilemask
  311. variable opt
  312. variable tree
  313. variable dup
  314. variable count
  315. set line ""
  316. set input ""
  317. set cmd ""
  318. set tree($mon) $GmTree::tree($mon)
  319. set id [GmTree::node_id $node]
  320. # If we are told dirty (for zoom) force dirty
  321. # Don't remove a dirty from a previous unrendered zoom
  322. if {$mod} {set opt($id,1,mod) 1}
  323. set atlist [split $opt($id,1,at) ","]
  324. set x1 [lindex $atlist 0]
  325. set y1 [expr 100 - [lindex $atlist 1]]
  326. set placement "$y1,[expr $y1+$opt($id,1,height)],$x1,[expr $x1+$opt($id,1,width)]"
  327. if { $opt($id,1,map) == "" } { return }
  328. set cmd "d.legend map=$opt($id,1,map) color=$opt($id,1,color) \
  329. lines=$opt($id,1,lines) thin=$opt($id,1,thin) \
  330. labelnum=$opt($id,1,labelnum) at=$placement"
  331. # use cats
  332. if { $opt($id,1,use) != "" } {
  333. append cmd " use=$opt($id,1,use)"
  334. }
  335. # range
  336. if { $opt($id,1,range) != "" } {
  337. append cmd " range=$opt($id,1,range)"
  338. }
  339. # nolbl
  340. if { $opt($id,1,nolbl) != 0 } {
  341. append cmd " -v"
  342. }
  343. # noval
  344. if { $opt($id,1,noval) != 0 } {
  345. append cmd " -c"
  346. }
  347. # skip
  348. if { $opt($id,1,skip) != 0} {
  349. append cmd " -n"
  350. }
  351. # smooth
  352. if { $opt($id,1,smooth) != 0 } {
  353. append cmd " -s"
  354. }
  355. # flip
  356. if { $opt($id,1,flip) != 0 } {
  357. append cmd " -f"
  358. }
  359. # check value of GRASS_FONT variable prior to display
  360. if {![catch {set env(GRASS_FONT)}]} {
  361. set currfont $env(GRASS_FONT)
  362. } else {
  363. set currfont "romans"
  364. }
  365. # set grass font environmental variable to user selection"
  366. if { $GmLegend::opt($id,1,font) != ""} { set env(GRASS_FONT) $GmLegend::opt($id,1,font) }
  367. # Decide whether to run, run command, and copy files to temp
  368. GmCommonLayer::display_command [namespace current] $id $cmd
  369. # set grass font environmental variable to whatever it was when we started
  370. # this lets different text layers have different fonts
  371. set env(GRASS_FONT) $currfont
  372. }
  373. ###############################################################################
  374. # duplicate legend layer
  375. proc GmLegend::duplicate { tree parent node id } {
  376. variable optlist
  377. variable lfile
  378. variable lfilemask
  379. variable opt
  380. variable count
  381. variable dup
  382. set node "legend:$count"
  383. set frm [ frame .legendicon$count]
  384. set check [checkbutton $frm.check \
  385. -variable GmLegend::opt($count,1,_check) \
  386. -height 1 -padx 0 -width 0]
  387. set ico [label $frm.ico -bd 1 -relief raised -text "Leg"]
  388. icon_configure $ico module d.legend
  389. bind $ico <ButtonPress-1> "GmTree::selectn $tree $node"
  390. pack $check $ico -side left
  391. # where to insert new layer
  392. if {[$tree selection get] != "" } {
  393. set sellayer [$tree index [$tree selection get]]
  394. } else {
  395. set sellayer "end"
  396. }
  397. if { $opt($id,1,map) == ""} {
  398. $tree insert $sellayer $parent $node \
  399. -text "legend $count" \
  400. -window $frm \
  401. -drawcross auto
  402. } else {
  403. $tree insert $sellayer $parent $node \
  404. -text "legend for $opt($id,1,map)" \
  405. -window $frm \
  406. -drawcross auto
  407. }
  408. set opt($count,1,opacity) $opt($id,1,opacity)
  409. set optlist { _check map opacity color lines thin labelnum at height width \
  410. mouseset use range nolbl noval skip smooth flip}
  411. foreach key $optlist {
  412. set opt($count,1,$key) $opt($id,1,$key)
  413. set opt($count,0,$key) $opt($count,1,$key)
  414. }
  415. set id $count
  416. # create files in tmp directory for layer output
  417. set mappid [pid]
  418. if {[catch {set lfile($count) [exec g.tempfile pid=$mappid]} error]} {
  419. GmLib::errmsg $error [G_msg "Error creating tempfile"]
  420. }
  421. set lfilemask($count) $lfile($count)
  422. append lfile($count) ".ppm"
  423. append lfilemask($count) ".pgm"
  424. incr count
  425. return $node
  426. }