profile.py 55 KB

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