[GRASS-SVN] r48580 - grass/trunk/gui/wxpython/gui_modules

svn_grass at osgeo.org svn_grass at osgeo.org
Sat Oct 1 03:41:04 EDT 2011


Author: cmbarton
Date: 2011-10-01 00:41:03 -0700 (Sat, 01 Oct 2011)
New Revision: 48580

Added:
   grass/trunk/gui/wxpython/gui_modules/wxplot.py
   grass/trunk/gui/wxpython/gui_modules/wxplot_dialogs.py
Modified:
   grass/trunk/gui/wxpython/gui_modules/mapdisp.py
   grass/trunk/gui/wxpython/gui_modules/preferences.py
Log:
wxgui: new abstract class for pyplot modules profile and histogram. Also common dialogs for pyplot modules

Modified: grass/trunk/gui/wxpython/gui_modules/mapdisp.py
===================================================================
--- grass/trunk/gui/wxpython/gui_modules/mapdisp.py	2011-10-01 07:31:11 UTC (rev 48579)
+++ grass/trunk/gui/wxpython/gui_modules/mapdisp.py	2011-10-01 07:41:03 UTC (rev 48580)
@@ -45,7 +45,6 @@
 import gcmd
 import dbm
 import dbm_dialogs
-import profile
 import globalvar
 import utils
 import gdialogs
@@ -55,7 +54,8 @@
 
 from mapdisp_window  import BufferedWindow
 from histogram       import HistFrame
-from histogram2      import HistFrame as HistFramePyPlot
+from wxplot          import HistFrame as HistFramePyPlot
+from wxplot          import ProfileFrame
 from grass.script import core as grass
 
 # for standalone app
@@ -1645,9 +1645,10 @@
                 self.tree.GetPyData(self.tree.layer_selected)[0]['type'] == 'raster':
             raster.append(self.tree.GetPyData(self.tree.layer_selected)[0]['maplayer'].name)
 
-        self.profile = profile.ProfileFrame(self,
+        self.profile = wxplot.ProfileFrame(self,
                                             id = wx.ID_ANY, pos = wx.DefaultPosition, size = (700,300),
-                                            style = wx.DEFAULT_FRAME_STYLE, rasterList = raster)
+                                            style = wx.DEFAULT_FRAME_STYLE, 
+                                            rasterList = raster)
         self.profile.Show()
         # Open raster select dialog to make sure that a raster (and the desired raster)
         # is selected to be profiled
@@ -1703,24 +1704,25 @@
         
         return (outdist, outunits)
     
+
     def OnHistogramPyPlot(self, event):
         """!Init PyPlot histogram display canvas and tools
         """
         raster = []
+
         for layer in self.tree.GetSelections():
             if self.tree.GetPyData(layer)[0]['maplayer'].GetType() != 'raster':
                 continue
             raster.append(self.tree.GetPyData(layer)[0]['maplayer'].GetName())
-        print raster
-        self.histogramPyPlot = HistFramePyPlot(parent = self, id = wx.ID_ANY, size = globalvar.HIST_WINDOW_SIZE,
-                                               style = wx.DEFAULT_FRAME_STYLE, rasterList = raster)
+
+        self.histogramPyPlot = HistFramePyPlot(self, id = wx.ID_ANY, 
+                                                pos = wx.DefaultPosition, size = (700,300),
+                                                style = wx.DEFAULT_FRAME_STYLE, 
+                                                rasterList = raster)
         self.histogramPyPlot.Show()
