profile.py 54 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411
  1. """
  2. @package profile
  3. Profile analysis of GRASS raster maps and images.
  4. Uses PyPlot (wx.lib.plot.py)
  5. Classes:
  6. - ProfileFrame
  7. - SetRasterDialog
  8. - TextDialog
  9. - OptDialog
  10. COPYRIGHT: (C) 2007-2008 by the GRASS Development Team
  11. This program is free software under the GNU General Public
  12. License (>=v2). Read the file COPYING that comes with GRASS
  13. for details.
  14. @author Michael Barton
  15. Various updates: Martin Landa <landa.martin gmail.com>
  16. """
  17. import os
  18. import sys
  19. import math
  20. import wx
  21. import wx.lib.colourselect as csel
  22. try:
  23. import wx.lib.plot as plot
  24. except:
  25. msg= """
  26. This module requires the NumPy module,
  27. which could not be imported. It probably is not installed
  28. (it's not part of the standard Python distribution). See the
  29. Numeric Python site (http://numpy.scipy.org) for information on
  30. downloading source or binaries."""
  31. print >> sys.stderr, "profile.py: " + msg
  32. import globalvar
  33. try:
  34. import subprocess
  35. except:
  36. CompatPath = os.path.join(globalvar.ETCWXDIR)
  37. sys.path.append(CompatPath)
  38. from compat import subprocess as subprocess
  39. import render
  40. import menuform
  41. import disp_print
  42. import gselect
  43. import gcmd
  44. import toolbars
  45. from debug import Debug as Debug
  46. from icon import Icons as Icons
  47. from preferences import globalSettings as UserSettings
  48. import grass
  49. class ProfileFrame(wx.Frame):
  50. """
  51. Mainframe for displaying profile of raster map. Uses wx.lib.plot.
  52. """
  53. def __init__(self, parent=None, id=wx.ID_ANY, title=_("Profile Analysis"),
  54. rasterList=[],
  55. pos=wx.DefaultPosition, size=wx.DefaultSize,
  56. style=wx.DEFAULT_FRAME_STYLE):
  57. self.parent = parent # MapFrame
  58. self.mapwin = self.parent.MapWindow
  59. self.Map = render.Map() # instance of render.Map to be associated with display
  60. self.pstyledict = { 'solid' : wx.SOLID,
  61. 'dot' : wx.DOT,
  62. 'long-dash' : wx.LONG_DASH,
  63. 'short-dash' : wx.SHORT_DASH,
  64. 'dot-dash' : wx.DOT_DASH }
  65. self.ptfilldict = { 'transparent' : wx.TRANSPARENT,
  66. 'solid' : wx.SOLID }
  67. wx.Frame.__init__(self, parent, id, title, pos, size, style)
  68. #
  69. # Icon
  70. #
  71. self.SetIcon(wx.Icon(os.path.join(globalvar.ETCICONDIR, 'grass_map.ico'), wx.BITMAP_TYPE_ICO))
  72. #
  73. # Add toolbar
  74. #
  75. self.toolbar = toolbars.ProfileToolbar(parent=self, tbframe=self).GetToolbar()
  76. self.SetToolBar(self.toolbar)
  77. #
  78. # Set the size & cursor
  79. #
  80. self.SetClientSize(size)
  81. #
  82. # Add statusbar
  83. #
  84. self.statusbar = self.CreateStatusBar(number=2, style=0)
  85. self.statusbar.SetStatusWidths([-2, -1])
  86. #
  87. # Define canvas
  88. #
  89. # plot canvas settings
  90. self.client = plot.PlotCanvas(self)
  91. #define the function for drawing pointLabels
  92. self.client.SetPointLabelFunc(self.DrawPointLabel)
  93. # Create mouse event for showing cursor coords in status bar
  94. self.client.canvas.Bind(wx.EVT_LEFT_DOWN, self.OnMouseLeftDown)
  95. # Show closest point when enabled
  96. self.client.canvas.Bind(wx.EVT_MOTION, self.OnMotion)
  97. #
  98. # Init variables
  99. #
  100. # 0 -> default raster map to profile
  101. # 1, 2 -> optional raster map to profile
  102. # units -> map data units (used for y axis legend)
  103. self.raster = {}
  104. for idx in (0, 1, 2):
  105. self.raster[idx] = {}
  106. self.raster[idx]['name'] = ''
  107. self.raster[idx]['units'] = ''
  108. self.raster[idx]['plegend'] = ''
  109. # list of distance,value pairs for plotting profile
  110. self.raster[idx]['datalist'] = []
  111. # first (default) profile line
  112. self.raster[idx]['pline'] = None
  113. self.raster[idx]['prop'] = UserSettings.Get(group='profile', key='raster' + str(idx))
  114. # set raster map name (if given)
  115. for idx in range(len(rasterList)):
  116. self.raster[idx]['name'] = rasterList[idx]
  117. # string of coordinates for r.profile
  118. self.coordstr = ''
  119. # segment endpoint list
  120. self.seglist = []
  121. # list of things to plot
  122. self.plotlist = []
  123. # segment endpoints data
  124. self.ppoints = ''
  125. # plot draw object
  126. self.profile = None
  127. # title of window
  128. self.ptitle = _('Profile of')
  129. # determine units (axis labels)
  130. if self.parent.Map.projinfo['units'] != '':
  131. self.xlabel = _('Distance (%s)') % self.parent.Map.projinfo['units']
  132. else:
  133. self.xlabel = _("Distance along transect")
  134. self.ylabel = _("Cell values")
  135. self.properties = {}
  136. self.properties['font'] = {}
  137. self.properties['font']['prop'] = UserSettings.Get(group='profile', key='font')
  138. self.properties['font']['wxfont'] = wx.Font(11, wx.FONTFAMILY_SWISS,
  139. wx.FONTSTYLE_NORMAL,
  140. wx.FONTWEIGHT_NORMAL)
  141. self.properties['marker'] = UserSettings.Get(group='profile', key='marker')
  142. self.properties['grid'] = UserSettings.Get(group='profile', key='grid')
  143. self.properties['x-axis'] = {}
  144. self.properties['x-axis']['prop'] = UserSettings.Get(group='profile', key='x-axis')
  145. self.properties['x-axis']['axis'] = None
  146. self.properties['y-axis'] = {}
  147. self.properties['y-axis']['prop'] = UserSettings.Get(group='profile', key='y-axis')
  148. self.properties['y-axis']['axis'] = None
  149. self.properties['legend'] = UserSettings.Get(group='profile', key='legend')
  150. # zooming disabled
  151. self.zoom = False
  152. # draging disabled
  153. self.drag = False
  154. # vertical and horizontal scrollbars
  155. self.client.SetShowScrollbars(True)
  156. # x and y axis set to normal (non-log)
  157. self.client.setLogScale((False, False))
  158. if self.properties['x-axis']['prop']['type']:
  159. self.client.SetXSpec(self.properties['x-axis']['prop']['type'])
  160. else:
  161. self.client.SetXSpec('auto')
  162. if self.properties['y-axis']['prop']['type']:
  163. self.client.SetYSpec(self.properties['y-axis']['prop']['type'])
  164. else:
  165. self.client.SetYSpec('auto')
  166. #
  167. # Bind various events
  168. #
  169. self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
  170. self.CentreOnScreen()
  171. def OnDrawTransect(self, event):
  172. """
  173. Draws transect to profile in map display
  174. """
  175. self.mapwin.polycoords = []
  176. self.seglist = []
  177. self.mapwin.ClearLines(self.mapwin.pdc)
  178. self.ppoints = ''
  179. self.parent.SetFocus()
  180. self.parent.Raise()
  181. self.mapwin.mouse['use'] = 'profile'
  182. self.mapwin.mouse['box'] = 'line'
  183. self.mapwin.pen = wx.Pen(colour='Red', width=2, style=wx.SHORT_DASH)
  184. self.mapwin.polypen = wx.Pen(colour='dark green', width=2, style=wx.SHORT_DASH)
  185. self.mapwin.SetCursor(self.Parent.cursors["cross"])
  186. def OnSelectRaster(self, event):
  187. """
  188. Select raster map(s) to profile
  189. """
  190. dlg = SetRasterDialog(parent=self)
  191. if dlg.ShowModal() == wx.ID_OK:
  192. for r in self.raster.keys():
  193. self.raster[r]['name'] = dlg.raster[r]['name']
  194. # plot profile
  195. if self.raster[0]['name'] and len(self.mapwin.polycoords) > 0:
  196. self.OnCreateProfile(event=None)
  197. dlg.Destroy()
  198. def SetRaster(self):
  199. """
  200. Create coordinate string for profiling. Create segment list for
  201. transect segment markers.
  202. """
  203. #
  204. # create list of coordinate points for r.profile
  205. #
  206. dist = 0
  207. cumdist = 0
  208. self.coordstr = ''
  209. lasteast = lastnorth = None
  210. if len(self.mapwin.polycoords) > 0:
  211. for point in self.mapwin.polycoords:
  212. # build string of coordinate points for r.profile
  213. if self.coordstr == '':
  214. self.coordstr = '%d,%d' % (point[0], point[1])
  215. else:
  216. self.coordstr = '%s,%d,%d' % (self.coordstr, point[0], point[1])
  217. if self.raster[0]['name'] == '':
  218. return
  219. # title of window
  220. self.ptitle = _('Profile of')
  221. #
  222. # create datalist for each raster map
  223. #
  224. for r in self.raster.itervalues():
  225. if r['name'] == '':
  226. continue
  227. r['datalist'] = self.CreateDatalist(r['name'], self.coordstr)
  228. r['plegend'] = _('Profile of %s') % r['name']
  229. ret = gcmd.RunCommand('r.info',
  230. parent = self,
  231. read = True,
  232. quiet = True,
  233. flags = 'u',
  234. map = r['name'])
  235. if ret:
  236. r['units'] = p.split('\n')[0].split('=')[1]
  237. # update title
  238. self.ptitle += ' %s and' % r['name']
  239. self.ptitle = self.ptitle.rstrip('and')
  240. #
  241. # set ylabel to match units if they exist
  242. #
  243. self.ylabel = ''
  244. i = 0
  245. for r in self.raster.itervalues():
  246. if r['name'] == '':
  247. continue
  248. if r['units'] != '':
  249. self.ylabel = '%s (%d),' % (r['units'], i)
  250. i += 1
  251. if self.ylabel == '':
  252. self.ylabel = _('Raster values')
  253. else:
  254. self.ylabel = self.ylabel.rstrip(',')
  255. #
  256. # create list of coordinates for transect segment markers
  257. #
  258. if len(self.mapwin.polycoords) > 0:
  259. for point in self.mapwin.polycoords:
  260. # get value of raster cell at coordinate point
  261. ret = gcmd.RunCommand('r.what',
  262. parent = self,
  263. read = True,
  264. input = self.raster[0]['name'],
  265. east_north = '%d,%d' % (point[0],point[1]))
  266. outlist = ret.split('\n')
  267. val = outlist[0].split('|')[3]
  268. # calculate distance between coordinate points
  269. if lasteast and lastnorth:
  270. dist = math.sqrt(math.pow((lasteast-point[0]),2) + math.pow((lastnorth-point[1]),2))
  271. cumdist += dist
  272. # build a list of distance,value pairs for each segment of transect
  273. self.seglist.append((cumdist,val))
  274. lasteast = point[0]
  275. lastnorth = point[1]
  276. # delete first and last segment point
  277. try:
  278. self.seglist.pop(0)
  279. self.seglist.pop()
  280. except:
  281. pass
  282. def SetGraphStyle(self):
  283. """
  284. Set plot and text options
  285. """
  286. self.client.SetFont(self.properties['font']['wxfont'])
  287. self.client.SetFontSizeTitle(self.properties['font']['prop']['titleSize'])
  288. self.client.SetFontSizeAxis(self.properties['font']['prop']['axisSize'])
  289. self.client.SetEnableZoom(self.zoom)
  290. self.client.SetEnableDrag(self.drag)
  291. #
  292. # axis settings
  293. #
  294. if self.properties['x-axis']['prop']['type'] == 'custom':
  295. self.client.SetXSpec('min')
  296. else:
  297. self.client.SetXSpec(self.properties['x-axis']['prop']['type'])
  298. if self.properties['y-axis']['prop']['type'] == 'custom':
  299. self.client.SetYSpec('min')
  300. else:
  301. self.client.SetYSpec(self.properties['y-axis']['prop']['type'])
  302. if self.properties['x-axis']['prop']['type'] == 'custom' and \
  303. self.properties['x-axis']['prop']['min'] < self.properties['x-axis']['prop']['max']:
  304. self.properties['x-axis']['axis'] = (self.properties['x-axis']['prop']['min'],
  305. self.properties['x-axis']['prop']['max'])
  306. else:
  307. self.properties['x-axis']['axis'] = None
  308. if self.properties['y-axis']['prop']['type'] == 'custom' and \
  309. self.properties['y-axis']['prop']['min'] < self.properties['y-axis']['prop']['max']:
  310. self.properties['y-axis']['axis'] = (self.properties['y-axis']['prop']['min'],
  311. self.properties['y-axis']['prop']['max'])
  312. else:
  313. self.properties['y-axis']['axis'] = None
  314. self.client.SetEnableGrid(self.properties['grid']['enabled'])
  315. self.client.SetGridColour(wx.Color(self.properties['grid']['color'][0],
  316. self.properties['grid']['color'][1],
  317. self.properties['grid']['color'][2],
  318. 255))
  319. self.client.SetFontSizeLegend(self.properties['font']['prop']['legendSize'])
  320. self.client.SetEnableLegend(self.properties['legend']['enabled'])
  321. if self.properties['x-axis']['prop']['log'] == True:
  322. self.properties['x-axis']['axis'] = None
  323. self.client.SetXSpec('min')
  324. if self.properties['y-axis']['prop']['log'] == True:
  325. self.properties['y-axis']['axis'] = None
  326. self.client.SetYSpec('min')
  327. self.client.setLogScale((self.properties['x-axis']['prop']['log'],
  328. self.properties['y-axis']['prop']['log']))
  329. # self.client.SetPointLabelFunc(self.DrawPointLabel())
  330. def CreateDatalist(self, raster, coords):
  331. """
  332. Build a list of distance, value pairs for points along transect
  333. """
  334. datalist = []
  335. import subprocess
  336. try:
  337. p = grass.read_command("r.profile",
  338. input=raster,
  339. profile=coords,
  340. null="nan",
  341. quiet=True
  342. )
  343. for outline in p.strip().split('\n'):
  344. dist, elev = outline.split(' ')
  345. if elev != 'nan': datalist.append((dist,elev))
  346. return datalist
  347. except gcmd.CmdError, e:
  348. print e
  349. return None
  350. def OnCreateProfile(self, event):
  351. """
  352. Main routine for creating a profile. Uses r.profile to create a list
  353. of distance,cell value pairs. This is passed to plot to create a
  354. line graph of the profile. If the profile transect is in multiple
  355. segments, these are drawn as points. Profile transect is drawn, using
  356. methods in mapdisp.py
  357. """
  358. if len(self.mapwin.polycoords) == 0 or self.raster[0]['name'] == '':
  359. dlg = wx.MessageDialog(parent=self,
  360. message=_('You must draw a transect to profile in the map display window.'),
  361. caption=_('Nothing to profile'),
  362. style=wx.OK | wx.ICON_INFORMATION | wx.CENTRE)
  363. dlg.ShowModal()
  364. dlg.Destroy()
  365. return
  366. self.mapwin.SetCursor(self.parent.cursors["default"])
  367. self.SetCursor(self.parent.cursors["default"])
  368. self.SetGraphStyle()
  369. self.SetRaster()
  370. self.DrawPlot()
  371. # reset transect
  372. self.mapwin.mouse['begin'] = self.mapwin.mouse['end'] = (0.0,0.0)
  373. self.mapwin.mouse['use'] = 'pointer'
  374. self.mapwin.mouse['box'] = 'point'
  375. def DrawPlot(self):
  376. """
  377. Draw line and point plot from transect datalist and
  378. transect segment endpoint coordinates.
  379. """
  380. # graph the distance, value pairs for the transect
  381. self.plotlist = []
  382. for r in self.raster.itervalues():
  383. if len(r['datalist']) > 0:
  384. col = wx.Color(r['prop']['pcolor'][0],
  385. r['prop']['pcolor'][1],
  386. r['prop']['pcolor'][2],
  387. 255)
  388. r['pline'] = plot.PolyLine(r['datalist'],
  389. colour=col,
  390. width=r['prop']['pwidth'],
  391. style=self.pstyledict[r['prop']['pstyle']],
  392. legend=r['plegend'])
  393. self.plotlist.append(r['pline'])
  394. if len(self.seglist) > 0 :
  395. self.ppoints = plot.PolyMarker(self.seglist,
  396. legend=' ' + self.properties['marker']['legend'],
  397. colour=wx.Color(self.properties['marker']['color'][0],
  398. self.properties['marker']['color'][1],
  399. self.properties['marker']['color'][2],
  400. 255),
  401. size=self.properties['marker']['size'],
  402. fillstyle=self.ptfilldict[self.properties['marker']['fill']],
  403. marker=self.properties['marker']['type'])
  404. self.plotlist.append(self.ppoints)
  405. self.profile = plot.PlotGraphics(self.plotlist,
  406. self.ptitle,
  407. self.xlabel,
  408. self.ylabel)
  409. if self.properties['x-axis']['prop']['type'] == 'custom':
  410. self.client.SetXSpec('min')
  411. else:
  412. self.client.SetXSpec(self.properties['x-axis']['prop']['type'])
  413. if self.properties['y-axis']['prop']['type'] == 'custom':
  414. self.client.SetYSpec('min')
  415. else:
  416. self.client.SetYSpec(self.properties['y-axis']['prop']['type'])
  417. self.client.Draw(self.profile, self.properties['x-axis']['axis'],
  418. self.properties['y-axis']['axis'])
  419. def OnZoom(self, event):
  420. """
  421. Enable zooming and disable dragging
  422. """
  423. self.zoom = True
  424. self.drag = False
  425. self.client.SetEnableZoom(self.zoom)
  426. self.client.SetEnableDrag(self.drag)
  427. def OnDrag(self, event):
  428. """
  429. Enable dragging and disable zooming
  430. """
  431. self.zoom = False
  432. self.drag = True
  433. self.client.SetEnableDrag(self.drag)
  434. self.client.SetEnableZoom(self.zoom)
  435. def OnRedraw(self, event):
  436. """
  437. Redraw the profile window. Unzoom to original size
  438. """
  439. self.client.Reset()
  440. self.client.Redraw()
  441. def Update(self):
  442. """
  443. Update profile after changing options
  444. """
  445. self.SetGraphStyle()
  446. self.DrawPlot()
  447. def OnErase(self, event):
  448. """
  449. Erase the profile window
  450. """
  451. self.client.Clear()
  452. self.mapwin.ClearLines(self.mapwin.pdc)
  453. self.mapwin.ClearLines(self.mapwin.pdcTmp)
  454. self.mapwin.polycoords = []
  455. self.mapwin.Refresh()
  456. # try:
  457. # self.mapwin.pdc.ClearId(self.mapwin.lineid)
  458. # self.mapwin.pdc.ClearId(self.mapwin.plineid)
  459. # self.mapwin.Refresh()
  460. # except:
  461. # pass
  462. def SaveToFile(self, event):
  463. """
  464. Save profile to graphics file
  465. """
  466. self.client.SaveFile()
  467. def DrawPointLabel(self, dc, mDataDict):
  468. """This is the fuction that defines how the pointLabels are plotted
  469. dc - DC that will be passed
  470. mDataDict - Dictionary of data that you want to use for the pointLabel
  471. As an example I have decided I want a box at the curve point
  472. with some text information about the curve plotted below.
  473. Any wxDC method can be used.
  474. """
  475. # ----------
  476. dc.SetPen(wx.Pen(wx.BLACK))
  477. dc.SetBrush(wx.Brush( wx.BLACK, wx.SOLID ) )
  478. sx, sy = mDataDict["scaledXY"] #scaled x,y of closest point
  479. dc.DrawRectangle( sx-5,sy-5, 10, 10) #10by10 square centered on point
  480. px,py = mDataDict["pointXY"]
  481. cNum = mDataDict["curveNum"]
  482. pntIn = mDataDict["pIndex"]
  483. legend = mDataDict["legend"]
  484. #make a string to display
  485. s = "Crv# %i, '%s', Pt. (%.2f,%.2f), PtInd %i" %(cNum, legend, px, py, pntIn)
  486. dc.DrawText(s, sx , sy+1)
  487. # -----------
  488. def OnMouseLeftDown(self,event):
  489. s= "Left Mouse Down at Point: (%.4f, %.4f)" % self.client._getXY(event)
  490. self.SetStatusText(s)
  491. event.Skip() #allows plotCanvas OnMouseLeftDown to be called
  492. def OnMotion(self, event):
  493. # indicate when mouse is outside the plot area
  494. if self.client.OnLeave(event): print 'out of area'
  495. #show closest point (when enbled)
  496. if self.client.GetEnablePointLabel() == True:
  497. #make up dict with info for the pointLabel
  498. #I've decided to mark the closest point on the closest curve
  499. dlst= self.client.GetClosetPoint( self.client._getXY(event), pointScaled= True)
  500. if dlst != []: #returns [] if none
  501. curveNum, legend, pIndex, pointXY, scaledXY, distance = dlst
  502. #make up dictionary to pass to my user function (see DrawPointLabel)
  503. mDataDict= {"curveNum":curveNum, "legend":legend, "pIndex":pIndex,\
  504. "pointXY":pointXY, "scaledXY":scaledXY}
  505. #pass dict to update the pointLabel
  506. self.client.UpdatePointLabel(mDataDict)
  507. event.Skip() #go to next handler
  508. def ProfileOptionsMenu(self, event):
  509. """
  510. Popup menu for profile and text options
  511. """
  512. point = wx.GetMousePosition()
  513. popt = wx.Menu()
  514. # Add items to the menu
  515. settext = wx.MenuItem(popt, -1, 'Profile text settings')
  516. popt.AppendItem(settext)
  517. self.Bind(wx.EVT_MENU, self.PText, settext)
  518. setgrid = wx.MenuItem(popt, -1, 'Profile plot settings')
  519. popt.AppendItem(setgrid)
  520. self.Bind(wx.EVT_MENU, self.POptions, setgrid)
  521. # Popup the menu. If an item is selected then its handler
  522. # will be called before PopupMenu returns.
  523. self.PopupMenu(popt)
  524. popt.Destroy()
  525. def NotFunctional(self):
  526. """
  527. Creates a 'not functional' message dialog
  528. """
  529. dlg = wx.MessageDialog(self, 'This feature is not yet functional',
  530. 'Under Construction', wx.OK | wx.ICON_INFORMATION)
  531. dlg.ShowModal()
  532. dlg.Destroy()
  533. def PText(self, event):
  534. """
  535. Set custom text values for profile
  536. title and axis labels.
  537. """
  538. dlg = TextDialog(parent=self, id=wx.ID_ANY, title=_('Profile text settings'))
  539. if dlg.ShowModal() == wx.ID_OK:
  540. self.ptitle = dlg.ptitle
  541. self.xlabel = dlg.xlabel
  542. self.ylabel = dlg.ylabel
  543. dlg.UpdateSettings()
  544. self.client.SetFont(self.properties['font']['wxfont'])
  545. self.client.SetFontSizeTitle(self.properties['font']['prop']['titleSize'])
  546. self.client.SetFontSizeAxis(self.properties['font']['prop']['axisSize'])
  547. if self.profile:
  548. self.profile.setTitle(dlg.ptitle)
  549. self.profile.setXLabel(dlg.xlabel)
  550. self.profile.setYLabel(dlg.ylabel)
  551. dlg.Destroy()
  552. self.OnRedraw(event=None)
  553. def POptions(self, event):
  554. """
  555. Set various profile options, including: line width, color, style;
  556. marker size, color, fill, and style; grid and legend options.
  557. Calls OptDialog class.
  558. """
  559. dlg = OptDialog(parent=self, id=wx.ID_ANY, title=_('Profile settings'))
  560. if dlg.ShowModal() == wx.ID_OK:
  561. dlg.UpdateSettings()
  562. self.SetGraphStyle()
  563. if self.profile:
  564. self.DrawPlot()
  565. dlg.Destroy()
  566. def PrintMenu(self, event):
  567. """
  568. Print options and output menu
  569. """
  570. point = wx.GetMousePosition()
  571. printmenu = wx.Menu()
  572. # Add items to the menu
  573. setup = wx.MenuItem(printmenu, -1,'Page setup')
  574. printmenu.AppendItem(setup)
  575. self.Bind(wx.EVT_MENU, self.OnPageSetup, setup)
  576. preview = wx.MenuItem(printmenu, -1,'Print preview')
  577. printmenu.AppendItem(preview)
  578. self.Bind(wx.EVT_MENU, self.OnPrintPreview, preview)
  579. doprint = wx.MenuItem(printmenu, -1,'Print display')
  580. printmenu.AppendItem(doprint)
  581. self.Bind(wx.EVT_MENU, self.OnDoPrint, doprint)
  582. # Popup the menu. If an item is selected then its handler
  583. # will be called before PopupMenu returns.
  584. self.PopupMenu(printmenu)
  585. printmenu.Destroy()
  586. def OnPageSetup(self, event):
  587. self.client.PageSetup()
  588. def OnPrintPreview(self, event):
  589. self.client.PrintPreview()
  590. def OnDoPrint(self, event):
  591. self.client.Printout()
  592. def OnQuit(self, event):
  593. self.Close(True)
  594. def OnCloseWindow(self, event):
  595. """
  596. Close profile window and clean up
  597. """
  598. self.mapwin.ClearLines()
  599. self.mapwin.mouse['begin'] = self.mapwin.mouse['end'] = (0.0, 0.0)
  600. self.mapwin.mouse['use'] = 'pointer'
  601. self.mapwin.mouse['box'] = 'point'
  602. self.mapwin.polycoords = []
  603. self.mapwin.SetCursor(self.Parent.cursors["default"])
  604. self.mapwin.UpdateMap(render=False, renderVector=False)
  605. self.Destroy()
  606. class SetRasterDialog(wx.Dialog):
  607. def __init__(self, parent, id=wx.ID_ANY, title=_("Select raster map to profile"),
  608. pos=wx.DefaultPosition, size=wx.DefaultSize,
  609. style=wx.DEFAULT_DIALOG_STYLE):
  610. """
  611. Dialog to select raster maps to profile.
  612. """
  613. wx.Dialog.__init__(self, parent, id, title, pos, size, style)
  614. self.parent = parent
  615. self.coordstr = self.parent.coordstr
  616. # if self.coordstr == '':
  617. # dlg = wx.MessageDialog(parent=self,
  618. # message=_('You must draw a transect to profile in the map display window.'),
  619. # caption=_('Nothing to profile'),
  620. # style=wx.OK | wx.ICON_INFORMATION | wx.CENTRE)
  621. # dlg.ShowModal()
  622. # dlg.Destroy()
  623. # self.Close(True)
  624. # return
  625. self.raster = { 0 : { 'name' : self.parent.raster[0]['name'],
  626. 'id' : None },
  627. 1 : { 'name' : self.parent.raster[1]['name'],
  628. 'id' : None },
  629. 2 : { 'name' : self.parent.raster[2]['name'],
  630. 'id' : None }
  631. }
  632. sizer = wx.BoxSizer(wx.VERTICAL)
  633. box = wx.GridBagSizer (hgap=3, vgap=3)
  634. i = 0
  635. for txt in [_("Select raster map 1 (required):"),
  636. _("Select raster map 2 (optional):"),
  637. _("Select raster map 3 (optional):")]:
  638. label = wx.StaticText(parent=self, id=wx.ID_ANY, label=txt)
  639. box.Add(item=label,
  640. flag=wx.ALIGN_CENTER_VERTICAL, pos=(i, 0))
  641. selection = gselect.Select(self, id=wx.ID_ANY,
  642. size=globalvar.DIALOG_GSELECT_SIZE,
  643. type='cell')
  644. selection.SetValue(str(self.raster[i]['name']))
  645. self.raster[i]['id'] = selection.GetChildren()[0].GetId()
  646. selection.Bind(wx.EVT_TEXT, self.OnSelection)
  647. box.Add(item=selection, pos=(i, 1))
  648. i += 1
  649. sizer.Add(item=box, proportion=0,
  650. flag=wx.ALL, border=10)
  651. line = wx.StaticLine(parent=self, id=wx.ID_ANY, size=(20, -1), style=wx.LI_HORIZONTAL)
  652. sizer.Add(item=line, proportion=0,
  653. flag=wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.LEFT|wx.RIGHT, border=5)
  654. btnsizer = wx.StdDialogButtonSizer()
  655. btn = wx.Button(self, wx.ID_OK)
  656. btn.SetDefault()
  657. btnsizer.AddButton(btn)
  658. btn = wx.Button(self, wx.ID_CANCEL)
  659. btnsizer.AddButton(btn)
  660. btnsizer.Realize()
  661. sizer.Add(item=btnsizer, proportion=0, flag=wx.ALIGN_RIGHT | wx.ALL, border=5)
  662. self.SetSizer(sizer)
  663. sizer.Fit(self)
  664. def OnSelection(self, event):
  665. id = event.GetId()
  666. for r in self.raster.itervalues():
  667. if r['id'] == id:
  668. r['name'] = event.GetString()
  669. break
  670. class TextDialog(wx.Dialog):
  671. def __init__(self, parent, id, title, pos=wx.DefaultPosition, size=wx.DefaultSize,
  672. style=wx.DEFAULT_DIALOG_STYLE):
  673. wx.Dialog.__init__(self, parent, id, title, pos, size, style)
  674. """
  675. Dialog to set profile text options: font, title
  676. and font size, axis labels and font size
  677. """
  678. #
  679. # initialize variables
  680. #
  681. # combo box entry lists
  682. self.ffamilydict = { 'default' : wx.FONTFAMILY_DEFAULT,
  683. 'decorative' : wx.FONTFAMILY_DECORATIVE,
  684. 'roman' : wx.FONTFAMILY_ROMAN,
  685. 'script' : wx.FONTFAMILY_SCRIPT,
  686. 'swiss' : wx.FONTFAMILY_SWISS,
  687. 'modern' : wx.FONTFAMILY_MODERN,
  688. 'teletype' : wx.FONTFAMILY_TELETYPE }
  689. self.fstyledict = { 'normal' : wx.FONTSTYLE_NORMAL,
  690. 'slant' : wx.FONTSTYLE_SLANT,
  691. 'italic' : wx.FONTSTYLE_ITALIC }
  692. self.fwtdict = { 'normal' : wx.FONTWEIGHT_NORMAL,
  693. 'light' : wx.FONTWEIGHT_LIGHT,
  694. 'bold' : wx.FONTWEIGHT_BOLD }
  695. self.parent = parent
  696. self.ptitle = self.parent.ptitle
  697. self.xlabel = self.parent.xlabel
  698. self.ylabel = self.parent.ylabel
  699. self.properties = self.parent.properties # read-only
  700. # font size
  701. self.fontfamily = self.properties['font']['wxfont'].GetFamily()
  702. self.fontstyle = self.properties['font']['wxfont'].GetStyle()
  703. self.fontweight = self.properties['font']['wxfont'].GetWeight()
  704. self._do_layout()
  705. def _do_layout(self):
  706. """Do layout"""
  707. # dialog layout
  708. sizer = wx.BoxSizer(wx.VERTICAL)
  709. box = wx.StaticBox(parent=self, id=wx.ID_ANY,
  710. label=" %s " % _("Text settings"))
  711. boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  712. gridSizer = wx.GridBagSizer(vgap=5, hgap=5)
  713. #
  714. # profile title
  715. #
  716. label = wx.StaticText(parent=self, id=wx.ID_ANY, label=_("Profile title:"))
  717. gridSizer.Add(item=label, flag=wx.ALIGN_CENTER_VERTICAL, pos=(0, 0))
  718. self.ptitleentry = wx.TextCtrl(parent=self, id=wx.ID_ANY, value="", size=(200,-1))
  719. # self.ptitleentry.SetFont(self.font)
  720. self.ptitleentry.SetValue(self.ptitle)
  721. gridSizer.Add(item=self.ptitleentry, pos=(0, 1))
  722. #
  723. # title font
  724. #
  725. tlabel = wx.StaticText(parent=self, id=wx.ID_ANY, label=_("Title font size (pts):"))
  726. gridSizer.Add(item=tlabel, flag=wx.ALIGN_CENTER_VERTICAL, pos=(1, 0))
  727. self.ptitlesize = wx.SpinCtrl(parent=self, id=wx.ID_ANY, value="", pos=(30, 50),
  728. size=(50,-1), style=wx.SP_ARROW_KEYS)
  729. self.ptitlesize.SetRange(5,100)
  730. self.ptitlesize.SetValue(int(self.properties['font']['prop']['titleSize']))
  731. gridSizer.Add(item=self.ptitlesize, pos=(1, 1))
  732. #
  733. # x-axis label
  734. #
  735. label = wx.StaticText(parent=self, id=wx.ID_ANY, label=("X-axis label:"))
  736. gridSizer.Add(item=label, flag=wx.ALIGN_CENTER_VERTICAL, pos=(2, 0))
  737. self.xlabelentry = wx.TextCtrl(parent=self, id=wx.ID_ANY, value="", size=(200,-1))
  738. # self.xlabelentry.SetFont(self.font)
  739. self.xlabelentry.SetValue(self.xlabel)
  740. gridSizer.Add(item=self.xlabelentry, pos=(2, 1))
  741. #
  742. # y-axis label
  743. #
  744. label = wx.StaticText(parent=self, id=wx.ID_ANY, label=_("Y-axis label:"))
  745. gridSizer.Add(item=label, flag=wx.ALIGN_CENTER_VERTICAL, pos=(3, 0))
  746. self.ylabelentry = wx.TextCtrl(parent=self, id=wx.ID_ANY, value="", size=(200,-1))
  747. # self.ylabelentry.SetFont(self.font)
  748. self.ylabelentry.SetValue(self.ylabel)
  749. gridSizer.Add(item=self.ylabelentry, pos=(3, 1))
  750. #
  751. # font size
  752. #
  753. llabel = wx.StaticText(parent=self, id=wx.ID_ANY, label=_("Label font size (pts):"))
  754. gridSizer.Add(item=llabel, flag=wx.ALIGN_CENTER_VERTICAL, pos=(4, 0))
  755. self.axislabelsize = wx.SpinCtrl(parent=self, id=wx.ID_ANY, value="", pos=(30, 50),
  756. size=(50, -1), style=wx.SP_ARROW_KEYS)
  757. self.axislabelsize.SetRange(5, 100)
  758. self.axislabelsize.SetValue(int(self.properties['font']['prop']['axisSize']))
  759. gridSizer.Add(item=self.axislabelsize, pos=(4,1))
  760. boxSizer.Add(item=gridSizer)
  761. sizer.Add(item=boxSizer, flag=wx.ALL | wx.EXPAND, border=3)
  762. #
  763. # font settings
  764. #
  765. box = wx.StaticBox(parent=self, id=wx.ID_ANY,
  766. label=" %s " % _("Font settings"))
  767. boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  768. gridSizer = wx.GridBagSizer(vgap=5, hgap=5)
  769. gridSizer.AddGrowableCol(1)
  770. #
  771. # font family
  772. #
  773. label1 = wx.StaticText(parent=self, id=wx.ID_ANY, label=_("Font family:"))
  774. gridSizer.Add(item=label1, flag=wx.ALIGN_CENTER_VERTICAL, pos=(0, 0))
  775. self.ffamilycb = wx.ComboBox(parent=self, id=wx.ID_ANY, size=(200, -1),
  776. choices=self.ffamilydict.keys(), style=wx.CB_DROPDOWN)
  777. self.ffamilycb.SetStringSelection('swiss')
  778. for item in self.ffamilydict.items():
  779. if self.fontfamily == item[1]:
  780. self.ffamilycb.SetStringSelection(item[0])
  781. break
  782. gridSizer.Add(item=self.ffamilycb, pos=(0, 1), flag=wx.ALIGN_RIGHT)
  783. #
  784. # font style
  785. #
  786. label = wx.StaticText(parent=self, id=wx.ID_ANY, label=_("Style:"))
  787. gridSizer.Add(item=label, flag=wx.ALIGN_CENTER_VERTICAL, pos=(1, 0))
  788. self.fstylecb = wx.ComboBox(parent=self, id=wx.ID_ANY, size=(200, -1),
  789. choices=self.fstyledict.keys(), style=wx.CB_DROPDOWN)
  790. self.fstylecb.SetStringSelection('normal')
  791. for item in self.fstyledict.items():
  792. if self.fontstyle == item[1]:
  793. self.fstylecb.SetStringSelection(item[0])
  794. break
  795. gridSizer.Add(item=self.fstylecb, pos=(1, 1), flag=wx.ALIGN_RIGHT)
  796. #
  797. # font weight
  798. #
  799. label = wx.StaticText(parent=self, id=wx.ID_ANY, label=_("Weight:"))
  800. gridSizer.Add(item=label, flag=wx.ALIGN_CENTER_VERTICAL, pos=(2, 0))
  801. self.fwtcb = wx.ComboBox(parent=self, size=(200, -1),
  802. choices=self.fwtdict.keys(), style=wx.CB_DROPDOWN)
  803. self.fwtcb.SetStringSelection('normal')
  804. for item in self.fwtdict.items():
  805. if self.fontweight == item[1]:
  806. self.fwtcb.SetStringSelection(item[0])
  807. break
  808. gridSizer.Add(item=self.fwtcb, pos=(2, 1), flag=wx.ALIGN_RIGHT)
  809. boxSizer.Add(item=gridSizer, flag=wx.EXPAND)
  810. sizer.Add(item=boxSizer, flag=wx.LEFT | wx.RIGHT | wx.BOTTOM | wx.EXPAND, border=3)
  811. line = wx.StaticLine(parent=self, id=wx.ID_ANY, size=(20, -1), style=wx.LI_HORIZONTAL)
  812. sizer.Add(item=line, proportion=0,
  813. flag=wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.LEFT|wx.RIGHT, border=3)
  814. #
  815. # buttons
  816. #
  817. btnSave = wx.Button(self, wx.ID_SAVE)
  818. btnApply = wx.Button(self, wx.ID_APPLY)
  819. btnCancel = wx.Button(self, wx.ID_CANCEL)
  820. btnSave.SetDefault()
  821. # bindigs
  822. btnApply.Bind(wx.EVT_BUTTON, self.OnApply)
  823. btnApply.SetToolTipString(_("Apply changes for the current session"))
  824. btnSave.Bind(wx.EVT_BUTTON, self.OnSave)
  825. btnSave.SetToolTipString(_("Apply and save changes to user settings file (default for next sessions)"))
  826. btnSave.SetDefault()
  827. btnCancel.Bind(wx.EVT_BUTTON, self.OnCancel)
  828. btnCancel.SetToolTipString(_("Close dialog and ignore changes"))
  829. # sizers
  830. btnStdSizer = wx.StdDialogButtonSizer()
  831. btnStdSizer.AddButton(btnCancel)
  832. btnStdSizer.AddButton(btnSave)
  833. btnStdSizer.AddButton(btnApply)
  834. btnStdSizer.Realize()
  835. sizer.Add(item=btnStdSizer, proportion=0, flag=wx.ALIGN_RIGHT | wx.ALL, border=5)
  836. #
  837. # bindings
  838. #
  839. self.ptitleentry.Bind(wx.EVT_TEXT, self.OnTitle)
  840. self.xlabelentry.Bind(wx.EVT_TEXT, self.OnXLabel)
  841. self.ylabelentry.Bind(wx.EVT_TEXT, self.OnYLabel)
  842. self.SetSizer(sizer)
  843. sizer.Fit(self)
  844. def OnTitle(self, event):
  845. self.ptitle = event.GetString()
  846. def OnXLabel(self, event):
  847. self.xlabel = event.GetString()
  848. def OnYLabel(self, event):
  849. self.ylabel = event.GetString()
  850. def UpdateSettings(self):
  851. self.properties['font']['prop']['titleSize'] = self.ptitlesize.GetValue()
  852. self.properties['font']['prop']['axisSize'] = self.axislabelsize.GetValue()
  853. family = self.ffamilydict[self.ffamilycb.GetStringSelection()]
  854. self.properties['font']['wxfont'].SetFamily(family)
  855. style = self.fstyledict[self.fstylecb.GetStringSelection()]
  856. self.properties['font']['wxfont'].SetStyle(style)
  857. weight = self.fwtdict[self.fwtcb.GetStringSelection()]
  858. self.properties['font']['wxfont'].SetWeight(weight)
  859. def OnSave(self, event):
  860. """Button 'Save' pressed"""
  861. self.UpdateSettings()
  862. fileSettings = {}
  863. UserSettings.ReadSettingsFile(settings=fileSettings)
  864. fileSettings['profile'] = UserSettings.Get(group='profile')
  865. file = UserSettings.SaveToFile(fileSettings)
  866. self.parent.parent.gismanager.goutput.WriteLog(_('Profile settings saved to file \'%s\'.') % file)
  867. self.Close()
  868. def OnApply(self, event):
  869. """Button 'Apply' pressed"""
  870. self.UpdateSettings()
  871. self.Close()
  872. def OnCancel(self, event):
  873. """Button 'Cancel' pressed"""
  874. self.Close()
  875. class OptDialog(wx.Dialog):
  876. def __init__(self, parent, id, title, pos=wx.DefaultPosition, size=wx.DefaultSize,
  877. style=wx.DEFAULT_DIALOG_STYLE):
  878. wx.Dialog.__init__(self, parent, id, title, pos, size, style)
  879. """
  880. Dialog to set various profile options, including: line width, color, style;
  881. marker size, color, fill, and style; grid and legend options.
  882. """
  883. # init variables
  884. self.pstyledict = parent.pstyledict
  885. self.ptfilldict = parent.ptfilldict
  886. self.pttypelist = ['circle',
  887. 'dot',
  888. 'square',
  889. 'triangle',
  890. 'triangle_down',
  891. 'cross',
  892. 'plus']
  893. self.axislist = ['min',
  894. 'auto',
  895. 'custom']
  896. # widgets ids
  897. self.wxId = {}
  898. self.parent = parent
  899. # read-only
  900. self.raster = self.parent.raster
  901. self.properties = self.parent.properties
  902. self._do_layout()
  903. def _do_layout(self):
  904. """Do layout"""
  905. # dialog layout
  906. sizer = wx.BoxSizer(wx.VERTICAL)
  907. #
  908. # profile line settings
  909. #
  910. box = wx.StaticBox(parent=self, id=wx.ID_ANY,
  911. label=" %s " % _("Profile line settings"))
  912. boxMainSizer = wx.StaticBoxSizer(box, wx.HORIZONTAL)
  913. idx = 1
  914. self.wxId['pcolor'] = []
  915. self.wxId['pwidth'] = []
  916. self.wxId['pstyle'] = []
  917. self.wxId['plegend'] = []
  918. for r in self.raster.itervalues():
  919. box = wx.StaticBox(parent=self, id=wx.ID_ANY,
  920. label=" %s %d " % (_("Profile"), idx))
  921. boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  922. gridSizer = wx.GridBagSizer(vgap=5, hgap=5)
  923. row = 0
  924. label = wx.StaticText(parent=self, id=wx.ID_ANY, label=_("Line color"))
  925. gridSizer.Add(item=label, flag=wx.ALIGN_CENTER_VERTICAL, pos=(row, 0))
  926. pcolor = csel.ColourSelect(parent=self, id=wx.ID_ANY, colour=r['prop']['pcolor'])
  927. self.wxId['pcolor'].append(pcolor.GetId())
  928. gridSizer.Add(item=pcolor, pos=(row, 1))
  929. row += 1
  930. label = wx.StaticText(parent=self, id=wx.ID_ANY, label=_("Line width"))
  931. gridSizer.Add(item=label, flag=wx.ALIGN_CENTER_VERTICAL, pos=(row, 0))
  932. pwidth = wx.SpinCtrl(parent=self, id=wx.ID_ANY, value="",
  933. size=(50,-1), style=wx.SP_ARROW_KEYS)
  934. pwidth.SetRange(1, 10)
  935. pwidth.SetValue(r['prop']['pwidth'])
  936. self.wxId['pwidth'].append(pwidth.GetId())
  937. gridSizer.Add(item=pwidth, pos=(row, 1))
  938. row +=1
  939. label = wx.StaticText(parent=self, id=wx.ID_ANY, label=_("Line style"))
  940. gridSizer.Add(item=label, flag=wx.ALIGN_CENTER_VERTICAL, pos=(row, 0))
  941. pstyle = wx.ComboBox(parent=self, id=wx.ID_ANY,
  942. size=(120, -1), choices=self.pstyledict.keys(), style=wx.CB_DROPDOWN)
  943. pstyle.SetStringSelection(r['prop']['pstyle'])
  944. self.wxId['pstyle'].append(pstyle.GetId())
  945. gridSizer.Add(item=pstyle, pos=(row, 1))
  946. row += 1
  947. label = wx.StaticText(parent=self, id=wx.ID_ANY, label=_("Legend"))
  948. gridSizer.Add(item=label, flag=wx.ALIGN_CENTER_VERTICAL, pos=(row, 0))
  949. plegend = wx.TextCtrl(parent=self, id=wx.ID_ANY, value="", size=(200,-1))
  950. plegend.SetValue(r['plegend'])
  951. gridSizer.Add(item=plegend, pos=(row, 1))
  952. self.wxId['plegend'].append(plegend.GetId())
  953. boxSizer.Add(item=gridSizer)
  954. if idx == 0:
  955. flag = wx.ALL
  956. else:
  957. flag = wx.TOP | wx.BOTTOM | wx.RIGHT
  958. boxMainSizer.Add(item=boxSizer, flag=flag, border=3)
  959. idx += 1
  960. sizer.Add(item=boxMainSizer, flag=wx.ALL | wx.EXPAND, border=3)
  961. middleSizer = wx.BoxSizer(wx.HORIZONTAL)
  962. #
  963. # segment marker settings
  964. #
  965. box = wx.StaticBox(parent=self, id=wx.ID_ANY,
  966. label=" %s " % _("Transect segment marker settings"))
  967. boxMainSizer = wx.StaticBoxSizer(box, wx.HORIZONTAL)
  968. self.wxId['marker'] = {}
  969. gridSizer = wx.GridBagSizer(vgap=5, hgap=5)
  970. label = wx.StaticText(parent=self, id=wx.ID_ANY, label=_("Color"))
  971. gridSizer.Add(item=label, flag=wx.ALIGN_CENTER_VERTICAL, pos=(0, 0))
  972. ptcolor = csel.ColourSelect(parent=self, id=wx.ID_ANY, colour=self.properties['marker']['color'])
  973. self.wxId['marker']['color'] = ptcolor.GetId()
  974. gridSizer.Add(item=ptcolor, pos=(0, 1))
  975. label = wx.StaticText(parent=self, id=wx.ID_ANY, label=_("Size"))
  976. gridSizer.Add(item=label, flag=wx.ALIGN_CENTER_VERTICAL, pos=(1, 0))
  977. ptsize = wx.SpinCtrl(parent=self, id=wx.ID_ANY, value="",
  978. size=(50, -1), style=wx.SP_ARROW_KEYS)
  979. ptsize.SetRange(1, 10)
  980. ptsize.SetValue(self.properties['marker']['size'])
  981. self.wxId['marker']['size'] = ptsize.GetId()
  982. gridSizer.Add(item=ptsize, pos=(1, 1))
  983. label = wx.StaticText(parent=self, id=wx.ID_ANY, label=_("Style"))
  984. gridSizer.Add(item=label, flag=wx.ALIGN_CENTER_VERTICAL, pos=(2, 0))
  985. ptfill = wx.ComboBox(parent=self, id=wx.ID_ANY,
  986. size=(120, -1), choices=self.ptfilldict.keys(), style=wx.CB_DROPDOWN)
  987. ptfill.SetStringSelection(self.properties['marker']['fill'])
  988. self.wxId['marker']['fill'] = ptfill.GetId()
  989. gridSizer.Add(item=ptfill, pos=(2, 1))
  990. label = wx.StaticText(parent=self, id=wx.ID_ANY, label=_("Legend"))
  991. gridSizer.Add(item=label, flag=wx.ALIGN_CENTER_VERTICAL, pos=(3, 0))
  992. ptlegend = wx.TextCtrl(parent=self, id=wx.ID_ANY, value="", size=(200,-1))
  993. ptlegend.SetValue(self.properties['marker']['legend'])
  994. self.wxId['marker']['legend'] = ptlegend.GetId()
  995. gridSizer.Add(item=ptlegend, pos=(3, 1))
  996. label = wx.StaticText(parent=self, id=wx.ID_ANY, label=_("Type"))
  997. gridSizer.Add(item=label, flag=wx.ALIGN_CENTER_VERTICAL, pos=(4, 0))
  998. pttype = wx.ComboBox(parent=self,
  999. size=(200, -1), choices=self.pttypelist, style=wx.CB_DROPDOWN)
  1000. pttype.SetStringSelection(self.properties['marker']['type'])
  1001. self.wxId['marker']['type'] = pttype.GetId()
  1002. gridSizer.Add(item=pttype, pos=(4, 1))
  1003. boxMainSizer.Add(item=gridSizer, flag=wx.ALL, border=3)
  1004. middleSizer.Add(item=boxMainSizer, flag=wx.ALL | wx.EXPAND, border=3)
  1005. #
  1006. # axis options
  1007. #
  1008. box = wx.StaticBox(parent=self, id=wx.ID_ANY,
  1009. label=" %s " % _("Axis settings"))
  1010. boxMainSizer = wx.StaticBoxSizer(box, wx.HORIZONTAL)
  1011. self.wxId['x-axis'] = {}
  1012. self.wxId['y-axis'] = {}
  1013. idx = 0
  1014. for axis, atype in [(_("X-Axis"), 'x-axis'),
  1015. (_("Y-Axis"), 'y-axis')]:
  1016. box = wx.StaticBox(parent=self, id=wx.ID_ANY,
  1017. label=" %s " % axis)
  1018. boxSizer = wx.StaticBoxSizer(box, wx.HORIZONTAL)
  1019. gridSizer = wx.GridBagSizer(vgap=5, hgap=5)
  1020. prop = self.properties[atype]['prop']
  1021. row = 0
  1022. label = wx.StaticText(parent=self, id=wx.ID_ANY, label=_("Style"))
  1023. gridSizer.Add(item=label, flag=wx.ALIGN_CENTER_VERTICAL, pos=(row, 0))
  1024. type = wx.ComboBox(parent=self, id=wx.ID_ANY,
  1025. size=(100, -1), choices=self.axislist, style=wx.CB_DROPDOWN)
  1026. type.SetStringSelection(prop['type'])
  1027. self.wxId[atype]['type'] = type.GetId()
  1028. gridSizer.Add(item=type, pos=(row, 1))
  1029. row += 1
  1030. label = wx.StaticText(parent=self, id=wx.ID_ANY, label=_("Custom min"))
  1031. gridSizer.Add(item=label, flag=wx.ALIGN_CENTER_VERTICAL, pos=(row, 0))
  1032. min = wx.TextCtrl(parent=self, id=wx.ID_ANY, value="", size=(70, -1))
  1033. min.SetValue(str(prop['min']))
  1034. self.wxId[atype]['min'] = min.GetId()
  1035. gridSizer.Add(item=min, pos=(row, 1))
  1036. row += 1
  1037. label = wx.StaticText(parent=self, id=wx.ID_ANY, label=_("Custom max"))
  1038. gridSizer.Add(item=label, flag=wx.ALIGN_CENTER_VERTICAL, pos=(row, 0))
  1039. max = wx.TextCtrl(parent=self, id=wx.ID_ANY, value="", size=(70, -1))
  1040. max.SetValue(str(prop['max']))
  1041. self.wxId[atype]['max'] = max.GetId()
  1042. gridSizer.Add(item=max, pos=(row, 1))
  1043. row += 1
  1044. log = wx.CheckBox(parent=self, id=wx.ID_ANY, label=_("Log scale"))
  1045. log.SetValue(prop['log'])
  1046. self.wxId[atype]['log'] = log.GetId()
  1047. gridSizer.Add(item=log, pos=(row, 0), span=(1, 2))
  1048. if idx == 0:
  1049. flag = wx.ALL | wx.EXPAND
  1050. else:
  1051. flag = wx.TOP | wx.BOTTOM | wx.RIGHT | wx.EXPAND
  1052. boxSizer.Add(item=gridSizer, flag=wx.ALL, border=3)
  1053. boxMainSizer.Add(item=boxSizer, flag=flag, border=3)
  1054. idx += 1
  1055. middleSizer.Add(item=boxMainSizer, flag=wx.ALL | wx.EXPAND, border=3)
  1056. #
  1057. # grid & legend options
  1058. #
  1059. self.wxId['grid'] = {}
  1060. self.wxId['legend'] = {}
  1061. self.wxId['font'] = {}
  1062. box = wx.StaticBox(parent=self, id=wx.ID_ANY,
  1063. label=" %s " % _("Grid and Legend settings"))
  1064. boxMainSizer = wx.StaticBoxSizer(box, wx.HORIZONTAL)
  1065. gridSizer = wx.GridBagSizer(vgap=5, hgap=5)
  1066. row = 0
  1067. label = wx.StaticText(parent=self, id=wx.ID_ANY, label=_("Grid color"))
  1068. gridSizer.Add(item=label, flag=wx.ALIGN_CENTER_VERTICAL, pos=(row, 0))
  1069. gridcolor = csel.ColourSelect(parent=self, id=wx.ID_ANY, colour=self.properties['grid']['color'])
  1070. self.wxId['grid']['color'] = gridcolor.GetId()
  1071. gridSizer.Add(item=gridcolor, pos=(row, 1))
  1072. row +=1
  1073. gridshow = wx.CheckBox(parent=self, id=wx.ID_ANY, label=_("Show grid"))
  1074. gridshow.SetValue(self.properties['grid']['enabled'])
  1075. self.wxId['grid']['enabled'] = gridshow.GetId()
  1076. gridSizer.Add(item=gridshow, pos=(row, 0), span=(1, 2))
  1077. row +=1
  1078. label = wx.StaticText(parent=self, id=wx.ID_ANY, label=_("Legend font size"))
  1079. gridSizer.Add(item=label, flag=wx.ALIGN_CENTER_VERTICAL, pos=(row, 0))
  1080. legendfontsize = wx.SpinCtrl(parent=self, id=wx.ID_ANY, value="",
  1081. size=(50, -1), style=wx.SP_ARROW_KEYS)
  1082. legendfontsize.SetRange(5,100)
  1083. legendfontsize.SetValue(int(self.properties['font']['prop']['legendSize']))
  1084. self.wxId['font']['legendSize'] = legendfontsize.GetId()
  1085. gridSizer.Add(item=legendfontsize, pos=(row, 1))
  1086. row += 1
  1087. legendshow = wx.CheckBox(parent=self, id=wx.ID_ANY, label=_("Show legend"))
  1088. legendshow.SetValue(self.properties['legend']['enabled'])
  1089. self.wxId['legend']['enabled'] = legendshow.GetId()
  1090. gridSizer.Add(item=legendshow, pos=(row, 0), span=(1, 2))
  1091. boxMainSizer.Add(item=gridSizer, flag=flag, border=3)
  1092. middleSizer.Add(item=boxMainSizer, flag=wx.LEFT | wx.RIGHT | wx.BOTTOM | wx.EXPAND, border=3)
  1093. sizer.Add(item=middleSizer, flag=wx.ALL, border=0)
  1094. #
  1095. # line & buttons
  1096. #
  1097. line = wx.StaticLine(parent=self, id=wx.ID_ANY, size=(20, -1), style=wx.LI_HORIZONTAL)
  1098. sizer.Add(item=line, proportion=0,
  1099. flag=wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.LEFT|wx.RIGHT, border=3)
  1100. #
  1101. # buttons
  1102. #
  1103. btnSave = wx.Button(self, wx.ID_SAVE)
  1104. btnApply = wx.Button(self, wx.ID_APPLY)
  1105. btnCancel = wx.Button(self, wx.ID_CANCEL)
  1106. btnSave.SetDefault()
  1107. # bindigs
  1108. btnApply.Bind(wx.EVT_BUTTON, self.OnApply)
  1109. btnApply.SetToolTipString(_("Apply changes for the current session"))
  1110. btnSave.Bind(wx.EVT_BUTTON, self.OnSave)
  1111. btnSave.SetToolTipString(_("Apply and save changes to user settings file (default for next sessions)"))
  1112. btnSave.SetDefault()
  1113. btnCancel.Bind(wx.EVT_BUTTON, self.OnCancel)
  1114. btnCancel.SetToolTipString(_("Close dialog and ignore changes"))
  1115. # sizers
  1116. btnStdSizer = wx.StdDialogButtonSizer()
  1117. btnStdSizer.AddButton(btnCancel)
  1118. btnStdSizer.AddButton(btnSave)
  1119. btnStdSizer.AddButton(btnApply)
  1120. btnStdSizer.Realize()
  1121. sizer.Add(item=btnStdSizer, proportion=0, flag=wx.ALIGN_RIGHT | wx.ALL, border=5)
  1122. self.SetSizer(sizer)
  1123. sizer.Fit(self)
  1124. def UpdateSettings(self):
  1125. idx = 0
  1126. for r in self.raster.itervalues():
  1127. r['prop']['pcolor'] = self.FindWindowById(self.wxId['pcolor'][idx]).GetColour()
  1128. r['prop']['pwidth'] = int(self.FindWindowById(self.wxId['pwidth'][idx]).GetValue())
  1129. r['prop']['pstyle'] = self.FindWindowById(self.wxId['pstyle'][idx]).GetStringSelection()
  1130. r['plegend'] = self.FindWindowById(self.wxId['plegend'][idx]).GetValue()
  1131. idx +=1
  1132. self.properties['marker']['color'] = self.FindWindowById(self.wxId['marker']['color']).GetColour()
  1133. self.properties['marker']['fill'] = self.FindWindowById(self.wxId['marker']['fill']).GetStringSelection()
  1134. self.properties['marker']['size'] = self.FindWindowById(self.wxId['marker']['size']).GetValue()
  1135. self.properties['marker']['type'] = self.FindWindowById(self.wxId['marker']['type']).GetValue()
  1136. self.properties['marker']['legend'] = self.FindWindowById(self.wxId['marker']['legend']).GetValue()
  1137. for axis in ('x-axis', 'y-axis'):
  1138. self.properties[axis]['prop']['type'] = self.FindWindowById(self.wxId[axis]['type']).GetValue()
  1139. self.properties[axis]['prop']['min'] = float(self.FindWindowById(self.wxId[axis]['min']).GetValue())
  1140. self.properties[axis]['prop']['max'] = float(self.FindWindowById(self.wxId[axis]['max']).GetValue())
  1141. self.properties[axis]['prop']['log'] = self.FindWindowById(self.wxId[axis]['log']).IsChecked()
  1142. self.properties['grid']['color'] = self.FindWindowById(self.wxId['grid']['color']).GetColour()
  1143. self.properties['grid']['enabled'] = self.FindWindowById(self.wxId['grid']['enabled']).IsChecked()
  1144. self.properties['font']['prop']['legendSize'] = self.FindWindowById(self.wxId['font']['legendSize']).GetValue()
  1145. self.properties['legend']['enabled'] = self.FindWindowById(self.wxId['legend']['enabled']).IsChecked()
  1146. def OnSave(self, event):
  1147. """Button 'Save' pressed"""
  1148. self.UpdateSettings()
  1149. fileSettings = {}
  1150. UserSettings.ReadSettingsFile(settings=fileSettings)
  1151. fileSettings['profile'] = UserSettings.Get(group='profile')
  1152. file = UserSettings.SaveToFile(fileSettings)
  1153. self.parent.parent.gismanager.goutput.WriteLog(_('Profile settings saved to file \'%s\'.') % file)
  1154. self.Close()
  1155. def OnApply(self, event):
  1156. """Button 'Apply' pressed"""
  1157. self.UpdateSettings()
  1158. self.Close()
  1159. def OnCancel(self, event):
  1160. """Button 'Cancel' pressed"""
  1161. self.Close()