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