-        # Open raster select dialog to make sure that a raster (and
-        # the desired raster) is selected to be histogrammed
-        if not raster:
-            self.histogramPyPlot.OnSelectRaster(None)
-        else:
-            self.histogramPyPlot.OnCreateHist(None)
+        # Open raster select dialog to make sure that a raster (and the desired raster)
+        # is selected to be histogrammed
+        self.histogram2.OnSelectRaster(None)
         
     def OnHistogram(self, event):
         """!Init histogram display canvas and tools
@@ -1731,7 +1733,8 @@
         # show new display
         self.histogram.Show()
         self.histogram.Refresh()
-        
+        self.histogram.Update()
+       
     def OnDecoration(self, event):
         """!Decorations overlay menu
         """

Modified: grass/trunk/gui/wxpython/gui_modules/preferences.py
===================================================================
--- grass/trunk/gui/wxpython/gui_modules/preferences.py	2011-10-01 07:31:11 UTC (rev 48579)
+++ grass/trunk/gui/wxpython/gui_modules/preferences.py	2011-10-01 07:41:03 UTC (rev 48580)
@@ -397,22 +397,16 @@
                     'enabled' : False,
                     },
                 },
+             # 
+             # plots for profiles, histograms, and scatterplots
+             #
             'profile': {
-                'raster0' : {
-                    'pcolor' : (0, 0, 255, 255), # profile line color
-                    'pwidth' : 1, # profile line width
-                    'pstyle' : 'solid', # profile line pen style
+                'raster' : {
+                    'pcolor'        : (0, 0, 255, 255), # line color
+                    'pwidth'        : 1, # line width
+                    'pstyle'        : 'solid', # line pen style
+                    'datatype'      : 'cell', # raster type
                     },
-                'raster1' : {
-                    'pcolor' : (255, 0, 0, 255), 
-                    'pwidth' : 1, 
-                    'pstyle' : 'solid', 
-                    },
-                'raster2' : {
-                    'pcolor' : (0, 255, 0, 255), 
-                    'pwidth' : 1, 
-                    'pstyle' : 'solid', 
-                    },
                 'font' : {
                     'titleSize' : 12,
                     'axisSize' : 11,
@@ -477,6 +471,39 @@
                     'enabled'       : True
                     },
                 },
+             'scatter': {
+                'marker' : {
+                    'color' : (0, 0, 0, 255),
+                    'fill' : 'solid',
+                    'size' : 1,
+                    'type' : 'dot',
+                    'legend' : _('Data point'),
+                    },
+                'font' : {
+                    'titleSize'     : 12,
+                    'axisSize'      : 11,
+                    'legendSize'    : 10,
+                    },
+                'grid' : {
+                    'color'         : (200, 200, 200, 255),
+                    'enabled'       : True,
+                    },
+                'x-axis' : {
+                    'type'          : 'auto', # axis format
+                    'min'           : 0, # axis min for custom axis range
+                    'max'           : 0, # axis max for custom axis range
+                    'log'           : False,
+                    },
+                'y-axis' : {
+                    'type'          : 'auto', # axis format
+                    'min'           : 0, # axis min for custom axis range
+                    'max'           : 0, # axis max for custom axis range
+                    'log'           : False,
+                    },
+                'legend' : {
+                    'enabled'       : True
+                    },
+                },
             'gcpman' : {
                 'rms' : {
                     'highestonly' : True,

Added: grass/trunk/gui/wxpython/gui_modules/wxplot.py
===================================================================
--- grass/trunk/gui/wxpython/gui_modules/wxplot.py	                        (rev 0)
+++ grass/trunk/gui/wxpython/gui_modules/wxplot.py	2011-10-01 07:41:03 UTC (rev 48580)
@@ -0,0 +1,982 @@
+"""!
+ at package histogram2.py
+
+Raster histogramming using PyPlot (wx.lib.plot.py); replacement for
+d.hist
+
+Classes:
+ - HistFrame
+ - SetupHistogramDialog
+ - TextDialog
+ - OptDialog
+
+(C) 2011 by the GRASS Development Team
+
+This program is free software under the GNU General Public License
+(>=v2). Read the file COPYING that comes with GRASS for details.
+
+ at author Michael Barton, Arizona State University
+"""
+
+import os
+import sys
+import math
+
+import wx
+import wx.lib.colourselect as  csel
+
+import globalvar
+import gcmd
+from gselect     import Select
+from render      import Map
+from toolbars    import Histogram2Toolbar
+from toolbars    import ProfileToolbar
+from debug       import Debug
+from preferences import globalSettings as UserSettings
+
+import wxplot_dialogs as dialogs
+
+from grass.script import core   as grass
+from grass.script import raster as raster
+
+try:
+    import numpy
+    import wx.lib.plot as plot
+except ImportError:
+    msg = _("This module requires the NumPy module, which could not be "
+            "imported. It probably is not installed (it's not part of the "
+            "standard Python distribution). See the Numeric Python site "
+            "(http://numpy.scipy.org) for information on downloading source or "
+            "binaries.")
+    print >> sys.stderr, "histogram2.py: " + msg
+
+class AbstractPlotFrame(wx.Frame):
+    """!Abstract PyPlot display frame class"""
+    def __init__(self, parent = None, id = wx.ID_ANY, title='', size = (700,300),
+                 style = wx.DEFAULT_FRAME_STYLE, rasterList = [],  **kwargs):
+
+        wx.Frame.__init__(self, parent, id, title, size = size, style = style, **kwargs)
+        
+        self.parent = parent            # MapFrame
+        self.mapwin = self.parent.MapWindow
+        self.Map    = Map()             # instance of render.Map to be associated with display
+        self.rasterList = rasterList    #list of rasters to plot
+        self.raster = {}    # dictionary of raster maps and their plotting parameters
+        self.plottype = ''
+        
+        self.pstyledict = { 'solid' : wx.SOLID,
+                            'dot' : wx.DOT,
+                            'long-dash' : wx.LONG_DASH,
+                            'short-dash' : wx.SHORT_DASH,
+                            'dot-dash' : wx.DOT_DASH }
+
+        self.ptfilldict = { 'transparent' : wx.TRANSPARENT,
+                            'solid' : wx.SOLID }
+
+        #
+        # Icon
+        #
+        self.SetIcon(wx.Icon(os.path.join(globalvar.ETCICONDIR, 'grass.ico'), wx.BITMAP_TYPE_ICO))
+                
+        #
+        # Add statusbar
+        #
+        self.statusbar = self.CreateStatusBar(number = 2, style = 0)
+        self.statusbar.SetStatusWidths([-2, -1])
+
+        #
+        # Define canvas and settings
+        #
+        # 
+        self.client = plot.PlotCanvas(self)
+
+        #define the function for drawing pointLabels
+        self.client.SetPointLabelFunc(self.DrawPointLabel)
+
+        # Create mouse event for showing cursor coords in status bar
+        self.client.canvas.Bind(wx.EVT_LEFT_DOWN, self.OnMouseLeftDown)
+
+        # Show closest point when enabled
+        self.client.canvas.Bind(wx.EVT_MOTION, self.OnMotion)
+
+        self.plotlist = []      # list of things to plot
+        self.plot = None        # plot draw object
+        self.ptitle = ""        # title of window
+        self.xlabel = ""        # default X-axis label
+        self.ylabel = ""        # default Y-axis label
+
+        #
+        # Bind various events
+        #
+        self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
+        
+        self.CentreOnScreen()
+        
+        self._createColorDict()
+
+
+    def _createColorDict(self):
+        """!Create color dictionary to return wx.Color tuples
+        for assigning colors to images in imagery groups"""
+                
+        self.colorDict = {}
+        for clr in grass.named_colors.iterkeys():
+            if clr == 'white' or clr == 'black': continue
+            r = grass.named_colors[clr][0] * 255
+            g = grass.named_colors[clr][1] * 255
+            b = grass.named_colors[clr][2] * 255
+            self.colorDict[clr] = (r,g,b,255)
+
+    def InitPlotOpts(self, plottype):
+        """!Initialize options for entire plot
+        """
+        
+        self.plottype = plottype                # histogram, profile, or scatter
+
+        self.properties = {}                    # plot properties
+        self.properties['font'] = {}
+        self.properties['font']['prop'] = UserSettings.Get(group = self.plottype, key = 'font')
+        self.properties['font']['wxfont'] = wx.Font(11, wx.FONTFAMILY_SWISS,
+                                                    wx.FONTSTYLE_NORMAL,
+                                                    wx.FONTWEIGHT_NORMAL)
+        
+        if self.plottype != 'histogram':
+            self.properties['marker'] = UserSettings.Get(group = self.plottype, key = 'marker')
+            # changing color string to tuple for markers/points
+            colstr = str(self.properties['marker']['color'])
+            self.properties['marker']['color'] = tuple(int(colval) for colval in colstr.strip('()').split(','))
+
+        self.properties['grid'] = UserSettings.Get(group = self.plottype, key = 'grid')        
+        colstr = str(self.properties['grid']['color']) # changing color string to tuple        
+        self.properties['grid']['color'] = tuple(int(colval) for colval in colstr.strip('()').split(','))
+                
+        self.properties['x-axis'] = {}
+        self.properties['x-axis']['prop'] = UserSettings.Get(group = self.plottype, key = 'x-axis')
+        self.properties['x-axis']['axis'] = None
+
+        self.properties['y-axis'] = {}
+        self.properties['y-axis']['prop'] = UserSettings.Get(group = self.plottype, key = 'y-axis')
+        self.properties['y-axis']['axis'] = None
+        
+        self.properties['legend'] = UserSettings.Get(group = self.plottype, key = 'legend')
+
+        self.zoom = False  # zooming disabled
+        self.drag = False  # draging disabled
+        self.client.SetShowScrollbars(True) # vertical and horizontal scrollbars
+
+        # x and y axis set to normal (non-log)
+        self.client.setLogScale((False, False))
+        if self.properties['x-axis']['prop']['type']:
+            self.client.SetXSpec(self.properties['x-axis']['prop']['type'])
+        else:
+            self.client.SetXSpec('auto')
+        
+        if self.properties['y-axis']['prop']['type']:
+            self.client.SetYSpec(self.properties['y-axis']['prop']['type'])
+        else:
+            self.client.SetYSpec('auto')
+        
+    def InitRasterOpts(self, rasterList):
+        """!Initialize or update raster dictionary for plotting
+        """
+
+        rdict = {} # initialize a dictionary
+
+        for r in rasterList:
+            idx = rasterList.index(r)
+            
+            try:
+                ret = raster.raster_info(r)
+            except:
+                continue
+                # if r.info cannot parse map, skip it
+
+#            self.raster[r] = UserSettings.Get(group = 'plot', key = 'raster') # some default settings
+            rdict[r] = {} # initialize sub-dictionaries for each raster in the list
+
+            if ret['units'] == '(none)' or ret['units'] == '' or ret['units'] == None:
+                rdict[r]['units'] = ''
+            else:
+                self.raster[r]['units'] = ret['units']
+
+            rdict[r]['plegend'] = r.split('@')[0]
+            rdict[r]['datalist'] = [] # list of cell value,frequency pairs for plotting histogram
+            rdict[r]['pline'] = None
+            rdict[r]['datatype'] = ret['datatype']
+            rdict[r]['pwidth'] = 1
+            rdict[r]['pstyle'] = 'solid'
+            
+            if idx <= len(self.colorList):
+                rdict[r]['pcolor'] = self.colorDict[self.colorList[idx]]
+            else:
+                r = randint(0, 255)
+                b = randint(0, 255)
+                g = randint(0, 255)
+                rdict[r]['pcolor'] = ((r,g,b,255))
+ 
+            
+        return rdict
+            
+    def SetGraphStyle(self):
+        """!Set plot and text options
+        """
+        self.client.SetFont(self.properties['font']['wxfont'])
+        self.client.SetFontSizeTitle(self.properties['font']['prop']['titleSize'])
+        self.client.SetFontSizeAxis(self.properties['font']['prop']['axisSize'])
+
+        self.client.SetEnableZoom(self.zoom)
+        self.client.SetEnableDrag(self.drag)
+        
+        #
+        # axis settings
+        #
+        if self.properties['x-axis']['prop']['type'] == 'custom':
+            self.client.SetXSpec('min')
+        else:
+            self.client.SetXSpec(self.properties['x-axis']['prop']['type'])
+
+        if self.properties['y-axis']['prop']['type'] == 'custom':
+            self.client.SetYSpec('min')
+        else:
+            self.client.SetYSpec(self.properties['y-axis']['prop']['type'])
+
+        if self.properties['x-axis']['prop']['type'] == 'custom' and \
+               self.properties['x-axis']['prop']['min'] < self.properties['x-axis']['prop']['max']:
+            self.properties['x-axis']['axis'] = (self.properties['x-axis']['prop']['min'],
+                                                 self.properties['x-axis']['prop']['max'])
+        else:
+            self.properties['x-axis']['axis'] = None
+
+        if self.properties['y-axis']['prop']['type'] == 'custom' and \
+                self.properties['y-axis']['prop']['min'] < self.properties['y-axis']['prop']['max']:
+            self.properties['y-axis']['axis'] = (self.properties['y-axis']['prop']['min'],
+                                                 self.properties['y-axis']['prop']['max'])
+        else:
+            self.properties['y-axis']['axis'] = None
+
+        self.client.SetEnableGrid(self.properties['grid']['enabled'])
+        
+        self.client.SetGridColour(wx.Color(self.properties['grid']['color'][0],
+                                           self.properties['grid']['color'][1],
+                                           self.properties['grid']['color'][2],
+                                           255))
+
+        self.client.SetFontSizeLegend(self.properties['font']['prop']['legendSize'])
+        self.client.SetEnableLegend(self.properties['legend']['enabled'])
+
+        if self.properties['x-axis']['prop']['log'] == True:
+            self.properties['x-axis']['axis'] = None
+            self.client.SetXSpec('min')
+        if self.properties['y-axis']['prop']['log'] == True:
+            self.properties['y-axis']['axis'] = None
+            self.client.SetYSpec('min')
+            
+        self.client.setLogScale((self.properties['x-axis']['prop']['log'],
+                                 self.properties['y-axis']['prop']['log']))
+
+    def DrawPlot(self, plotlist):
+        """!Draw line and point plot from list plot elements.
+        """
+
+        self.plot = plot.PlotGraphics(plotlist,
+                                         self.ptitle,
+                                         self.xlabel,
+                                         self.ylabel)
+
+        if self.properties['x-axis']['prop']['type'] == 'custom':
+            self.client.SetXSpec('min')
+        else:
+            self.client.SetXSpec(self.properties['x-axis']['prop']['type'])
+
+        if self.properties['y-axis']['prop']['type'] == 'custom':
+            self.client.SetYSpec('min')
+        else:
+            self.client.SetYSpec(self.properties['y-axis']['prop']['type'])
+
+        self.client.Draw(self.plot, self.properties['x-axis']['axis'],
+                         self.properties['y-axis']['axis'])
+                
+    def DrawPointLabel(self, dc, mDataDict):
+        """!This is the fuction that defines how the pointLabels are
+            plotted dc - DC that will be passed mDataDict - Dictionary
+            of data that you want to use for the pointLabel
+
+            As an example I have decided I want a box at the curve
+            point with some text information about the curve plotted
+            below.  Any wxDC method can be used.
+        """
+        dc.SetPen(wx.Pen(wx.BLACK))
+        dc.SetBrush(wx.Brush( wx.BLACK, wx.SOLID ) )
+
+        sx, sy = mDataDict["scaledXY"] #scaled x,y of closest point
+        dc.DrawRectangle( sx-5,sy-5, 10, 10)  #10by10 square centered on point
+        px,py = mDataDict["pointXY"]
+        cNum = mDataDict["curveNum"]
+        pntIn = mDataDict["pIndex"]
+        legend = mDataDict["legend"]
+        #make a string to display
+        s = "Crv# %i, '%s', Pt. (%.2f,%.2f), PtInd %i" %(cNum, legend, px, py, pntIn)
+        dc.DrawText(s, sx , sy+1)
+
+    def OnZoom(self, event):
+        """!Enable zooming and disable dragging
+        """
+        self.zoom = True
+        self.drag = False
+        self.client.SetEnableZoom(self.zoom)
+        self.client.SetEnableDrag(self.drag)
+
+    def OnDrag(self, event):
+        """!Enable dragging and disable zooming
+        """
+        self.zoom = False
+        self.drag = True
+        self.client.SetEnableDrag(self.drag)
+        self.client.SetEnableZoom(self.zoom)
+
+    def OnRedraw(self, event):
+        """!Redraw the plot window. Unzoom to original size
+        """
+        self.client.Reset()
+        self.client.Redraw()
+       
+    def OnErase(self, event):
+        """!Erase the plot window
+        """
+        self.client.Clear()
+        self.mapwin.ClearLines(self.mapwin.pdc)
+        self.mapwin.ClearLines(self.mapwin.pdcTmp)
+        self.mapwin.polycoords = []
+        self.mapwin.Refresh()
+
+    def SaveToFile(self, event):
+        """!Save plot to graphics file
+        """
+        self.client.SaveFile()
+
+    def OnMouseLeftDown(self,event):
+        self.SetStatusText(_("Left Mouse Down at Point: (%.4f, %.4f)") % \
+                               self.client._getXY(event))
+        event.Skip() # allows plotCanvas OnMouseLeftDown to be called
+
+    def OnMotion(self, event):
+        """!Indicate when mouse is outside the plot area
+        """
+        if self.client.OnLeave(event): print 'out of area'
+        #show closest point (when enbled)
+        if self.client.GetEnablePointLabel() == True:
+            #make up dict with info for the pointLabel
+            #I've decided to mark the closest point on the closest curve
+            dlst =  self.client.GetClosetPoint( self.client._getXY(event), pointScaled =  True)
+            if dlst != []:      #returns [] if none
+                curveNum, legend, pIndex, pointXY, scaledXY, distance = dlst
+                #make up dictionary to pass to my user function (see DrawPointLabel)
+                mDataDict =  {"curveNum":curveNum, "legend":legend, "pIndex":pIndex,\
+                    "pointXY":pointXY, "scaledXY":scaledXY}
+                #pass dict to update the pointLabel
+                self.client.UpdatePointLabel(mDataDict)
+        event.Skip()           #go to next handler        
+ 
+ 
+    def PlotOptionsMenu(self, event):
+        """!Popup menu for plot and text options
+        """
+        point = wx.GetMousePosition()
+        popt = wx.Menu()
+        # Add items to the menu
+        settext = wx.MenuItem(popt, wx.ID_ANY, _('Text settings'))
+        popt.AppendItem(settext)
+        self.Bind(wx.EVT_MENU, self.PlotText, settext)
+
+        setgrid = wx.MenuItem(popt, wx.ID_ANY, _('Plot settings'))
+        popt.AppendItem(setgrid)
+        self.Bind(wx.EVT_MENU, self.PlotOptions, setgrid)
+
+        # Popup the menu.  If an item is selected then its handler
+        # will be called before PopupMenu returns.
+        self.PopupMenu(popt)
+        popt.Destroy()
+
+    def NotFunctional(self):
+        """!Creates a 'not functional' message dialog
+        """
+        dlg = wx.MessageDialog(parent = self,
+                               message = _('This feature is not yet functional'),
+                               caption = _('Under Construction'),
+                               style = wx.OK | wx.ICON_INFORMATION)
+        dlg.ShowModal()
+        dlg.Destroy()
+
+    def OnPlotText(self, dlg):
+        """!Custom text settings for histogram plot.
+        """
+        self.ptitle = dlg.ptitle
+        self.xlabel = dlg.xlabel
+        self.ylabel = dlg.ylabel
+        dlg.UpdateSettings()
+
+        self.client.SetFont(self.properties['font']['wxfont'])
+        self.client.SetFontSizeTitle(self.properties['font']['prop']['titleSize'])
+        self.client.SetFontSizeAxis(self.properties['font']['prop']['axisSize'])
+
+        if self.plot:
+            self.plot.setTitle(dlg.ptitle)
+            self.plot.setXLabel(dlg.xlabel)
+            self.plot.setYLabel(dlg.ylabel)
+        
+        self.OnRedraw(event = None)
+    
+    def PlotText(self, event):
+        """!Set custom text values for profile title and axis labels.
+        """
+        dlg = dialogs.TextDialog(parent = self, id = wx.ID_ANY, 
+                                 plottype = self.plottype, 
+                                 title = _('Histogram text settings'))
+
+        if dlg.ShowModal() == wx.ID_OK:
+            self.OnPlotText(dlg)
+
+        dlg.Destroy()
+
+    def PlotOptions(self, event):
+        """!Set various profile options, including: line width, color,
+        style; marker size, color, fill, and style; grid and legend
+        options.  Calls OptDialog class.
+        """
+        dlg = dialogs.OptDialog(parent = self, id = wx.ID_ANY, 
+                                plottype = self.plottype, 
+                                title = _('Plot settings'))
+        btnval = dlg.ShowModal()
+
+        if btnval == wx.ID_SAVE:
+            dlg.UpdateSettings()            
+            self.SetGraphStyle()            
+            dlg.Destroy()            
+        elif btnval == wx.ID_CANCEL:
+            dlg.Destroy()
+
+    def PrintMenu(self, event):
+        """!Print options and output menu
+        """
+        point = wx.GetMousePosition()
+        printmenu = wx.Menu()
+        for title, handler in ((_("Page setup"), self.OnPageSetup),
+                               (_("Print preview"), self.OnPrintPreview),
+                               (_("Print display"), self.OnDoPrint)):
+            item = wx.MenuItem(printmenu, wx.ID_ANY, title)
+            printmenu.AppendItem(item)
+            self.Bind(wx.EVT_MENU, handler, item)
+        
+        # Popup the menu.  If an item is selected then its handler
+        # will be called before PopupMenu returns.
+        self.PopupMenu(printmenu)
+        printmenu.Destroy()
+
+    def OnPageSetup(self, event):
+        self.client.PageSetup()
+
+    def OnPrintPreview(self, event):
+        self.client.PrintPreview()
+
+    def OnDoPrint(self, event):
+        self.client.Printout()
+
+    def OnQuit(self, event):
+        self.Close(True)
+
+    def OnCloseWindow(self, event):
+        """!Close plot window and clean up
+        """
+        try:
+            self.mapwin.ClearLines()
+            self.mapwin.mouse['begin'] = self.mapwin.mouse['end'] = (0.0, 0.0)
+            self.mapwin.mouse['use'] = 'pointer'
+            self.mapwin.mouse['box'] = 'point'
+            self.mapwin.polycoords = []
+            self.mapwin.UpdateMap(render = False, renderVector = False)
+        except:
+            pass
+        
+        self.mapwin.SetCursor(self.Parent.cursors["default"])
+        self.Destroy()
+        
+class HistFrame(AbstractPlotFrame):
+    def __init__(self, parent, id, pos, style, size,
+                 title = _("GRASS Histogramming Tool"), rasterList = []):
+        """!Mainframe for displaying histogram of raster map. Uses wx.lib.plot.
+        """
+        AbstractPlotFrame.__init__(self, parent)
+        
+        self.toolbar = Histogram2Toolbar(parent = self)
+        self.SetToolBar(self.toolbar)
+
+        #
+        # Init variables
+        #
+        self.rasterList = rasterList
+        self.plottype = 'histogram'
+        self.group = '' 
+        self.ptitle = _('Histogram of')         # title of window
+        self.xlabel = _("Raster cell values")   # default X-axis label
+        self.ylabel = _("Cell counts")          # default Y-axis label
+        self.maptype = 'raster'                 # default type of histogram to plot
+        self.histtype = 'count' 
+        self.bins = 255
+        self.colorList = ["blue", "green", "red", "yellow", "magenta", "cyan", \
+                    "aqua", "black", "grey", "orange", "brown", "purple", "violet", \
+                    "indigo"]
+        
+        if len(self.rasterList) > 0: # set raster name(s) from layer manager if a map is selected
+            self.InitRasterOpts(self.rasterList)
+
+        self._initOpts()
+
+    def _initOpts(self):
+        """!Initialize plot options
+        """
+        self.InitPlotOpts('histogram')            
+
+    def OnCreateHist(self, event):
+        """!Main routine for creating a histogram. Uses r.stats to
+        create a list of cell value and count/percent/area pairs. This is passed to
+        plot to create a line graph of the histogram.
+        """
+        self.SetCursor(self.parent.cursors["default"])
+        self.SetGraphStyle()
+        self.SetupHistogram()
+        p = self.CreatePlotList()
+        self.DrawPlot(p)
+
+    def OnSelectRaster(self, event):
+        """!Select raster map(s) to profile
+        """
+        dlg = dialogs.HistRasterDialog(parent = self)
+
+        if dlg.ShowModal() == wx.ID_OK:
+            self.rasterList = dlg.rasterList
+            self.group = dlg.group
+            self.bins = dlg.bins
+            self.histtype = dlg.histtype
+            self.maptype = dlg.maptype
+            self.raster = self.InitRasterOpts(self.rasterList)
+
+            # plot histogram
+            if len(self.rasterList) > 0:
+                self.OnCreateHist(event = None)
+                self.SetupHistogram()
+                p = self.CreatePlotList()
+                self.DrawPlot(p)
+
+        dlg.Destroy()
+
+    def SetupHistogram(self):
+        """!Build data list for ploting each raster
+        """
+
+        #
+        # populate raster dictionary
+        #
+        if len(self.rasterList) == 0: return  # nothing selected
+        
+        for r in self.rasterList:
+            self.raster[r]['datalist'] = self.CreateDatalist(r)
+            
+        #
+        # update title
+        #
+        if self.maptype == 'group':
+            self.ptitle = _('Histogram of %s') % self.group.split('@')[0] 
+        else: 
+            self.ptitle = _('Histogram of %s') % self.rasterList[0].split('@')[0] 
+
+        
+        #
+        # set xlabel based on first raster map in list to be histogrammed
+        #
+        units = self.raster[self.rasterList[0]]['units']
+        if units != '' and units != '(none)' and units != None:
+            self.xlabel = _('Raster cell values %s') % units
+        else:
+            self.xlabel = _('Raster cell values') 
+
+        #
+        # set ylabel from self.histtype
+        #
+        if self.histtype == 'count': self.ylabel = _('Cell counts')
+        if self.histtype == 'percent': self.ylabel = _('Percent of total cells')
+        if self.histtype == 'area': self.ylabel = _('Area')
+
+    def CreateDatalist(self, raster):
+        """!Build a list of cell value, frequency pairs for histogram
+            frequency can be in cell counts, percents, or area
+        """
+        datalist = []
+        
+        if self.histtype == 'count': freqflag = 'cn'
+        if self.histtype == 'percent': freqflag = 'pn'
+        if self.histtype == 'area': freqflag = 'an'
+                
+        try:
+            ret = gcmd.RunCommand("r.stats",
+                                  parent = self,
+                                  input = raster,
+                                  flags = freqflag,
+                                  nsteps = self.bins,
+                                  fs = ',',
+                                  quiet = True,
+                                  read = True)
+            
+            if not ret:
+                return datalist
+            
+            for line in ret.splitlines():
+                cellval, histval = line.strip().split(',')
+                histval = histval.strip()
+                if self.raster[raster]['datatype'] != 'CELL':
+                    cellval = cellval.split('-')[0]
+                if self.histtype == 'percent':
+                    histval = histval.rstrip('%')
+                    
+                datalist.append((cellval,histval))
+
+            return datalist
+        except gcmd.GException, e:
+            gcmd.GError(parent = self,
+                        message = e.value)
+            return None
+        
+    def CreatePlotList(self):
+        """!Make list of elements to plot
+        """
+        
+        # graph the cell value, frequency pairs for the histogram
+        self.plotlist = []
+
+        for r in self.rasterList:
+            if len(self.raster[r]['datalist']) > 0:
+                col = wx.Color(self.raster[r]['pcolor'][0],
+                               self.raster[r]['pcolor'][1],
+                               self.raster[r]['pcolor'][2],
+                               255)
+                self.raster[r]['pline'] = plot.PolyLine(self.raster[r]['datalist'],
+                                                        colour = col,
+                                                        width = self.raster[r]['pwidth'],
+                                                        style = self.pstyledict[self.raster[r]['pstyle']],
+                                                        legend = self.raster[r]['plegend'])
+
+                self.plotlist.append(self.raster[r]['pline'])
+          
+        if len(self.plotlist) > 0:        
+            return self.plotlist
+        else:
+            return None
+
+    def Update(self):
+        """!Update histogram after changing options
+        """
+        self.SetGraphStyle()
+        p = self.CreatePlotList()
+        self.DrawPlot(p)
+        
+        
+class ProfileFrame(AbstractPlotFrame):
+    """!Mainframe for displaying profile of one or more raster maps. Uses wx.lib.plot.
+    """
+    def __init__(self, parent, id, pos, style, size,
+                 title = _("GRASS Profile Analysis Tool"), rasterList = []):
+
+        AbstractPlotFrame.__init__(self, parent)
+
+        self.toolbar = ProfileToolbar(parent = self)
+        self.SetToolBar(self.toolbar)
+
+        #
+        # Init variables
+        #
+        self.rasterList = rasterList
+        self.plottype = 'profile'
+        self.coordstr = ''              # string of coordinates for r.profile
+        self.seglist = []               # segment endpoint list
+        self.ppoints = ''               # segment endpoints data         
+        self.transect_length = 0.0      # total transect length        
+        self.ptitle = _('Profile of')   # title of window
+        self.raster = {}
+
+        self.colorList =  ["blue", "red", "green", "yellow", "magenta", "cyan", \
+                    "aqua", "black", "grey", "orange", "brown", "purple", "violet", \
+                    "indigo"]
+
+        if len(self.rasterList) > 0: # set raster name(s) from layer manager if a map is selected
+            self.InitRasterOpts(self.rasterList)
+            
+        
+        self._initOpts()
+
+        # determine units (axis labels)
+        if self.parent.Map.projinfo['units'] != '':
+            self.xlabel = _('Distance (%s)') % self.parent.Map.projinfo['units']
+        else:
+            self.xlabel = _("Distance along transect")
+        self.ylabel = _("Cell values")
+        
+    def _initOpts(self):
+        """!Initialize plot options
+        """
+        self.InitPlotOpts('profile')
+
+    def OnDrawTransect(self, event):
+        """!Draws transect to profile in map display
+        """
+        self.mapwin.polycoords = []
+        self.seglist = []
+        self.mapwin.ClearLines(self.mapwin.pdc)
+        self.ppoints = ''
+
+        self.parent.SetFocus()
+        self.parent.Raise()
+        
+        self.mapwin.mouse['use'] = 'profile'
+        self.mapwin.mouse['box'] = 'line'
+        self.mapwin.pen = wx.Pen(colour = 'Red', width = 2, style = wx.SHORT_DASH)
+        self.mapwin.polypen = wx.Pen(colour = 'dark green', width = 2, style = wx.SHORT_DASH)
+        self.mapwin.SetCursor(self.Parent.cursors["cross"])
+
+    def OnSelectRaster(self, event):
+        """!Select raster map(s) to profile
+        """
+        dlg = dialogs.ProfileRasterDialog(parent = self)
+
+        if dlg.ShowModal() == wx.ID_OK:
+            self.rasterList = dlg.rasterList
+            self.raster = self.InitRasterOpts(self.rasterList)
+            
+            # plot profile
+            if len(self.mapwin.polycoords) > 0 and len(self.rasterList) > 0:
+                self.OnCreateProfile(event = None)
+
+        dlg.Destroy()
+
+    def SetupProfile(self):
+        """!Create coordinate string for profiling. Create segment list for
+           transect segment markers.
+        """
+
+        #
+        # create list of coordinate points for r.profile
+        #
+                
+        dist = 0
+        cumdist = 0
+        self.coordstr = ''
+        lasteast = lastnorth = None
+        
+        if len(self.mapwin.polycoords) > 0:
+            for point in self.mapwin.polycoords:
+                # build string of coordinate points for r.profile
+                if self.coordstr == '':
+                    self.coordstr = '%d,%d' % (point[0], point[1])
+                else:
+                    self.coordstr = '%s,%d,%d' % (self.coordstr, point[0], point[1])
+
+        if len(self.rasterList) == 0:
+            return
+
+        # title of window
+        self.ptitle = _('Profile of')
+
+        #
+        # create list of coordinates for transect segment markers
+        #
+        if len(self.mapwin.polycoords) > 0:
+            for point in self.mapwin.polycoords:
+                # get value of raster cell at coordinate point
+                ret = gcmd.RunCommand('r.what',
+                                      parent = self,
+                                      read = True,
+                                      input = self.rasterList[0],
+                                      east_north = '%d,%d' % (point[0],point[1]))
+                
+                val = ret.splitlines()[0].split('|')[3]
+                
+                # calculate distance between coordinate points
+                if lasteast and lastnorth:
+                    dist = math.sqrt(math.pow((lasteast-point[0]),2) + math.pow((lastnorth-point[1]),2))
+                cumdist += dist
+                
+                #store total transect length
+                self.transect_length = cumdist
+
+                # build a list of distance,value pairs for each segment of transect
+                self.seglist.append((cumdist,val))
+                lasteast = point[0]
+                lastnorth = point[1]
+
+            # delete first and last segment point
+            try:
+                self.seglist.pop(0)
+                self.seglist.pop()
+            except:
+                pass
+
+
+        #
+        # create datalist for each raster map
+        #    
+        for r in self.raster.iterkeys():
+            self.raster[r]['datalist'] = []  
+            self.raster[r]['datalist'] = self.CreateDatalist(r, self.coordstr)
+
+            # update title
+            self.ptitle += ' %s and' % r
+
+        self.ptitle = self.ptitle.rstrip('and')
+
+        #
+        # set ylabel to match units if they exist
+        #
+        self.ylabel = ''
+        i = 0
+        for r in self.rasterList:
+            if self.raster[r]['units'] != '':
+                self.ylabel += '%s (%d),' % (r['units'], i)
+            i += 1
+            
+        if self.ylabel == '':
+            self.ylabel = _('Raster values')
+        else:
+            self.ylabel = self.ylabel.rstrip(',')
+
+    def CreateDatalist(self, raster, coords):
+        """!Build a list of distance, value pairs for points along transect using r.profile
+        """
+        datalist = []
+        
+        # keep total number of transect points to 500 or less to avoid 
+        # freezing with large, high resolution maps
+        region = grass.region()
+        curr_res = min(float(region['nsres']),float(region['ewres']))
+        transect_rec = 0
+        if self.transect_length / curr_res > 500:
+            transect_res = self.transect_length / 500
+        else: transect_res = curr_res
+        
+        ret = gcmd.RunCommand("r.profile",
+                              parent = self,
+                              input = raster,
+                              profile = coords,
+                              res = transect_res,
+                              null = "nan",
+                              quiet = True,
+                              read = True)
+        
+        if not ret:
+            return []
+            
+        for line in ret.splitlines():
+            dist, elev = line.strip().split(' ')
+            if elev != 'nan':
+                datalist.append((dist,elev))
+
+        return datalist
+
+    def OnCreateProfile(self, event):
+        """!Main routine for creating a profile. Uses r.profile to
+        create a list of distance,cell value pairs. This is passed to
+        plot to create a line graph of the profile. If the profile
+        transect is in multiple segments, these are drawn as
+        points. Profile transect is drawn, using methods in mapdisp.py
+        """
+            
+        if len(self.mapwin.polycoords) == 0 or len(self.rasterList) == 0:
+            dlg = wx.MessageDialog(parent = self,
+                                   message = _('You must draw a transect to profile in the map display window.'),
+                                   caption = _('Nothing to profile'),
+                                   style = wx.OK | wx.ICON_INFORMATION | wx.CENTRE)
+            dlg.ShowModal()
+            dlg.Destroy()
+            return
+
+        self.mapwin.SetCursor(self.parent.cursors["default"])
+        self.SetCursor(self.parent.cursors["default"])
+        self.SetGraphStyle()
+        self.SetupProfile()
+        p = self.CreatePlotList()
+        self.DrawPlot(p)
+
+        # reset transect
+        self.mapwin.mouse['begin'] = self.mapwin.mouse['end'] = (0.0,0.0)
+        self.mapwin.mouse['use'] = 'pointer'
+        self.mapwin.mouse['box'] = 'point'
+
+    def CreatePlotList(self):
+        """!Create a plot data list from transect datalist and
+            transect segment endpoint coordinates.
+        """
+        # graph the distance, value pairs for the transect
+        self.plotlist = []
+        # Add segment marker points to plot data list
+        if len(self.seglist) > 0 :
+            self.ppoints = plot.PolyMarker(self.seglist,
+                                           legend = ' ' + self.properties['marker']['legend'],
+                                           colour = wx.Color(self.properties['marker']['color'][0],
+                                                           self.properties['marker']['color'][1],
+                                                           self.properties['marker']['color'][2],
+                                                           255),
+                                           size = self.properties['marker']['size'],
+                                           fillstyle = self.ptfilldict[self.properties['marker']['fill']],
+                                           marker = self.properties['marker']['type'])
+            self.plotlist.append(self.ppoints)
+
+        # Add profile distance/elevation pairs to plot data list for each raster profiled
+        for r in self.rasterList:
+            col = wx.Color(self.raster[r]['pcolor'][0],
+                           self.raster[r]['pcolor'][1],
+                           self.raster[r]['pcolor'][2],
+                           255)
+            self.raster[r]['pline'] = plot.PolyLine(self.raster[r]['datalist'],
+                                                    colour = col,
+                                                    width = self.raster[r]['pwidth'],
+                                                    style = self.pstyledict[self.raster[r]['pstyle']],
+                                                    legend = self.raster[r]['plegend'])
+
+            self.plotlist.append(self.raster[r]['pline'])
+
+        if len(self.plotlist) > 0:        
+            return self.plotlist
+        else:
+            return None
+
+    def Update(self):
+        """!Update profile after changing options
+        """
+        self.SetGraphStyle()
+        p = self.CreatePlotList()
+        self.DrawPlot(p)
+
+    def SaveProfileToFile(self, event):
+        """!Save r.profile data to a csv file
+        """    
+        wildcard = _("Comma separated value (*.csv)|*.csv")
+        
+        dlg = wx.FileDialog(parent = self,
+                            message = _("Path and prefix (for raster name) to save profile values..."),
+                            defaultDir = os.getcwd(), 
+                            defaultFile = "",  wildcard = wildcard, style = wx.SAVE)
+        if dlg.ShowModal() == wx.ID_OK:
+            path = dlg.GetPath()
+            
+            for r in self.rasterList:
+                pfile = path+'_'+str(r['name'])+'.csv'
+                try:
+                    file = open(pfile, "w")
+                except IOError:
+                    wx.MessageBox(parent = self,
+                                  message = _("Unable to open file <%s> for writing.") % pfile,
+                                  caption = _("Error"), style = wx.OK | wx.ICON_ERROR | wx.CENTRE)
+                    return False
+                for datapair in self.raster[r]['datalist']:
+                    file.write('%d,%d\n' % (float(datapair[0]),float(datapair[1])))
+                                        
+                file.close()
+
+        dlg.Destroy()
\ No newline at end of file


Property changes on: grass/trunk/gui/wxpython/gui_modules/wxplot.py
___________________________________________________________________
Added: svn:executable
   + *

Added: grass/trunk/gui/wxpython/gui_modules/wxplot_dialogs.py
===================================================================
--- grass/trunk/gui/wxpython/gui_modules/wxplot_dialogs.py	                        (rev 0)
+++ grass/trunk/gui/wxpython/gui_modules/wxplot_dialogs.py	2011-10-01 07:41:03 UTC (rev 48580)
@@ -0,0 +1,931 @@
+"""!
+ at package wxplot_dialogs.py
+
+GRASS interactive plotting using PyPlot (wx.lib.plot.py). Dialogs for different
+    plotting routines
+
+Classes:
+ - ProfileRasterDialog
+ - HistRasterDialog
+ - TextDialog
+ - OptDialog
+
+(C) 2011 by the GRASS Development Team
+
+This program is free software under the GNU General Public License
+(>=v2). Read the file COPYING that comes with GRASS for details.
+
+ at author Michael Barton, Arizona State University
+"""
+
+import os
+import sys
+
+import wx
+import wx.lib.colourselect as  csel
+
+import globalvar
+import gcmd
+from gselect     import Select
+from render      import Map
+from toolbars    import Histogram2Toolbar
+from debug       import Debug
+from preferences import globalSettings as UserSettings
+
+from grass.script import core   as grass
+from grass.script import raster as raster
+
+class ProfileRasterDialog(wx.Dialog):
+    def __init__(self, parent, id = wx.ID_ANY, 
+                 title = _("Select raster map or imagery group to histogram"),
+                 style = wx.DEFAULT_DIALOG_STYLE, **kwargs):
+        """!Dialog to select raster maps to profile.
+        """
+
+        wx.Dialog.__init__(self, parent, id, title, style = style, **kwargs)
+
+
+        self.parent = parent
+        self.colorList = ["blue", "red", "green", "yellow", "magenta", "cyan", \
+                    "aqua", "black", "grey", "orange", "brown", "purple", "violet", \
+                    "indigo"]
+
+        self.rasterList = self.parent.rasterList
+        
+        self._do_layout()
+        
+    def _do_layout(self):
+
+        sizer = wx.BoxSizer(wx.VERTICAL)
+
+        box = wx.GridBagSizer (hgap = 3, vgap = 3)
+        
+        rastText = ''
+        for r in self.rasterList:
+            rastText += '%s,' % r
+            
+        rastText = rastText.rstrip(',')
+        
+        txt = _("Select raster map(s) to profile:")
+        label = wx.StaticText(parent = self, id = wx.ID_ANY, label = txt)
+        box.Add(item = label,
+                flag = wx.ALIGN_CENTER_VERTICAL, pos = (0, 0))
+        
+        selection = Select(self, id = wx.ID_ANY,
+                           size = globalvar.DIALOG_GSELECT_SIZE,
+                           type = 'cell', multiple=True)
+        selection.SetValue(rastText)
+        selection.Bind(wx.EVT_TEXT, self.OnSelection)
+        
+        box.Add(item = selection, pos = (0, 1))
+            
+        sizer.Add(item = box, proportion = 0,
+                  flag = wx.ALL, border = 10)
+
+        line = wx.StaticLine(parent = self, id = wx.ID_ANY, size = (20, -1), style = wx.LI_HORIZONTAL)
+        sizer.Add(item = line, proportion = 0,
+                  flag = wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.LEFT|wx.RIGHT, border = 5)
+
+        btnsizer = wx.StdDialogButtonSizer()
+
+        btn = wx.Button(self, wx.ID_OK)
+        btn.SetDefault()
+        btnsizer.AddButton(btn)
+
+        btn = wx.Button(self, wx.ID_CANCEL)
+        btnsizer.AddButton(btn)
+        btnsizer.Realize()
+
+        sizer.Add(item = btnsizer, proportion = 0, flag = wx.ALIGN_RIGHT | wx.ALL, border = 5)
+
+        self.SetSizer(sizer)
+        sizer.Fit(self)
+
+    def OnSelection(self, event):
+        # for now this is limited to 14 rasters (number of colors in colorList), but it could be increased
+        rstring = event.GetString()
+        rList = rstring.split(',')
+        n = min(len(rList), len(self.colorList))
+        self.rasterList = []
+        for idx in range(0,n):
+            self.rasterList.append(rList[idx])
+
+class HistRasterDialog(wx.Dialog):
+    def __init__(self, parent, id = wx.ID_ANY, 
+                 title = _("Select raster map or imagery group to histogram"),
+                 style = wx.DEFAULT_DIALOG_STYLE, **kwargs):
+        """!Dialog to select raster maps to histogram.
+        """
+
+        wx.Dialog.__init__(self, parent, id, title, style = style, **kwargs)
+
+        self.parent = parent
+        self.rasterList = self.parent.rasterList
+        self.group = self.parent.group
+        self.bins = self.parent.bins
+        self.histtype = self.parent.histtype
+        self.maptype = self.parent.maptype
+        self.spinbins = ''
+        
+        self._do_layout()
+        
+    def _do_layout(self):
+
+        sizer = wx.BoxSizer(wx.VERTICAL)
+
+        box = wx.GridBagSizer (hgap = 3, vgap = 3)
+        
+        #
+        # select single raster or image group to histogram radio buttons
+        #
+        self.rasterRadio = wx.RadioButton(self, id = wx.ID_ANY, label = " %s " % _("Histogram single raster"), style = wx.RB_GROUP)
+        self.groupRadio = wx.RadioButton(self, id = wx.ID_ANY, label = " %s " % _("Histogram imagery group"))
+        if self.maptype == 'raster': 
+            self.rasterRadio.SetValue(True)
+        elif self.maptype == 'group': 
+            self.groupRadio.SetValue(True)
+        box.Add(item = self.rasterRadio, flag = wx.ALIGN_CENTER_VERTICAL, pos = (0, 0))
+        box.Add(item = self.groupRadio, flag = wx.ALIGN_CENTER_VERTICAL, pos = (0, 1))
+        
+        #
+        # Select a raster to histogram
+        #
+        label = wx.StaticText(parent = self, id = wx.ID_ANY, 
+                              label = _("Select raster map:"))
+        box.Add(item = label, flag = wx.ALIGN_CENTER_VERTICAL, pos = (1, 0))
+        self.rselection = Select(self, id = wx.ID_ANY,
+                                 size = globalvar.DIALOG_GSELECT_SIZE,
+                                 type = 'cell')
+        if self.groupRadio.GetValue() == True: 
+            self.rselection.Disable()
+        else:
+            if len(self.rasterList) > 0: self.rselection.SetValue(self.rasterList[0])
+        box.Add(item = self.rselection, pos = (1, 1))       
+
+        #
+        # Select an image group to histogram
+        #
+        label = wx.StaticText(parent = self, id = wx.ID_ANY, 
+                              label = _("Select image group:"))
+        box.Add(item = label, flag = wx.ALIGN_CENTER_VERTICAL, pos = (2, 0))
+        self.gselection = Select(self, id = wx.ID_ANY,
+                                 size = globalvar.DIALOG_GSELECT_SIZE,
+                                 type = 'group')
+        if self.rasterRadio.GetValue() == True: 
+            self.gselection.Disable()
+        else:
+            if self.group != None: self.gselection.SetValue(self.group)
+        box.Add(item = self.gselection, pos = (2, 1))
+            
+        #
+        # Nsteps for FP maps and histogram type selection
+        #
+
+        label = wx.StaticText(parent = self, id = wx.ID_ANY, 
+                              label = _("Number of bins (for FP maps)"))
+        box.Add(item = label,
+                flag = wx.ALIGN_CENTER_VERTICAL, pos = (3, 0))
+        self.spinbins = wx.SpinCtrl(parent = self, id = wx.ID_ANY, value = "", pos = (30, 50),
+                                      size = (100,-1), style = wx.SP_ARROW_KEYS)
+        self.spinbins.SetRange(1,1000)
+        self.spinbins.SetValue(self.bins)
+        box.Add(item = self.spinbins,
+                flag = wx.ALIGN_CENTER_VERTICAL, pos = (3, 1))
+
+        label = wx.StaticText(parent = self, id = wx.ID_ANY, 
+                              label = _("Histogram type"))
+        box.Add(item = label,
+                flag = wx.ALIGN_CENTER_VERTICAL, pos = (4, 0))
+        types = ['count', 'percent', 'area']
+        histtype = wx.ComboBox(parent = self, id = wx.ID_ANY, size = (250, -1),
+                                choices = types, style = wx.CB_DROPDOWN)
+        histtype.SetStringSelection(self.histtype)
+        box.Add(item = histtype,
+                flag = wx.ALIGN_CENTER_VERTICAL, pos = (4, 1))
+          
+        sizer.Add(item = box, proportion = 0,
+                  flag = wx.ALL, border = 10)
+
+        line = wx.StaticLine(parent = self, id = wx.ID_ANY, size = (20, -1), style = wx.LI_HORIZONTAL)
+        sizer.Add(item = line, proportion = 0,
+                  flag = wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.LEFT|wx.RIGHT, border = 5)
+
+        btnsizer = wx.StdDialogButtonSizer()
+
+        btn = wx.Button(self, wx.ID_OK)
+        btn.SetDefault()
+        btnsizer.AddButton(btn)
+
+        btn = wx.Button(self, wx.ID_CANCEL)
+        btnsizer.AddButton(btn)
+        btnsizer.Realize()
+
+        sizer.Add(item = btnsizer, proportion = 0, flag = wx.ALIGN_RIGHT | wx.ALL, border = 5)
+
+        #
+        # bindings
+        #
+        self.Bind(wx.EVT_RADIOBUTTON, self.OnHistMap, self.rasterRadio)
+        self.Bind(wx.EVT_RADIOBUTTON, self.OnHistMap, self.groupRadio)
+        self.rselection.Bind(wx.EVT_TEXT, self.OnRasterSelection)
+        self.gselection.Bind(wx.EVT_TEXT, self.OnGroupSelection)
+        self.spinbins.Bind(wx.EVT_TEXT, self.OnSetBins)
+        self.spinbins.Bind(wx.EVT_SPINCTRL, self.OnSetBins)
+        histtype.Bind(wx.EVT_TEXT, self.OnSetHisttypes)
+
+        self.SetSizer(sizer)
+        sizer.Fit(self)
+
+    def OnHistMap(self, event):
+        """!Hander for radio buttons to choose between histogramming a
+            single raster and an imagery group
+        """
+        if self.rasterRadio.GetValue() == True:
+            self.maptype = 'raster'
+            self.rselection.Enable()
+            self.gselection.Disable()
+            self.gselection.SetValue('')
+        elif self.groupRadio.GetValue() == True:
+            self.maptype = 'group'
+            self.gselection.Enable()
+            self.rselection.Disable()
+            self.rselection.SetValue('')
+        else:
+            pass
+        
+    def OnRasterSelection(self, event):
+        """!Handler for selecting a single raster map
+        """
+        self.rasterList = []
+        self.rasterList.append(event.GetString())
+
+    def OnGroupSelection(self, event):
+        """!Handler for selecting imagery group
+        """
+        self.rasterList = []
+        self.group = event.GetString()
+        ret = grass.read_command('i.group', 
+                                  group = '%s' % self.group, 
+                                  quiet = True,
+                                  flags = 'g').strip().split('\n')
+        if ret != None and ret != '':
+            self.rasterList = ret
+                                                                                            
+    def OnSetBins(self, event):
+        """!Bins for histogramming FP maps (=nsteps in r.stats)
+        """
+        self.bins = self.spinbins.GetValue()
+        
+    def OnSetHisttypes(self, event):
+        self.histtype = event.GetString()
+        
+
+class TextDialog(wx.Dialog):
+    def __init__(self, parent, id, title, plottype = '',
+                 style = wx.DEFAULT_DIALOG_STYLE, **kwargs):
+        """!Dialog to set histogram text options: font, title
+        and font size, axis labels and font size
+        """
+        wx.Dialog.__init__(self, parent, id, title, style = style, **kwargs)
+        #
+        # initialize variables
+        #
+        # combo box entry lists
+        self.ffamilydict = { 'default' : wx.FONTFAMILY_DEFAULT,
+                             'decorative' : wx.FONTFAMILY_DECORATIVE,
+                             'roman' : wx.FONTFAMILY_ROMAN,
+                             'script' : wx.FONTFAMILY_SCRIPT,
+                             'swiss' : wx.FONTFAMILY_SWISS,
+                             'modern' : wx.FONTFAMILY_MODERN,
+                             'teletype' : wx.FONTFAMILY_TELETYPE }
+
+        self.fstyledict = { 'normal' : wx.FONTSTYLE_NORMAL,
+                            'slant' : wx.FONTSTYLE_SLANT,
+                            'italic' : wx.FONTSTYLE_ITALIC }
+
+        self.fwtdict = { 'normal' : wx.FONTWEIGHT_NORMAL,
+                         'light' : wx.FONTWEIGHT_LIGHT,
+                         'bold' : wx.FONTWEIGHT_BOLD }
+
+        self.parent = parent
+
+        self.ptitle = self.parent.ptitle
+        self.xlabel = self.parent.xlabel
+        self.ylabel = self.parent.ylabel
+
+        self.properties = self.parent.properties # read-only
+        
+        # font size
+        self.fontfamily = self.properties['font']['wxfont'].GetFamily()
+        self.fontstyle = self.properties['font']['wxfont'].GetStyle()
+        self.fontweight = self.properties['font']['wxfont'].GetWeight()
+
+        self._do_layout()
+                
+    def _do_layout(self):
+        """!Do layout"""
+        # dialog layout
+        sizer = wx.BoxSizer(wx.VERTICAL)
+
+        box = wx.StaticBox(parent = self, id = wx.ID_ANY,
+                           label = " %s " % _("Text settings"))
+        boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
+        gridSizer = wx.GridBagSizer(vgap = 5, hgap = 5)
+
+        #
+        # profile title
+        #
+        label = wx.StaticText(parent = self, id = wx.ID_ANY, label = _("Profile title:"))
+        gridSizer.Add(item = label, flag = wx.ALIGN_CENTER_VERTICAL, pos = (0, 0))
+        self.ptitleentry = wx.TextCtrl(parent = self, id = wx.ID_ANY, value = "", size = (250,-1))
+        # self.ptitleentry.SetFont(self.font)
+        self.ptitleentry.SetValue(self.ptitle)
+        gridSizer.Add(item = self.ptitleentry, pos = (0, 1))
+
+        #
+        # title font
+        #
+        tlabel = wx.StaticText(parent = self, id = wx.ID_ANY, label = _("Title font size (pts):"))
+        gridSizer.Add(item = tlabel, flag = wx.ALIGN_CENTER_VERTICAL, pos = (1, 0))
+        self.ptitlesize = wx.SpinCtrl(parent = self, id = wx.ID_ANY, value = "", pos = (30, 50),
+                                      size = (50,-1), style = wx.SP_ARROW_KEYS)
+        self.ptitlesize.SetRange(5,100)
+        self.ptitlesize.SetValue(int(self.properties['font']['prop']['titleSize']))
+        gridSizer.Add(item = self.ptitlesize, pos = (1, 1))
+
+        #
+        # x-axis label
+        #
+        label = wx.StaticText(parent = self, id = wx.ID_ANY, label = _("X-axis label:"))
+        gridSizer.Add(item = label, flag = wx.ALIGN_CENTER_VERTICAL, pos = (2, 0))
+        self.xlabelentry = wx.TextCtrl(parent = self, id = wx.ID_ANY, value = "", size = (250,-1))
+        # self.xlabelentry.SetFont(self.font)
+        self.xlabelentry.SetValue(self.xlabel)
+        gridSizer.Add(item = self.xlabelentry, pos = (2, 1))
+
+        #
+        # y-axis label
+        #
+        label = wx.StaticText(parent = self, id = wx.ID_ANY, label = _("Y-axis label:"))
+        gridSizer.Add(item = label, flag = wx.ALIGN_CENTER_VERTICAL, pos = (3, 0))
+        self.ylabelentry = wx.TextCtrl(parent = self, id = wx.ID_ANY, value = "", size = (250,-1))
+        # self.ylabelentry.SetFont(self.font)
+        self.ylabelentry.SetValue(self.ylabel)
+        gridSizer.Add(item = self.ylabelentry, pos = (3, 1))
+
+        #
+        # font size
+        #
+        llabel = wx.StaticText(parent = self, id = wx.ID_ANY, label = _("Label font size (pts):"))
+        gridSizer.Add(item = llabel, flag = wx.ALIGN_CENTER_VERTICAL, pos = (4, 0))
+        self.axislabelsize = wx.SpinCtrl(parent = self, id = wx.ID_ANY, value = "", pos = (30, 50),
+                                         size = (50, -1), style = wx.SP_ARROW_KEYS)
+        self.axislabelsize.SetRange(5, 100) 
+        self.axislabelsize.SetValue(int(self.properties['font']['prop']['axisSize']))
+        gridSizer.Add(item = self.axislabelsize, pos = (4,1))
+
+        boxSizer.Add(item = gridSizer)
+        sizer.Add(item = boxSizer, flag = wx.ALL | wx.EXPAND, border = 3)
+
+        #
+        # font settings
+        #
+        box = wx.StaticBox(parent = self, id = wx.ID_ANY,
+                           label = " %s " % _("Font settings"))
+        boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
+        gridSizer = wx.GridBagSizer(vgap = 5, hgap = 5)
+        gridSizer.AddGrowableCol(1)
+
+        #
+        # font family
+        #
+        label1 = wx.StaticText(parent = self, id = wx.ID_ANY, label = _("Font family:"))
+        gridSizer.Add(item = label1, flag = wx.ALIGN_CENTER_VERTICAL, pos = (0, 0))
+        self.ffamilycb = wx.ComboBox(parent = self, id = wx.ID_ANY, size = (250, -1),
+                                choices = self.ffamilydict.keys(), style = wx.CB_DROPDOWN)
+        self.ffamilycb.SetStringSelection('swiss')
+        for item in self.ffamilydict.items():
+            if self.fontfamily == item[1]:
+                self.ffamilycb.SetStringSelection(item[0])
+                break
+        gridSizer.Add(item = self.ffamilycb, pos = (0, 1), flag = wx.ALIGN_RIGHT)
+
+        #
+        # font style
+        #
+        label = wx.StaticText(parent = self, id = wx.ID_ANY, label = _("Style:"))
+        gridSizer.Add(item = label, flag = wx.ALIGN_CENTER_VERTICAL, pos = (1, 0))
+        self.fstylecb = wx.ComboBox(parent = self, id = wx.ID_ANY, size = (250, -1),
+                                    choices = self.fstyledict.keys(), style = wx.CB_DROPDOWN)
+        self.fstylecb.SetStringSelection('normal')
+        for item in self.fstyledict.items():
+            if self.fontstyle == item[1]:
+                self.fstylecb.SetStringSelection(item[0])
+                break
+        gridSizer.Add(item = self.fstylecb, pos = (1, 1), flag = wx.ALIGN_RIGHT)
+
+        #
+        # font weight
+        #
+        label = wx.StaticText(parent = self, id = wx.ID_ANY, label = _("Weight:"))
+        gridSizer.Add(item = label, flag = wx.ALIGN_CENTER_VERTICAL, pos = (2, 0))
+        self.fwtcb = wx.ComboBox(parent = self, size = (250, -1),
+                                 choices = self.fwtdict.keys(), style = wx.CB_DROPDOWN)
+        self.fwtcb.SetStringSelection('normal')
+        for item in self.fwtdict.items():
+            if self.fontweight == item[1]:
+                self.fwtcb.SetStringSelection(item[0])
+                break
+
+        gridSizer.Add(item = self.fwtcb, pos = (2, 1), flag = wx.ALIGN_RIGHT)
+                      
+        boxSizer.Add(item = gridSizer, flag = wx.EXPAND)
+        sizer.Add(item = boxSizer, flag = wx.LEFT | wx.RIGHT | wx.BOTTOM | wx.EXPAND, border = 3)
+
+        line = wx.StaticLine(parent = self, id = wx.ID_ANY, size = (20, -1), style = wx.LI_HORIZONTAL)
+        sizer.Add(item = line, proportion = 0,
+                  flag = wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.LEFT|wx.RIGHT, border = 3)
+
+        #
+        # buttons
+        #
+        btnSave = wx.Button(self, wx.ID_SAVE)
+        btnApply = wx.Button(self, wx.ID_APPLY)
+        btnOk = wx.Button(self, wx.ID_OK)
+        btnCancel = wx.Button(self, wx.ID_CANCEL)
+        btnOk.SetDefault()
+
+        # bindings
+        btnApply.Bind(wx.EVT_BUTTON, self.OnApply)
+        btnApply.SetToolTipString(_("Apply changes for the current session"))
+        btnOk.Bind(wx.EVT_BUTTON, self.OnOk)
+        btnOk.SetToolTipString(_("Apply changes for the current session and close dialog"))
+        btnOk.SetDefault()
+        btnSave.Bind(wx.EVT_BUTTON, self.OnSave)
+        btnSave.SetToolTipString(_("Apply and save changes to user settings file (default for next sessions)"))
+        btnCancel.Bind(wx.EVT_BUTTON, self.OnCancel)
+        btnCancel.SetToolTipString(_("Close dialog and ignore changes"))
+
+        # sizers
+        btnStdSizer = wx.StdDialogButtonSizer()
+        btnStdSizer.AddButton(btnOk)
+        btnStdSizer.AddButton(btnApply)
+        btnStdSizer.AddButton(btnCancel)
+        btnStdSizer.Realize()
+        
+        btnSizer = wx.BoxSizer(wx.HORIZONTAL)
+        btnSizer.Add(item = btnSave, proportion = 0, flag = wx.ALIGN_LEFT | wx.ALL, border = 5)
+        btnSizer.Add(item = btnStdSizer, proportion = 0, flag = wx.ALIGN_RIGHT | wx.ALL, border = 5)
+        sizer.Add(item = btnSizer, proportion = 0, flag = wx.ALIGN_RIGHT | wx.ALL, border = 5)
+
+        #
+        # bindings
+        #
+        self.ptitleentry.Bind(wx.EVT_TEXT, self.OnTitle)
+        self.xlabelentry.Bind(wx.EVT_TEXT, self.OnXLabel)
+        self.ylabelentry.Bind(wx.EVT_TEXT, self.OnYLabel)
+
+        self.SetSizer(sizer)
+        sizer.Fit(self)
+
+    def OnTitle(self, event):
+        self.ptitle = event.GetString()
+
+    def OnXLabel(self, event):
+        self.xlabel = event.GetString()
+
+    def OnYLabel(self, event):
+        self.ylabel = event.GetString()
+
+    def UpdateSettings(self):
+        self.properties['font']['prop']['titleSize'] = self.ptitlesize.GetValue()
+        self.properties['font']['prop']['axisSize'] = self.axislabelsize.GetValue()
+
+        family = self.ffamilydict[self.ffamilycb.GetStringSelection()]
+        self.properties['font']['wxfont'].SetFamily(family)
+        style = self.fstyledict[self.fstylecb.GetStringSelection()]
+        self.properties['font']['wxfont'].SetStyle(style)
+        weight = self.fwtdict[self.fwtcb.GetStringSelection()]
+        self.properties['font']['wxfont'].SetWeight(weight)
+
+    def OnSave(self, event):
+        """!Button 'Save' pressed"""
+        self.UpdateSettings()
+        fileSettings = {}
+        UserSettings.ReadSettingsFile(settings=fileSettings)
+        fileSettings['plot'] = UserSettings.Get(group = 'plot')
+        file = UserSettings.SaveToFile(fileSettings)
+        self.parent.parent.GetLayerManager().goutput.WriteLog(_('Plot text settings saved to file \'%s\'.') % file)
+        self.EndModal(wx.ID_OK)
+
+    def OnApply(self, event):
+        """!Button 'Apply' pressed"""
+        self.UpdateSettings()
+        self.parent.OnPlotText(self)
+        
+    def OnOk(self, event):
+        """!Button 'OK' pressed"""
+        self.UpdateSettings()
+        self.EndModal(wx.ID_OK)
+
+    def OnCancel(self, event):
+        """!Button 'Cancel' pressed"""
+        self.EndModal(wx.ID_CANCEL)
+        
+class OptDialog(wx.Dialog):
+    def __init__(self, parent, id, title, plottype = '',
+                 style = wx.DEFAULT_DIALOG_STYLE, **kwargs): 
+        """!Dialog to set various options for data plotted, including: line
+        width, color, style; marker size, color, fill, and style; grid
+        and legend options.
+        """
+        wx.Dialog.__init__(self, parent, id, title, style = style, **kwargs)
+        # init variables
+        self.parent = parent
+        self.pstyledict = parent.pstyledict
+        self.ptfilldict = parent.ptfilldict
+        self.plottype = plottype
+        
+        self.pttypelist = ['circle',
+                           'dot',
+                           'square',
+                           'triangle',
+                           'triangle_down',
+                           'cross',
+                           'plus']
+        
+        self.axislist = ['min',
+                         'auto',
+                         'custom']
+
+        # widgets ids
+        self.wxId = {}
+        
+        self.parent = parent
+
+        # read-only
+        self.raster = self.parent.raster
+        self.rasterList = self.parent.rasterList
+        self.properties = self.parent.properties
+        self.map = ''
+        
+        if len(self.rasterList) == 0:
+            wx.MessageBox(parent = self,
+                              message = _("No map or image group selected to plot."),
+                              caption = _("Warning"), style = wx.OK | wx.ICON_ERROR)
+            
+        self._do_layout()
+
+    def _do_layout(self):
+        """!Do layout"""
+        # dialog layout
+        sizer = wx.BoxSizer(wx.VERTICAL)
+
+        box = wx.StaticBox(parent = self, id = wx.ID_ANY,
+                           label = " %s " % _("Plot settings")) 
+        boxMainSizer = wx.StaticBoxSizer(box, wx.HORIZONTAL)
+
+        self.wxId['pcolor']  = 0
+        self.wxId['pwidth']  = 0
+        self.wxId['pstyle']  = 0
+        self.wxId['plegend'] = 0
+        self.wxId['marker'] = {}
+        self.wxId['x-axis'] = {}
+        self.wxId['y-axis'] = {}
+
+        #
+        # plot line settings
+        #
+        if len(self.rasterList) > 0:
+            box = wx.StaticBox(parent = self, id = wx.ID_ANY,
+                               label = _("Map/image plotted"))
+            boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
+            
+            gridSizer = wx.GridBagSizer(vgap = 5, hgap = 5)
+            
+            row = 0
+            self.mapchoice = wx.Choice(parent = self, id = wx.ID_ANY, size = (300, -1),
+                                       choices = self.rasterList)
+            if not self.map:
+                self.map = self.rasterList[self.mapchoice.GetCurrentSelection()]
+            else:
+                self.mapchoice.SetStringSelection(self.map)
+            gridSizer.Add(item = self.mapchoice, flag = wx.ALIGN_CENTER_VERTICAL, 
+                          pos = (row, 0), span = (1, 2))
+            
+            row +=1            
+            label = wx.StaticText(parent = self, id = wx.ID_ANY, label = _("Line color"))
+            gridSizer.Add(item = label, flag = wx.ALIGN_CENTER_VERTICAL, pos = (row, 0))
+            pcolor = csel.ColourSelect(parent = self, id = wx.ID_ANY, colour = self.raster[self.map]['pcolor'])
+            self.wxId['pcolor'] = pcolor.GetId()
+            gridSizer.Add(item = pcolor, pos = (row, 1))
+
+            row += 1
+            label = wx.StaticText(parent = self, id = wx.ID_ANY, label = _("Line width"))
+            gridSizer.Add(item = label, flag = wx.ALIGN_CENTER_VERTICAL, pos = (row, 0))
+            pwidth = wx.SpinCtrl(parent = self, id = wx.ID_ANY, value = "",
+                                 size = (50,-1), style = wx.SP_ARROW_KEYS)
+            pwidth.SetRange(1, 10)
+            pwidth.SetValue(self.raster[self.map]['pwidth'])
+            self.wxId['pwidth'] = pwidth.GetId()
+            gridSizer.Add(item = pwidth, pos = (row, 1))
+
+            row +=1
+            label = wx.StaticText(parent = self, id = wx.ID_ANY, label = _("Line style"))
+            gridSizer.Add(item = label, flag = wx.ALIGN_CENTER_VERTICAL, pos = (row, 0))
+            pstyle = wx.Choice(parent = self, id = wx.ID_ANY, 
+                                 size = (120, -1), choices = self.pstyledict.keys(), style = wx.CB_DROPDOWN)
+            pstyle.SetStringSelection(self.raster[self.map]['pstyle'])
+            self.wxId['pstyle'] = pstyle.GetId()
+            gridSizer.Add(item = pstyle, pos = (row, 1))
+
+            row += 1
+            label = wx.StaticText(parent = self, id = wx.ID_ANY, label = _("Legend"))
+            gridSizer.Add(item = label, flag = wx.ALIGN_CENTER_VERTICAL, pos = (row, 0))
+            plegend = wx.TextCtrl(parent = self, id = wx.ID_ANY, value = "", size = (200,-1))
+            plegend.SetValue(self.raster[self.map]['plegend'])
+            gridSizer.Add(item = plegend, pos = (row, 1))
+            self.wxId['plegend'] = plegend.GetId()
+            
+            boxSizer.Add(item = gridSizer)
+            boxMainSizer.Add(item = boxSizer, flag = wx.ALL, border = 3)
+
+
+        #
+        # segment marker settings
+        #       
+        if self.plottype != 'histogram':
+            box = wx.StaticBox(parent = self, id = wx.ID_ANY,
+                               label = " %s " % _("Transect segment marker settings"))
+            
+            boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
+            
+            gridSizer = wx.GridBagSizer(vgap = 5, hgap = 5)
+            label = wx.StaticText(parent = self, id = wx.ID_ANY, label = _("Color"))
+            gridSizer.Add(item = label, flag = wx.ALIGN_CENTER_VERTICAL, pos = (0, 0))
+            ptcolor = csel.ColourSelect(parent = self, id = wx.ID_ANY, colour = self.properties['marker']['color'])
+            self.wxId['marker']['color'] = ptcolor.GetId()
+            gridSizer.Add(item = ptcolor, pos = (0, 1))
+
+            label = wx.StaticText(parent = self, id = wx.ID_ANY, label = _("Size"))
+            gridSizer.Add(item = label, flag = wx.ALIGN_CENTER_VERTICAL, pos = (1, 0))
+            ptsize = wx.SpinCtrl(parent = self, id = wx.ID_ANY, value = "",
+                                 size = (50, -1), style = wx.SP_ARROW_KEYS)
+            ptsize.SetRange(1, 10)
+            ptsize.SetValue(self.properties['marker']['size'])
+            self.wxId['marker']['size'] = ptsize.GetId()
+            gridSizer.Add(item = ptsize, pos = (1, 1))
+            
+            label = wx.StaticText(parent = self, id = wx.ID_ANY, label = _("Style"))
+            gridSizer.Add(item = label, flag = wx.ALIGN_CENTER_VERTICAL, pos = (2, 0))
+            ptfill = wx.ComboBox(parent = self, id = wx.ID_ANY,
+                                 size = (120, -1), choices = self.ptfilldict.keys(), style = wx.CB_DROPDOWN)
+            ptfill.SetStringSelection(self.properties['marker']['fill'])
+            self.wxId['marker']['fill'] = ptfill.GetId()
+            gridSizer.Add(item = ptfill, pos = (2, 1))
+            
+            label = wx.StaticText(parent = self, id = wx.ID_ANY, label = _("Legend"))
+            gridSizer.Add(item = label, flag = wx.ALIGN_CENTER_VERTICAL, pos = (3, 0))
+            ptlegend = wx.TextCtrl(parent = self, id = wx.ID_ANY, value = "", size = (200,-1))
+            ptlegend.SetValue(self.properties['marker']['legend'])
+            self.wxId['marker']['legend'] = ptlegend.GetId()
+            gridSizer.Add(item = ptlegend, pos = (3, 1))
+                    
+            label = wx.StaticText(parent = self, id = wx.ID_ANY, label = _("Type"))
+            gridSizer.Add(item = label, flag = wx.ALIGN_CENTER_VERTICAL, pos = (4, 0))
+            pttype = wx.ComboBox(parent = self, 
+                                 size = (200, -1), choices = self.pttypelist, style = wx.CB_DROPDOWN)
+            pttype.SetStringSelection(self.properties['marker']['type'])
+            self.wxId['marker']['type'] = pttype.GetId()
+            gridSizer.Add(item = pttype, pos = (4, 1))
+
+            boxSizer.Add(item = gridSizer)
+            boxMainSizer.Add(item = boxSizer, flag = wx.ALL, border = 3)
+            
+        sizer.Add(item = boxMainSizer, flag = wx.ALL | wx.EXPAND, border = 3)
+
+        #
+        # axis options
+        #
+        box = wx.StaticBox(parent = self, id = wx.ID_ANY,
+                           label = " %s " % _("Axis settings"))
+        boxMainSizer = wx.StaticBoxSizer(box, wx.HORIZONTAL)
+
+        middleSizer = wx.BoxSizer(wx.HORIZONTAL)
+
+        idx = 0
+        for axis, atype in [(_("X-Axis"), 'x-axis'),
+                     (_("Y-Axis"), 'y-axis')]:
+            box = wx.StaticBox(parent = self, id = wx.ID_ANY,
+                               label = " %s " % axis)
+            boxSizer = wx.StaticBoxSizer(box, wx.HORIZONTAL)
+            gridSizer = wx.GridBagSizer(vgap = 5, hgap = 5)
+
+            prop = self.properties[atype]['prop']
+            
+            row = 0
+            label = wx.StaticText(parent = self, id = wx.ID_ANY, label = _("Style"))
+            gridSizer.Add(item = label, flag = wx.ALIGN_CENTER_VERTICAL, pos = (row, 0))
+            type = wx.Choice(parent = self, id = wx.ID_ANY,
+                               size = (100, -1), choices = self.axislist, style = wx.CB_DROPDOWN)
+            type.SetStringSelection(prop['type']) 
+            self.wxId[atype]['type'] = type.GetId()
+            gridSizer.Add(item = type, pos = (row, 1))
+                        
+            row += 1
+            label = wx.StaticText(parent = self, id = wx.ID_ANY, label = _("Custom min"))
+            gridSizer.Add(item = label, flag = wx.ALIGN_CENTER_VERTICAL, pos = (row, 0))
+            min = wx.TextCtrl(parent = self, id = wx.ID_ANY, value = "", size = (70, -1))
+            min.SetValue(str(prop['min']))
+            self.wxId[atype]['min'] = min.GetId()
+            gridSizer.Add(item = min, pos = (row, 1))
+
+            row += 1
+            label = wx.StaticText(parent = self, id = wx.ID_ANY, label = _("Custom max"))
+            gridSizer.Add(item = label, flag = wx.ALIGN_CENTER_VERTICAL, pos = (row, 0))
+            max = wx.TextCtrl(parent = self, id = wx.ID_ANY, value = "", size = (70, -1))
+            max.SetValue(str(prop['max']))
+            self.wxId[atype]['max'] = max.GetId()
+            gridSizer.Add(item = max, pos = (row, 1))
+            
+            row += 1
+            log = wx.CheckBox(parent = self, id = wx.ID_ANY, label = _("Log scale"))
+            log.SetValue(prop['log'])
+            self.wxId[atype]['log'] = log.GetId()
+            gridSizer.Add(item = log, pos = (row, 0), span = (1, 2))
+
+            if idx == 0:
+                flag = wx.ALL | wx.EXPAND
+            else:
+                flag = wx.TOP | wx.BOTTOM | wx.RIGHT | wx.EXPAND
+
+            boxSizer.Add(item = gridSizer, flag = wx.ALL, border = 3)
+            boxMainSizer.Add(item = boxSizer, flag = flag, border = 3)
+
+            idx += 1
+            
+        middleSizer.Add(item = boxMainSizer, flag = wx.ALL | wx.EXPAND, border = 3)
+
+        #
+        # grid & legend options
+        #
+        self.wxId['grid'] = {}
+        self.wxId['legend'] = {}
+        self.wxId['font'] = {}
+        box = wx.StaticBox(parent = self, id = wx.ID_ANY,
+                           label = " %s " % _("Grid and Legend settings"))
+        boxMainSizer = wx.StaticBoxSizer(box, wx.HORIZONTAL)
+        gridSizer = wx.GridBagSizer(vgap = 5, hgap = 5)
+
+        row = 0
+        label = wx.StaticText(parent = self, id = wx.ID_ANY, label = _("Grid color"))
+        gridSizer.Add(item = label, flag = wx.ALIGN_CENTER_VERTICAL, pos = (row, 0))
+        gridcolor = csel.ColourSelect(parent = self, id = wx.ID_ANY, colour = self.properties['grid']['color'])
+        self.wxId['grid']['color'] = gridcolor.GetId()
+        gridSizer.Add(item = gridcolor, pos = (row, 1))
+
+        row +=1
+        gridshow = wx.CheckBox(parent = self, id = wx.ID_ANY, label = _("Show grid"))
+        gridshow.SetValue(self.properties['grid']['enabled'])
+        self.wxId['grid']['enabled'] = gridshow.GetId()
+        gridSizer.Add(item = gridshow, pos = (row, 0), span = (1, 2))
+
+        row +=1
+        label = wx.StaticText(parent = self, id = wx.ID_ANY, label = _("Legend font size"))
+        gridSizer.Add(item = label, flag = wx.ALIGN_CENTER_VERTICAL, pos = (row, 0))
+        legendfontsize = wx.SpinCtrl(parent = self, id = wx.ID_ANY, value = "", 
+                                     size = (50, -1), style = wx.SP_ARROW_KEYS)
+        legendfontsize.SetRange(5,100)
+        legendfontsize.SetValue(int(self.properties['font']['prop']['legendSize']))
+        self.wxId['font']['legendSize'] = legendfontsize.GetId()
+        gridSizer.Add(item = legendfontsize, pos = (row, 1))
+
+        row += 1
+        legendshow = wx.CheckBox(parent = self, id = wx.ID_ANY, label = _("Show legend"))
+        legendshow.SetValue(self.properties['legend']['enabled'])
+        self.wxId['legend']['enabled'] = legendshow.GetId()
+        gridSizer.Add(item = legendshow, pos = (row, 0), span = (1, 2))
+
+        boxMainSizer.Add(item = gridSizer, flag = flag, border = 3)
+
+        middleSizer.Add(item = boxMainSizer, flag = wx.LEFT | wx.RIGHT | wx.BOTTOM | wx.EXPAND, border = 3)
+
+        sizer.Add(item = middleSizer, flag = wx.ALL, border = 0)
+        
+        #
+        # line & buttons
+        #
+        line = wx.StaticLine(parent = self, id = wx.ID_ANY, size = (20, -1), style = wx.LI_HORIZONTAL)
+        sizer.Add(item = line, proportion = 0,
+                  flag = wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.LEFT|wx.RIGHT, border = 3)
+
+        #
+        # buttons
+        #
+        btnSave = wx.Button(self, wx.ID_SAVE)
+        btnApply = wx.Button(self, wx.ID_APPLY)
+        btnCancel = wx.Button(self, wx.ID_CANCEL)
+        btnSave.SetDefault()
+
+        # tooltips for buttons
+        btnApply.SetToolTipString(_("Apply changes for the current session"))
+        btnSave.SetToolTipString(_("Apply and save changes to user settings file (default for next sessions)"))
+        btnSave.SetDefault()
+        btnCancel.SetToolTipString(_("Close dialog and ignore changes"))
+
+        # sizers
+        btnStdSizer = wx.StdDialogButtonSizer()
+        btnStdSizer.AddButton(btnCancel)
+        btnStdSizer.AddButton(btnSave)
+        btnStdSizer.AddButton(btnApply)
+        btnStdSizer.Realize()
+        
+        sizer.Add(item = btnStdSizer, proportion = 0, flag = wx.ALIGN_RIGHT | wx.ALL, border = 5)
+
+        #
+        # bindings for buttons and map plot settings controls
+        #
+        self.mapchoice.Bind(wx.EVT_CHOICE, self.OnSetMap)
+        pcolor.Bind(csel.EVT_COLOURSELECT, self.OnSetOpt)
+        pwidth.Bind(wx.EVT_SPINCTRL, self.OnSetOpt)
+        pstyle.Bind(wx.EVT_CHOICE, self.OnSetOpt)
+        plegend.Bind(wx.EVT_TEXT, self.OnSetOpt)
+        btnApply.Bind(wx.EVT_BUTTON, self.OnApply)
+        btnSave.Bind(wx.EVT_BUTTON, self.OnSave)
+        btnCancel.Bind(wx.EVT_BUTTON, self.OnCancel)
+
+        self.SetSizer(sizer)
+        sizer.Fit(self)
+
+    def OnSetMap(self, event):
+        """!Handler for changing map selection"""
+        self.map = event.GetString()
+        
+        # update plot settings controls for selected map
+        self.FindWindowById(self.wxId['pcolor']).SetColour(self.raster[self.map]['pcolor'])
+        self.FindWindowById(self.wxId['pwidth']).SetValue(self.raster[self.map]['pwidth'])
+        self.FindWindowById(self.wxId['pstyle']).SetStringSelection(self.raster[self.map]['pstyle'])
+        self.FindWindowById(self.wxId['plegend']).SetValue(self.raster[self.map]['plegend'])
+        self.Refresh()
+        
+    def OnSetOpt(self, event):
+        """!Handler for changing any other option"""
+        self.map = self.rasterList[self.mapchoice.GetCurrentSelection()]
+        self.UpdateSettings()
+        self.parent.SetGraphStyle()
+        if self.parent.plot:
+            p = self.parent.CreatPlotList()
+            self.parent.DrawPlot(p)
+
+    def UpdateSettings(self):
+        """!Apply settings to each map and to entire plot"""
+        
+        # update plot settings for selected map
+        self.raster[self.map]['pcolor'] = self.FindWindowById(self.wxId['pcolor']).GetColour()
+        self.raster[self.map]['pwidth'] = int(self.FindWindowById(self.wxId['pwidth']).GetValue())
+        self.raster[self.map]['pstyle'] = self.FindWindowById(self.wxId['pstyle']).GetStringSelection()
+        self.raster[self.map]['plegend'] = self.FindWindowById(self.wxId['plegend']).GetValue()
+
+        # update settings for entire plot
+        for axis in ('x-axis', 'y-axis'):
+            self.properties[axis]['prop']['type'] = self.FindWindowById(self.wxId[axis]['type']).GetStringSelection()
+            self.properties[axis]['prop']['min'] = float(self.FindWindowById(self.wxId[axis]['min']).GetValue())
+            self.properties[axis]['prop']['max'] = float(self.FindWindowById(self.wxId[axis]['max']).GetValue())
+            self.properties[axis]['prop']['log'] = self.FindWindowById(self.wxId[axis]['log']).IsChecked()
+
+        if self.plottype != 'histogram':
+            self.properties['marker']['color'] = self.FindWindowById(self.wxId['marker']['color']).GetColour()
+            self.properties['marker']['fill'] = self.FindWindowById(self.wxId['marker']['fill']).GetStringSelection()
+            self.properties['marker']['size'] = self.FindWindowById(self.wxId['marker']['size']).GetValue()
+            self.properties['marker']['type'] = self.FindWindowById(self.wxId['marker']['type']).GetValue()
+            self.properties['marker']['legend'] = self.FindWindowById(self.wxId['marker']['legend']).GetValue()
+
+        self.properties['grid']['color'] = self.FindWindowById(self.wxId['grid']['color']).GetColour()
+        self.properties['grid']['enabled'] = self.FindWindowById(self.wxId['grid']['enabled']).IsChecked()
+
+        self.properties['font']['prop']['legendSize'] = self.FindWindowById(self.wxId['font']['legendSize']).GetValue()
+        self.properties['legend']['enabled'] = self.FindWindowById(self.wxId['legend']['enabled']).IsChecked()
+
+    def OnSave(self, event):
+        """!Button 'Save' pressed"""
+        self.OnApply(None)
+        fileSettings = {}
+        UserSettings.ReadSettingsFile(settings = fileSettings)
+        fileSettings[self.plottype] = UserSettings.Get(group = self.plottype)
+        file = UserSettings.SaveToFile(fileSettings)
+        self.parent.parent.GetLayerManager().goutput.WriteLog(_('Plot settings saved to file \'%s\'.') % file)
+        self.Close()
+
+    def OnApply(self, event):
+        """!Button 'Apply' pressed. Does not close dialog"""
+        self.UpdateSettings()
+        self.parent.SetGraphStyle()
+        if self.parent.plot:
+            p = self.parent.CreatePlotList()
+            self.parent.DrawPlot(p)
+        
+    def OnCancel(self, event):
+        """!Button 'Cancel' pressed"""
+        self.Close()
+
+#### merge with generic options dialog        


Property changes on: grass/trunk/gui/wxpython/gui_modules/wxplot_dialogs.py
___________________________________________________________________
Added: svn:executable
   + *



More information about the grass-commit mailing list