"""! @package psmap_dialogs.py @brief Map feature objects and dialogs for ps.map Classes: - UnitConversion - TCValidator - PenStyleComboBox - CheckListCtrl - Instruction - InstructionObject - InitMap - MapFrame - PageSetup - Mapinfo - Text - Image - NorthArrow - Scalebar - RasterLegend - VectorLegend - Raster - Vector - VProperties - PsmapDialog - PageSetupDialog - MapDialog - MapFramePanel - RasterPanel - VectorPanel - RasterDialog - MainVectorDialog - VPropertiesDialog - LegendDialog - MapinfoDialog - ScalebarDialog - TextDialog - ImageDialog - NorthArrowDialog (C) 2011 by Anna Kratochvilova, and 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. @author Anna Kratochvilova (bachelor's project) @author Martin Landa (mentor) """ import os import sys import string from math import ceil, floor, sin, cos, pi from copy import deepcopy from time import strftime, localtime try: import Image as PILImage havePILImage = True except ImportError: havePILImage = False import grass.script as grass if int(grass.version()['version'].split('.')[0]) > 6: sys.path.append(os.path.join(os.getenv('GISBASE'), 'etc', 'gui', 'wxpython', 'gui_modules')) else: sys.path.append(os.path.join(os.getenv('GISBASE'), 'etc', 'wxpython', 'gui_modules')) import globalvar import dbm_base from utils import CmdToTuple, GetCmdString from gselect import Select from gcmd import RunCommand, GError, GMessage, GWarning import wx import wx.lib.scrolledpanel as scrolled import wx.lib.filebrowsebutton as filebrowse from wx.lib.mixins.listctrl import CheckListCtrlMixin, ListCtrlAutoWidthMixin from wx.lib.expando import ExpandoTextCtrl, EVT_ETC_LAYOUT_NEEDED try: import wx.lib.agw.floatspin as fs except ImportError: fs = None grass.set_raise_on_error(True) PSMAP_COLORS = ['aqua', 'black', 'blue', 'brown', 'cyan', 'gray', 'grey', 'green', 'indigo', 'magenta','orange', 'purple', 'red', 'violet', 'white', 'yellow'] class UnitConversion: """! Class for converting units""" def __init__(self, parent = None): self.parent = parent if self.parent: ppi = wx.PaintDC(self.parent).GetPPI() else: ppi = (72, 72) self._unitsPage = { 'inch' : {'val': 1.0, 'tr' : _("inch")}, 'point' : {'val': 72.0, 'tr' : _("point")}, 'centimeter' : {'val': 2.54, 'tr' : _("centimeter")}, 'millimeter' : {'val': 25.4, 'tr' : _("millimeter")}} self._unitsMap = { 'meters' : {'val': 0.0254, 'tr' : _("meters")}, 'kilometers' : {'val': 2.54e-5, 'tr' : _("kilometers")}, 'feet' : {'val': 1./12, 'tr' : _("feet")}, 'miles' : {'val': 1./63360, 'tr' : _("miles")}, 'nautical miles': {'val': 1/72913.386, 'tr' : _("nautical miles")}} self._units = { 'pixel' : {'val': ppi[0], 'tr' : _("pixel")}, 'meter' : {'val': 0.0254, 'tr' : _("meter")}, 'nautmiles' : {'val': 1/72913.386, 'tr' :_("nautical miles")}, 'degrees' : {'val': 0.0254 , 'tr' : _("degree")} #like 1 meter, incorrect } self._units.update(self._unitsPage) self._units.update(self._unitsMap) def getPageUnitsNames(self): return sorted(self._unitsPage[unit]['tr'] for unit in self._unitsPage.keys()) def getMapUnitsNames(self): return sorted(self._unitsMap[unit]['tr'] for unit in self._unitsMap.keys()) def getAllUnits(self): return sorted(self._units.keys()) def findUnit(self, name): """!Returns unit by its tr. string""" for unit in self._units.keys(): if self._units[unit]['tr'] == name: return unit return None def findName(self, unit): """!Returns tr. string of a unit""" try: return self._units[unit]['tr'] except KeyError: return None def convert(self, value, fromUnit = None, toUnit = None): return float(value)/self._units[fromUnit]['val']*self._units[toUnit]['val'] class TCValidator(wx.PyValidator): """!validates input in textctrls, combobox, taken from wxpython demo""" def __init__(self, flag = None): wx.PyValidator.__init__(self) self.flag = flag self.Bind(wx.EVT_CHAR, self.OnChar) def Clone(self): return TCValidator(self.flag) def Validate(self, win): tc = self.GetWindow() val = tc.GetValue() if self.flag == 'DIGIT_ONLY': for x in val: if x not in string.digits: return False return True def OnChar(self, event): key = event.GetKeyCode() if key < wx.WXK_SPACE or key == wx.WXK_DELETE or key > 255: event.Skip() return if self.flag == 'DIGIT_ONLY' and chr(key) in string.digits + '.': event.Skip() return ## if self.flag == 'SCALE' and chr(key) in string.digits + ':': ## event.Skip() ## return if self.flag == 'ZERO_AND_ONE_ONLY' and chr(key) in '01': event.Skip() return if not wx.Validator_IsSilent(): wx.Bell() # Returning without calling even.Skip eats the event before it # gets to the text control return class PenStyleComboBox(wx.combo.OwnerDrawnComboBox): """!Combo for selecting line style, taken from wxpython demo""" # Overridden from OwnerDrawnComboBox, called to draw each # item in the list def OnDrawItem(self, dc, rect, item, flags): if item == wx.NOT_FOUND: # painting the control, but there is no valid item selected yet return r = wx.Rect(*rect) # make a copy r.Deflate(3, 5) penStyle = wx.SOLID if item == 1: penStyle = wx.LONG_DASH elif item == 2: penStyle = wx.DOT elif item == 3: penStyle = wx.DOT_DASH pen = wx.Pen(dc.GetTextForeground(), 3, penStyle) dc.SetPen(pen) # for painting the items in the popup dc.DrawText(self.GetString(item ), r.x + 3, (r.y + 0) + ((r.height/2) - dc.GetCharHeight() )/2 ) dc.DrawLine(r.x+5, r.y+((r.height/4)*3)+1, r.x+r.width - 5, r.y+((r.height/4)*3)+1 ) def OnDrawBackground(self, dc, rect, item, flags): """!Overridden from OwnerDrawnComboBox, called for drawing the background area of each item.""" # If the item is selected, or its item # iseven, or we are painting the # combo control itself, then use the default rendering. if (item & 1 == 0 or flags & (wx.combo.ODCB_PAINTING_CONTROL | wx.combo.ODCB_PAINTING_SELECTED)): wx.combo.OwnerDrawnComboBox.OnDrawBackground(self, dc, rect, item, flags) return # Otherwise, draw every other background with different colour. bgCol = wx.Colour(240,240,250) dc.SetBrush(wx.Brush(bgCol)) dc.SetPen(wx.Pen(bgCol)) dc.DrawRectangleRect(rect); def OnMeasureItem(self, item): """!Overridden from OwnerDrawnComboBox, should return the height needed to display an item in the popup, or -1 for default""" return 30 def OnMeasureItemWidth(self, item): """!Overridden from OwnerDrawnComboBox. Callback for item width, or -1 for default/undetermined""" return -1; # default - will be measured from text width class CheckListCtrl(wx.ListCtrl, CheckListCtrlMixin, ListCtrlAutoWidthMixin): """!List control for managing order and labels of vector maps in legend""" def __init__(self, parent): wx.ListCtrl.__init__(self, parent, id = wx.ID_ANY, style = wx.LC_REPORT|wx.LC_SINGLE_SEL|wx.BORDER_SUNKEN|wx.LC_VRULES|wx.LC_HRULES) CheckListCtrlMixin.__init__(self) ListCtrlAutoWidthMixin.__init__(self) class Instruction: """!Class which represents instruction file""" def __init__(self, parent, objectsToDraw): self.parent = parent self.objectsToDraw = objectsToDraw #here are kept objects like mapinfo, rasterlegend, etc. self.instruction = list() def __str__(self): """!Returns text for instruction file""" comment = "# timestamp: " + strftime("%Y-%m-%d %H:%M", localtime()) + '\n' env = grass.gisenv() comment += "# location: %s\n" % env['LOCATION_NAME'] comment += "# mapset: %s\n" % env['MAPSET'] comment += "# page orientation: %s\n" % self.FindInstructionByType('page')['Orientation'] border = '' if not self.FindInstructionByType('map'): border = 'border n\n' text = [str(each) for each in self.instruction] return comment + border + '\n'.join(text) + '\nend' def __getitem__(self, id): for each in self.instruction: if each.id == id: return each return None def __contains__(self, id): """!Test if instruction is included""" for each in self.instruction: if each.id == id: return True return False def __delitem__(self, id): """!Delete instruction""" for each in self.instruction: if each.id == id: if each.type == 'map': #must remove raster, vector layers too vektor = self.FindInstructionByType('vector', list = True) vProperties = self.FindInstructionByType('vProperties', list = True) raster = self.FindInstructionByType('raster', list = True) for item in vektor + vProperties + raster: if item in self.instruction: self.instruction.remove(item) self.instruction.remove(each) if id in self.objectsToDraw: self.objectsToDraw.remove(id) return def AddInstruction(self, instruction): """!Add instruction""" # add to instructions if instruction.type == 'map': self.instruction.insert(0, instruction) else: self.instruction.append(instruction) # add to drawable objects if instruction.type not in ('page', 'raster', 'vector', 'vProperties', 'initMap'): if instruction.type == 'map': self.objectsToDraw.insert(0, instruction.id) else: self.objectsToDraw.append(instruction.id) def FindInstructionByType(self, type, list = False): """!Find instruction(s) with the given type""" inst = [] for each in self.instruction: if each.type == type: inst.append(each) if len(inst) == 1 and not list: return inst[0] return inst def Read(self, filename): """!Reads instruction file and creates instruction objects""" self.filename = filename # open file try: file = open(filename, 'r') except IOError: GError(message = _("Unable to open file\n%s") % filename) return # first read file to get information about region and scaletype isRegionComment = False orientation = 'Portrait' for line in file: if '# g.region' in line: self.SetRegion(regionInstruction = line) isRegionComment = True break if '# page orientation' in line: orientation = line.split(':')[-1].strip() if not isRegionComment: self.SetRegion(regionInstruction = None) # then run ps.map -b to get information for maploc # compute scale and center map = self.FindInstructionByType('map') region = grass.region() map['center'] = (region['n'] + region['s']) / 2, (region['w'] + region['e']) / 2 mapRect = GetMapBounds(self.filename, portrait = (orientation == 'Portrait')) map['rect'] = mapRect proj = projInfo() toM = 1.0 if proj['units']: toM = float(proj['meters']) units = UnitConversion(self.parent) w = units.convert(value = mapRect.Get()[2], fromUnit = 'inch', toUnit = 'meter') / toM map['scale'] = w / abs((region['w'] - region['e'])) SetResolution(dpi = 300, width = map['rect'].width, height = map['rect'].height) # read file again, now with information about map bounds isBuffer = False buffer = [] instruction = None vectorMapNumber = 1 file.seek(0) for line in file: if not line.strip(): continue line = line.strip() if isBuffer: buffer.append(line) if 'end' in line: isBuffer = False kwargs = {} if instruction == 'scalebar': kwargs['scale'] = map['scale'] elif instruction in ('text', 'eps'): kwargs['mapInstruction'] = map elif instruction in ('vpoints', 'vlines', 'vareas'): kwargs['id'] = wx.NewId() kwargs['vectorMapNumber'] = vectorMapNumber vectorMapNumber += 1 elif instruction == 'paper': kwargs['Orientation'] = orientation ok = self.SendToRead(instruction, buffer, **kwargs) if not ok: return False buffer = [] continue elif line.startswith('paper'): instruction = 'paper' isBuffer = True buffer.append(line) elif line.startswith('border'): if line.split()[1].lower() in ('n', 'no', 'none'): ok = self.SendToRead('border', [line]) if not ok: return False elif line.split()[1].lower() in ('y', 'yes'): instruction = 'border' isBuffer = True buffer.append(line) elif line.startswith('scale '): if isBuffer: continue ok = self.SendToRead('scale', line, isRegionComment = isRegionComment) if not ok: return False elif line.startswith('maploc'): ok = self.SendToRead(instruction = 'maploc', text = line) if not ok: return False elif line.startswith('raster'): ok = self.SendToRead(instruction = 'raster', text = line) if not ok: return False elif line.startswith('mapinfo'): instruction = 'mapinfo' isBuffer = True buffer.append(line) elif line.startswith('scalebar'): instruction = 'scalebar' isBuffer = True buffer.append(line) elif line.startswith('text'): instruction = 'text' isBuffer = True buffer.append(line) elif line.startswith('eps'): instruction = 'eps' isBuffer = True buffer.append(line) elif line.startswith('colortable'): if len(line.split()) == 2 and line.split()[1].lower() in ('n', 'no', 'none'): break instruction = 'colortable' isBuffer = True buffer.append(line) elif line.startswith('vlegend'): instruction = 'vlegend' isBuffer = True buffer.append(line) elif line.startswith('vpoints'): instruction = 'vpoints' isBuffer = True buffer.append(line) elif line.startswith('vlines'): instruction = 'vlines' isBuffer = True buffer.append(line) elif line.startswith('vareas'): instruction = 'vareas' isBuffer = True buffer.append(line) rasterLegend = self.FindInstructionByType('rasterLegend') raster = self.FindInstructionByType('raster') page = self.FindInstructionByType('page') vector = self.FindInstructionByType('vector') vectorLegend = self.FindInstructionByType('vectorLegend') vectorMaps = self.FindInstructionByType('vProperties', list = True) # check (in case of scaletype 0) if map is drawn also map['drawMap'] = False if map['scaleType'] == 0: mapForRegion = map['map'] if map['mapType'] == 'raster' and raster: if mapForRegion == raster['raster']: map['drawMap'] = True elif map['mapType'] == 'vector' and vector: for vmap in vector['list']: if mapForRegion == vmap[0]: map['drawMap'] = True # rasterLegend if rasterLegend: if rasterLegend['rasterDefault'] and raster: rasterLegend['raster'] = raster['raster'] if not rasterLegend['discrete']: rasterType = getRasterType(map = rasterLegend['raster']) if rasterType == 'CELL': rasterLegend['discrete'] = 'y' else: rasterLegend['discrete'] = 'n' #estimate size height = rasterLegend.EstimateHeight(raster = rasterLegend['raster'], discrete = rasterLegend['discrete'], fontsize = rasterLegend['fontsize'], cols = rasterLegend['cols'], height = rasterLegend['height']) width = rasterLegend.EstimateWidth(raster = rasterLegend['raster'], discrete = rasterLegend['discrete'], fontsize = rasterLegend['fontsize'], cols = rasterLegend['cols'] , width = rasterLegend['width'], paperInstr = page) rasterLegend['rect'] = wx.Rect2D(x = float(rasterLegend['where'][0]), y = float(rasterLegend['where'][1]), w = width, h = height) # vectors, vlegend if vector: for vmap in vectorMaps: for i, each in enumerate(vector['list']): if each[2] == vmap.id: vector['list'][i][4] = vmap['label'] vector['list'][i][3] = vmap['lpos'] if vectorLegend: size = vectorLegend.EstimateSize(vectorInstr = vector, fontsize = vectorLegend['fontsize'], width = vectorLegend['width'], cols = vectorLegend['cols']) vectorLegend['rect'] = wx.Rect2D(x = float(vectorLegend['where'][0]), y = float(vectorLegend['where'][1]), w = size[0], h = size[1]) page = self.FindInstructionByType('page') if not page: page = PageSetup(wx.NewId()) self.AddInstruction(page) else: page['Orientation'] = orientation # return True def SendToRead(self, instruction, text, **kwargs): psmapInstrDict = dict(paper = ['page'], maploc = ['map'], scale = ['map'], border = ['map'], raster = ['raster'], mapinfo = ['mapinfo'], scalebar = ['scalebar'], text = ['text'], eps = ['image', 'northArrow'], vpoints = ['vector', 'vProperties'], vlines = ['vector', 'vProperties'], vareas = ['vector', 'vProperties'], colortable = ['rasterLegend'], vlegend = ['vectorLegend'] ) myInstrDict = dict(page = PageSetup, map = MapFrame, raster = Raster, mapinfo = Mapinfo, scalebar = Scalebar, text = Text, image = Image, northArrow = NorthArrow, rasterLegend = RasterLegend, vectorLegend = VectorLegend, vector = Vector, vProperties = VProperties ) myInstruction = psmapInstrDict[instruction] for i in myInstruction: instr = self.FindInstructionByType(i) if i in ('text', 'vProperties', 'image', 'northArrow') or not instr: id = wx.NewId() #!vProperties expect subtype if i == 'vProperties': id = kwargs['id'] newInstr = myInstrDict[i](id, subType = instruction[1:]) elif i in ('image', 'northArrow'): commentFound = False for line in text: if line.find("# north arrow") >= 0: commentFound = True if i == 'image' and commentFound or \ i == 'northArrow' and not commentFound: continue newInstr = myInstrDict[i](id, settings = self) else: newInstr = myInstrDict[i](id) ok = newInstr.Read(instruction, text, **kwargs) if ok: self.AddInstruction(newInstr) else: return False else: ok = instr.Read(instruction, text, **kwargs) if not ok: return False return True def SetRegion(self, regionInstruction): """!Sets region from file comment or sets current region in case of no comment""" map = MapFrame(wx.NewId()) self.AddInstruction(map) if regionInstruction: cmd = CmdToTuple(regionInstruction.strip('# ').split()) # define scaleType if len(cmd[1]) <= 3: if 'rast' in cmd[1]: map['scaleType'] = 0 map['mapType'] = 'raster' map['map'] = cmd[1]['rast'] elif 'vect' in cmd[1]: map['scaleType'] = 0 map['mapType'] = 'vector' map['map'] = cmd[1]['vect'] elif 'region' in cmd[1]: map['scaleType'] = 1 map['region'] = cmd[1]['region'] else: map['scaleType'] = 2 else: map['scaleType'] = 2 grass.del_temp_region() region = grass.region() grass.use_temp_region() cmd = ['g.region', region] cmdString = GetCmdString(cmd).replace('g.region', '') GMessage(_("Instruction file will be loaded with following region: %s\n") % cmdString) try: RunCommand(cmd[0], **cmd[1]) except grass.ScriptError, e: GError(_("Region cannot be set\n%s") % e) return False class InstructionObject: """!Abtract class representing single instruction""" def __init__(self, id): self.id = id # default values self.defaultInstruction = dict() # current values self.instruction = self.defaultInstruction # converting units self.unitConv = UnitConversion() def __str__(self): """!Returns particular part of text instruction""" return '' def __getitem__(self, key): for each in self.instruction.keys(): if each == key: return self.instruction[key] return None def __setitem__(self, key, value): self.instruction[key] = value def GetInstruction(self): """!Get current values""" return self.instruction def SetInstruction(self, instruction): """!Set default values""" self.instruction = instruction def Read(self, instruction, text, **kwargs): """!Read instruction and save them""" pass class InitMap(InstructionObject): """!Class representing virtual map""" def __init__(self, id): InstructionObject.__init__(self, id = id) self.type = 'initMap' # default values self.defaultInstruction = dict(rect = None, scale = None) # current values self.instruction = dict(self.defaultInstruction) class MapFrame(InstructionObject): """!Class representing map (instructions maploc, scale, border)""" def __init__(self, id): InstructionObject.__init__(self, id = id) self.type = 'map' # default values self.defaultInstruction = dict(map = None, mapType = None, drawMap = True, region = None, rect = wx.Rect2D(), scaleType = 0, scale = None, center = None, resolution = 300, border = 'y', width = 1, color = '0:0:0') # current values self.instruction = dict(self.defaultInstruction) def __str__(self): instr = '' comment = '' #region settings region = grass.region() if self.instruction['scaleType'] == 0: #match map map = self.instruction['map'] if self.instruction['mapType'] == 'raster': comment = "# g.region rast=%s nsres=%s ewres=%s\n" % (map, region['nsres'], region['ewres']) else: comment = "# g.region vect=%s\n" % (map) elif self.instruction['scaleType'] == 1:# saved region region = self.instruction['region'] comment = "# g.region region=%s\n" % region elif self.instruction['scaleType'] in (2, 3): #current region, fixed scale comment = string.Template("# g.region n=$n s=$s e=$e w=$w rows=$rows cols=$cols \n").substitute(**region) instr += comment instr += '\n' # maploc maplocInstruction = "maploc %.3f %.3f" % (self.instruction['rect'].x, self.instruction['rect'].y) if self.instruction['scaleType'] != 3: maplocInstruction += " %.3f %.3f"% (self.instruction['rect'].width, self.instruction['rect'].height) instr += maplocInstruction instr += '\n' # scale if self.instruction['scaleType'] == 3: #fixed scale scaleInstruction = "scale 1:%.0f" % (1/self.instruction['scale']) instr += scaleInstruction instr += '\n' # border borderInstruction = '' if self.instruction['border'] == 'n': borderInstruction = "border n" else: borderInstruction = "border y\n" borderInstruction += string.Template(" width $width\n color $color\n").substitute(self.instruction) borderInstruction += " end" instr += borderInstruction instr += '\n' return instr def Read(self, instruction, text, **kwargs): """!Read instruction and save information""" if 'isRegionComment' in kwargs: isRegionComment = kwargs['isRegionComment'] instr = {} if instruction == 'border': for line in text: if line.startswith('end'): break try: if line.split()[1].lower() in ('n', 'no', 'none'): instr['border'] = 'n' break elif line.split()[1].lower() in ('y', 'yes'): instr['border'] = 'y' elif line.startswith('width'): instr['width'] = line.split()[1] elif line.startswith('color'): instr['color'] = line.split()[1] except IndexError: GError(_("Failed to read instruction %s") % instruction) return False elif instruction == 'scale': try: scaleText = text.strip('scale ').split(':')[1] # when scale instruction given and region comment also, then scaletype is fixed scale if not isRegionComment: instr['scaleType'] = 2 else: instr['scaleType'] = 3 scale = 1/float(scaleText) if abs(scale - self.instruction['scale']) > (0.01 * scale): GWarning(_("Scale has changed, old value: %(old)s\nnew value: %(new)s") % \ { 'old' : scale, 'new' : self.instruction['scale'] }) except (ValueError, IndexError): GError(_("Failed to read instruction %s.\nUse 1:25000 notation.") % instruction) return False elif instruction == 'maploc': maploc = text.strip('maploc ').split() if len(maploc) >= 2: if abs(self.instruction['rect'].Get()[0] - float(maploc[0])) > 0.5 or \ abs(self.instruction['rect'].Get()[1] - float(maploc[1])) > 0.5: GWarning(_("Map frame position changed, old value: %(old1)s %(old2)s\nnew value: %(new1)s %(new2)s") % \ { 'old1' : maploc[0], 'old2' : maploc[1], 'new1' : self.instruction['rect'].Get()[0], 'new2' : self.instruction['rect'].Get()[1] }) #instr['rect'] = wx.Rect2D(float(maploc[0]), float(maploc[1]), self.instruction['rect'][2], self.instruction['rect'][3]) if len(maploc) == 4: if abs(self.instruction['rect'].Get()[2] - float(maploc[2])) > 0.5 or \ abs(self.instruction['rect'].Get()[3] - float(maploc[3])) > 0.5: GWarning(_("Map frame size changed, old value: %(old1)s %(old2)s\nnew value: %(new1)s %(new2)s") % \ { 'old1' : maploc[2], 'old2' : maploc[3], 'new1' : self.instruction['rect'].Get()[2], 'new2' : self.instruction['rect'].Get()[3] }) #instr['rect'] = wx.Rect2D(*map(float, maploc)) self.instruction.update(instr) return True class PageSetup(InstructionObject): """!Class representing page instruction""" def __init__(self, id): InstructionObject.__init__(self, id = id) self.type = 'page' # default values self.defaultInstruction = dict(Units = 'inch', Format = 'a4', Orientation = 'Portrait', Width = 8.268, Height = 11.693, Left = 0.5, Right = 0.5, Top = 1, Bottom = 1) # current values self.instruction = dict(self.defaultInstruction) def __str__(self): if self.instruction['Format'] == 'custom': instr = string.Template("paper\n width $Width\n height $Height\n").substitute(self.instruction) else: instr = string.Template("paper $Format\n").substitute(self.instruction) instr += string.Template(" left $Left\n right $Right\n bottom $Bottom\n top $Top\n end").substitute(self.instruction) return instr def Read(self, instruction, text, **kwargs): """!Read instruction and save information""" instr = {} self.cats = ['Width', 'Height', 'Left', 'Right', 'Top', 'Bottom'] self.subInstr = dict(zip(['width', 'height', 'left', 'right', 'top', 'bottom'], self.cats)) if instruction == 'paper': # just for sure for line in text: if line.startswith('paper'): if len(line.split()) > 1: pformat = line.split()[1] availableFormats = self._toDict(grass.read_command('ps.map', flags = 'p', quiet = True)) # e.g. paper a3 try: instr['Format'] = pformat for key, value in availableFormats[pformat].iteritems(): instr[key] = float(value) break except KeyError: GError(_("Failed to read instruction %(file)s.\nUnknown format %(for)s") % \ { 'file' : instruction, 'for' : format }) return False else: # paper # width ... instr['Format'] = 'custom' # read subinstructions elif instr['Format'] == 'custom' and not line.startswith('end'): text = line.split() try: instr[self.subInstr[text[0]]] = float(text[1]) except (IndexError, KeyError): GError(_("Failed to read instruction %s.") % instruction) return False if 'Orientation' in kwargs and kwargs['Orientation'] == 'Landscape': instr['Width'], instr['Height'] = instr['Height'], instr['Width'] self.instruction.update(instr) return True def _toDict(self, paperStr): sizeDict = dict() # cats = self.subInstr[ 'Width', 'Height', 'Left', 'Right', 'Top', 'Bottom'] for line in paperStr.strip().split('\n'): d = dict(zip(self.cats, line.split()[1:])) sizeDict[line.split()[0]] = d return sizeDict class Mapinfo(InstructionObject): """!Class representing mapinfo instruction""" def __init__(self, id): InstructionObject.__init__(self, id = id) self.type = 'mapinfo' # default values self.defaultInstruction = dict(unit = 'inch', where = (0, 0), font = 'Helvetica', fontsize = 10, color = '0:0:0', background = 'none', border = 'none', rect = None) # current values self.instruction = dict(self.defaultInstruction) def __str__(self): instr = "mapinfo\n" instr += " where %.3f %.3f\n" % (self.instruction['where'][0], self.instruction['where'][1]) instr += string.Template(" font $font\n fontsize $fontsize\n color $color\n").substitute(self.instruction) instr += string.Template(" background $background\n border $border\n").substitute(self.instruction) instr += " end" return instr def Read(self, instruction, text): """!Read instruction and save information""" instr = {} try: for line in text: sub = line.split(None,1) if sub[0] == 'font': instr['font'] = sub[1] elif sub[0] == 'fontsize': instr['fontsize'] = int(sub[1]) elif sub[0] == 'color': instr['color'] = sub[1] elif sub[0] == 'background': instr['background'] = sub[1] elif sub[0] == 'border': instr['border'] = sub[1] elif sub[0] == 'where': instr['where'] = float(sub[1].split()[0]), float(sub[1].split()[1]) except (ValueError, IndexError): GError(_("Failed to read instruction %s") % instruction) return False self.instruction.update(instr) self.instruction['rect'] = self.EstimateRect(mapinfoDict = self.instruction) return True def EstimateRect(self, mapinfoDict): """!Estimate size to draw mapinfo""" w = mapinfoDict['fontsize'] * 20 # any better estimation? h = mapinfoDict['fontsize'] * 7 width = self.unitConv.convert(value = w, fromUnit = 'point', toUnit = 'inch') height = self.unitConv.convert(value = h, fromUnit = 'point', toUnit = 'inch') return wx.Rect2D(x = float(mapinfoDict['where'][0]), y = float(mapinfoDict['where'][1]), w = width, h = height) class Text(InstructionObject): """!Class representing text instruction""" def __init__(self, id): InstructionObject.__init__(self, id = id) self.type = 'text' # default values self.defaultInstruction = dict(text = "", font = "Helvetica", fontsize = 10, color = 'black', background = 'none', hcolor = 'none', hwidth = 1, border = 'none', width = '1', XY = True, where = (0,0), unit = 'inch', rotate = None, ref = "center center", xoffset = 0, yoffset = 0, east = None, north = None) # current values self.instruction = dict(self.defaultInstruction) def __str__(self): text = self.instruction['text'].replace('\n','\\n') instr = "text %s %s" % (self.instruction['east'], self.instruction['north']) try: instr += " %s\n" % text.encode('latin_1') except UnicodeEncodeError, err: try: pos = str(err).split('position')[1].split(':')[0].strip() except IndexError: pos = '' if pos: message = _("Characters on position %s are not supported " "by ISO-8859-1 (Latin 1) encoding " "which is required by module ps.map.") % pos else: message = _("Not all characters are supported " "by ISO-8859-1 (Latin 1) encoding " "which is required by module ps.map.") GMessage(message = message) return '' instr += (string.Template(" font $font\n fontsize $fontsize\n color $color\n"). substitute(self.instruction). encode('latin_1')) instr += string.Template(" hcolor $hcolor\n").substitute(self.instruction).encode('latin_1') if self.instruction['hcolor'] != 'none': instr += string.Template(" hwidth $hwidth\n").substitute(self.instruction).encode('latin_1') instr += string.Template(" border $border\n").substitute(self.instruction).encode('latin_1') if self.instruction['border'] != 'none': instr += string.Template(" width $width\n").substitute(self.instruction).encode('latin_1') instr += string.Template(" background $background\n").substitute(self.instruction).encode('latin_1') if self.instruction["ref"] != '0': instr += string.Template(" ref $ref\n").substitute(self.instruction).encode('latin_1') if self.instruction["rotate"]: instr += string.Template(" rotate $rotate\n").substitute(self.instruction).encode('latin_1') if float(self.instruction["xoffset"]) or float(self.instruction["yoffset"]): instr += (string.Template(" xoffset $xoffset\n yoffset $yoffset\n"). substitute(self.instruction).encode('latin_1')) instr += " end" return instr def Read(self, instruction, text, **kwargs): """!Read instruction and save information""" map = kwargs['mapInstruction'] instr = {} for line in text: try: sub = line.split(None, 1)[0] if sub == 'text': e, n = line.split(None, 3)[1:3] if '%' in e and '%' in n: instr['XY'] = True instr['east'], instr['north'] = self.PercentToReal(e, n) else: instr['XY'] = False instr['east'], instr['north'] = float(e), float(n) instr['text'] = line.split(None, 3)[3] elif sub == 'font': instr['font'] = line.split(None, 1)[1] elif sub == 'fontsize': instr['fontsize'] = float(line.split(None, 1)[1]) elif sub == 'color': instr['color'] = line.split(None, 1)[1] elif sub == 'width': instr['width'] = line.split(None, 1)[1] elif sub == 'hcolor': instr['hcolor'] = line.split(None, 1)[1] elif sub == 'hwidth': instr['hwidth'] = line.split(None, 1)[1] elif sub == 'background': instr['background'] = line.split(None, 1)[1] elif sub == 'border': instr['border'] = line.split(None, 1)[1] elif sub == 'ref': instr['ref'] = line.split(None, 1)[1] elif sub == 'rotate': instr['rotate'] = float(line.split(None, 1)[1]) elif sub == 'xoffset': instr['xoffset'] = int(line.split(None, 1)[1]) elif sub == 'yoffset': instr['yoffset'] = int(line.split(None, 1)[1]) elif sub == 'opaque': if line.split(None, 1)[1].lower() in ('n', 'none'): instr['background'] = 'none' except(IndexError, ValueError): GError(_("Failed to read instruction %s") % instruction) return False instr['where'] = PaperMapCoordinates(map = map, x = instr['east'], y = instr['north'], paperToMap = False) self.instruction.update(instr) return True def PercentToReal(self, e, n): """!Converts text coordinates from percent of region to map coordinates""" e, n = float(e.strip('%')), float(n.strip('%')) region = grass.region() N = region['s'] + (region['n'] - region['s']) / 100 * n E = region['w'] + (region['e'] - region['w']) / 100 * e return E, N class Image(InstructionObject): """!Class representing eps instruction - image""" def __init__(self, id, settings): InstructionObject.__init__(self, id = id) self.settings = settings self.type = 'image' # default values self.defaultInstruction = dict(epsfile = "", XY = True, where = (0,0), unit = 'inch', east = None, north = None, rotate = None, scale = 1) # current values self.instruction = dict(self.defaultInstruction) def __str__(self): self.ChangeRefPoint(toCenter = True) instr = "eps %s %s\n" % (self.instruction['east'], self.instruction['north']) instr += string.Template(" epsfile $epsfile\n").substitute(self.instruction) if self.instruction["rotate"]: instr += string.Template(" rotate $rotate\n").substitute(self.instruction) if self.instruction["scale"]: instr += string.Template(" scale $scale\n").substitute(self.instruction) instr += " end" return instr def Read(self, instruction, text, **kwargs): """!Read instruction and save information""" mapInstr = kwargs['mapInstruction'] instr = {} for line in text: try: sub = line.split(None, 1)[0] if sub == 'eps': e, n = line.split(None, 3)[1:3] if '%' in e and '%' in n: instr['XY'] = True instr['east'], instr['north'] = self.PercentToReal(e, n) else: instr['XY'] = False instr['east'], instr['north'] = float(e), float(n) elif sub == 'epsfile': instr['epsfile'] = line.split(None, 1)[1] elif sub == 'rotate': instr['rotate'] = float(line.split(None, 1)[1]) elif sub == 'scale': instr['scale'] = float(line.split(None, 1)[1]) except(IndexError, ValueError): GError(_("Failed to read instruction %s") % instruction) return False if not os.path.exists(instr['epsfile']): GError(_("Failed to read instruction %s: file %s not found.") % instruction, instr['epsfile']) return False instr['epsfile'] = os.path.abspath(instr['epsfile']) instr['size'] = self.GetImageOrigSize(instr['epsfile']) if 'rotate' in instr: instr['size'] = BBoxAfterRotation(instr['size'][0], instr['size'][1], instr['rotate']) self.instruction.update(instr) self.ChangeRefPoint(toCenter = False) instr['where'] = PaperMapCoordinates(map = mapInstr, x = self.instruction['east'], y = self.instruction['north'], paperToMap = False) w = self.unitConv.convert(value = instr['size'][0], fromUnit = 'point', toUnit = 'inch') h = self.unitConv.convert(value = instr['size'][1], fromUnit = 'point', toUnit = 'inch') instr['rect'] = wx.Rect2D(x = float(instr['where'][0]), y = float(instr['where'][1]), w = w * self.instruction['scale'], h = h * self.instruction['scale']) self.instruction.update(instr) return True def PercentToReal(self, e, n): """!Converts eps coordinates from percent of region to map coordinates""" e, n = float(e.strip('%')), float(n.strip('%')) region = grass.region() N = region['s'] + (region['n'] - region['s']) / 100 * n E = region['w'] + (region['e'] - region['w']) / 100 * e return E, N def ChangeRefPoint(self, toCenter): """!Change reference point (left top x center)""" mapInstr = self.settings.FindInstructionByType('map') if not mapInstr: mapInstr = self.settings.FindInstructionByType('initMap') mapId = mapInstr.id if toCenter: center = self.instruction['rect'].GetCentre() ENCenter = PaperMapCoordinates(map = self.settings[mapId], x = center[0], y = center[1], paperToMap = True) self.instruction['east'], self.instruction['north'] = ENCenter else: x, y = PaperMapCoordinates(map = self.settings[mapId], x = self.instruction['east'], y = self.instruction['north'], paperToMap = False) w = self.unitConv.convert(value = self.instruction['size'][0], fromUnit = 'point', toUnit = 'inch') h = self.unitConv.convert(value = self.instruction['size'][1], fromUnit = 'point', toUnit = 'inch') x -= w * self.instruction['scale'] / 2 y -= h * self.instruction['scale'] / 2 e, n = PaperMapCoordinates(map = self.settings[mapId], x = x, y = y, paperToMap = True) self.instruction['east'], self.instruction['north'] = e, n def GetImageOrigSize(self, imagePath): """!Get image size. If eps, size is read from image header. """ fileName = os.path.split(imagePath)[1] # if eps, read info from header if os.path.splitext(fileName)[1].lower() == '.eps': bbInfo = "%%BoundingBox" file = open(imagePath,"r") w = h = 0 while file: line = file.readline() if line.find(bbInfo) == 0: w, h = line.split()[3:5] break file.close() return float(w), float(h) else: # we can use wx.Image img = wx.Image(fileName, type=wx.BITMAP_TYPE_ANY) return img.GetWidth(), img.GetHeight() class NorthArrow(Image): """!Class representing eps instruction -- North Arrow""" def __init__(self, id, settings): Image.__init__(self, id = id, settings = settings) self.type = 'northArrow' def __str__(self): self.ChangeRefPoint(toCenter = True) instr = "eps %s %s\n" % (self.instruction['east'], self.instruction['north']) instr += "# north arrow\n" instr += string.Template(" epsfile $epsfile\n").substitute(self.instruction) if self.instruction["rotate"]: instr += string.Template(" rotate $rotate\n").substitute(self.instruction) if self.instruction["scale"]: instr += string.Template(" scale $scale\n").substitute(self.instruction) instr += " end" return instr class Scalebar(InstructionObject): """!Class representing scalebar instruction""" def __init__(self, id): InstructionObject.__init__(self, id = id) self.type = 'scalebar' # default values self.defaultInstruction = dict(unit = 'inch', where = (1,1), unitsLength = 'auto', unitsHeight = 'inch', length = None, height = 0.1, rect = None, fontsize = 10, background = 'y', scalebar = 'f', segment = 4, numbers = 1) # current values self.instruction = dict(self.defaultInstruction) def __str__(self): instr = string.Template("scalebar $scalebar\n").substitute(self.instruction) instr += " where %.3f %.3f\n" % (self.instruction['where'][0], self.instruction['where'][1]) instr += string.Template(" length $length\n units $unitsLength\n").substitute(self.instruction) instr += string.Template(" height $height\n").substitute(self.instruction) instr += string.Template(" segment $segment\n numbers $numbers\n").substitute(self.instruction) instr += string.Template(" fontsize $fontsize\n background $background\n").substitute(self.instruction) instr += " end" return instr def Read(self, instruction, text, **kwargs): """!Read instruction and save information""" scale = kwargs['scale'] instr = {} for line in text: try: if line.startswith('scalebar'): if 'scalebar s' in line: instr['scalebar'] = 's' else: instr['scalebar'] = 'f' elif line.startswith('where'): instr['where'] = map(float, line.split()[1:3]) elif line.startswith('length'): instr['length'] = float(line.split()[1]) elif line.startswith('units'): if line.split()[1] in ['auto', 'meters', 'kilometers', 'feet', 'miles', 'nautmiles']: instr['unitsLength'] = line.split()[1] elif line.startswith('height'): instr['height'] = float(line.split()[1]) elif line.startswith('fontsize'): instr['fontsize'] = float(line.split()[1]) elif line.startswith('numbers'): instr['numbers'] = int(line.split()[1]) elif line.startswith('segment'): instr['segment'] = int(line.split()[1]) elif line.startswith('background'): if line.split()[1].strip().lower() in ('y','yes'): instr['background'] = 'y' elif line.split()[1].strip().lower() in ('n','no', 'none'): instr['background'] = 'n' except(IndexError, ValueError): GError(_("Failed to read instruction %s") % instruction) return False self.instruction.update(instr) w, h = self.EstimateSize(scalebarDict = self.instruction, scale = scale) x = self.instruction['where'][0] - w / 2 y = self.instruction['where'][1] - h / 2 self.instruction['rect'] = wx.Rect2D(x, y, w, h) return True def EstimateSize(self, scalebarDict, scale): """!Estimate size to draw scalebar""" units = projInfo()['units'] if not units or units not in self.unitConv.getAllUnits(): units = 'meters' if scalebarDict['unitsLength'] != 'auto': length = self.unitConv.convert(value = scalebarDict['length'], fromUnit = scalebarDict['unitsLength'], toUnit = 'inch') else: length = self.unitConv.convert(value = scalebarDict['length'], fromUnit = units, toUnit = 'inch') length *= scale length *= 1.1 #for numbers on the edge height = scalebarDict['height'] + 2 * self.unitConv.convert(value = scalebarDict['fontsize'], fromUnit = 'point', toUnit = 'inch') return (length, height) class RasterLegend(InstructionObject): """!Class representing colortable instruction""" def __init__(self, id): InstructionObject.__init__(self, id = id) self.type = 'rasterLegend' # default values self.defaultInstruction = dict(rLegend = False, unit = 'inch', rasterDefault = True, raster = None, discrete = None, type = None, where = (0, 0), width = None, height = None, cols = 1, font = "Helvetica", fontsize = 10, #color = '0:0:0', tickbar = False, range = False, min = 0, max = 0, color = 'black', tickbar = 'n', range = False, min = 0, max = 0, nodata = 'n') # current values self.instruction = dict(self.defaultInstruction) def __str__(self): instr = "colortable y\n" instr += string.Template(" raster $raster\n").substitute(self.instruction) instr += " where %.3f %.3f\n" % (self.instruction['where'][0], self.instruction['where'][1]) if self.instruction['width']: instr += string.Template(" width $width\n").substitute(self.instruction) instr += string.Template(" discrete $discrete\n").substitute(self.instruction) if self.instruction['discrete'] == 'n': if self.instruction['height']: instr += string.Template(" height $height\n").substitute(self.instruction) instr += string.Template(" tickbar $tickbar\n").substitute(self.instruction) if self.instruction['range']: instr += string.Template(" range $min $max\n").substitute(self.instruction) else: instr += string.Template(" cols $cols\n").substitute(self.instruction) instr += string.Template(" nodata $nodata\n").substitute(self.instruction) instr += string.Template(" font $font\n fontsize $fontsize\n color $color\n")\ .substitute(self.instruction) instr += " end" return instr def Read(self, instruction, text, **kwargs): """!Read instruction and save information""" instr = {} instr['rLegend'] = True for line in text: try: if line.startswith('where'): instr['where'] = map(float, line.split()[1:3]) elif line.startswith('font '): instr['font'] = line.split()[1] elif line.startswith('fontsize'): instr['fontsize'] = float(line.split()[1]) elif line.startswith('color '): instr['color'] = line.split()[1] elif line.startswith('raster'): instr['raster'] = line.split()[1] elif line.startswith('width'): instr['width'] = float(line.split()[1]) elif line.startswith('height'): instr['height'] = float(line.split()[1]) elif line.startswith('cols'): instr['cols'] = int(line.split()[1]) elif line.startswith('range'): instr['range'] = True instr['min'] = float(line.split()[1]) instr['max'] = float(line.split()[2]) elif line.startswith('nodata'): if line.split()[1].strip().lower() in ('y','yes'): instr['nodata'] = 'y' elif line.split()[1].strip().lower() in ('n','no', 'none'): instr['nodata'] = 'n' elif line.startswith('tickbar'): if line.split()[1].strip().lower() in ('y','yes'): instr['tickbar'] = 'y' elif line.split()[1].strip().lower() in ('n','no', 'none'): instr['tickbar'] = 'n' elif line.startswith('discrete'): if line.split()[1].strip().lower() in ('y','yes'): instr['discrete'] = 'y' elif line.split()[1].strip().lower() in ('n','no', 'none'): instr['discrete'] = 'n' except(IndexError, ValueError): GError(_("Failed to read instruction %s") % instruction) return False if 'raster' in instr: instr['rasterDefault'] = False if 'discrete' not in instr: rasterType = getRasterType(map = instr['raster']) instr['type'] = rasterType if rasterType == 'CELL': instr['discrete'] = 'y' else: instr['discrete'] = 'n' else: instr['rasterDefault'] = True self.instruction.update(instr) # add 'rect' in the end return True def EstimateHeight(self, raster, discrete, fontsize, cols = None, height = None): """!Estimate height to draw raster legend""" if discrete == 'n': if height: height = height else: height = self.unitConv.convert(value = fontsize * 10, fromUnit = 'point', toUnit = 'inch') if discrete == 'y': if cols: cols = cols else: cols = 1 rinfo = grass.raster_info(raster) if rinfo['datatype'] in ('DCELL', 'FCELL'): minim, maxim = rinfo['min'], rinfo['max'] rows = ceil(maxim / cols ) else: cat = grass.read_command('r.category', map = raster, fs = ':').strip().split('\n') rows = ceil(float(len(cat)) / cols ) height = self.unitConv.convert(value = 1.5 * rows * fontsize, fromUnit = 'point', toUnit = 'inch') return height def EstimateWidth(self, raster, discrete, fontsize, cols = None, width = None, paperInstr = None): """!Estimate size to draw raster legend""" if discrete == 'n': rinfo = grass.raster_info(raster) minim, maxim = rinfo['min'], rinfo['max'] if width: width = width else: width = self.unitConv.convert(value = fontsize * 2, fromUnit = 'point', toUnit = 'inch') text = len(max(str(minim), str(maxim), key = len)) textPart = self.unitConv.convert(value = text * fontsize / 2, fromUnit = 'point', toUnit = 'inch') width += textPart elif discrete == 'y': if cols: cols = cols else: cols = 1 if width: width = width else: paperWidth = paperInstr['Width'] - paperInstr['Right'] - paperInstr['Left'] width = (paperWidth / cols) * (cols - 1) + 1 return width class VectorLegend(InstructionObject): """!Class representing colortable instruction""" def __init__(self, id): InstructionObject.__init__(self, id = id) self.type = 'vectorLegend' # default values self.defaultInstruction = dict(vLegend = False, unit = 'inch', where = (0, 0), defaultSize = True, width = 0.4, cols = 1, span = None, font = "Helvetica", fontsize = 10, border = 'none') # current values self.instruction = dict(self.defaultInstruction) def __str__(self): instr = "vlegend\n" instr += " where %.3f %.3f\n" % (self.instruction['where'][0], self.instruction['where'][1]) instr += string.Template(" font $font\n fontsize $fontsize\n").substitute(self.instruction) instr += string.Template(" width $width\n cols $cols\n").substitute(self.instruction) if self.instruction['span']: instr += string.Template(" span $span\n").substitute(self.instruction) instr += string.Template(" border $border\n").substitute(self.instruction) instr += " end" return instr def Read(self, instruction, text, **kwargs): """!Read instruction and save information""" instr = {} instr['vLegend'] = True for line in text: try: if line.startswith('where'): instr['where'] = map(float, line.split()[1:3]) elif line.startswith('font '): instr['font'] = line.split()[1] elif line.startswith('fontsize'): instr['fontsize'] = float(line.split()[1]) elif line.startswith('width'): instr['width'] = float(line.split()[1]) elif line.startswith('cols'): instr['cols'] = int(line.split()[1]) elif line.startswith('span'): instr['span'] = float(line.split()[1]) elif line.startswith('border'): instr['border'] = line.split()[1] except(IndexError, ValueError): GError(_("Failed to read instruction %s") % instruction) return False self.instruction.update(instr) return True def EstimateSize(self, vectorInstr, fontsize, width = None, cols = None): """!Estimate size to draw vector legend""" if width: width = width else: width = fontsize/24.0 if cols: cols = cols else: cols = 1 vectors = vectorInstr['list'] labels = [vector[4] for vector in vectors if vector[3] != 0] extent = (len(max(labels, key = len)) * fontsize / 2, fontsize) wExtent = self.unitConv.convert(value = extent[0], fromUnit = 'point', toUnit = 'inch') hExtent = self.unitConv.convert(value = extent[1], fromUnit = 'point', toUnit = 'inch') w = (width + wExtent) * cols h = len(labels) * hExtent / cols h *= 1.1 return (w, h) class Raster(InstructionObject): """!Class representing raster instruction""" def __init__(self, id): InstructionObject.__init__(self, id = id) self.type = 'raster' # default values self.defaultInstruction = dict(isRaster = False, raster = None) # current values self.instruction = dict(self.defaultInstruction) def __str__(self): instr = string.Template("raster $raster").substitute(self.instruction) return instr def Read(self, instruction, text): """!Read instruction and save information""" instr = {} instr['isRaster'] = True try: map = text.split()[1] except IndexError: GError(_("Failed to read instruction %s") % instruction) return False try: info = grass.find_file(map, element = 'cell') except grass.ScriptError, e: GError(message = e.value) return False instr['raster'] = info['fullname'] self.instruction.update(instr) return True class Vector(InstructionObject): """!Class keeps vector layers""" def __init__(self, id): InstructionObject.__init__(self, id = id) self.type = 'vector' # default values self.defaultInstruction = dict(list = None)# [vmap, type, id, lpos, label] # current values self.instruction = dict(self.defaultInstruction) def __str__(self): return '' def Read(self, instruction, text, **kwargs): """!Read instruction and save information""" instr = {} for line in text: if line.startswith('vpoints') or line.startswith('vlines') or line.startswith('vareas'): # subtype if line.startswith('vpoints'): subType = 'points' elif line.startswith('vlines'): subType = 'lines' elif line.startswith('vareas'): subType = 'areas' # name of vector map vmap = line.split()[1] try: info = grass.find_file(vmap, element = 'vector') except grass.ScriptError, e: GError(message = e.value) return False vmap = info['fullname'] # id id = kwargs['id'] # lpos lpos = kwargs['vectorMapNumber'] #label label = '('.join(vmap.split('@')) + ')' break instr = [vmap, subType, id, lpos, label] if not self.instruction['list']: self.instruction['list'] = [] self.instruction['list'].append(instr) return True class VProperties(InstructionObject): """!Class represents instructions vareas, vlines, vpoints""" def __init__(self, id, subType): InstructionObject.__init__(self, id = id) self.type = 'vProperties' self.subType = subType # default values if self.subType == 'points': dd = dict(subType = 'points', name = None, type = 'point or centroid', connection = False, layer = '1', masked = 'n', color = '0:0:0', width = 1, fcolor = '255:0:0', rgbcolumn = None, symbol = os.path.join('basic', 'x'), eps = None, size = 5, sizecolumn = None, scale = None, rotation = False, rotate = 0, rotatecolumn = None, label = None, lpos = None) elif self.subType == 'lines': dd = dict(subType = 'lines', name = None, type = 'line or boundary', connection = False, layer = '1', masked = 'n', color = '0:0:0', hwidth = 1, hcolor = 'none', rgbcolumn = None, width = 1, cwidth = None, style = 'solid', linecap = 'butt', label = None, lpos = None) else: # areas dd = dict(subType = 'areas', name = None, connection = False, layer = '1', masked = 'n', color = '0:0:0', width = 1, fcolor = 'none', rgbcolumn = None, pat = None, pwidth = 1, scale = 1, label = None, lpos = None) self.defaultInstruction = dd # current values self.instruction = dict(self.defaultInstruction) def __str__(self): dic = self.instruction vInstruction = string.Template("v$subType $name\n").substitute(dic) #data selection if self.subType in ('points', 'lines'): vInstruction += string.Template(" type $type\n").substitute(dic) if dic['connection']: vInstruction += string.Template(" layer $layer\n").substitute(dic) if dic.has_key('cats'): vInstruction += string.Template(" cats $cats\n").substitute(dic) elif dic.has_key('where'): vInstruction += string.Template(" where $where\n").substitute(dic) vInstruction += string.Template(" masked $masked\n").substitute(dic) #colors vInstruction += string.Template(" color $color\n").substitute(dic) if self.subType in ('points', 'areas'): if dic['color'] != 'none': vInstruction += string.Template(" width $width\n").substitute(dic) if dic['rgbcolumn']: vInstruction += string.Template(" rgbcolumn $rgbcolumn\n").substitute(dic) vInstruction += string.Template(" fcolor $fcolor\n").substitute(dic) else: if dic['rgbcolumn']: vInstruction += string.Template(" rgbcolumn $rgbcolumn\n").substitute(dic) elif dic['hcolor'] != 'none': vInstruction += string.Template(" hwidth $hwidth\n").substitute(dic) vInstruction += string.Template(" hcolor $hcolor\n").substitute(dic) # size and style if self.subType == 'points': if dic['symbol']: vInstruction += string.Template(" symbol $symbol\n").substitute(dic) else: #eps vInstruction += string.Template(" eps $eps\n").substitute(dic) if dic['size']: vInstruction += string.Template(" size $size\n").substitute(dic) else: # sizecolumn vInstruction += string.Template(" sizecolumn $sizecolumn\n").substitute(dic) vInstruction += string.Template(" scale $scale\n").substitute(dic) if dic['rotation']: if dic['rotate'] is not None: vInstruction += string.Template(" rotate $rotate\n").substitute(dic) else: vInstruction += string.Template(" rotatecolumn $rotatecolumn\n").substitute(dic) if self.subType == 'areas': if dic['pat'] is not None: vInstruction += string.Template(" pat $pat\n").substitute(dic) vInstruction += string.Template(" pwidth $pwidth\n").substitute(dic) vInstruction += string.Template(" scale $scale\n").substitute(dic) if self.subType == 'lines': if dic['width'] is not None: vInstruction += string.Template(" width $width\n").substitute(dic) else: vInstruction += string.Template(" cwidth $cwidth\n").substitute(dic) vInstruction += string.Template(" style $style\n").substitute(dic) vInstruction += string.Template(" linecap $linecap\n").substitute(dic) #position and label in vlegend vInstruction += string.Template(" label $label\n lpos $lpos\n").substitute(dic) vInstruction += " end" return vInstruction def Read(self, instruction, text, **kwargs): """!Read instruction and save information""" instr = {} try: info = grass.find_file(name = text[0].split()[1], element = 'vector') except grass.ScriptError, e: GError(message = e.value) return False instr['name'] = info['fullname'] #connection instr['connection'] = True self.mapDBInfo = dbm_base.VectorDBInfo(instr['name']) self.layers = self.mapDBInfo.layers.keys() if not self.layers: instr['connection'] = False # points if text[0].startswith('vpoints'): for line in text[1:]: if line.startswith('type'): tp = [] if line.find('point') != -1: tp.append('point') if line.find('centroid') != -1: tp.append('centroid') instr['type'] = ' or '.join(tp) elif line.startswith('fcolor'): instr['fcolor'] = line.split()[1] elif line.startswith('rgbcolumn'): instr['rgbcolumn'] = line.split()[1] elif line.startswith('symbol'): instr['symbol'] = line.split()[1] elif line.startswith('eps'): instr['eps'] = line.split()[1] elif line.startswith('size '): instr['size'] = line.split()[1] elif line.startswith('sizecolumn'): instr['size'] = None instr['sizecolumn'] = line.split()[1] elif line.startswith('scale '): instr['scale'] = float(line.split()[1]) elif line.startswith('rotate '): instr['rotation'] = True instr['rotate'] = line.split()[1] elif line.startswith('rotatecolumn'): instr['rotatecolumn'] = line.split()[1] instr['rotation'] = True instr['rotate'] = None # lines elif text[0].startswith('vlines'): for line in text[1:]: if line.startswith('type'): tp = [] if line.find('line') != -1: tp.append('line') if line.find('boundary') != -1: tp.append('boundary') instr['type'] = ' or '.join(tp) elif line.startswith('hwidth'): instr['hwidth'] = float(line.split()[1]) elif line.startswith('hcolor'): instr['hcolor'] = line.split()[1] elif line.startswith('rgbcolumn'): instr['rgbcolumn'] = line.split()[1] elif line.startswith('cwidth'): instr['cwidth'] = float(line.split()[1]) instr['width'] = None elif line.startswith('style'): instr['style'] = line.split()[1] elif line.startswith('linecap'): instr['linecap'] = line.split()[1] elif text[0].startswith('vareas'): for line in text[1:]: if line.startswith('fcolor'): instr['fcolor'] = line.split()[1] elif line.startswith('pat'): instr['pat'] = line.split()[1] elif line.startswith('pwidth'): instr['pwidth'] = float(line.split()[1]) elif line.startswith('scale'): instr['scale'] = float(line.split()[1]) # same properties for all for line in text[1:]: if line.startswith('lpos'): instr['lpos'] = int(line.split()[1]) elif line.startswith('label'): instr['label'] = line.split(None, 1)[1] elif line.startswith('layer'): instr['layer'] = line.split()[1] elif line.startswith('masked'): if line.split()[1].lower() in ('y', 'yes'): instr['masked'] = 'y' else: instr['masked'] = 'n' elif line.startswith('color'): instr['color'] = line.split()[1] elif line.startswith('rgbcolumn'): instr['rgbcolumn'] = line.split()[1] elif line.startswith('width'): instr['width'] = float(line.split()[1]) if 'label' not in instr: instr['label'] = '('.join(instr['name'].split('@')) + ')' if 'lpos' not in instr: instr['lpos'] = kwargs['vectorMapNumber'] self.instruction.update(instr) return True class PsmapDialog(wx.Dialog): def __init__(self, parent, id, title, settings, apply = True): wx.Dialog.__init__(self, parent = parent, id = wx.ID_ANY, title = title, size = wx.DefaultSize, style = wx.CAPTION|wx.MINIMIZE_BOX|wx.CLOSE_BOX) self.apply = apply self.id = id self.parent = parent self.instruction = settings self.objectType = None self.unitConv = UnitConversion(self) self.spinCtrlSize = (65, -1) self.Bind(wx.EVT_CLOSE, self.OnClose) def AddUnits(self, parent, dialogDict): parent.units = dict() parent.units['unitsLabel'] = wx.StaticText(parent, id = wx.ID_ANY, label = _("Units:")) choices = self.unitConv.getPageUnitsNames() parent.units['unitsCtrl'] = wx.Choice(parent, id = wx.ID_ANY, choices = choices) parent.units['unitsCtrl'].SetStringSelection(self.unitConv.findName(dialogDict['unit'])) def AddPosition(self, parent, dialogDict): if not hasattr(parent, "position"): parent.position = dict() parent.position['comment'] = wx.StaticText(parent, id = wx.ID_ANY,\ label = _("Position of the top left corner\nfrom the top left edge of the paper")) parent.position['xLabel'] = wx.StaticText(parent, id = wx.ID_ANY, label = _("X:")) parent.position['yLabel'] = wx.StaticText(parent, id = wx.ID_ANY, label = _("Y:")) parent.position['xCtrl'] = wx.TextCtrl(parent, id = wx.ID_ANY, value = str(dialogDict['where'][0]), validator = TCValidator(flag = 'DIGIT_ONLY')) parent.position['yCtrl'] = wx.TextCtrl(parent, id = wx.ID_ANY, value = str(dialogDict['where'][1]), validator = TCValidator(flag = 'DIGIT_ONLY')) if dialogDict.has_key('unit'): x = self.unitConv.convert(value = dialogDict['where'][0], fromUnit = 'inch', toUnit = dialogDict['unit']) y = self.unitConv.convert(value = dialogDict['where'][1], fromUnit = 'inch', toUnit = dialogDict['unit']) parent.position['xCtrl'].SetValue("%5.3f" % x) parent.position['yCtrl'].SetValue("%5.3f" % y) def AddExtendedPosition(self, panel, gridBagSizer, dialogDict): """!Add widgets for setting position relative to paper and to map""" panel.position = dict() positionLabel = wx.StaticText(panel, id = wx.ID_ANY, label = _("Position is given:")) panel.position['toPaper'] = wx.RadioButton(panel, id = wx.ID_ANY, label = _("relatively to paper"), style = wx.RB_GROUP) panel.position['toMap'] = wx.RadioButton(panel, id = wx.ID_ANY, label = _("by map coordinates")) panel.position['toPaper'].SetValue(dialogDict['XY']) panel.position['toMap'].SetValue(not dialogDict['XY']) gridBagSizer.Add(positionLabel, pos = (0,0), span = (1,3), flag = wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT, border = 0) gridBagSizer.Add(panel.position['toPaper'], pos = (1,0), flag = wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT, border = 0) gridBagSizer.Add(panel.position['toMap'], pos = (1,1),flag = wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT, border = 0) # first box - paper coordinates box1 = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = "") sizerP = wx.StaticBoxSizer(box1, wx.VERTICAL) self.gridBagSizerP = wx.GridBagSizer (hgap = 5, vgap = 5) self.gridBagSizerP.AddGrowableCol(1) self.gridBagSizerP.AddGrowableRow(3) self.AddPosition(parent = panel, dialogDict = dialogDict) panel.position['comment'].SetLabel(_("Position from the top left\nedge of the paper")) self.AddUnits(parent = panel, dialogDict = dialogDict) self.gridBagSizerP.Add(panel.units['unitsLabel'], pos = (0,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) self.gridBagSizerP.Add(panel.units['unitsCtrl'], pos = (0,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) self.gridBagSizerP.Add(panel.position['xLabel'], pos = (1,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) self.gridBagSizerP.Add(panel.position['xCtrl'], pos = (1,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) self.gridBagSizerP.Add(panel.position['yLabel'], pos = (2,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) self.gridBagSizerP.Add(panel.position['yCtrl'], pos = (2,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) self.gridBagSizerP.Add(panel.position['comment'], pos = (3,0), span = (1,2), flag = wx.ALIGN_BOTTOM, border = 0) sizerP.Add(self.gridBagSizerP, proportion = 1, flag = wx.EXPAND|wx.ALL, border = 5) gridBagSizer.Add(sizerP, pos = (2,0),span = (1,1), flag = wx.ALIGN_CENTER_HORIZONTAL|wx.EXPAND, border = 0) # second box - map coordinates box2 = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = "") sizerM = wx.StaticBoxSizer(box2, wx.VERTICAL) self.gridBagSizerM = wx.GridBagSizer (hgap = 5, vgap = 5) self.gridBagSizerM.AddGrowableCol(0) self.gridBagSizerM.AddGrowableCol(1) eastingLabel = wx.StaticText(panel, id = wx.ID_ANY, label = "E:") northingLabel = wx.StaticText(panel, id = wx.ID_ANY, label = "N:") panel.position['eCtrl'] = wx.TextCtrl(panel, id = wx.ID_ANY, value = "") panel.position['nCtrl'] = wx.TextCtrl(panel, id = wx.ID_ANY, value = "") east, north = PaperMapCoordinates(map = self.instruction[self.mapId], x = dialogDict['where'][0], y = dialogDict['where'][1], paperToMap = True) panel.position['eCtrl'].SetValue(str(east)) panel.position['nCtrl'].SetValue(str(north)) self.gridBagSizerM.Add(eastingLabel, pos = (0,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) self.gridBagSizerM.Add(northingLabel, pos = (1,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) self.gridBagSizerM.Add(panel.position['eCtrl'], pos = (0,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) self.gridBagSizerM.Add(panel.position['nCtrl'], pos = (1,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) sizerM.Add(self.gridBagSizerM, proportion = 1, flag = wx.EXPAND|wx.ALL, border = 5) gridBagSizer.Add(sizerM, pos = (2,1), flag = wx.ALIGN_LEFT|wx.EXPAND, border = 0) def AddFont(self, parent, dialogDict, color = True): parent.font = dict() ## parent.font['fontLabel'] = wx.StaticText(parent, id = wx.ID_ANY, label = _("Choose font:")) ## parent.font['fontCtrl'] = wx.FontPickerCtrl(parent, id = wx.ID_ANY) ## ## parent.font['fontCtrl'].SetSelectedFont( ## wx.FontFromNativeInfoString(dialogDict['font'] + " " + str(dialogDict['fontsize']))) ## parent.font['fontCtrl'].SetMaxPointSize(50) ## ## if color: ## parent.font['colorLabel'] = wx.StaticText(parent, id = wx.ID_ANY, label = _("Choose color:")) ## parent.font['colorCtrl'] = wx.ColourPickerCtrl(parent, id = wx.ID_ANY, style=wx.FNTP_FONTDESC_AS_LABEL) ## parent.font['colorCtrl'].SetColour(dialogDict['color']) ## parent.font['colorCtrl'].SetColour(convertRGB(dialogDict['color'])) parent.font['fontLabel'] = wx.StaticText(parent, id = wx.ID_ANY, label = _("Font:")) parent.font['fontSizeLabel'] = wx.StaticText(parent, id = wx.ID_ANY, label = _("Font size:")) fontChoices = [ 'Times-Roman', 'Times-Italic', 'Times-Bold', 'Times-BoldItalic', 'Helvetica',\ 'Helvetica-Oblique', 'Helvetica-Bold', 'Helvetica-BoldOblique', 'Courier',\ 'Courier-Oblique', 'Courier-Bold', 'Courier-BoldOblique'] parent.font['fontCtrl'] = wx.Choice(parent, id = wx.ID_ANY, choices = fontChoices) if dialogDict['font'] in fontChoices: parent.font['fontCtrl'].SetStringSelection(dialogDict['font']) else: parent.font['fontCtrl'].SetStringSelection('Helvetica') parent.font['fontSizeCtrl'] = wx.SpinCtrl(parent, id = wx.ID_ANY, min = 4, max = 50, initial = 10) parent.font['fontSizeCtrl'].SetValue(dialogDict['fontsize']) if color: parent.font['colorLabel'] = wx.StaticText(parent, id = wx.ID_ANY, label = _("Choose color:")) parent.font['colorCtrl'] = wx.ColourPickerCtrl(parent, id = wx.ID_ANY) parent.font['colorCtrl'].SetColour(convertRGB(dialogDict['color'])) ## parent.font['colorLabel'] = wx.StaticText(parent, id = wx.ID_ANY, label = _("Color:")) ## colorChoices = [ 'aqua', 'black', 'blue', 'brown', 'cyan', 'gray', 'green', 'indigo', 'magenta',\ ## 'orange', 'purple', 'red', 'violet', 'white', 'yellow'] ## parent.colorCtrl = wx.Choice(parent, id = wx.ID_ANY, choices = colorChoices) ## parent.colorCtrl.SetStringSelection(parent.rLegendDict['color']) ## parent.font['colorCtrl'] = wx.ColourPickerCtrl(parent, id = wx.ID_ANY) ## parent.font['colorCtrl'].SetColour(dialogDict['color']) def OnApply(self, event): ok = self.update() if ok: self.parent.DialogDataChanged(id = self.id) return True else: return False def OnOK(self, event): """!Apply changes, close dialog""" ok = self.OnApply(event) if ok: self.Close() def OnCancel(self, event): """!Close dialog""" self.Close() def OnClose(self, event): """!Destroy dialog and delete it from open dialogs""" if self.objectType: for each in self.objectType: if each in self.parent.openDialogs: del self.parent.openDialogs[each] event.Skip() self.Destroy() def _layout(self, panel): #buttons btnCancel = wx.Button(self, wx.ID_CANCEL) btnOK = wx.Button(self, wx.ID_OK) btnOK.SetDefault() if self.apply: btnApply = wx.Button(self, wx.ID_APPLY) # bindigs btnOK.Bind(wx.EVT_BUTTON, self.OnOK) btnOK.SetToolTipString(_("Close dialog and apply changes")) #btnCancel.Bind(wx.EVT_BUTTON, self.OnCancel) btnCancel.SetToolTipString(_("Close dialog and ignore changes")) btnCancel.Bind(wx.EVT_BUTTON, self.OnCancel) if self.apply: btnApply.Bind(wx.EVT_BUTTON, self.OnApply) btnApply.SetToolTipString(_("Apply changes")) # sizers btnSizer = wx.StdDialogButtonSizer() btnSizer.AddButton(btnCancel) if self.apply: btnSizer.AddButton(btnApply) btnSizer.AddButton(btnOK) btnSizer.Realize() mainSizer = wx.BoxSizer(wx.VERTICAL) mainSizer.Add(item = panel, proportion = 1, flag = wx.EXPAND | wx.ALL, border = 5) mainSizer.Add(item = btnSizer, proportion = 0, flag = wx.EXPAND | wx.ALL | wx.ALIGN_CENTER, border = 5) self.SetSizer(mainSizer) mainSizer.Layout() mainSizer.Fit(self) class PageSetupDialog(PsmapDialog): def __init__(self, parent, id, settings): PsmapDialog.__init__(self, parent = parent, id = id, title = "Page setup", settings = settings) self.cat = ['Units', 'Format', 'Orientation', 'Width', 'Height', 'Left', 'Right', 'Top', 'Bottom'] labels = [_('Units'), _('Format'), _('Orientation'), _('Width'), _('Height'), _('Left'), _('Right'), _('Top'), _('Bottom')] self.catsLabels = dict(zip(self.cat, labels)) paperString = RunCommand('ps.map', flags = 'p', read = True, quiet = True) self.paperTable = self._toList(paperString) self.unitsList = self.unitConv.getPageUnitsNames() self.pageSetupDict = settings[id].GetInstruction() self._layout() if self.pageSetupDict: self.getCtrl('Units').SetStringSelection(self.unitConv.findName(self.pageSetupDict['Units'])) if self.pageSetupDict['Format'] == 'custom': self.getCtrl('Format').SetSelection(self.getCtrl('Format').GetCount() - 1) else: self.getCtrl('Format').SetStringSelection(self.pageSetupDict['Format']) if self.pageSetupDict['Orientation'] == 'Portrait': self.getCtrl('Orientation').SetSelection(0) else: self.getCtrl('Orientation').SetSelection(1) for item in self.cat[3:]: val = self.unitConv.convert(value = self.pageSetupDict[item], fromUnit = 'inch', toUnit = self.pageSetupDict['Units']) self.getCtrl(item).SetValue("%4.3f" % val) if self.getCtrl('Format').GetSelection() != self.getCtrl('Format').GetCount() - 1: # custom self.getCtrl('Width').Disable() self.getCtrl('Height').Disable() else: self.getCtrl('Orientation').Disable() # events self.getCtrl('Units').Bind(wx.EVT_CHOICE, self.OnChoice) self.getCtrl('Format').Bind(wx.EVT_CHOICE, self.OnChoice) self.getCtrl('Orientation').Bind(wx.EVT_CHOICE, self.OnChoice) self.btnOk.Bind(wx.EVT_BUTTON, self.OnOK) def update(self): self.pageSetupDict['Units'] = self.unitConv.findUnit(self.getCtrl('Units').GetStringSelection()) self.pageSetupDict['Format'] = self.paperTable[self.getCtrl('Format').GetSelection()]['Format'] if self.getCtrl('Orientation').GetSelection() == 0: self.pageSetupDict['Orientation'] = 'Portrait' else: self.pageSetupDict['Orientation'] = 'Landscape' for item in self.cat[3:]: self.pageSetupDict[item] = self.unitConv.convert(value = float(self.getCtrl(item).GetValue()), fromUnit = self.pageSetupDict['Units'], toUnit = 'inch') def OnOK(self, event): try: self.update() except ValueError: wx.MessageBox(message = _("Literal is not allowed!"), caption = _('Invalid input'), style = wx.OK|wx.ICON_ERROR) else: event.Skip() def _layout(self): size = (110,-1) #sizers mainSizer = wx.BoxSizer(wx.VERTICAL) pageBox = wx.StaticBox(self, id = wx.ID_ANY, label = " %s " % _("Page size")) pageSizer = wx.StaticBoxSizer(pageBox, wx.VERTICAL) marginBox = wx.StaticBox(self, id = wx.ID_ANY, label = " %s " % _("Margins")) marginSizer = wx.StaticBoxSizer(marginBox, wx.VERTICAL) horSizer = wx.BoxSizer(wx.HORIZONTAL) #staticText + choice choices = [self.unitsList, [item['Format'] for item in self.paperTable], [_('Portrait'), _('Landscape')]] propor = [0,1,1] border = [5,3,3] self.hBoxDict={} for i, item in enumerate(self.cat[:3]): hBox = wx.BoxSizer(wx.HORIZONTAL) stText = wx.StaticText(self, id = wx.ID_ANY, label = self.catsLabels[item] + ':') choice = wx.Choice(self, id = wx.ID_ANY, choices = choices[i], size = size) hBox.Add(stText, proportion = propor[i], flag = wx.ALIGN_CENTER_VERTICAL|wx.ALL, border = border[i]) hBox.Add(choice, proportion = 0, flag = wx.ALL, border = border[i]) if item == 'Units': hBox.Add(size,1) self.hBoxDict[item] = hBox #staticText + TextCtrl for item in self.cat[3:]: hBox = wx.BoxSizer(wx.HORIZONTAL) label = wx.StaticText(self, id = wx.ID_ANY, label = self.catsLabels[item] + ':') textctrl = wx.TextCtrl(self, id = wx.ID_ANY, size = size, value = '') hBox.Add(label, proportion = 1, flag = wx.ALIGN_CENTER_VERTICAL|wx.ALL, border = 3) hBox.Add(textctrl, proportion = 0, flag = wx.ALIGN_CENTRE|wx.ALL, border = 3) self.hBoxDict[item] = hBox sizer = list([mainSizer] + [pageSizer]*4 + [marginSizer]*4) for i, item in enumerate(self.cat): sizer[i].Add(self.hBoxDict[item], 0, wx.GROW|wx.RIGHT|wx.LEFT,5) # OK button btnSizer = wx.StdDialogButtonSizer() self.btnOk = wx.Button(self, wx.ID_OK) self.btnOk.SetDefault() btnSizer.AddButton(self.btnOk) btn = wx.Button(self, wx.ID_CANCEL) btnSizer.AddButton(btn) btnSizer.Realize() horSizer.Add(pageSizer, proportion = 0, flag = wx.LEFT|wx.RIGHT|wx.BOTTOM, border = 10) horSizer.Add(marginSizer, proportion = 0, flag = wx.LEFT|wx.RIGHT|wx.BOTTOM|wx.EXPAND, border = 10) mainSizer.Add(horSizer, proportion = 0, border = 10) mainSizer.Add(btnSizer, proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_RIGHT|wx.ALL, border = 10) self.SetSizer(mainSizer) mainSizer.Fit(self) def OnChoice(self, event): currPaper = self.paperTable[self.getCtrl('Format').GetSelection()] currUnit = self.unitConv.findUnit(self.getCtrl('Units').GetStringSelection()) currOrientIdx = self.getCtrl('Orientation').GetSelection() newSize = dict() for item in self.cat[3:]: newSize[item] = self.unitConv.convert(float(currPaper[item]), fromUnit = 'inch', toUnit = currUnit) enable = True if currPaper['Format'] != _('custom'): if currOrientIdx == 1: # portrait newSize['Width'], newSize['Height'] = newSize['Height'], newSize['Width'] for item in self.cat[3:]: self.getCtrl(item).ChangeValue("%4.3f" % newSize[item]) enable = False self.getCtrl('Width').Enable(enable) self.getCtrl('Height').Enable(enable) self.getCtrl('Orientation').Enable(not enable) def getCtrl(self, item): return self.hBoxDict[item].GetItem(1).GetWindow() def _toList(self, paperStr): sizeList = list() for line in paperStr.strip().split('\n'): d = dict(zip([self.cat[1]]+ self.cat[3:],line.split())) sizeList.append(d) d = {}.fromkeys([self.cat[1]]+ self.cat[3:], 100) d.update(Format = _('custom')) sizeList.append(d) return sizeList class MapDialog(PsmapDialog): """!Dialog for map frame settings and optionally raster and vector map selection""" def __init__(self, parent, id, settings, rect = None, notebook = False): PsmapDialog.__init__(self, parent = parent, id = id, title = "", settings = settings) self.isNotebook = notebook if self.isNotebook: self.objectType = ('mapNotebook',) else: self.objectType = ('map',) #notebook if self.isNotebook: self.notebook = wx.Notebook(parent = self, id = wx.ID_ANY, style = wx.BK_DEFAULT) self.mPanel = MapFramePanel(parent = self.notebook, id = self.id[0], settings = self.instruction, rect = rect, notebook = True) self.id[0] = self.mPanel.getId() self.rPanel = RasterPanel(parent = self.notebook, id = self.id[1], settings = self.instruction, notebook = True) self.id[1] = self.rPanel.getId() self.vPanel = VectorPanel(parent = self.notebook, id = self.id[2], settings = self.instruction, notebook = True) self.id[2] = self.vPanel.getId() self._layout(self.notebook) self.SetTitle(_("Map settings")) else: self.mPanel = MapFramePanel(parent = self, id = self.id[0], settings = self.instruction, rect = rect, notebook = False) self.id[0] = self.mPanel.getId() self._layout(self.mPanel) self.SetTitle(_("Map frame settings")) def OnApply(self, event): """!Apply changes""" if self.isNotebook: okV = self.vPanel.update() okR = self.rPanel.update() if okV and self.id[2] in self.instruction: self.parent.DialogDataChanged(id = self.id[2]) if okR and self.id[1] in self.instruction: self.parent.DialogDataChanged(id = self.id[1]) if not okR or not okV: return False ok = self.mPanel.update() if ok: self.parent.DialogDataChanged(id = self.id[0]) return True return False def OnCancel(self, event): """!Close dialog and remove tmp red box""" self.parent.canvas.pdcTmp.RemoveId(self.parent.canvas.idZoomBoxTmp) self.parent.canvas.Refresh() self.Close() def updateDialog(self): """!Update raster and vector information""" if self.mPanel.scaleChoice.GetSelection() == 0: if self.mPanel.rasterTypeRadio.GetValue(): if 'raster' in self.parent.openDialogs: if self.parent.openDialogs['raster'].rPanel.rasterYesRadio.GetValue() and \ self.parent.openDialogs['raster'].rPanel.rasterSelect.GetValue() == self.mPanel.select.GetValue(): self.mPanel.drawMap.SetValue(True) else: self.mPanel.drawMap.SetValue(False) else: if 'vector' in self.parent.openDialogs: found = False for each in self.parent.openDialogs['vector'].vPanel.vectorList: if each[0] == self.mPanel.select.GetValue(): found = True self.mPanel.drawMap.SetValue(found) class MapFramePanel(wx.Panel): """!wx.Panel with map (scale, region, border) settings""" def __init__(self, parent, id, settings, rect, notebook = True): wx.Panel.__init__(self, parent, id = wx.ID_ANY, style = wx.TAB_TRAVERSAL) self.id = id self.instruction = settings if notebook: self.book = parent self.book.AddPage(page = self, text = _("Map frame")) self.mapDialog = self.book.GetParent() else: self.mapDialog = parent if self.id is not None: self.mapFrameDict = self.instruction[self.id].GetInstruction() else: self.id = wx.NewId() mapFrame = MapFrame(self.id) self.mapFrameDict = mapFrame.GetInstruction() self.mapFrameDict['rect'] = rect self._layout() self.scale = [None]*4 self.center = [None]*4 self.selectedMap = self.mapFrameDict['map'] self.selectedRegion = self.mapFrameDict['region'] self.scaleType = self.mapFrameDict['scaleType'] self.mapType = self.mapFrameDict['mapType'] self.scaleChoice.SetSelection(self.mapFrameDict['scaleType']) if self.instruction[self.id]: self.drawMap.SetValue(self.mapFrameDict['drawMap']) else: self.drawMap.SetValue(True) if self.mapFrameDict['scaleType'] == 0 and self.mapFrameDict['map']: self.select.SetValue(self.mapFrameDict['map']) if self.mapFrameDict['mapType'] == 'raster': self.rasterTypeRadio.SetValue(True) self.vectorTypeRadio.SetValue(False) else: self.rasterTypeRadio.SetValue(False) self.vectorTypeRadio.SetValue(True) elif self.mapFrameDict['scaleType'] == 1 and self.mapFrameDict['region']: self.select.SetValue(self.mapFrameDict['region']) self.OnMap(None) self.scale[self.mapFrameDict['scaleType']] = self.mapFrameDict['scale'] self.center[self.mapFrameDict['scaleType']] = self.mapFrameDict['center'] self.OnScaleChoice(None) self.OnElementType(None) self.OnBorder(None) def _layout(self): """!Do layout""" border = wx.BoxSizer(wx.VERTICAL) box = wx.StaticBox (parent = self, id = wx.ID_ANY, label = " %s " % _("Map frame")) sizer = wx.StaticBoxSizer(box, wx.HORIZONTAL) gridBagSizer = wx.GridBagSizer(hgap = 5, vgap = 5) #scale options frameText = wx.StaticText(self, id = wx.ID_ANY, label = _("Map frame options:")) scaleChoices = [_("fit frame to match selected map"), _("fit frame to match saved region"), _("fit frame to match current computational region"), _("fixed scale and map center")] self.scaleChoice = wx.Choice(self, id = wx.ID_ANY, choices = scaleChoices) gridBagSizer.Add(frameText, pos = (0, 0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) gridBagSizer.Add(self.scaleChoice, pos = (1, 0), flag = wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, border = 0) #map and region selection self.staticBox = wx.StaticBox (parent = self, id = wx.ID_ANY, label = " %s " % _("Map selection")) sizerM = wx.StaticBoxSizer(self.staticBox, wx.HORIZONTAL) self.mapSizer = wx.GridBagSizer(hgap = 5, vgap = 5) self.rasterTypeRadio = wx.RadioButton(self, id = wx.ID_ANY, label = " %s " % _("raster"), style = wx.RB_GROUP) self.vectorTypeRadio = wx.RadioButton(self, id = wx.ID_ANY, label = " %s " % _("vector")) self.drawMap = wx.CheckBox(self, id = wx.ID_ANY, label = "add selected map") self.mapOrRegionText = [_("Map:"), _("Region:")] dc = wx.PaintDC(self)# determine size of labels width = max(dc.GetTextExtent(self.mapOrRegionText[0])[0], dc.GetTextExtent(self.mapOrRegionText[1])[0]) self.mapText = wx.StaticText(self, id = wx.ID_ANY, label = self.mapOrRegionText[0], size = (width, -1)) self.select = Select(self, id = wx.ID_ANY, size = globalvar.DIALOG_GSELECT_SIZE, type = 'raster', multiple = False, updateOnPopup = True, onPopup = None) self.mapSizer.Add(self.rasterTypeRadio, pos = (0, 1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) self.mapSizer.Add(self.vectorTypeRadio, pos = (0, 2), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) self.mapSizer.Add(self.drawMap, pos = (0, 3), flag = wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_RIGHT, border = 0) self.mapSizer.Add(self.mapText, pos = (1, 0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) self.mapSizer.Add(self.select, pos = (1, 1), span = (1, 3), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) sizerM.Add(self.mapSizer, proportion = 1, flag = wx.EXPAND|wx.ALL, border = 5) gridBagSizer.Add(sizerM, pos = (2, 0), flag = wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, border = 0) #map scale and center boxC = wx.StaticBox (parent = self, id = wx.ID_ANY, label = " %s " % _("Map scale and center")) sizerC = wx.StaticBoxSizer(boxC, wx.HORIZONTAL) self.centerSizer = wx.FlexGridSizer(rows = 2, cols = 5, hgap = 5, vgap = 5) centerText = wx.StaticText(self, id = wx.ID_ANY, label = _("Center:")) self.eastingText = wx.StaticText(self, id = wx.ID_ANY, label = _("E:")) self.northingText = wx.StaticText(self, id = wx.ID_ANY, label = _("N:")) self.eastingTextCtrl = wx.TextCtrl(self, id = wx.ID_ANY, style = wx.TE_RIGHT, validator = TCValidator(flag = 'DIGIT_ONLY')) self.northingTextCtrl = wx.TextCtrl(self, id = wx.ID_ANY, style = wx.TE_RIGHT, validator = TCValidator(flag = 'DIGIT_ONLY')) scaleText = wx.StaticText(self, id = wx.ID_ANY, label = _("Scale:")) scalePrefixText = wx.StaticText(self, id = wx.ID_ANY, label = _("1 :")) self.scaleTextCtrl = wx.TextCtrl(self, id = wx.ID_ANY, value = "", style = wx.TE_RIGHT, validator = TCValidator('DIGIT_ONLY')) self.centerSizer.Add(centerText, proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL|wx.RIGHT, border = 10) self.centerSizer.Add(self.eastingText, proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_RIGHT, border = 0) self.centerSizer.Add(self.eastingTextCtrl, proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL, border = 0) self.centerSizer.Add(self.northingText, proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_RIGHT, border = 0) self.centerSizer.Add(self.northingTextCtrl, proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL, border = 0) self.centerSizer.Add(scaleText, proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL|wx.RIGHT, border = 10) self.centerSizer.Add(scalePrefixText, proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_RIGHT, border = 0) self.centerSizer.Add(self.scaleTextCtrl, proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL, border = 0) sizerC.Add(self.centerSizer, proportion = 1, flag = wx.EXPAND|wx.ALL, border = 5) gridBagSizer.Add(sizerC, pos = (3, 0), flag = wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, border = 0) #resolution flexSizer = wx.FlexGridSizer(rows = 1, cols = 2, hgap = 5, vgap = 5) resolutionText = wx.StaticText(self, id = wx.ID_ANY, label = _("Map max resolution (dpi):")) self.resolutionSpin = wx.SpinCtrl(self, id = wx.ID_ANY, min = 1, max = 1000, initial = 300) flexSizer.Add(resolutionText, proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL, border = 0) flexSizer.Add(self.resolutionSpin, proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL, border = 0) self.resolutionSpin.SetValue(self.mapFrameDict['resolution']) gridBagSizer.Add(flexSizer, pos = (4, 0), flag = wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, border = 0) sizer.Add(gridBagSizer, proportion = 1, flag = wx.EXPAND|wx.ALL, border = 5) border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5) # border box = wx.StaticBox (parent = self, id = wx.ID_ANY, label = " %s " % _("Border")) sizer = wx.StaticBoxSizer(box, wx.HORIZONTAL) gridBagSizer = wx.GridBagSizer(hgap = 5, vgap = 5) self.borderCheck = wx.CheckBox(self, id = wx.ID_ANY, label = (_("draw border around map frame"))) if self.mapFrameDict['border'] == 'y': self.borderCheck.SetValue(True) else: self.borderCheck.SetValue(False) self.borderColorText = wx.StaticText(self, id = wx.ID_ANY, label = _("border color:")) self.borderWidthText = wx.StaticText(self, id = wx.ID_ANY, label = _("border width (pts):")) self.borderColourPicker = wx.ColourPickerCtrl(self, id = wx.ID_ANY) self.borderWidthCtrl = wx.SpinCtrl(self, id = wx.ID_ANY, min = 1, max = 100, initial = 1) if self.mapFrameDict['border'] == 'y': self.borderWidthCtrl.SetValue(int(self.mapFrameDict['width'])) self.borderColourPicker.SetColour(convertRGB(self.mapFrameDict['color'])) gridBagSizer.Add(self.borderCheck, pos = (0, 0), span = (1,2), flag = wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, border = 0) gridBagSizer.Add(self.borderColorText, pos = (1, 1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) gridBagSizer.Add(self.borderWidthText, pos = (2, 1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) gridBagSizer.Add(self.borderColourPicker, pos = (1, 2), flag = wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, border = 0) gridBagSizer.Add(self.borderWidthCtrl, pos = (2, 2), flag = wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, border = 0) sizer.Add(gridBagSizer, proportion = 1, flag = wx.EXPAND|wx.ALL, border = 5) border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5) self.SetSizer(border) self.Fit() if projInfo()['proj'] == 'll': self.scaleChoice.SetItems(self.scaleChoice.GetItems()[0:3]) boxC.Hide() for each in self.centerSizer.GetChildren(): each.GetWindow().Hide() # bindings self.scaleChoice.Bind(wx.EVT_CHOICE, self.OnScaleChoice) self.select.GetTextCtrl().Bind(wx.EVT_TEXT, self.OnMap) self.Bind(wx.EVT_RADIOBUTTON, self.OnElementType, self.vectorTypeRadio) self.Bind(wx.EVT_RADIOBUTTON, self.OnElementType, self.rasterTypeRadio) self.Bind(wx.EVT_CHECKBOX, self.OnBorder, self.borderCheck) def OnMap(self, event): """!Selected map or region changing""" if self.select.GetValue(): self.selected = self.select.GetValue() else: self.selected = None if self.scaleChoice.GetSelection() == 0: self.selectedMap = self.selected if self.rasterTypeRadio.GetValue(): mapType = 'raster' else: mapType = 'vector' self.scale[0], self.center[0], foo = AutoAdjust(self, scaleType = 0, map = self.selected, mapType = mapType, rect = self.mapFrameDict['rect']) #self.center[0] = self.RegionCenter(self.RegionDict(scaleType = 0)) elif self.scaleChoice.GetSelection() == 1: self.selectedRegion = self.selected self.scale[1], self.center[1], foo = AutoAdjust(self, scaleType = 1, region = self.selected, rect = self.mapFrameDict['rect']) #self.center[1] = self.RegionCenter(self.RegionDict(scaleType = 1)) elif self.scaleChoice.GetSelection() == 2: self.scale[2], self.center[2], foo = AutoAdjust(self, scaleType = 2, rect = self.mapFrameDict['rect']) #self.center[2] = self.RegionCenter(self.RegionDict(scaleType = 2)) else: self.scale[3] = None self.center[3] = None self.OnScaleChoice(None) def OnScaleChoice(self, event): """!Selected scale type changing""" scaleType = self.scaleChoice.GetSelection() if self.scaleType != scaleType: self.scaleType = scaleType self.select.SetValue("") if scaleType in (0, 1): # automatic - region from raster map, saved region if scaleType == 0: # set map selection self.rasterTypeRadio.Show() self.vectorTypeRadio.Show() self.drawMap.Show() self.staticBox.SetLabel(" %s " % _("Map selection")) if self.rasterTypeRadio.GetValue(): stype = 'raster' else: stype = 'vector' self.select.SetElementList(type = stype) self.mapText.SetLabel(self.mapOrRegionText[0]) self.select.SetToolTipString(_("Region is set to match this map,\nraster or vector map must be added later")) if scaleType == 1: # set region selection self.rasterTypeRadio.Hide() self.vectorTypeRadio.Hide() self.drawMap.Hide() self.staticBox.SetLabel(" %s " % _("Region selection")) stype = 'region' self.select.SetElementList(type = stype) self.mapText.SetLabel(self.mapOrRegionText[1]) self.select.SetToolTipString("") for each in self.mapSizer.GetChildren(): each.GetWindow().Enable() for each in self.centerSizer.GetChildren(): each.GetWindow().Disable() if self.scale[scaleType]: self.scaleTextCtrl.SetValue("%.0f" % (1/self.scale[scaleType])) if self.center[scaleType]: self.eastingTextCtrl.SetValue(str(self.center[scaleType][0])) self.northingTextCtrl.SetValue(str(self.center[scaleType][1])) elif scaleType == 2: for each in self.mapSizer.GetChildren(): each.GetWindow().Disable() for each in self.centerSizer.GetChildren(): each.GetWindow().Disable() if self.scale[scaleType]: self.scaleTextCtrl.SetValue("%.0f" % (1/self.scale[scaleType])) if self.center[scaleType]: self.eastingTextCtrl.SetValue(str(self.center[scaleType][0])) self.northingTextCtrl.SetValue(str(self.center[scaleType][1])) else: # fixed for each in self.mapSizer.GetChildren(): each.GetWindow().Disable() for each in self.centerSizer.GetChildren(): each.GetWindow().Enable() if self.scale[scaleType]: self.scaleTextCtrl.SetValue("%.0f" % (1/self.scale[scaleType])) if self.center[scaleType]: self.eastingTextCtrl.SetValue(str(self.center[scaleType][0])) self.northingTextCtrl.SetValue(str(self.center[scaleType][1])) def OnElementType(self, event): """!Changes data in map selection tree ctrl popup""" if self.rasterTypeRadio.GetValue(): mapType = 'raster' else: mapType = 'vector' self.select.SetElementList(type = mapType) if self.mapType != mapType and event is not None: self.mapType = mapType self.select.SetValue('') self.mapType = mapType def OnBorder(self, event): """!Enables/disable the part relating to border of map frame""" for each in (self.borderColorText, self.borderWidthText, self.borderColourPicker, self.borderWidthCtrl): each.Enable(self.borderCheck.GetValue()) def getId(self): """!Returns id of raster map""" return self.id def update(self): """!Save changes""" mapFrameDict = dict(self.mapFrameDict) # resolution mapFrameDict['resolution'] = self.resolutionSpin.GetValue() #scale scaleType = self.scaleType mapFrameDict['scaleType'] = scaleType if mapFrameDict['scaleType'] == 0: if self.select.GetValue(): mapFrameDict['drawMap'] = self.drawMap.GetValue() mapFrameDict['map'] = self.select.GetValue() mapFrameDict['mapType'] = self.mapType mapFrameDict['region'] = None if mapFrameDict['drawMap']: if mapFrameDict['mapType'] == 'raster': mapFile = grass.find_file(mapFrameDict['map'], element = 'cell') if mapFile['file'] == '': GMessage("Raster %s not found" % mapFrameDict['map']) return False raster = self.instruction.FindInstructionByType('raster') if raster: raster['raster'] = mapFrameDict['map'] else: raster = Raster(wx.NewId()) raster['raster'] = mapFrameDict['map'] raster['isRaster'] = True self.instruction.AddInstruction(raster) elif mapFrameDict['mapType'] == 'vector': mapFile = grass.find_file(mapFrameDict['map'], element = 'vector') if mapFile['file'] == '': GMessage("Vector %s not found" % mapFrameDict['map']) return False vector = self.instruction.FindInstructionByType('vector') isAdded = False if vector: for each in vector['list']: if each[0] == mapFrameDict['map']: isAdded = True if not isAdded: topoInfo = grass.vector_info_topo(map = mapFrameDict['map']) if topoInfo: if bool(topoInfo['areas']): topoType = 'areas' elif bool(topoInfo['lines']): topoType = 'lines' else: topoType = 'points' label = '('.join(mapFrameDict['map'].split('@')) + ')' if not vector: vector = Vector(wx.NewId()) vector['list'] = [] self.instruction.AddInstruction(vector) id = wx.NewId() vector['list'].insert(0, [mapFrameDict['map'], topoType, id, 1, label]) vProp = VProperties(id, topoType) vProp['name'], vProp['label'], vProp['lpos'] = mapFrameDict['map'], label, 1 self.instruction.AddInstruction(vProp) else: return False self.scale[0], self.center[0], self.rectAdjusted = AutoAdjust(self, scaleType = 0, map = mapFrameDict['map'], mapType = self.mapType, rect = self.mapFrameDict['rect']) if self.rectAdjusted: mapFrameDict['rect'] = self.rectAdjusted else: mapFrameDict['rect'] = self.mapFrameDict['rect'] mapFrameDict['scale'] = self.scale[0] mapFrameDict['center'] = self.center[0] # set region if self.mapType == 'raster': RunCommand('g.region', rast = mapFrameDict['map']) if self.mapType == 'vector': raster = self.instruction.FindInstructionByType('raster') if raster: rasterId = raster.id else: rasterId = None if rasterId: RunCommand('g.region', vect = mapFrameDict['map'], rast = self.instruction[rasterId]['raster']) else: RunCommand('g.region', vect = mapFrameDict['map']) else: wx.MessageBox(message = _("No map selected!"), caption = _('Invalid input'), style = wx.OK|wx.ICON_ERROR) return False elif mapFrameDict['scaleType'] == 1: if self.select.GetValue(): mapFrameDict['drawMap'] = False mapFrameDict['map'] = None mapFrameDict['mapType'] = None mapFrameDict['region'] = self.select.GetValue() self.scale[1], self.center[1], self.rectAdjusted = AutoAdjust(self, scaleType = 1, region = mapFrameDict['region'], rect = self.mapFrameDict['rect']) if self.rectAdjusted: mapFrameDict['rect'] = self.rectAdjusted else: mapFrameDict['rect'] = self.mapFrameDict['rect'] mapFrameDict['scale'] = self.scale[1] mapFrameDict['center'] = self.center[1] # set region RunCommand('g.region', region = mapFrameDict['region']) else: wx.MessageBox(message = _("No region selected!"), caption = _('Invalid input'), style = wx.OK|wx.ICON_ERROR) return False elif scaleType == 2: mapFrameDict['drawMap'] = False mapFrameDict['map'] = None mapFrameDict['mapType'] = None mapFrameDict['region'] = None self.scale[2], self.center[2], self.rectAdjusted = AutoAdjust(self, scaleType = 2, rect = self.mapFrameDict['rect']) if self.rectAdjusted: mapFrameDict['rect'] = self.rectAdjusted else: mapFrameDict['rect'] = self.mapFrameDict['rect'] mapFrameDict['scale'] = self.scale[2] mapFrameDict['center'] = self.center[2] env = grass.gisenv() windFilePath = os.path.join(env['GISDBASE'], env['LOCATION_NAME'], env['MAPSET'], 'WIND') try: windFile = open(windFilePath, 'r').read() region = grass.parse_key_val(windFile, sep = ':', val_type = float) except IOError: region = grass.region() raster = self.instruction.FindInstructionByType('raster') if raster: rasterId = raster.id else: rasterId = None if rasterId: # because of resolution RunCommand('g.region', n = region['north'], s = region['south'], e = region['east'], w = region['west'], rast = self.instruction[rasterId]['raster']) else: RunCommand('g.region', n = region['north'], s = region['south'], e = region['east'], w = region['west']) elif scaleType == 3: mapFrameDict['drawMap'] = False mapFrameDict['map'] = None mapFrameDict['mapType'] = None mapFrameDict['region'] = None mapFrameDict['rect'] = self.mapFrameDict['rect'] try: scaleNumber = float(self.scaleTextCtrl.GetValue()) centerE = float(self.eastingTextCtrl.GetValue()) centerN = float(self.northingTextCtrl.GetValue()) except (ValueError, SyntaxError): wx.MessageBox(message = _("Invalid scale or map center!"), caption = _('Invalid input'), style = wx.OK|wx.ICON_ERROR) return False mapFrameDict['scale'] = 1/scaleNumber mapFrameDict['center'] = centerE, centerN ComputeSetRegion(self, mapDict = mapFrameDict) # check resolution SetResolution(dpi = mapFrameDict['resolution'], width = mapFrameDict['rect'].width, height = mapFrameDict['rect'].height) # border if self.borderCheck.GetValue(): mapFrameDict['border'] = 'y' else: mapFrameDict['border'] = 'n' if mapFrameDict['border'] == 'y': mapFrameDict['width'] = self.borderWidthCtrl.GetValue() mapFrameDict['color'] = convertRGB(self.borderColourPicker.GetColour()) if self.id not in self.instruction: mapFrame = MapFrame(self.id) self.instruction.AddInstruction(mapFrame) self.instruction[self.id].SetInstruction(mapFrameDict) if self.id not in self.mapDialog.parent.objectId: self.mapDialog.parent.objectId.insert(0, self.id)# map frame is drawn first return True class RasterPanel(wx.Panel): """!Panel for raster map settings""" def __init__(self, parent, id, settings, notebook = True): wx.Panel.__init__(self, parent, id = wx.ID_ANY, style = wx.TAB_TRAVERSAL) self.instruction = settings if notebook: self.book = parent self.book.AddPage(page = self, text = _("Raster map")) self.mainDialog = self.book.GetParent() else: self.mainDialog = parent if id: self.id = id self.rasterDict = self.instruction[self.id].GetInstruction() else: self.id = wx.NewId() raster = Raster(self.id) self.rasterDict = raster.GetInstruction() self._layout() self.OnRaster(None) def _layout(self): """!Do layout""" border = wx.BoxSizer(wx.VERTICAL) # choose raster map box = wx.StaticBox (parent = self, id = wx.ID_ANY, label = " %s " % _("Choose raster map")) sizer = wx.StaticBoxSizer(box, wx.VERTICAL) gridBagSizer = wx.GridBagSizer (hgap = 5, vgap = 5) self.rasterNoRadio = wx.RadioButton(self, id = wx.ID_ANY, label = _("no raster map"), style = wx.RB_GROUP) self.rasterYesRadio = wx.RadioButton(self, id = wx.ID_ANY, label = _("raster:")) self.rasterSelect = Select(self, id = wx.ID_ANY, size = globalvar.DIALOG_GSELECT_SIZE, type = 'raster', multiple = False, updateOnPopup = True, onPopup = None) if self.rasterDict['isRaster']: self.rasterYesRadio.SetValue(True) self.rasterNoRadio.SetValue(False) self.rasterSelect.SetValue(self.rasterDict['raster']) else: self.rasterYesRadio.SetValue(False) self.rasterNoRadio.SetValue(True) mapId = self.instruction.FindInstructionByType('map').id if self.instruction[mapId]['map'] and self.instruction[mapId]['mapType'] == 'raster': self.rasterSelect.SetValue(self.instruction[mapId]['map'])# raster map from map frame dialog if possible else: self.rasterSelect.SetValue('') gridBagSizer.Add(self.rasterNoRadio, pos = (0, 0), span = (1, 2), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) gridBagSizer.Add(self.rasterYesRadio, pos = (1, 0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) gridBagSizer.Add(self.rasterSelect, pos = (1, 1), flag = wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, border = 0) sizer.Add(gridBagSizer, proportion = 1, flag = wx.EXPAND|wx.ALL, border = 5) border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5) #self.rasterSelect.GetTextCtrl().Bind(wx.EVT_TEXT, self.OnRaster) self.Bind(wx.EVT_RADIOBUTTON, self.OnRaster, self.rasterNoRadio) self.Bind(wx.EVT_RADIOBUTTON, self.OnRaster, self.rasterYesRadio) self.SetSizer(border) self.Fit() def OnRaster(self, event): """!Enable/disable raster selection""" self.rasterSelect.Enable(self.rasterYesRadio.GetValue()) def update(self): #draw raster mapInstr = self.instruction.FindInstructionByType('map') if not mapInstr: # no map frame GMessage(message = _("Please, create map frame first.")) return if self.rasterNoRadio.GetValue() or not self.rasterSelect.GetValue(): self.rasterDict['isRaster'] = False self.rasterDict['raster'] = None mapInstr['drawMap'] = False if self.id in self.instruction: del self.instruction[self.id] else: self.rasterDict['isRaster'] = True self.rasterDict['raster'] = self.rasterSelect.GetValue() if self.rasterDict['raster'] != mapInstr['drawMap']: mapInstr['drawMap'] = False raster = self.instruction.FindInstructionByType('raster') if not raster: raster = Raster(self.id) self.instruction.AddInstruction(raster) self.instruction[self.id].SetInstruction(self.rasterDict) else: self.instruction[raster.id].SetInstruction(self.rasterDict) if 'map' in self.mainDialog.parent.openDialogs: self.mainDialog.parent.openDialogs['map'].updateDialog() return True def getId(self): return self.id class VectorPanel(wx.Panel): """!Panel for vector maps settings""" def __init__(self, parent, id, settings, notebook = True): wx.Panel.__init__(self, parent, id = wx.ID_ANY, style = wx.TAB_TRAVERSAL) self.parent = parent self.instruction = settings self.tmpDialogDict = {} vectors = self.instruction.FindInstructionByType('vProperties', list = True) for vector in vectors: self.tmpDialogDict[vector.id] = dict(self.instruction[vector.id].GetInstruction()) if id: self.id = id self.vectorList = deepcopy(self.instruction[id]['list']) else: self.id = wx.NewId() self.vectorList = [] vLegend = self.instruction.FindInstructionByType('vectorLegend') if vLegend: self.vLegendId = vLegend.id else: self.vLegendId = None self._layout() if notebook: self.parent.AddPage(page = self, text = _("Vector maps")) self.parent = self.parent.GetParent() def _layout(self): """!Do layout""" border = wx.BoxSizer(wx.VERTICAL) # choose vector map box = wx.StaticBox (parent = self, id = wx.ID_ANY, label = " %s " % _("Add map")) sizer = wx.StaticBoxSizer(box, wx.VERTICAL) gridBagSizer = wx.GridBagSizer (hgap = 5, vgap = 5) text = wx.StaticText(self, id = wx.ID_ANY, label = _("Map:")) self.select = Select(self, id = wx.ID_ANY,# size = globalvar.DIALOG_GSELECT_SIZE, type = 'vector', multiple = False, updateOnPopup = True, onPopup = None) topologyType = [_("points"), _("lines"), _("areas")] self.vectorType = wx.RadioBox(self, id = wx.ID_ANY, label = " %s " % _("Data Type"), choices = topologyType, majorDimension = 3, style = wx.RA_SPECIFY_COLS) self.AddVector = wx.Button(self, id = wx.ID_ANY, label = _("Add")) gridBagSizer.Add(text, pos = (0,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) gridBagSizer.Add(self.select, pos = (0,1), span = (1, 2), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) gridBagSizer.Add(self.vectorType, pos = (1,1), flag = wx.ALIGN_CENTER, border = 0) gridBagSizer.Add(self.AddVector, pos = (1,2), flag = wx.ALIGN_BOTTOM|wx.ALIGN_RIGHT, border = 0) sizer.Add(gridBagSizer, proportion = 1, flag = wx.EXPAND|wx.ALL, border = 5) border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5) # manage vector layers box = wx.StaticBox (parent = self, id = wx.ID_ANY, label = " %s " % _("Manage vector maps")) sizer = wx.StaticBoxSizer(box, wx.VERTICAL) gridBagSizer = wx.GridBagSizer (hgap = 5, vgap = 5) gridBagSizer.AddGrowableCol(0,2) gridBagSizer.AddGrowableCol(1,1) text = wx.StaticText(self, id = wx.ID_ANY, label = _("The topmost vector map overlaps the others")) self.listbox = wx.ListBox(self, id = wx.ID_ANY, choices = [], style = wx.LB_SINGLE|wx.LB_NEEDED_SB) self.btnUp = wx.Button(self, id = wx.ID_ANY, label = _("Up")) self.btnDown = wx.Button(self, id = wx.ID_ANY, label = _("Down")) self.btnDel = wx.Button(self, id = wx.ID_ANY, label = _("Delete")) self.btnProp = wx.Button(self, id = wx.ID_ANY, label = _("Properties...")) self.updateListBox(selected=0) gridBagSizer.Add(text, pos = (0,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) gridBagSizer.Add(self.listbox, pos = (1,0), span = (4, 1), flag = wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, border = 0) gridBagSizer.Add(self.btnUp, pos = (1,1), flag = wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, border = 0) gridBagSizer.Add(self.btnDown, pos = (2,1), flag = wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, border = 0) gridBagSizer.Add(self.btnDel, pos = (3,1), flag = wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, border = 0) gridBagSizer.Add(self.btnProp, pos = (4,1), flag = wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, border = 0) sizer.Add(gridBagSizer, proportion = 0, flag = wx.ALL, border = 5) border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5) self.Bind(wx.EVT_BUTTON, self.OnAddVector, self.AddVector) self.Bind(wx.EVT_BUTTON, self.OnDelete, self.btnDel) self.Bind(wx.EVT_BUTTON, self.OnUp, self.btnUp) self.Bind(wx.EVT_BUTTON, self.OnDown, self.btnDown) self.Bind(wx.EVT_BUTTON, self.OnProperties, self.btnProp) self.select.GetTextCtrl().Bind(wx.EVT_TEXT, self.OnVector) self.SetSizer(border) self.Fit() self.Bind(wx.EVT_LISTBOX_DCLICK, self.OnProperties, self.listbox) def OnVector(self, event): """!Gets info about toplogy and enables/disables choices point/line/area""" vmap = self.select.GetValue() try: topoInfo = grass.vector_info_topo(map = vmap) except grass.ScriptError: return if topoInfo: self.vectorType.EnableItem(2, bool(topoInfo['areas'])) self.vectorType.EnableItem(1, bool(topoInfo['boundaries']) or bool(topoInfo['lines'])) self.vectorType.EnableItem(0, bool(topoInfo['centroids'] or bool(topoInfo['points']) )) for item in range(2,-1,-1): if self.vectorType.IsItemEnabled(item): self.vectorType.SetSelection(item) break self.AddVector.SetFocus() def OnAddVector(self, event): """!Adds vector map to list""" vmap = self.select.GetValue() if vmap: mapname = vmap.split('@')[0] try: mapset = '(' + vmap.split('@')[1] + ')' except IndexError: mapset = '' type = self.vectorType.GetStringSelection() record = "%s - %s" % (vmap,type) id = wx.NewId() lpos = 1 label = mapname + mapset self.vectorList.insert(0, [vmap, type, id, lpos, label]) self.reposition() self.listbox.InsertItems([record], 0) vector = VProperties(id, type) self.tmpDialogDict[id] = vector.GetInstruction() self.tmpDialogDict[id]['name'] = vmap self.listbox.SetSelection(0) self.listbox.EnsureVisible(0) self.btnProp.SetFocus() self.enableButtons() def OnDelete(self, event): """!Deletes vector map from the list""" if self.listbox.GetSelections(): pos = self.listbox.GetSelection() id = self.vectorList[pos][2] del self.vectorList[pos] del self.tmpDialogDict[id] for i in range(pos, len(self.vectorList)): if self.vectorList[i][3]:# can be 0 self.vectorList[i][3] -= 1 if pos < len(self.vectorList) -1: selected = pos else: selected = len(self.vectorList) -1 self.updateListBox(selected = selected) if self.listbox.IsEmpty(): self.enableButtons(False) def OnUp(self, event): """!Moves selected map to top""" if self.listbox.GetSelections(): pos = self.listbox.GetSelection() if pos: self.vectorList.insert(pos - 1, self.vectorList.pop(pos)) if not self.vLegendId: self.reposition() if pos > 0: self.updateListBox(selected = (pos - 1)) else: self.updateListBox(selected = 0) def OnDown(self, event): """!Moves selected map to bottom""" if self.listbox.GetSelections(): pos = self.listbox.GetSelection() if pos != len(self.vectorList) - 1: self.vectorList.insert(pos + 1, self.vectorList.pop(pos)) if not self.vLegendId: self.reposition() if pos < len(self.vectorList) -1: self.updateListBox(selected = (pos + 1)) else: self.updateListBox(selected = len(self.vectorList) -1) def OnProperties(self, event): """!Opens vector map properties dialog""" if self.listbox.GetSelections(): pos = self.listbox.GetSelection() id = self.vectorList[pos][2] dlg = VPropertiesDialog(self, id = id, settings = self.instruction, vectors = self.vectorList, tmpSettings = self.tmpDialogDict[id]) dlg.ShowModal() self.parent.FindWindowById(wx.ID_OK).SetFocus() def enableButtons(self, enable = True): """!Enable/disable up, down, properties, delete buttons""" self.btnUp.Enable(enable) self.btnDown.Enable(enable) self.btnProp.Enable(enable) self.btnDel.Enable(enable) def updateListBox(self, selected = None): mapList = ["%s - %s" % (item[0], item[1]) for item in self.vectorList] self.listbox.Set(mapList) if self.listbox.IsEmpty(): self.enableButtons(False) else: self.enableButtons(True) if selected is not None: self.listbox.SetSelection(selected) self.listbox.EnsureVisible(selected) def reposition(self): """!Update position in legend, used only if there is no vlegend yet""" for i in range(len(self.vectorList)): if self.vectorList[i][3]: self.vectorList[i][3] = i + 1 def getId(self): return self.id def update(self): vectors = self.instruction.FindInstructionByType('vProperties', list = True) for vector in vectors: del self.instruction[vector.id] if self.id in self.instruction: del self.instruction[self.id] if len(self.vectorList) > 0: vector = Vector(self.id) self.instruction.AddInstruction(vector) vector.SetInstruction({'list': deepcopy(self.vectorList)}) # save new vectors for item in self.vectorList: id = item[2] vLayer = VProperties(id, item[1]) self.instruction.AddInstruction(vLayer) vLayer.SetInstruction(self.tmpDialogDict[id]) vLayer['name'] = item[0] vLayer['label'] = item[4] vLayer['lpos'] = item[3] else: if self.id in self.instruction: del self.instruction[self.id] if 'map' in self.parent.parent.openDialogs: self.parent.parent.openDialogs['map'].updateDialog() return True class RasterDialog(PsmapDialog): def __init__(self, parent, id, settings): PsmapDialog.__init__(self, parent = parent, id = id, title = _("Raster map settings"), settings = settings) self.objectType = ('raster',) self.rPanel = RasterPanel(parent = self, id = self.id, settings = self.instruction, notebook = False) self.id = self.rPanel.getId() self._layout(self.rPanel) def update(self): ok = self.rPanel.update() if ok: return True return False def OnApply(self, event): ok = self.update() if not ok: return False if self.id in self.instruction: self.parent.DialogDataChanged(id = self.id) else: mapId = self.instruction.FindInstructionByType('map').id self.parent.DialogDataChanged(id = mapId) return True def updateDialog(self): """!Update information (not used)""" pass ## if 'map' in self.parent.openDialogs: ## if self.parent.openDialogs['map'].mPanel.rasterTypeRadio.GetValue()\ ## and self.parent.openDialogs['map'].mPanel.select.GetValue(): ## if self.parent.openDialogs['map'].mPanel.drawMap.IsChecked(): ## self.rPanel.rasterSelect.SetValue(self.parent.openDialogs['map'].mPanel.select.GetValue()) class MainVectorDialog(PsmapDialog): def __init__(self, parent, id, settings): PsmapDialog.__init__(self, parent = parent, id = id, title = _("Vector maps settings"), settings = settings) self.objectType = ('vector',) self.vPanel = VectorPanel(parent = self, id = self.id, settings = self.instruction, notebook = False) self.id = self.vPanel.getId() self._layout(self.vPanel) def update(self): self.vPanel.update() def OnApply(self, event): self.update() if self.id in self.instruction: self.parent.DialogDataChanged(id = self.id) else: mapId = self.instruction.FindInstructionByType('map').id self.parent.DialogDataChanged(id = mapId) return True def updateDialog(self): """!Update information (not used)""" pass class VPropertiesDialog(PsmapDialog): def __init__(self, parent, id, settings, vectors, tmpSettings): PsmapDialog.__init__(self, parent = parent, id = id, title = "", settings = settings, apply = False) vectorList = vectors self.vPropertiesDict = tmpSettings # determine map and its type for item in vectorList: if id == item[2]: self.vectorName = item[0] self.type = item[1] self.SetTitle(self.vectorName + " "+ _("properties")) #vector map info self.connection = True try: self.mapDBInfo = dbm_base.VectorDBInfo(self.vectorName) self.layers = self.mapDBInfo.layers.keys() except grass.ScriptError: self.connection = False self.layers = [] if not self.layers: self.connection = False self.layers = [] self.currLayer = self.vPropertiesDict['layer'] #path to symbols, patterns gisbase = os.getenv("GISBASE") self.symbolPath = os.path.join(gisbase, 'etc', 'symbol') self.symbols = [] for dir in os.listdir(self.symbolPath): for symbol in os.listdir(os.path.join(self.symbolPath, dir)): self.symbols.append(os.path.join(dir, symbol)) self.patternPath = os.path.join(gisbase, 'etc', 'paint', 'patterns') #notebook notebook = wx.Notebook(parent = self, id = wx.ID_ANY, style = wx.BK_DEFAULT) self.DSpanel = self._DataSelectionPanel(notebook) self.EnableLayerSelection(enable = self.connection) selectPanel = { 'points': [self._ColorsPointAreaPanel, self._StylePointPanel], 'lines': [self._ColorsLinePanel, self._StyleLinePanel], 'areas': [self._ColorsPointAreaPanel, self._StyleAreaPanel]} self.ColorsPanel = selectPanel[self.type][0](notebook) self.OnOutline(None) if self.type in ('points', 'areas'): self.OnFill(None) self.OnColor(None) self.StylePanel = selectPanel[self.type][1](notebook) if self.type == 'points': self.OnSize(None) self.OnRotation(None) if self.type == 'areas': self.OnPattern(None) self._layout(notebook) def _DataSelectionPanel(self, notebook): panel = wx.Panel(parent = notebook, id = wx.ID_ANY, size = (-1, -1), style = wx.TAB_TRAVERSAL) notebook.AddPage(page = panel, text = _("Data selection")) border = wx.BoxSizer(wx.VERTICAL) # data type self.checkType1 = self.checkType2 = None if self.type in ('lines', 'points'): box = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Feature type")) sizer = wx.StaticBoxSizer(box, wx.HORIZONTAL) gridBagSizer = wx.GridBagSizer(hgap = 5, vgap = 5) if self.type == 'points': label = (_("points"), _("centroids")) else: label = (_("lines"), _("boundaries")) if self.type == 'points': name = ("point", "centroid") else: name = ("line", "boundary") self.checkType1 = wx.CheckBox(panel, id = wx.ID_ANY, label = label[0], name = name[0]) self.checkType2 = wx.CheckBox(panel, id = wx.ID_ANY, label = label[1], name = name[1]) self.checkType1.SetValue(self.vPropertiesDict['type'].find(name[0]) >= 0) self.checkType2.SetValue(self.vPropertiesDict['type'].find(name[1]) >= 0) gridBagSizer.Add(self.checkType1, pos = (0,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) gridBagSizer.Add(self.checkType2, pos = (0,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) sizer.Add(gridBagSizer, proportion = 1, flag = wx.EXPAND|wx.ALL, border = 5) border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5) # layer selection box = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Layer selection")) sizer = wx.StaticBoxSizer(box, wx.HORIZONTAL) self.gridBagSizerL = wx.GridBagSizer(hgap = 5, vgap = 5) self.warning = wx.StaticText(panel, id = wx.ID_ANY, label = "") if not self.connection: self.warning = wx.StaticText(panel, id = wx.ID_ANY, label = _("Database connection is not defined in DB file.")) text = wx.StaticText(panel, id = wx.ID_ANY, label = _("Select layer:")) self.layerChoice = wx.Choice(panel, id = wx.ID_ANY, choices = map(str, self.layers), size = self.spinCtrlSize) self.layerChoice.SetStringSelection(self.currLayer) if self.connection: table = self.mapDBInfo.layers[int(self.currLayer)]['table'] else: table = "" self.radioWhere = wx.RadioButton(panel, id = wx.ID_ANY, label = "SELECT * FROM %s WHERE" % table, style = wx.RB_GROUP) self.textCtrlWhere = wx.TextCtrl(panel, id = wx.ID_ANY, value = "") if self.connection: cols = self.mapDBInfo.GetColumns(self.mapDBInfo.layers[int(self.currLayer)]['table']) else: cols = [] self.choiceColumns = wx.Choice(panel, id = wx.ID_ANY, choices = cols) self.radioCats = wx.RadioButton(panel, id = wx.ID_ANY, label = "Choose categories ") self.textCtrlCats = wx.TextCtrl(panel, id = wx.ID_ANY, value = "") self.textCtrlCats.SetToolTipString(_("list of categories (e.g. 1,3,5-7)")) if self.vPropertiesDict.has_key('cats'): self.radioCats.SetValue(True) self.textCtrlCats.SetValue(self.vPropertiesDict['cats']) if self.vPropertiesDict.has_key('where'): self.radioWhere.SetValue(True) where = self.vPropertiesDict['where'].strip().split(" ",1) self.choiceColumns.SetStringSelection(where[0]) self.textCtrlWhere.SetValue(where[1]) row = 0 if not self.connection: self.gridBagSizerL.Add(self.warning, pos = (0,0), span = (1,3), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) row = 1 self.gridBagSizerL.Add(text, pos = (0 + row,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) self.gridBagSizerL.Add(self.layerChoice, pos = (0 + row,1), flag = wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, border = 0) self.gridBagSizerL.Add(self.radioWhere, pos = (1 + row,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) self.gridBagSizerL.Add(self.choiceColumns, pos = (1 + row,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) self.gridBagSizerL.Add(self.textCtrlWhere, pos = (1 + row,2), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) self.gridBagSizerL.Add(self.radioCats, pos = (2 + row,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) self.gridBagSizerL.Add(self.textCtrlCats, pos = (2 + row,1), span = (1, 2), flag = wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, border = 0) sizer.Add(self.gridBagSizerL, proportion = 1, flag = wx.EXPAND|wx.ALL, border = 5) border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5) #mask box = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Mask")) sizer = wx.StaticBoxSizer(box, wx.HORIZONTAL) self.mask = wx.CheckBox(panel, id = wx.ID_ANY, label = _("Use current mask")) if self.vPropertiesDict['masked'] == 'y': self.mask.SetValue(True) else: self.mask.SetValue(False) sizer.Add(self.mask, proportion = 1, flag = wx.EXPAND|wx.ALL, border = 5) border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5) self.Bind(wx.EVT_CHOICE, self.OnLayer, self.layerChoice) panel.SetSizer(border) panel.Fit() return panel def _ColorsPointAreaPanel(self, notebook): panel = wx.Panel(parent = notebook, id = wx.ID_ANY, size = (-1, -1), style = wx.TAB_TRAVERSAL) notebook.AddPage(page = panel, text = _("Colors")) border = wx.BoxSizer(wx.VERTICAL) #colors - outline box = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Outline")) sizer = wx.StaticBoxSizer(box, wx.HORIZONTAL) self.gridBagSizerO = wx.GridBagSizer(hgap = 5, vgap = 2) self.outlineCheck = wx.CheckBox(panel, id = wx.ID_ANY, label = _("draw outline")) self.outlineCheck.SetValue(self.vPropertiesDict['color'] != 'none') widthText = wx.StaticText(panel, id = wx.ID_ANY, label = _("Width (pts):")) if fs: self.widthSpin = fs.FloatSpin(panel, id = wx.ID_ANY, min_val = 0, max_val = 30, increment = 0.5, value = 1, style = fs.FS_RIGHT) self.widthSpin.SetFormat("%f") self.widthSpin.SetDigits(2) else: self.widthSpin = wx.SpinCtrl(panel, id = wx.ID_ANY, min = 1, max = 25, initial = 1, size = self.spinCtrlSize) if self.vPropertiesDict['color'] == None: self.vPropertiesDict['color'] = 'none' if self.vPropertiesDict['color'] != 'none': self.widthSpin.SetValue(self.vPropertiesDict['width'] ) else: self.widthSpin.SetValue(1) colorText = wx.StaticText(panel, id = wx.ID_ANY, label = _("Color:")) self.colorPicker = wx.ColourPickerCtrl(panel, id = wx.ID_ANY) if self.vPropertiesDict['color'] != 'none': self.colorPicker.SetColour(convertRGB(self.vPropertiesDict['color'])) else: self.colorPicker.SetColour(convertRGB('black')) self.gridBagSizerO.Add(self.outlineCheck, pos = (0, 0), span = (1,2), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) self.gridBagSizerO.Add(widthText, pos = (1, 1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) self.gridBagSizerO.Add(self.widthSpin, pos = (1, 2), flag = wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, border = 0) self.gridBagSizerO.Add(colorText, pos = (2, 1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) self.gridBagSizerO.Add(self.colorPicker, pos = (2, 2), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) sizer.Add(self.gridBagSizerO, proportion = 1, flag = wx.EXPAND|wx.ALL, border = 5) border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5) self.Bind(wx.EVT_CHECKBOX, self.OnOutline, self.outlineCheck) #colors - fill box = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Fill")) sizer = wx.StaticBoxSizer(box, wx.HORIZONTAL) self.gridBagSizerF = wx.GridBagSizer(hgap = 5, vgap = 2) self.fillCheck = wx.CheckBox(panel, id = wx.ID_ANY, label = _("fill color")) self.fillCheck.SetValue(self.vPropertiesDict['fcolor'] != 'none' or self.vPropertiesDict['rgbcolumn'] is not None) self.colorPickerRadio = wx.RadioButton(panel, id = wx.ID_ANY, label = _("choose color:"), style = wx.RB_GROUP) #set choose color option if there is no db connection if self.connection: self.colorPickerRadio.SetValue(not self.vPropertiesDict['rgbcolumn']) else: self.colorPickerRadio.SetValue(False) self.fillColorPicker = wx.ColourPickerCtrl(panel, id = wx.ID_ANY) if self.vPropertiesDict['fcolor'] != 'none': self.fillColorPicker.SetColour(convertRGB(self.vPropertiesDict['fcolor'])) else: self.fillColorPicker.SetColour(convertRGB('red')) self.colorColRadio = wx.RadioButton(panel, id = wx.ID_ANY, label = _("color from map table column:")) self.colorColChoice = self.getColsChoice(parent = panel) if self.connection: if self.vPropertiesDict['rgbcolumn']: self.colorColRadio.SetValue(True) self.colorColChoice.SetStringSelection(self.vPropertiesDict['rgbcolumn']) else: self.colorColRadio.SetValue(False) self.colorColChoice.SetSelection(0) self.colorColChoice.Enable(self.connection) self.colorColRadio.Enable(self.connection) self.gridBagSizerF.Add(self.fillCheck, pos = (0, 0), span = (1,2), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) self.gridBagSizerF.Add(self.colorPickerRadio, pos = (1, 1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) self.gridBagSizerF.Add(self.fillColorPicker, pos = (1, 2), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) self.gridBagSizerF.Add(self.colorColRadio, pos = (2, 1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) self.gridBagSizerF.Add(self.colorColChoice, pos = (2, 2), flag = wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, border = 0) sizer.Add(self.gridBagSizerF, proportion = 1, flag = wx.EXPAND|wx.ALL, border = 5) border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5) self.Bind(wx.EVT_CHECKBOX, self.OnFill, self.fillCheck) self.Bind(wx.EVT_RADIOBUTTON, self.OnColor, self.colorColRadio) self.Bind(wx.EVT_RADIOBUTTON, self.OnColor, self.colorPickerRadio) panel.SetSizer(border) panel.Fit() return panel def _ColorsLinePanel(self, notebook): panel = wx.Panel(parent = notebook, id = wx.ID_ANY, size = (-1, -1), style = wx.TAB_TRAVERSAL) notebook.AddPage(page = panel, text = _("Colors")) border = wx.BoxSizer(wx.VERTICAL) #colors - outline box = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Outline")) sizer = wx.StaticBoxSizer(box, wx.HORIZONTAL) self.gridBagSizerO = wx.GridBagSizer(hgap = 5, vgap = 2) if self.vPropertiesDict['hcolor'] == None: self.vPropertiesDict['hcolor'] = 'none' if self.vPropertiesDict['color'] == None: self.vPropertiesDict['color'] = 'none' self.outlineCheck = wx.CheckBox(panel, id = wx.ID_ANY, label = _("draw outline")) self.outlineCheck.SetValue(self.vPropertiesDict['hcolor'] != 'none') self.outlineCheck.SetToolTipString(_("No effect for fill color from table column")) widthText = wx.StaticText(panel, id = wx.ID_ANY, label = _("Width (pts):")) if fs: self.outWidthSpin = fs.FloatSpin(panel, id = wx.ID_ANY, min_val = 0, max_val = 30, increment = 0.5, value = 1, style = fs.FS_RIGHT) self.outWidthSpin.SetFormat("%f") self.outWidthSpin.SetDigits(1) else: self.outWidthSpin = wx.SpinCtrl(panel, id = wx.ID_ANY, min = 1, max = 30, initial = 1, size = self.spinCtrlSize) if self.vPropertiesDict['hcolor'] != 'none': self.outWidthSpin.SetValue(self.vPropertiesDict['hwidth'] ) else: self.outWidthSpin.SetValue(1) colorText = wx.StaticText(panel, id = wx.ID_ANY, label = _("Color:")) self.colorPicker = wx.ColourPickerCtrl(panel, id = wx.ID_ANY) if self.vPropertiesDict['hcolor'] != 'none': self.colorPicker.SetColour(convertRGB(self.vPropertiesDict['hcolor']) ) else: self.colorPicker.SetColour(convertRGB('black')) self.gridBagSizerO.Add(self.outlineCheck, pos = (0, 0), span = (1,2), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) self.gridBagSizerO.Add(widthText, pos = (1, 1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) self.gridBagSizerO.Add(self.outWidthSpin, pos = (1, 2), flag = wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, border = 0) self.gridBagSizerO.Add(colorText, pos = (2, 1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) self.gridBagSizerO.Add(self.colorPicker, pos = (2, 2), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) sizer.Add(self.gridBagSizerO, proportion = 1, flag = wx.EXPAND|wx.ALL, border = 5) border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5) self.Bind(wx.EVT_CHECKBOX, self.OnOutline, self.outlineCheck) #colors - fill box = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Fill")) sizer = wx.StaticBoxSizer(box, wx.HORIZONTAL) self.gridBagSizerF = wx.GridBagSizer(hgap = 5, vgap = 2) fillText = wx.StaticText(panel, id = wx.ID_ANY, label = _("Color of lines:")) self.colorPickerRadio = wx.RadioButton(panel, id = wx.ID_ANY, label = _("choose color:"), style = wx.RB_GROUP) #set choose color option if there is no db connection if self.connection: self.colorPickerRadio.SetValue(not self.vPropertiesDict['rgbcolumn']) else: self.colorPickerRadio.SetValue(False) self.fillColorPicker = wx.ColourPickerCtrl(panel, id = wx.ID_ANY) if self.vPropertiesDict['color'] != 'none': self.fillColorPicker.SetColour(convertRGB(self.vPropertiesDict['color']) ) else: self.fillColorPicker.SetColour(convertRGB('black')) self.colorColRadio = wx.RadioButton(panel, id = wx.ID_ANY, label = _("color from map table column:")) self.colorColChoice = self.getColsChoice(parent = panel) if self.connection: if self.vPropertiesDict['rgbcolumn']: self.colorColRadio.SetValue(True) self.colorColChoice.SetStringSelection(self.vPropertiesDict['rgbcolumn']) else: self.colorColRadio.SetValue(False) self.colorColChoice.SetSelection(0) self.colorColChoice.Enable(self.connection) self.colorColRadio.Enable(self.connection) self.gridBagSizerF.Add(fillText, pos = (0, 0), span = (1,2), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) self.gridBagSizerF.Add(self.colorPickerRadio, pos = (1, 1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) self.gridBagSizerF.Add(self.fillColorPicker, pos = (1, 2), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) self.gridBagSizerF.Add(self.colorColRadio, pos = (2, 1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) self.gridBagSizerF.Add(self.colorColChoice, pos = (2, 2), flag = wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, border = 0) sizer.Add(self.gridBagSizerF, proportion = 1, flag = wx.EXPAND|wx.ALL, border = 5) border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5) self.Bind(wx.EVT_RADIOBUTTON, self.OnColor, self.colorColRadio) self.Bind(wx.EVT_RADIOBUTTON, self.OnColor, self.colorPickerRadio) panel.SetSizer(border) panel.Fit() return panel def _StylePointPanel(self, notebook): panel = wx.Panel(parent = notebook, id = wx.ID_ANY, size = (-1, -1), style = wx.TAB_TRAVERSAL) notebook.AddPage(page = panel, text = _("Size and style")) border = wx.BoxSizer(wx.VERTICAL) #symbology box = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Symbology")) sizer = wx.StaticBoxSizer(box, wx.HORIZONTAL) gridBagSizer = wx.GridBagSizer(hgap = 5, vgap = 5) gridBagSizer.AddGrowableCol(1) self.symbolRadio = wx.RadioButton(panel, id = wx.ID_ANY, label = _("symbol:"), style = wx.RB_GROUP) self.symbolRadio.SetValue(bool(self.vPropertiesDict['symbol'])) self.symbolChoice = wx.Choice(panel, id = wx.ID_ANY, choices = self.symbols) self.epsRadio = wx.RadioButton(panel, id = wx.ID_ANY, label = _("eps file:")) self.epsRadio.SetValue(bool(self.vPropertiesDict['eps'])) self.epsFileCtrl = filebrowse.FileBrowseButton(panel, id = wx.ID_ANY, labelText = '', buttonText = _("Browse"), toolTip = _("Type filename or click browse to choose file"), dialogTitle = _("Choose a file"), startDirectory = '', initialValue = '', fileMask = "Encapsulated PostScript (*.eps)|*.eps|All files (*.*)|*.*", fileMode = wx.OPEN) if self.vPropertiesDict['symbol']: self.symbolChoice.SetStringSelection(self.vPropertiesDict['symbol']) self.epsFileCtrl.SetValue('') else: #eps chosen self.epsFileCtrl.SetValue(self.vPropertiesDict['eps']) self.symbolChoice.SetSelection(0) gridBagSizer.Add(self.symbolRadio, pos = (0, 0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) gridBagSizer.Add(self.symbolChoice, pos = (0, 1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) gridBagSizer.Add(self.epsRadio, pos = (1, 0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) gridBagSizer.Add(self.epsFileCtrl, pos = (1, 1), flag = wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, border = 0) sizer.Add(gridBagSizer, proportion = 1, flag = wx.EXPAND|wx.ALL, border = 5) border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5) #size box = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Size")) sizer = wx.StaticBoxSizer(box, wx.HORIZONTAL) gridBagSizer = wx.GridBagSizer(hgap = 5, vgap = 5) gridBagSizer.AddGrowableCol(0) self.sizeRadio = wx.RadioButton(panel, id = wx.ID_ANY, label = _("size:"), style = wx.RB_GROUP) self.sizeSpin = wx.SpinCtrl(panel, id = wx.ID_ANY, min = 1, max = 50, initial = 1) self.sizecolumnRadio = wx.RadioButton(panel, id = wx.ID_ANY, label = _("size from map table column:")) self.sizeColChoice = self.getColsChoice(panel) self.scaleText = wx.StaticText(panel, id = wx.ID_ANY, label = _("scale:")) self.scaleSpin = wx.SpinCtrl(panel, id = wx.ID_ANY, min = 1, max = 25, initial = 1) self.sizeRadio.SetValue(self.vPropertiesDict['size'] is not None) self.sizecolumnRadio.SetValue(bool(self.vPropertiesDict['sizecolumn'])) if self.vPropertiesDict['size']: self.sizeSpin.SetValue(self.vPropertiesDict['size']) else: self.sizeSpin.SetValue(5) if self.vPropertiesDict['sizecolumn']: self.scaleSpin.SetValue(self.vPropertiesDict['scale']) self.sizeColChoice.SetStringSelection(self.vPropertiesDict['sizecolumn']) else: self.scaleSpin.SetValue(1) self.sizeColChoice.SetSelection(0) if not self.connection: for each in (self.sizecolumnRadio, self.sizeColChoice, self.scaleSpin, self.scaleText): each.Disable() gridBagSizer.Add(self.sizeRadio, pos = (0, 0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) gridBagSizer.Add(self.sizeSpin, pos = (0, 1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) gridBagSizer.Add(self.sizecolumnRadio, pos = (1, 0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) gridBagSizer.Add(self.sizeColChoice, pos = (1, 1), flag = wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, border = 0) gridBagSizer.Add(self.scaleText, pos = (2, 0), flag = wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_RIGHT, border = 0) gridBagSizer.Add(self.scaleSpin, pos = (2, 1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) sizer.Add(gridBagSizer, proportion = 1, flag = wx.EXPAND|wx.ALL, border = 5) border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5) self.Bind(wx.EVT_RADIOBUTTON, self.OnSize, self.sizeRadio) self.Bind(wx.EVT_RADIOBUTTON, self.OnSize, self.sizecolumnRadio) #rotation box = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Rotation")) sizer = wx.StaticBoxSizer(box, wx.HORIZONTAL) gridBagSizer = wx.GridBagSizer(hgap = 5, vgap = 5) gridBagSizer.AddGrowableCol(1) self.rotateCheck = wx.CheckBox(panel, id = wx.ID_ANY, label = _("rotate symbols:")) self.rotateRadio = wx.RadioButton(panel, id = wx.ID_ANY, label = _("counterclockwise in degrees:"), style = wx.RB_GROUP) self.rotateSpin = wx.SpinCtrl(panel, id = wx.ID_ANY, min = 0, max = 360, initial = 0) self.rotatecolumnRadio = wx.RadioButton(panel, id = wx.ID_ANY, label = _("from map table column:")) self.rotateColChoice = self.getColsChoice(panel) self.rotateCheck.SetValue(self.vPropertiesDict['rotation']) self.rotateRadio.SetValue(self.vPropertiesDict['rotate'] is not None) self.rotatecolumnRadio.SetValue(bool(self.vPropertiesDict['rotatecolumn'])) if self.vPropertiesDict['rotate']: self.rotateSpin.SetValue(self.vPropertiesDict['rotate']) else: self.rotateSpin.SetValue(0) if self.vPropertiesDict['rotatecolumn']: self.rotateColChoice.SetStringSelection(self.vPropertiesDict['rotatecolumn']) else: self.rotateColChoice.SetSelection(0) gridBagSizer.Add(self.rotateCheck, pos = (0, 0), span = (1, 2), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) gridBagSizer.Add(self.rotateRadio, pos = (1, 1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) gridBagSizer.Add(self.rotateSpin, pos = (1, 2), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) gridBagSizer.Add(self.rotatecolumnRadio, pos = (2, 1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) gridBagSizer.Add(self.rotateColChoice, pos = (2, 2), flag = wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, border = 0) sizer.Add(gridBagSizer, proportion = 1, flag = wx.EXPAND|wx.ALL, border = 5) border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5) self.Bind(wx.EVT_CHECKBOX, self.OnRotation, self.rotateCheck) self.Bind(wx.EVT_RADIOBUTTON, self.OnRotationType, self.rotateRadio) self.Bind(wx.EVT_RADIOBUTTON, self.OnRotationType, self.rotatecolumnRadio) panel.SetSizer(border) panel.Fit() return panel def _StyleLinePanel(self, notebook): panel = wx.Panel(parent = notebook, id = wx.ID_ANY, size = (-1, -1), style = wx.TAB_TRAVERSAL) notebook.AddPage(page = panel, text = _("Size and style")) border = wx.BoxSizer(wx.VERTICAL) #width box = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Width")) sizer = wx.StaticBoxSizer(box, wx.HORIZONTAL) gridBagSizer = wx.GridBagSizer(hgap = 5, vgap = 5) widthText = wx.StaticText(panel, id = wx.ID_ANY, label = _("Set width (pts):")) if fs: self.widthSpin = fs.FloatSpin(panel, id = wx.ID_ANY, min_val = 0, max_val = 30, increment = 0.5, value = 1, style = fs.FS_RIGHT) self.widthSpin.SetFormat("%f") self.widthSpin.SetDigits(1) else: self.widthSpin = wx.SpinCtrl(panel, id = wx.ID_ANY, min = 1, max = 30, initial = 1) self.cwidthCheck = wx.CheckBox(panel, id = wx.ID_ANY, label = _("multiply width by category value")) if self.vPropertiesDict['width']: self.widthSpin.SetValue(self.vPropertiesDict['width']) self.cwidthCheck.SetValue(False) else: self.widthSpin.SetValue(self.vPropertiesDict['cwidth']) self.cwidthCheck.SetValue(True) gridBagSizer.Add(widthText, pos = (0, 0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) gridBagSizer.Add(self.widthSpin, pos = (0, 1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) gridBagSizer.Add(self.cwidthCheck, pos = (1, 0), span = (1, 2), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) sizer.Add(gridBagSizer, proportion = 1, flag = wx.EXPAND|wx.ALL, border = 5) border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5) #style box = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Line style")) sizer = wx.StaticBoxSizer(box, wx.HORIZONTAL) gridBagSizer = wx.GridBagSizer(hgap = 5, vgap = 5) styleText = wx.StaticText(panel, id = wx.ID_ANY, label = _("Choose line style:")) penStyles = ["solid", "dashed", "dotted", "dashdotted"] self.styleCombo = PenStyleComboBox(panel, choices = penStyles, validator = TCValidator(flag = 'ZERO_AND_ONE_ONLY')) ## self.styleCombo = wx.ComboBox(panel, id = wx.ID_ANY, ## choices = ["solid", "dashed", "dotted", "dashdotted"], ## validator = TCValidator(flag = 'ZERO_AND_ONE_ONLY')) ## self.styleCombo.SetToolTipString(_("It's possible to enter a series of 0's and 1's too. "\ ## "The first block of repeated zeros or ones represents 'draw', "\ ## "the second block represents 'blank'. An even number of blocks "\ ## "will repeat the pattern, an odd number of blocks will alternate the pattern.")) linecapText = wx.StaticText(panel, id = wx.ID_ANY, label = _("Choose linecap:")) self.linecapChoice = wx.Choice(panel, id = wx.ID_ANY, choices = ["butt", "round", "extended_butt"]) self.styleCombo.SetValue(self.vPropertiesDict['style']) self.linecapChoice.SetStringSelection(self.vPropertiesDict['linecap']) gridBagSizer.Add(styleText, pos = (0, 0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) gridBagSizer.Add(self.styleCombo, pos = (0, 1), flag = wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, border = 0) gridBagSizer.Add(linecapText, pos = (1, 0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) gridBagSizer.Add(self.linecapChoice, pos = (1, 1), flag = wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, border = 0) sizer.Add(gridBagSizer, proportion = 1, flag = wx.EXPAND|wx.ALL, border = 5) border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5) panel.SetSizer(border) panel.Fit() return panel def _StyleAreaPanel(self, notebook): panel = wx.Panel(parent = notebook, id = wx.ID_ANY, size = (-1, -1), style = wx.TAB_TRAVERSAL) notebook.AddPage(page = panel, text = _("Size and style")) border = wx.BoxSizer(wx.VERTICAL) #pattern box = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Pattern")) sizer = wx.StaticBoxSizer(box, wx.HORIZONTAL) gridBagSizer = wx.GridBagSizer(hgap = 5, vgap = 5) gridBagSizer.AddGrowableCol(1) self.patternCheck = wx.CheckBox(panel, id = wx.ID_ANY, label = _("use pattern:")) self.patFileCtrl = filebrowse.FileBrowseButton(panel, id = wx.ID_ANY, labelText = _("Choose pattern file:"), buttonText = _("Browse"), toolTip = _("Type filename or click browse to choose file"), dialogTitle = _("Choose a file"), startDirectory = self.patternPath, initialValue = '', fileMask = "Encapsulated PostScript (*.eps)|*.eps|All files (*.*)|*.*", fileMode = wx.OPEN) self.patWidthText = wx.StaticText(panel, id = wx.ID_ANY, label = _("pattern line width (pts):")) self.patWidthSpin = wx.SpinCtrl(panel, id = wx.ID_ANY, min = 1, max = 25, initial = 1) self.patScaleText = wx.StaticText(panel, id = wx.ID_ANY, label = _("pattern scale factor:")) self.patScaleSpin = wx.SpinCtrl(panel, id = wx.ID_ANY, min = 1, max = 25, initial = 1) self.patternCheck.SetValue(bool(self.vPropertiesDict['pat'])) if self.patternCheck.GetValue(): self.patFileCtrl.SetValue(self.vPropertiesDict['pat']) self.patWidthSpin.SetValue(self.vPropertiesDict['pwidth']) self.patScaleSpin.SetValue(self.vPropertiesDict['scale']) gridBagSizer.Add(self.patternCheck, pos = (0, 0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) gridBagSizer.Add(self.patFileCtrl, pos = (1, 0), span = (1, 2),flag = wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, border = 0) gridBagSizer.Add(self.patWidthText, pos = (2, 0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) gridBagSizer.Add(self.patWidthSpin, pos = (2, 1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) gridBagSizer.Add(self.patScaleText, pos = (3, 0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) gridBagSizer.Add(self.patScaleSpin, pos = (3, 1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) sizer.Add(gridBagSizer, proportion = 1, flag = wx.EXPAND|wx.ALL, border = 5) border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5) self.Bind(wx.EVT_CHECKBOX, self.OnPattern, self.patternCheck) panel.SetSizer(border) panel.Fit() return panel def OnLayer(self, event): """!Change columns on layer change """ if self.layerChoice.GetStringSelection() == self.currLayer: return self.currLayer = self.layerChoice.GetStringSelection() if self.connection: cols = self.mapDBInfo.GetColumns(self.mapDBInfo.layers[int(self.currLayer)]['table']) else: cols = [] self.choiceColumns.SetItems(cols) self.choiceColumns.SetSelection(0) if self.type in ('points', 'lines'): self.colorColChoice.SetItems(cols) self.colorColChoice.SetSelection(0) def OnOutline(self, event): for widget in self.gridBagSizerO.GetChildren(): if widget.GetWindow() != self.outlineCheck: widget.GetWindow().Enable(self.outlineCheck.GetValue()) def OnFill(self, event): enable = self.fillCheck.GetValue() self.colorColChoice.Enable(enable) self.colorColRadio.Enable(enable) self.fillColorPicker.Enable(enable) self.colorPickerRadio.Enable(enable) if enable: self.OnColor(None) if not self.connection: self.colorColChoice.Disable() self.colorColRadio.Disable() def OnColor(self, event): self.colorColChoice.Enable(self.colorColRadio.GetValue()) self.fillColorPicker.Enable(self.colorPickerRadio.GetValue()) def OnSize(self, event): self.sizeSpin.Enable(self.sizeRadio.GetValue()) self.sizeColChoice.Enable(self.sizecolumnRadio.GetValue()) self.scaleText.Enable(self.sizecolumnRadio.GetValue()) self.scaleSpin.Enable(self.sizecolumnRadio.GetValue()) def OnRotation(self, event): for each in (self.rotateRadio, self.rotatecolumnRadio, self.rotateColChoice, self.rotateSpin): if self.rotateCheck.GetValue(): each.Enable() self.OnRotationType(event = None) else: each.Disable() def OnRotationType(self, event): self.rotateSpin.Enable(self.rotateRadio.GetValue()) self.rotateColChoice.Enable(self.rotatecolumnRadio.GetValue()) def OnPattern(self, event): for each in (self.patFileCtrl, self.patWidthText, self.patWidthSpin, self.patScaleText, self.patScaleSpin): each.Enable(self.patternCheck.GetValue()) def EnableLayerSelection(self, enable = True): for widget in self.gridBagSizerL.GetChildren(): if widget.GetWindow() != self.warning: widget.GetWindow().Enable(enable) def getColsChoice(self, parent): """!Returns a wx.Choice with table columns""" if self.connection: cols = self.mapDBInfo.GetColumns(self.mapDBInfo.layers[int(self.currLayer)]['table']) else: cols = [] choice = wx.Choice(parent = parent, id = wx.ID_ANY, choices = cols) return choice def update(self): #feature type if self.type in ('lines', 'points'): featureType = None if self.checkType1.GetValue(): featureType = self.checkType1.GetName() if self.checkType2.GetValue(): featureType += " or " + self.checkType2.GetName() elif self.checkType2.GetValue(): featureType = self.checkType2.GetName() if featureType: self.vPropertiesDict['type'] = featureType # is connection self.vPropertiesDict['connection'] = self.connection if self.connection: self.vPropertiesDict['layer'] = self.layerChoice.GetStringSelection() if self.radioCats.GetValue() and not self.textCtrlCats.IsEmpty(): self.vPropertiesDict['cats'] = self.textCtrlCats.GetValue() elif self.radioWhere.GetValue() and not self.textCtrlWhere.IsEmpty(): self.vPropertiesDict['where'] = self.choiceColumns.GetStringSelection() + " " \ + self.textCtrlWhere.GetValue() #mask if self.mask.GetValue(): self.vPropertiesDict['masked'] = 'y' else: self.vPropertiesDict['masked'] = 'n' #colors if self.type in ('points', 'areas'): if self.outlineCheck.GetValue(): self.vPropertiesDict['color'] = convertRGB(self.colorPicker.GetColour()) self.vPropertiesDict['width'] = self.widthSpin.GetValue() else: self.vPropertiesDict['color'] = 'none' if self.fillCheck.GetValue(): if self.colorPickerRadio.GetValue(): self.vPropertiesDict['fcolor'] = convertRGB(self.fillColorPicker.GetColour()) self.vPropertiesDict['rgbcolumn'] = None if self.colorColRadio.GetValue(): self.vPropertiesDict['fcolor'] = 'none'# this color is taken in case of no record in rgb column self.vPropertiesDict['rgbcolumn'] = self.colorColChoice.GetStringSelection() else: self.vPropertiesDict['fcolor'] = 'none' if self.type == 'lines': #hcolor only when no rgbcolumn if self.outlineCheck.GetValue():# and self.fillCheck.GetValue() and self.colorColRadio.GetValue(): self.vPropertiesDict['hcolor'] = convertRGB(self.colorPicker.GetColour()) self.vPropertiesDict['hwidth'] = self.outWidthSpin.GetValue() else: self.vPropertiesDict['hcolor'] = 'none' if self.colorPickerRadio.GetValue(): self.vPropertiesDict['color'] = convertRGB(self.fillColorPicker.GetColour()) self.vPropertiesDict['rgbcolumn'] = None if self.colorColRadio.GetValue(): self.vPropertiesDict['color'] = 'none'# this color is taken in case of no record in rgb column self.vPropertiesDict['rgbcolumn'] = self.colorColChoice.GetStringSelection() # #size and style # if self.type == 'points': #symbols if self.symbolRadio.GetValue(): self.vPropertiesDict['symbol'] = self.symbolChoice.GetStringSelection() self.vPropertiesDict['eps'] = None else: self.vPropertiesDict['eps'] = self.epsFileCtrl.GetValue() self.vPropertiesDict['symbol'] = None #size if self.sizeRadio.GetValue(): self.vPropertiesDict['size'] = self.sizeSpin.GetValue() self.vPropertiesDict['sizecolumn'] = None self.vPropertiesDict['scale'] = None else: self.vPropertiesDict['sizecolumn'] = self.sizeColChoice.GetStringSelection() self.vPropertiesDict['scale'] = self.scaleSpin.GetValue() self.vPropertiesDict['size'] = None #rotation self.vPropertiesDict['rotate'] = None self.vPropertiesDict['rotatecolumn'] = None self.vPropertiesDict['rotation'] = False if self.rotateCheck.GetValue(): self.vPropertiesDict['rotation'] = True if self.rotateRadio.GetValue(): self.vPropertiesDict['rotate'] = self.rotateSpin.GetValue() else: self.vPropertiesDict['rotatecolumn'] = self.rotateColChoice.GetStringSelection() if self.type == 'areas': #pattern self.vPropertiesDict['pat'] = None if self.patternCheck.GetValue() and bool(self.patFileCtrl.GetValue()): self.vPropertiesDict['pat'] = self.patFileCtrl.GetValue() self.vPropertiesDict['pwidth'] = self.patWidthSpin.GetValue() self.vPropertiesDict['scale'] = self.patScaleSpin.GetValue() if self.type == 'lines': #width if self.cwidthCheck.GetValue(): self.vPropertiesDict['cwidth'] = self.widthSpin.GetValue() self.vPropertiesDict['width'] = None else: self.vPropertiesDict['width'] = self.widthSpin.GetValue() self.vPropertiesDict['cwidth'] = None #line style if self.styleCombo.GetValue(): self.vPropertiesDict['style'] = self.styleCombo.GetValue() else: self.vPropertiesDict['style'] = 'solid' self.vPropertiesDict['linecap'] = self.linecapChoice.GetStringSelection() def OnOK(self, event): self.update() event.Skip() class LegendDialog(PsmapDialog): def __init__(self, parent, id, settings, page): PsmapDialog.__init__(self, parent = parent, id = id, title = "Legend settings", settings = settings) self.objectType = ('rasterLegend', 'vectorLegend') self.instruction = settings map = self.instruction.FindInstructionByType('map') if map: self.mapId = map.id else: self.mapId = None vector = self.instruction.FindInstructionByType('vector') if vector: self.vectorId = vector.id else: self.vectorId = None raster = self.instruction.FindInstructionByType('raster') if raster: self.rasterId = raster.id else: self.rasterId = None self.pageId = self.instruction.FindInstructionByType('page').id currPage = self.instruction[self.pageId].GetInstruction() #raster legend if self.id[0] is not None: self.rasterLegend = self.instruction[self.id[0]] self.rLegendDict = self.rasterLegend.GetInstruction() else: self.id[0] = wx.NewId() self.rasterLegend = RasterLegend(self.id[0]) self.rLegendDict = self.rasterLegend.GetInstruction() self.rLegendDict['where'] = currPage['Left'], currPage['Top'] #vector legend if self.id[1] is not None: self.vLegendDict = self.instruction[self.id[1]].GetInstruction() else: self.id[1] = wx.NewId() vectorLegend = VectorLegend(self.id[1]) self.vLegendDict = vectorLegend.GetInstruction() self.vLegendDict['where'] = currPage['Left'], currPage['Top'] if self.rasterId: self.currRaster = self.instruction[self.rasterId]['raster'] else: self.currRaster = None #notebook self.notebook = wx.Notebook(parent = self, id = wx.ID_ANY, style = wx.BK_DEFAULT) self.panelRaster = self._rasterLegend(self.notebook) self.panelVector = self._vectorLegend(self.notebook) self.OnRaster(None) self.OnRange(None) self.OnIsLegend(None) self.OnSpan(None) self.OnBorder(None) self._layout(self.notebook) self.notebook.ChangeSelection(page) self.notebook.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGING, self.OnPageChanging) def OnPageChanging(self, event): """!Workaround to scroll up to see the checkbox""" wx.CallAfter(self.FindWindowByName('rasterPanel').ScrollChildIntoView, self.FindWindowByName('showRLegend')) wx.CallAfter(self.FindWindowByName('vectorPanel').ScrollChildIntoView, self.FindWindowByName('showVLegend')) def _rasterLegend(self, notebook): panel = scrolled.ScrolledPanel(parent = notebook, id = wx.ID_ANY, size = (-1, 500), style = wx.TAB_TRAVERSAL) panel.SetupScrolling(scroll_x = False, scroll_y = True) panel.SetName('rasterPanel') notebook.AddPage(page = panel, text = _("Raster legend")) border = wx.BoxSizer(wx.VERTICAL) # is legend self.isRLegend = wx.CheckBox(panel, id = wx.ID_ANY, label = _("Show raster legend")) self.isRLegend.SetValue(self.rLegendDict['rLegend']) self.isRLegend.SetName("showRLegend") border.Add(item = self.isRLegend, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5) # choose raster box = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Source raster")) sizer = wx.StaticBoxSizer(box, wx.VERTICAL) flexSizer = wx.FlexGridSizer (cols = 2, hgap = 5, vgap = 5) flexSizer.AddGrowableCol(1) self.rasterDefault = wx.RadioButton(panel, id = wx.ID_ANY, label = _("current raster"), style = wx.RB_GROUP) self.rasterOther = wx.RadioButton(panel, id = wx.ID_ANY, label = _("select raster")) self.rasterDefault.SetValue(self.rLegendDict['rasterDefault'])# self.rasterOther.SetValue(not self.rLegendDict['rasterDefault'])# rasterType = getRasterType(map = self.currRaster) self.rasterCurrent = wx.StaticText(panel, id = wx.ID_ANY, label = _("%(rast)s: type %(type)s") % { 'rast' : self.currRaster, 'type' : rasterType }) self.rasterSelect = Select(panel, id = wx.ID_ANY, size = globalvar.DIALOG_GSELECT_SIZE, type = 'raster', multiple = False, updateOnPopup = True, onPopup = None) if not self.rLegendDict['rasterDefault']: self.rasterSelect.SetValue(self.rLegendDict['raster']) else: self.rasterSelect.SetValue('') flexSizer.Add(self.rasterDefault, proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL, border = 0) flexSizer.Add(self.rasterCurrent, proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL|wx.LEFT, border = 10) flexSizer.Add(self.rasterOther, proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL, border = 0) flexSizer.Add(self.rasterSelect, proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_RIGHT, border = 0) sizer.Add(item = flexSizer, proportion = 1, flag = wx.ALL | wx.EXPAND, border = 1) border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5) # type of legend box = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Type of legend")) sizer = wx.StaticBoxSizer(box, wx.VERTICAL) vbox = wx.BoxSizer(wx.VERTICAL) self.discrete = wx.RadioButton(parent = panel, id = wx.ID_ANY, label = " %s " % _("discrete legend (categorical maps)"), style = wx.RB_GROUP) self.continuous = wx.RadioButton(parent = panel, id = wx.ID_ANY, label = " %s " % _("continuous color gradient legend (floating point map)")) vbox.Add(self.discrete, proportion = 1, flag = wx.EXPAND|wx.ALL, border = 0) vbox.Add(self.continuous, proportion = 1, flag = wx.EXPAND|wx.ALL, border = 0) sizer.Add(item = vbox, proportion = 1, flag = wx.ALL | wx.EXPAND, border = 1) border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5) # size, position and font self.sizePositionFont(legendType = 'raster', parent = panel, mainSizer = border) # advanced settings box = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Advanced legend settings")) sizer = wx.StaticBoxSizer(box, wx.VERTICAL) gridBagSizer = wx.GridBagSizer (hgap = 5, vgap = 5) # no data self.nodata = wx.CheckBox(panel, id = wx.ID_ANY, label = _('draw "no data" box')) if self.rLegendDict['nodata'] == 'y': self.nodata.SetValue(True) else: self.nodata.SetValue(False) #tickbar self.ticks = wx.CheckBox(panel, id = wx.ID_ANY, label = _("draw ticks across color table")) if self.rLegendDict['tickbar'] == 'y': self.ticks.SetValue(True) else: self.ticks.SetValue(False) # range if self.rasterId and self.instruction[self.rasterId]['raster']: rinfo = grass.raster_info(self.instruction[self.rasterId]['raster']) self.minim, self.maxim = rinfo['min'], rinfo['max'] else: self.minim, self.maxim = 0,0 self.range = wx.CheckBox(panel, id = wx.ID_ANY, label = _("range")) self.range.SetValue(self.rLegendDict['range']) self.minText = wx.StaticText(panel, id = wx.ID_ANY, label = "min (%s)" % self.minim) self.maxText = wx.StaticText(panel, id = wx.ID_ANY, label = "max (%s)" % self.maxim) self.min = wx.TextCtrl(panel, id = wx.ID_ANY, value = str(self.rLegendDict['min'])) self.max = wx.TextCtrl(panel, id = wx.ID_ANY, value = str(self.rLegendDict['max'])) gridBagSizer.Add(self.nodata, pos = (0,0), span = (1,5), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) gridBagSizer.Add(self.ticks, pos = (1,0), span = (1,5), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) gridBagSizer.Add(self.range, pos = (2,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) gridBagSizer.Add(self.minText, pos = (2,1), flag = wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_RIGHT, border = 0) gridBagSizer.Add(self.min, pos = (2,2), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) gridBagSizer.Add(self.maxText, pos = (2,3), flag = wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_RIGHT, border = 0) gridBagSizer.Add(self.max, pos = (2,4), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) sizer.Add(gridBagSizer, proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL, border = 0) border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5) panel.SetSizer(border) panel.Fit() # bindings self.Bind(wx.EVT_RADIOBUTTON, self.OnRaster, self.rasterDefault) self.Bind(wx.EVT_RADIOBUTTON, self.OnRaster, self.rasterOther) self.Bind(wx.EVT_CHECKBOX, self.OnIsLegend, self.isRLegend) self.Bind(wx.EVT_RADIOBUTTON, self.OnDiscrete, self.discrete) self.Bind(wx.EVT_RADIOBUTTON, self.OnDiscrete, self.continuous) ## self.Bind(wx.EVT_CHECKBOX, self.OnDefaultSize, panel.defaultSize) self.Bind(wx.EVT_CHECKBOX, self.OnRange, self.range) self.rasterSelect.GetTextCtrl().Bind(wx.EVT_TEXT, self.OnRaster) return panel def _vectorLegend(self, notebook): panel = scrolled.ScrolledPanel(parent = notebook, id = wx.ID_ANY, size = (-1, 500), style = wx.TAB_TRAVERSAL) panel.SetupScrolling(scroll_x = False, scroll_y = True) panel.SetName('vectorPanel') notebook.AddPage(page = panel, text = _("Vector legend")) border = wx.BoxSizer(wx.VERTICAL) # is legend self.isVLegend = wx.CheckBox(panel, id = wx.ID_ANY, label = _("Show vector legend")) self.isVLegend.SetValue(self.vLegendDict['vLegend']) self.isVLegend.SetName("showVLegend") border.Add(item = self.isVLegend, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5) #vector maps, their order, labels box = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Source vector maps")) sizer = wx.StaticBoxSizer(box, wx.VERTICAL) gridBagSizer = wx.GridBagSizer (hgap = 5, vgap = 5) gridBagSizer.AddGrowableCol(0,3) gridBagSizer.AddGrowableCol(1,1) vectorText = wx.StaticText(panel, id = wx.ID_ANY, label = _("Choose vector maps and their order in legend")) self.vectorListCtrl = CheckListCtrl(panel) self.vectorListCtrl.InsertColumn(0, _("Vector map")) self.vectorListCtrl.InsertColumn(1, _("Label")) if self.vectorId: vectors = sorted(self.instruction[self.vectorId]['list'], key = lambda x: x[3]) for vector in vectors: index = self.vectorListCtrl.InsertStringItem(sys.maxint, vector[0].split('@')[0]) self.vectorListCtrl.SetStringItem(index, 1, vector[4]) self.vectorListCtrl.SetItemData(index, index) self.vectorListCtrl.CheckItem(index, True) if vector[3] == 0: self.vectorListCtrl.CheckItem(index, False) if not self.vectorId: self.vectorListCtrl.SetColumnWidth(0, 100) else: self.vectorListCtrl.SetColumnWidth(0, wx.LIST_AUTOSIZE) self.vectorListCtrl.SetColumnWidth(1, wx.LIST_AUTOSIZE) self.btnUp = wx.Button(panel, id = wx.ID_ANY, label = _("Up")) self.btnDown = wx.Button(panel, id = wx.ID_ANY, label = _("Down")) self.btnLabel = wx.Button(panel, id = wx.ID_ANY, label = _("Edit label")) gridBagSizer.Add(vectorText, pos = (0,0), span = (1,2), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) gridBagSizer.Add(self.vectorListCtrl, pos = (1,0), span = (3,1), flag = wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, border = 0) gridBagSizer.Add(self.btnUp, pos = (1,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) gridBagSizer.Add(self.btnDown, pos = (2,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) gridBagSizer.Add(self.btnLabel, pos = (3,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) sizer.Add(gridBagSizer, proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, border = 0) border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5) # size, position and font self.sizePositionFont(legendType = 'vector', parent = panel, mainSizer = border) # border box = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Border")) sizer = wx.StaticBoxSizer(box, wx.VERTICAL) flexGridSizer = wx.FlexGridSizer(cols = 2, hgap = 5, vgap = 5) self.borderCheck = wx.CheckBox(panel, id = wx.ID_ANY, label = _("draw border around legend")) self.borderColorCtrl = wx.ColourPickerCtrl(panel, id = wx.ID_ANY, style = wx.FNTP_FONTDESC_AS_LABEL) if self.vLegendDict['border'] == 'none': self.borderColorCtrl.SetColour(wx.BLACK) self.borderCheck.SetValue(False) else: self.borderColorCtrl.SetColour(convertRGB(self.vLegendDict['border'])) self.borderCheck.SetValue(True) flexGridSizer.Add(self.borderCheck, proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL, border = 0) flexGridSizer.Add(self.borderColorCtrl, proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL, border = 0) sizer.Add(item = flexGridSizer, proportion = 1, flag = wx.ALL | wx.EXPAND, border = 1) border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5) self.Bind(wx.EVT_BUTTON, self.OnUp, self.btnUp) self.Bind(wx.EVT_BUTTON, self.OnDown, self.btnDown) self.Bind(wx.EVT_BUTTON, self.OnEditLabel, self.btnLabel) self.Bind(wx.EVT_CHECKBOX, self.OnIsLegend, self.isVLegend) self.Bind(wx.EVT_CHECKBOX, self.OnSpan, panel.spanRadio) self.Bind(wx.EVT_CHECKBOX, self.OnBorder, self.borderCheck) self.Bind(wx.EVT_FONTPICKER_CHANGED, self.OnFont, panel.font['fontCtrl']) panel.SetSizer(border) panel.Fit() return panel def sizePositionFont(self, legendType, parent, mainSizer): """!Insert widgets for size, position and font control""" if legendType == 'raster': legendDict = self.rLegendDict else: legendDict = self.vLegendDict panel = parent border = mainSizer # size and position box = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Size and position")) sizer = wx.StaticBoxSizer(box, wx.VERTICAL) #unit self.AddUnits(parent = panel, dialogDict = legendDict) unitBox = wx.BoxSizer(wx.HORIZONTAL) unitBox.Add(panel.units['unitsLabel'], proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL|wx.LEFT, border = 10) unitBox.Add(panel.units['unitsCtrl'], proportion = 1, flag = wx.ALL, border = 5) sizer.Add(unitBox, proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL, border = 0) hBox = wx.BoxSizer(wx.HORIZONTAL) posBox = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " %_("Position")) posSizer = wx.StaticBoxSizer(posBox, wx.VERTICAL) sizeBox = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Size")) sizeSizer = wx.StaticBoxSizer(sizeBox, wx.VERTICAL) posGridBagSizer = wx.GridBagSizer(hgap = 10, vgap = 5) posGridBagSizer.AddGrowableRow(2) #position self.AddPosition(parent = panel, dialogDict = legendDict) posGridBagSizer.Add(panel.position['xLabel'], pos = (0,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) posGridBagSizer.Add(panel.position['xCtrl'], pos = (0,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) posGridBagSizer.Add(panel.position['yLabel'], pos = (1,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) posGridBagSizer.Add(panel.position['yCtrl'], pos = (1,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) posGridBagSizer.Add(panel.position['comment'], pos = (2,0), span = (1,2), flag =wx.ALIGN_BOTTOM, border = 0) posSizer.Add(posGridBagSizer, proportion = 1, flag = wx.EXPAND|wx.ALL, border = 5) #size width = wx.StaticText(panel, id = wx.ID_ANY, label = _("Width:")) if legendDict['width']: w = self.unitConv.convert(value = float(legendDict['width']), fromUnit = 'inch', toUnit = legendDict['unit']) else: w = '' panel.widthCtrl = wx.TextCtrl(panel, id = wx.ID_ANY, value = str(w), validator = TCValidator("DIGIT_ONLY")) panel.widthCtrl.SetToolTipString(_("Leave the edit field empty, to use default values.")) if legendType == 'raster': ## panel.defaultSize = wx.CheckBox(panel, id = wx.ID_ANY, label = _("Use default size")) ## panel.defaultSize.SetValue(legendDict['defaultSize']) panel.heightOrColumnsLabel = wx.StaticText(panel, id = wx.ID_ANY, label = _("Height:")) if legendDict['height']: h = self.unitConv.convert(value = float(legendDict['height']), fromUnit = 'inch', toUnit = legendDict['unit']) else: h = '' panel.heightOrColumnsCtrl = wx.TextCtrl(panel, id = wx.ID_ANY, value = str(h), validator = TCValidator("DIGIT_ONLY")) self.rSizeGBSizer = wx.GridBagSizer(hgap = 5, vgap = 5) ## self.rSizeGBSizer.Add(panel.defaultSize, pos = (0,0), span = (1,2), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) self.rSizeGBSizer.Add(width, pos = (0,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) self.rSizeGBSizer.Add(panel.widthCtrl, pos = (0,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) self.rSizeGBSizer.Add(panel.heightOrColumnsLabel, pos = (1,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) self.rSizeGBSizer.Add(panel.heightOrColumnsCtrl, pos = (1,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) sizeSizer.Add(self.rSizeGBSizer, proportion = 1, flag = wx.EXPAND|wx.ALL, border = 5) if legendType == 'vector': panel.widthCtrl.SetToolTipString(_("Width of the color symbol (for lines)\nin front of the legend text")) #columns minVect, maxVect = 0, 0 if self.vectorId: minVect = 1 maxVect = min(10, len(self.instruction[self.vectorId]['list'])) cols = wx.StaticText(panel, id = wx.ID_ANY, label = _("Columns:")) panel.colsCtrl = wx.SpinCtrl(panel, id = wx.ID_ANY, value = "", min = minVect, max = maxVect, initial = legendDict['cols']) #span panel.spanRadio = wx.CheckBox(panel, id = wx.ID_ANY, label = _("column span:")) panel.spanTextCtrl = wx.TextCtrl(panel, id = wx.ID_ANY, value = '') panel.spanTextCtrl.SetToolTipString(_("Column separation distance between the left edges\n"\ "of two columns in a multicolumn legend")) if legendDict['span']: panel.spanRadio.SetValue(True) s = self.unitConv.convert(value = float(legendDict['span']), fromUnit = 'inch', toUnit = legendDict['unit']) panel.spanTextCtrl.SetValue(str(s)) else: panel.spanRadio.SetValue(False) self.vSizeGBSizer = wx.GridBagSizer(hgap = 5, vgap = 5) self.vSizeGBSizer.AddGrowableCol(1) self.vSizeGBSizer.Add(width, pos = (0,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) self.vSizeGBSizer.Add(panel.widthCtrl, pos = (0,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) self.vSizeGBSizer.Add(cols, pos = (1,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) self.vSizeGBSizer.Add(panel.colsCtrl, pos = (1,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) self.vSizeGBSizer.Add(panel.spanRadio, pos = (2,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) self.vSizeGBSizer.Add(panel.spanTextCtrl, pos = (2,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) sizeSizer.Add(self.vSizeGBSizer, proportion = 1, flag = wx.EXPAND|wx.ALL, border = 5) hBox.Add(posSizer, proportion = 1, flag = wx.EXPAND|wx.ALL, border = 3) hBox.Add(sizeSizer, proportion = 1, flag = wx.EXPAND|wx.ALL, border = 3) sizer.Add(hBox, proportion = 0, flag = wx.EXPAND, border = 0) border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5) # font box = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Font settings")) fontSizer = wx.StaticBoxSizer(box, wx.VERTICAL) flexSizer = wx.FlexGridSizer (cols = 2, hgap = 5, vgap = 5) flexSizer.AddGrowableCol(1) if legendType == 'raster': self.AddFont(parent = panel, dialogDict = legendDict, color = True) else: self.AddFont(parent = panel, dialogDict = legendDict, color = False) flexSizer.Add(panel.font['fontLabel'], proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL, border = 0) flexSizer.Add(panel.font['fontCtrl'], proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL, border = 0) flexSizer.Add(panel.font['fontSizeLabel'], proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL, border = 0) flexSizer.Add(panel.font['fontSizeCtrl'], proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL, border = 0) if legendType == 'raster': flexSizer.Add(panel.font['colorLabel'], proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL, border = 0) flexSizer.Add(panel.font['colorCtrl'], proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL, border = 0) fontSizer.Add(item = flexSizer, proportion = 1, flag = wx.ALL | wx.EXPAND, border = 1) border.Add(item = fontSizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5) # some enable/disable methods def OnIsLegend(self, event): """!Enables and disables controls, it depends if raster or vector legend is checked""" page = self.notebook.GetSelection() if page == 0 or event is None: children = self.panelRaster.GetChildren() if self.isRLegend.GetValue(): for i,widget in enumerate(children): widget.Enable() self.OnRaster(None) self.OnRange(None) self.OnDiscrete(None) else: for widget in children: if widget.GetName() != 'showRLegend': widget.Disable() if page == 1 or event is None: children = self.panelVector.GetChildren() if self.isVLegend.GetValue(): for i, widget in enumerate(children): widget.Enable() self.OnSpan(None) self.OnBorder(None) else: for widget in children: if widget.GetName() != 'showVLegend': widget.Disable() def OnRaster(self, event): if self.rasterDefault.GetValue():#default self.rasterSelect.Disable() type = getRasterType(self.currRaster) else:#select raster self.rasterSelect.Enable() map = self.rasterSelect.GetValue() type = getRasterType(map) if type == 'CELL': self.discrete.SetValue(True) elif type in ('FCELL', 'DCELL'): self.continuous.SetValue(True) if event is None: if self.rLegendDict['discrete'] == 'y': self.discrete.SetValue(True) elif self.rLegendDict['discrete'] == 'n': self.continuous.SetValue(True) self.OnDiscrete(None) def OnDiscrete(self, event): """! Change control according to the type of legend""" enabledSize = self.panelRaster.heightOrColumnsCtrl.IsEnabled() self.panelRaster.heightOrColumnsCtrl.Destroy() if self.discrete.GetValue(): self.panelRaster.heightOrColumnsLabel.SetLabel(_("Columns:")) self.panelRaster.heightOrColumnsCtrl = wx.SpinCtrl(self.panelRaster, id = wx.ID_ANY, value = "", min = 1, max = 10, initial = self.rLegendDict['cols']) self.panelRaster.heightOrColumnsCtrl.Enable(enabledSize) self.nodata.Enable() self.range.Disable() self.min.Disable() self.max.Disable() self.minText.Disable() self.maxText.Disable() self.ticks.Disable() else: self.panelRaster.heightOrColumnsLabel.SetLabel(_("Height:")) if self.rLegendDict['height']: h = self.unitConv.convert(value = float(self.rLegendDict['height']), fromUnit = 'inch', toUnit = self.rLegendDict['unit']) else: h = '' self.panelRaster.heightOrColumnsCtrl = wx.TextCtrl(self.panelRaster, id = wx.ID_ANY, value = str(h), validator = TCValidator("DIGIT_ONLY")) self.panelRaster.heightOrColumnsCtrl.Enable(enabledSize) self.nodata.Disable() self.range.Enable() if self.range.GetValue(): self.minText.Enable() self.maxText.Enable() self.min.Enable() self.max.Enable() self.ticks.Enable() self.rSizeGBSizer.Add(self.panelRaster.heightOrColumnsCtrl, pos = (1,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) self.panelRaster.Layout() self.panelRaster.Fit() def OnRange(self, event): if not self.range.GetValue(): self.min.Disable() self.max.Disable() self.minText.Disable() self.maxText.Disable() else: self.min.Enable() self.max.Enable() self.minText.Enable() self.maxText.Enable() def OnUp(self, event): """!Moves selected map up, changes order in vector legend""" if self.vectorListCtrl.GetFirstSelected() != -1: pos = self.vectorListCtrl.GetFirstSelected() if pos: idx1 = self.vectorListCtrl.GetItemData(pos) - 1 idx2 = self.vectorListCtrl.GetItemData(pos - 1) + 1 self.vectorListCtrl.SetItemData(pos, idx1) self.vectorListCtrl.SetItemData(pos - 1, idx2) self.vectorListCtrl.SortItems(cmp) if pos > 0: selected = (pos - 1) else: selected = 0 self.vectorListCtrl.Select(selected) def OnDown(self, event): """!Moves selected map down, changes order in vector legend""" if self.vectorListCtrl.GetFirstSelected() != -1: pos = self.vectorListCtrl.GetFirstSelected() if pos != self.vectorListCtrl.GetItemCount() - 1: idx1 = self.vectorListCtrl.GetItemData(pos) + 1 idx2 = self.vectorListCtrl.GetItemData(pos + 1) - 1 self.vectorListCtrl.SetItemData(pos, idx1) self.vectorListCtrl.SetItemData(pos + 1, idx2) self.vectorListCtrl.SortItems(cmp) if pos < self.vectorListCtrl.GetItemCount() -1: selected = (pos + 1) else: selected = self.vectorListCtrl.GetItemCount() -1 self.vectorListCtrl.Select(selected) def OnEditLabel(self, event): """!Change legend label of vector map""" if self.vectorListCtrl.GetFirstSelected() != -1: idx = self.vectorListCtrl.GetFirstSelected() default = self.vectorListCtrl.GetItem(idx, 1).GetText() dlg = wx.TextEntryDialog(self, message = _("Edit legend label:"), caption = _("Edit label"), defaultValue = default, style = wx.OK|wx.CANCEL|wx.CENTRE) if dlg.ShowModal() == wx.ID_OK: new = dlg.GetValue() self.vectorListCtrl.SetStringItem(idx, 1, new) dlg.Destroy() def OnSpan(self, event): self.panelVector.spanTextCtrl.Enable(self.panelVector.spanRadio.GetValue()) def OnFont(self, event): """!Changes default width according to fontsize, width [inch] = fontsize[pt]/24""" ## fontsize = self.panelVector.font['fontCtrl'].GetSelectedFont().GetPointSize() fontsize = self.panelVector.font['fontSizeCtrl'].GetValue() unit = self.unitConv.findUnit(self.panelVector.units['unitsCtrl'].GetStringSelection()) w = fontsize/24. width = self.unitConv.convert(value = w, fromUnit = 'inch', toUnit = unit) self.panelVector.widthCtrl.SetValue("%3.2f" % width) def OnBorder(self, event): """!Enables/disables colorPickerCtrl for border""" self.borderColorCtrl.Enable(self.borderCheck.GetValue()) def updateRasterLegend(self): """!Save information from raster legend dialog to dictionary""" #is raster legend if not self.isRLegend.GetValue(): self.rLegendDict['rLegend'] = False else: self.rLegendDict['rLegend'] = True #units currUnit = self.unitConv.findUnit(self.panelRaster.units['unitsCtrl'].GetStringSelection()) self.rLegendDict['unit'] = currUnit # raster if self.rasterDefault.GetValue(): self.rLegendDict['rasterDefault'] = True self.rLegendDict['raster'] = self.currRaster else: self.rLegendDict['rasterDefault'] = False self.rLegendDict['raster'] = self.rasterSelect.GetValue() if self.rLegendDict['rLegend'] and not self.rLegendDict['raster']: wx.MessageBox(message = _("No raster map selected!"), caption = _('No raster'), style = wx.OK|wx.ICON_ERROR) return False if self.rLegendDict['raster']: # type and range of map rasterType = getRasterType(self.rLegendDict['raster']) if rasterType is None: return False self.rLegendDict['type'] = rasterType #discrete if self.discrete.GetValue(): self.rLegendDict['discrete'] = 'y' else: self.rLegendDict['discrete'] = 'n' # font self.rLegendDict['font'] = self.panelRaster.font['fontCtrl'].GetStringSelection() self.rLegendDict['fontsize'] = self.panelRaster.font['fontSizeCtrl'].GetValue() color = self.panelRaster.font['colorCtrl'].GetColour() self.rLegendDict['color'] = convertRGB(color) # position x = self.unitConv.convert(value = float(self.panelRaster.position['xCtrl'].GetValue()), fromUnit = currUnit, toUnit = 'inch') y = self.unitConv.convert(value = float(self.panelRaster.position['yCtrl'].GetValue()), fromUnit = currUnit, toUnit = 'inch') self.rLegendDict['where'] = (x, y) # estimated size width = self.panelRaster.widthCtrl.GetValue() try: width = float(width) width = self.unitConv.convert(value = width, fromUnit = currUnit, toUnit = 'inch') except ValueError: width = None self.rLegendDict['width'] = width if self.rLegendDict['discrete'] == 'n': height = self.panelRaster.heightOrColumnsCtrl.GetValue() try: height = float(height) height = self.unitConv.convert(value = height, fromUnit = currUnit, toUnit = 'inch') except ValueError: height = None self.rLegendDict['height'] = height else: cols = self.panelRaster.heightOrColumnsCtrl.GetValue() self.rLegendDict['cols'] = cols drawHeight = self.rasterLegend.EstimateHeight(raster = self.rLegendDict['raster'], discrete = self.rLegendDict['discrete'], fontsize = self.rLegendDict['fontsize'], cols = self.rLegendDict['cols'], height = self.rLegendDict['height']) drawWidth = self.rasterLegend.EstimateWidth(raster = self.rLegendDict['raster'], discrete = self.rLegendDict['discrete'], fontsize = self.rLegendDict['fontsize'], cols = self.rLegendDict['cols'], width = self.rLegendDict['width'], paperInstr = self.instruction[self.pageId]) self.rLegendDict['rect'] = wx.Rect2D(x = x, y = y, w = drawWidth, h = drawHeight) # no data if self.rLegendDict['discrete'] == 'y': if self.nodata.GetValue(): self.rLegendDict['nodata'] = 'y' else: self.rLegendDict['nodata'] = 'n' # tickbar elif self.rLegendDict['discrete'] == 'n': if self.ticks.GetValue(): self.rLegendDict['tickbar'] = 'y' else: self.rLegendDict['tickbar'] = 'n' # range if self.range.GetValue(): self.rLegendDict['range'] = True self.rLegendDict['min'] = self.min.GetValue() self.rLegendDict['max'] = self.max.GetValue() else: self.rLegendDict['range'] = False if not self.id[0] in self.instruction: rasterLegend = RasterLegend(self.id[0]) self.instruction.AddInstruction(rasterLegend) self.instruction[self.id[0]].SetInstruction(self.rLegendDict) if self.id[0] not in self.parent.objectId: self.parent.objectId.append(self.id[0]) return True def updateVectorLegend(self): """!Save information from vector legend dialog to dictionary""" vector = self.instruction.FindInstructionByType('vector') if vector: self.vectorId = vector.id else: self.vectorId = None #is vector legend if not self.isVLegend.GetValue(): self.vLegendDict['vLegend'] = False else: self.vLegendDict['vLegend'] = True if self.vLegendDict['vLegend'] == True and self.vectorId is not None: # labels #reindex order idx = 1 for item in range(self.vectorListCtrl.GetItemCount()): if self.vectorListCtrl.IsChecked(item): self.vectorListCtrl.SetItemData(item, idx) idx += 1 else: self.vectorListCtrl.SetItemData(item, 0) if idx == 1: self.vLegendDict['vLegend'] = False else: vList = self.instruction[self.vectorId]['list'] for i, vector in enumerate(vList): item = self.vectorListCtrl.FindItem(start = -1, str = vector[0].split('@')[0]) vList[i][3] = self.vectorListCtrl.GetItemData(item) vList[i][4] = self.vectorListCtrl.GetItem(item, 1).GetText() vmaps = self.instruction.FindInstructionByType('vProperties', list = True) for vmap, vector in zip(vmaps, vList): self.instruction[vmap.id]['lpos'] = vector[3] self.instruction[vmap.id]['label'] = vector[4] #units currUnit = self.unitConv.findUnit(self.panelVector.units['unitsCtrl'].GetStringSelection()) self.vLegendDict['unit'] = currUnit # position x = self.unitConv.convert(value = float(self.panelVector.position['xCtrl'].GetValue()), fromUnit = currUnit, toUnit = 'inch') y = self.unitConv.convert(value = float(self.panelVector.position['yCtrl'].GetValue()), fromUnit = currUnit, toUnit = 'inch') self.vLegendDict['where'] = (x, y) # font self.vLegendDict['font'] = self.panelVector.font['fontCtrl'].GetStringSelection() self.vLegendDict['fontsize'] = self.panelVector.font['fontSizeCtrl'].GetValue() dc = wx.PaintDC(self) font = dc.GetFont() dc.SetFont(wx.Font(pointSize = self.vLegendDict['fontsize'], family = font.GetFamily(), style = font.GetStyle(), weight = wx.FONTWEIGHT_NORMAL)) #size width = self.unitConv.convert(value = float(self.panelVector.widthCtrl.GetValue()), fromUnit = currUnit, toUnit = 'inch') self.vLegendDict['width'] = width self.vLegendDict['cols'] = self.panelVector.colsCtrl.GetValue() if self.panelVector.spanRadio.GetValue() and self.panelVector.spanTextCtrl.GetValue(): self.vLegendDict['span'] = self.panelVector.spanTextCtrl.GetValue() else: self.vLegendDict['span'] = None # size estimation vectors = self.instruction[self.vectorId]['list'] labels = [vector[4] for vector in vectors if vector[3] != 0] extent = dc.GetTextExtent(max(labels, key = len)) wExtent = self.unitConv.convert(value = extent[0], fromUnit = 'pixel', toUnit = 'inch') hExtent = self.unitConv.convert(value = extent[1], fromUnit = 'pixel', toUnit = 'inch') w = (width + wExtent) * self.vLegendDict['cols'] h = len(labels) * hExtent / self.vLegendDict['cols'] h *= 1.1 self.vLegendDict['rect'] = wx.Rect2D(x, y, w, h) #border if self.borderCheck.GetValue(): color = self.borderColorCtrl.GetColour() self.vLegendDict['border'] = convertRGB(color) else: self.vLegendDict['border'] = 'none' if not self.id[1] in self.instruction: vectorLegend = VectorLegend(self.id[1]) self.instruction.AddInstruction(vectorLegend) self.instruction[self.id[1]].SetInstruction(self.vLegendDict) if self.id[1] not in self.parent.objectId: self.parent.objectId.append(self.id[1]) return True def update(self): okR = self.updateRasterLegend() okV = self.updateVectorLegend() if okR and okV: return True return False def updateDialog(self): """!Update legend coordinates after moving""" # raster legend if 'rect' in self.rLegendDict: x, y = self.rLegendDict['rect'][:2] currUnit = self.unitConv.findUnit(self.panelRaster.units['unitsCtrl'].GetStringSelection()) x = self.unitConv.convert(value = x, fromUnit = 'inch', toUnit = currUnit) y = self.unitConv.convert(value = y, fromUnit = 'inch', toUnit = currUnit) self.panelRaster.position['xCtrl'].SetValue("%5.3f" % x) self.panelRaster.position['yCtrl'].SetValue("%5.3f" % y) #update name and type of raster raster = self.instruction.FindInstructionByType('raster') if raster: self.rasterId = raster.id else: self.rasterId = None if raster: currRaster = raster['raster'] else: currRaster = None rasterType = getRasterType(map = currRaster) self.rasterCurrent.SetLabel(_("%(rast)s: type %(type)s") % \ { 'rast' : currRaster, 'type' : str(rasterType) }) # vector legend if 'rect' in self.vLegendDict: x, y = self.vLegendDict['rect'][:2] currUnit = self.unitConv.findUnit(self.panelVector.units['unitsCtrl'].GetStringSelection()) x = self.unitConv.convert(value = x, fromUnit = 'inch', toUnit = currUnit) y = self.unitConv.convert(value = y, fromUnit = 'inch', toUnit = currUnit) self.panelVector.position['xCtrl'].SetValue("%5.3f" % x) self.panelVector.position['yCtrl'].SetValue("%5.3f" % y) # update vector maps if self.instruction.FindInstructionByType('vector'): vectors = sorted(self.instruction.FindInstructionByType('vector')['list'], key = lambda x: x[3]) self.vectorListCtrl.DeleteAllItems() for vector in vectors: index = self.vectorListCtrl.InsertStringItem(sys.maxint, vector[0].split('@')[0]) self.vectorListCtrl.SetStringItem(index, 1, vector[4]) self.vectorListCtrl.SetItemData(index, index) self.vectorListCtrl.CheckItem(index, True) if vector[3] == 0: self.vectorListCtrl.CheckItem(index, False) self.panelVector.colsCtrl.SetRange(1, min(10, len(self.instruction.FindInstructionByType('vector')['list']))) self.panelVector.colsCtrl.SetValue(1) else: self.vectorListCtrl.DeleteAllItems() self.panelVector.colsCtrl.SetRange(0,0) self.panelVector.colsCtrl.SetValue(0) class MapinfoDialog(PsmapDialog): def __init__(self, parent, id, settings): PsmapDialog.__init__(self, parent = parent, id = id, title = "Mapinfo settings", settings = settings) self.objectType = ('mapinfo',) if self.id is not None: self.mapinfo = self.instruction[self.id] self.mapinfoDict = self.mapinfo.GetInstruction() else: self.id = wx.NewId() self.mapinfo = Mapinfo(self.id) self.mapinfoDict = self.mapinfo.GetInstruction() page = self.instruction.FindInstructionByType('page').GetInstruction() self.mapinfoDict['where'] = page['Left'], page['Top'] self.panel = self._mapinfoPanel() self._layout(self.panel) self.OnIsBackground(None) self.OnIsBorder(None) def _mapinfoPanel(self): panel = wx.Panel(parent = self, id = wx.ID_ANY, size = (-1, -1), style = wx.TAB_TRAVERSAL) #panel.SetupScrolling(scroll_x = False, scroll_y = True) border = wx.BoxSizer(wx.VERTICAL) # position box = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Position")) sizer = wx.StaticBoxSizer(box, wx.VERTICAL) gridBagSizer = wx.GridBagSizer (hgap = 5, vgap = 5) gridBagSizer.AddGrowableCol(1) self.AddPosition(parent = panel, dialogDict = self.mapinfoDict) self.AddUnits(parent = panel, dialogDict = self.mapinfoDict) gridBagSizer.Add(panel.units['unitsLabel'], pos = (0,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) gridBagSizer.Add(panel.units['unitsCtrl'], pos = (0,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) gridBagSizer.Add(panel.position['xLabel'], pos = (1,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) gridBagSizer.Add(panel.position['xCtrl'], pos = (1,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) gridBagSizer.Add(panel.position['yLabel'], pos = (2,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) gridBagSizer.Add(panel.position['yCtrl'], pos = (2,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) gridBagSizer.Add(panel.position['comment'], pos = (3,0), span = (1,2), flag =wx.ALIGN_BOTTOM, border = 0) sizer.Add(gridBagSizer, proportion = 1, flag = wx.EXPAND|wx.ALL, border = 5) border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5) # font box = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Font settings")) sizer = wx.StaticBoxSizer(box, wx.VERTICAL) gridBagSizer = wx.GridBagSizer (hgap = 5, vgap = 5) gridBagSizer.AddGrowableCol(1) self.AddFont(parent = panel, dialogDict = self.mapinfoDict)#creates font color too, used below gridBagSizer.Add(panel.font['fontLabel'], pos = (0,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) gridBagSizer.Add(panel.font['fontCtrl'], pos = (0,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) gridBagSizer.Add(panel.font['fontSizeLabel'], pos = (1,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) gridBagSizer.Add(panel.font['fontSizeCtrl'], pos = (1,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) gridBagSizer.Add(panel.font['colorLabel'], pos = (2,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) gridBagSizer.Add(panel.font['colorCtrl'], pos = (2,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) sizer.Add(item = gridBagSizer, proportion = 1, flag = wx.ALL | wx.EXPAND, border = 1) border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5) # colors box = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " %_("Color settings")) sizer = wx.StaticBoxSizer(box, wx.VERTICAL) flexSizer = wx.FlexGridSizer (cols = 2, hgap = 5, vgap = 5) flexSizer.AddGrowableCol(1) self.colors = {} self.colors['borderCtrl'] = wx.CheckBox(panel, id = wx.ID_ANY, label = _("use border color:")) self.colors['backgroundCtrl'] = wx.CheckBox(panel, id = wx.ID_ANY, label = _("use background color:")) self.colors['borderColor'] = wx.ColourPickerCtrl(panel, id = wx.ID_ANY) self.colors['backgroundColor'] = wx.ColourPickerCtrl(panel, id = wx.ID_ANY) if self.mapinfoDict['border'] == None: self.mapinfoDict['border'] = 'none' if self.mapinfoDict['border'] != 'none': self.colors['borderCtrl'].SetValue(True) self.colors['borderColor'].SetColour(convertRGB(self.mapinfoDict['border'])) else: self.colors['borderCtrl'].SetValue(False) self.colors['borderColor'].SetColour(convertRGB('black')) if self.mapinfoDict['background'] == None: self.mapinfoDict['background'] == 'none' if self.mapinfoDict['background'] != 'none': self.colors['backgroundCtrl'].SetValue(True) self.colors['backgroundColor'].SetColour(convertRGB(self.mapinfoDict['background'])) else: self.colors['backgroundCtrl'].SetValue(False) self.colors['backgroundColor'].SetColour(convertRGB('white')) flexSizer.Add(self.colors['borderCtrl'], proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL, border = 0) flexSizer.Add(self.colors['borderColor'], proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL, border = 0) flexSizer.Add(self.colors['backgroundCtrl'], proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL, border = 0) flexSizer.Add(self.colors['backgroundColor'], proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL, border = 0) sizer.Add(item = flexSizer, proportion = 1, flag = wx.ALL | wx.EXPAND, border = 1) border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5) panel.SetSizer(border) self.Bind(wx.EVT_CHECKBOX, self.OnIsBorder, self.colors['borderCtrl']) self.Bind(wx.EVT_CHECKBOX, self.OnIsBackground, self.colors['backgroundCtrl']) return panel def OnIsBackground(self, event): if self.colors['backgroundCtrl'].GetValue(): self.colors['backgroundColor'].Enable() self.update() else: self.colors['backgroundColor'].Disable() def OnIsBorder(self, event): if self.colors['borderCtrl'].GetValue(): self.colors['borderColor'].Enable() self.update() else: self.colors['borderColor'].Disable() def update(self): #units currUnit = self.unitConv.findUnit(self.panel.units['unitsCtrl'].GetStringSelection()) self.mapinfoDict['unit'] = currUnit # position if self.panel.position['xCtrl'].GetValue(): x = self.panel.position['xCtrl'].GetValue() else: x = self.mapinfoDict['where'][0] if self.panel.position['yCtrl'].GetValue(): y = self.panel.position['yCtrl'].GetValue() else: y = self.mapinfoDict['where'][1] x = self.unitConv.convert(value = float(self.panel.position['xCtrl'].GetValue()), fromUnit = currUnit, toUnit = 'inch') y = self.unitConv.convert(value = float(self.panel.position['yCtrl'].GetValue()), fromUnit = currUnit, toUnit = 'inch') self.mapinfoDict['where'] = (x, y) # font self.mapinfoDict['font'] = self.panel.font['fontCtrl'].GetStringSelection() self.mapinfoDict['fontsize'] = self.panel.font['fontSizeCtrl'].GetValue() #colors color = self.panel.font['colorCtrl'].GetColour() self.mapinfoDict['color'] = convertRGB(color) if self.colors['backgroundCtrl'].GetValue(): background = self.colors['backgroundColor'].GetColour() self.mapinfoDict['background'] = convertRGB(background) else: self.mapinfoDict['background'] = 'none' if self.colors['borderCtrl'].GetValue(): border = self.colors['borderColor'].GetColour() self.mapinfoDict['border'] = convertRGB(border) else: self.mapinfoDict['border'] = 'none' # estimation of size self.mapinfoDict['rect'] = self.mapinfo.EstimateRect(self.mapinfoDict) if self.id not in self.instruction: mapinfo = Mapinfo(self.id) self.instruction.AddInstruction(mapinfo) self.instruction[self.id].SetInstruction(self.mapinfoDict) if self.id not in self.parent.objectId: self.parent.objectId.append(self.id) self.updateDialog() return True def updateDialog(self): """!Update mapinfo coordinates, after moving""" x, y = self.mapinfoDict['where'] currUnit = self.unitConv.findUnit(self.panel.units['unitsCtrl'].GetStringSelection()) x = self.unitConv.convert(value = x, fromUnit = 'inch', toUnit = currUnit) y = self.unitConv.convert(value = y, fromUnit = 'inch', toUnit = currUnit) self.panel.position['xCtrl'].SetValue("%5.3f" % x) self.panel.position['yCtrl'].SetValue("%5.3f" % y) class ScalebarDialog(PsmapDialog): """!Dialog for scale bar""" def __init__(self, parent, id, settings): PsmapDialog.__init__(self, parent = parent, id = id, title = "Scale bar settings", settings = settings) self.objectType = ('scalebar',) if self.id is not None: self.scalebar = self.instruction[id] self.scalebarDict = self.scalebar.GetInstruction() else: self.id = wx.NewId() self.scalebar = Scalebar(self.id) self.scalebarDict = self.scalebar.GetInstruction() page = self.instruction.FindInstructionByType('page').GetInstruction() self.scalebarDict['where'] = page['Left'], page['Top'] self.panel = self._scalebarPanel() self._layout(self.panel) self.mapUnit = projInfo()['units'].lower() if projInfo()['proj'] == 'xy': self.mapUnit = 'meters' if self.mapUnit not in self.unitConv.getAllUnits(): wx.MessageBox(message = _("Units of current projection are not supported,\n meters will be used!"), caption = _('Unsupported units'), style = wx.OK|wx.ICON_ERROR) self.mapUnit = 'meters' def _scalebarPanel(self): panel = wx.Panel(parent = self, id = wx.ID_ANY, style = wx.TAB_TRAVERSAL) border = wx.BoxSizer(wx.VERTICAL) # # position # box = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Position")) sizer = wx.StaticBoxSizer(box, wx.VERTICAL) gridBagSizer = wx.GridBagSizer (hgap = 5, vgap = 5) gridBagSizer.AddGrowableCol(1) self.AddUnits(parent = panel, dialogDict = self.scalebarDict) self.AddPosition(parent = panel, dialogDict = self.scalebarDict) if self.scalebarDict['rect']: # set position, ref point is center and not left top corner x = self.unitConv.convert(value = self.scalebarDict['where'][0] - self.scalebarDict['rect'].Get()[2]/2, fromUnit = 'inch', toUnit = self.scalebarDict['unit']) y = self.unitConv.convert(value = self.scalebarDict['where'][1] - self.scalebarDict['rect'].Get()[3]/2, fromUnit = 'inch', toUnit = self.scalebarDict['unit']) panel.position['xCtrl'].SetValue("%5.3f" % x) panel.position['yCtrl'].SetValue("%5.3f" % y) gridBagSizer.Add(panel.units['unitsLabel'], pos = (0,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) gridBagSizer.Add(panel.units['unitsCtrl'], pos = (0,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) gridBagSizer.Add(panel.position['xLabel'], pos = (1,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) gridBagSizer.Add(panel.position['xCtrl'], pos = (1,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) gridBagSizer.Add(panel.position['yLabel'], pos = (2,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) gridBagSizer.Add(panel.position['yCtrl'], pos = (2,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) gridBagSizer.Add(panel.position['comment'], pos = (3,0), span = (1,2), flag =wx.ALIGN_BOTTOM, border = 0) sizer.Add(gridBagSizer, proportion = 1, flag = wx.EXPAND|wx.ALL, border = 5) border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5) # # size # box = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Size")) sizer = wx.StaticBoxSizer(box, wx.VERTICAL) gridBagSizer = wx.GridBagSizer (hgap = 5, vgap = 5) gridBagSizer.AddGrowableCol(1) lengthText = wx.StaticText(panel, id = wx.ID_ANY, label = _("Length:")) heightText = wx.StaticText(panel, id = wx.ID_ANY, label = _("Height:")) self.lengthTextCtrl = wx.TextCtrl(panel, id = wx.ID_ANY, validator = TCValidator('DIGIT_ONLY')) self.lengthTextCtrl.SetToolTipString(_("Scalebar length is given in map units")) self.heightTextCtrl = wx.TextCtrl(panel, id = wx.ID_ANY, validator = TCValidator('DIGIT_ONLY')) self.heightTextCtrl.SetToolTipString(_("Scalebar height is real height on paper")) choices = [_('default')] + self.unitConv.getMapUnitsNames() self.unitsLength = wx.Choice(panel, id = wx.ID_ANY, choices = choices) choices = self.unitConv.getPageUnitsNames() self.unitsHeight = wx.Choice(panel, id = wx.ID_ANY, choices = choices) # set values unitName = self.unitConv.findName(self.scalebarDict['unitsLength']) if unitName: self.unitsLength.SetStringSelection(unitName) else: if self.scalebarDict['unitsLength'] == 'auto': self.unitsLength.SetSelection(0) elif self.scalebarDict['unitsLength'] == 'nautmiles': self.unitsLength.SetStringSelection(self.unitConv.findName("nautical miles")) self.unitsHeight.SetStringSelection(self.unitConv.findName(self.scalebarDict['unitsHeight'])) if self.scalebarDict['length']: self.lengthTextCtrl.SetValue(str(self.scalebarDict['length'])) else: #estimate default reg = grass.region() w = int((reg['e'] - reg['w'])/3) w = round(w, -len(str(w)) + 2) #12345 -> 12000 self.lengthTextCtrl.SetValue(str(w)) h = self.unitConv.convert(value = self.scalebarDict['height'], fromUnit = 'inch', toUnit = self.scalebarDict['unitsHeight']) self.heightTextCtrl.SetValue(str(h)) gridBagSizer.Add(lengthText, pos = (0,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) gridBagSizer.Add(self.lengthTextCtrl, pos = (0, 1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) gridBagSizer.Add(self.unitsLength, pos = (0, 2), flag = wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, border = 0) gridBagSizer.Add(heightText, pos = (1,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) gridBagSizer.Add(self.heightTextCtrl, pos = (1, 1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) gridBagSizer.Add(self.unitsHeight, pos = (1, 2), flag = wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, border = 0) sizer.Add(gridBagSizer, proportion = 1, flag = wx.EXPAND|wx.ALL, border = 5) border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5) # #style # box = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Style")) sizer = wx.StaticBoxSizer(box, wx.VERTICAL) gridBagSizer = wx.GridBagSizer (hgap = 5, vgap = 5) sbTypeText = wx.StaticText(panel, id = wx.ID_ANY, label = _("Type:")) self.sbCombo = wx.combo.BitmapComboBox(panel, style = wx.CB_READONLY) # only temporary, images must be moved away imagePath = os.path.join(globalvar.ETCIMGDIR, "scalebar-fancy.png"), os.path.join(globalvar.ETCIMGDIR, "scalebar-simple.png") for item, path in zip(['fancy', 'simple'], imagePath): if not os.path.exists(path): bitmap = wx.EmptyBitmap(0,0) else: bitmap = wx.Bitmap(path) self.sbCombo.Append(item = '', bitmap = bitmap, clientData = item[0]) #self.sbCombo.Append(item = 'simple', bitmap = wx.Bitmap("./images/scalebar-simple.png"), clientData = 's') if self.scalebarDict['scalebar'] == 'f': self.sbCombo.SetSelection(0) elif self.scalebarDict['scalebar'] == 's': self.sbCombo.SetSelection(1) sbSegmentsText = wx.StaticText(panel, id = wx.ID_ANY, label = _("Number of segments:")) self.sbSegmentsCtrl = wx.SpinCtrl(panel, id = wx.ID_ANY, min = 1, max = 30, initial = 4) self.sbSegmentsCtrl.SetValue(self.scalebarDict['segment']) sbLabelsText1 = wx.StaticText(panel, id = wx.ID_ANY, label = _("Label every ")) sbLabelsText2 = wx.StaticText(panel, id = wx.ID_ANY, label = _("segments")) self.sbLabelsCtrl = wx.SpinCtrl(panel, id = wx.ID_ANY, min = 1, max = 30, initial = 1) self.sbLabelsCtrl.SetValue(self.scalebarDict['numbers']) #font fontsizeText = wx.StaticText(panel, id = wx.ID_ANY, label = _("Font size:")) self.fontsizeCtrl = wx.SpinCtrl(panel, id = wx.ID_ANY, min = 4, max = 30, initial = 10) self.fontsizeCtrl.SetValue(self.scalebarDict['fontsize']) self.backgroundCheck = wx.CheckBox(panel, id = wx.ID_ANY, label = _("transparent text background")) if self.scalebarDict['background'] == 'y': self.backgroundCheck.SetValue(False) else: self.backgroundCheck.SetValue(True) gridBagSizer.Add(sbTypeText, pos = (0,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) gridBagSizer.Add(self.sbCombo, pos = (0,1), span = (1, 2), flag = wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, border = 0) gridBagSizer.Add(sbSegmentsText, pos = (1,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) gridBagSizer.Add(self.sbSegmentsCtrl, pos = (1,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) gridBagSizer.Add(sbLabelsText1, pos = (2,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) gridBagSizer.Add(self.sbLabelsCtrl, pos = (2,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) gridBagSizer.Add(sbLabelsText2, pos = (2,2), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) gridBagSizer.Add(fontsizeText, pos = (3,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) gridBagSizer.Add(self.fontsizeCtrl, pos = (3,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) gridBagSizer.Add(self.backgroundCheck, pos = (4, 0), span = (1,3), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) sizer.Add(gridBagSizer, proportion = 1, flag = wx.ALIGN_CENTER_VERTICAL, border = 5) border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5) panel.SetSizer(border) return panel def update(self): """!Save information from dialog""" #units currUnit = self.unitConv.findUnit(self.panel.units['unitsCtrl'].GetStringSelection()) self.scalebarDict['unit'] = currUnit # position if self.panel.position['xCtrl'].GetValue(): x = self.panel.position['xCtrl'].GetValue() else: x = self.scalebarDict['where'][0] if self.panel.position['yCtrl'].GetValue(): y = self.panel.position['yCtrl'].GetValue() else: y = self.scalebarDict['where'][1] x = self.unitConv.convert(value = float(self.panel.position['xCtrl'].GetValue()), fromUnit = currUnit, toUnit = 'inch') y = self.unitConv.convert(value = float(self.panel.position['yCtrl'].GetValue()), fromUnit = currUnit, toUnit = 'inch') #style self.scalebarDict['scalebar'] = self.sbCombo.GetClientData(self.sbCombo.GetSelection()) self.scalebarDict['segment'] = self.sbSegmentsCtrl.GetValue() self.scalebarDict['numbers'] = self.sbLabelsCtrl.GetValue() self.scalebarDict['fontsize'] = self.fontsizeCtrl.GetValue() if self.backgroundCheck.GetValue(): self.scalebarDict['background'] = 'n' else: self.scalebarDict['background'] = 'y' # size # height self.scalebarDict['unitsHeight'] = self.unitConv.findUnit(self.unitsHeight.GetStringSelection()) try: height = float(self.heightTextCtrl.GetValue()) height = self.unitConv.convert(value = height, fromUnit = self.scalebarDict['unitsHeight'], toUnit = 'inch') except (ValueError, SyntaxError): height = 0.1 #default in inch self.scalebarDict['height'] = height #length if self.unitsLength.GetSelection() == 0: selected = 'auto' else: selected = self.unitConv.findUnit(self.unitsLength.GetStringSelection()) if selected == 'nautical miles': selected = 'nautmiles' self.scalebarDict['unitsLength'] = selected try: length = float(self.lengthTextCtrl.GetValue()) except (ValueError, SyntaxError): wx.MessageBox(message = _("Length of scale bar is not defined"), caption = _('Invalid input'), style = wx.OK|wx.ICON_ERROR) return False self.scalebarDict['length'] = length # estimation of size map = self.instruction.FindInstructionByType('map') if not map: map = self.instruction.FindInstructionByType('initMap') mapId = map.id rectSize = self.scalebar.EstimateSize(scalebarDict = self.scalebarDict, scale = self.instruction[mapId]['scale']) self.scalebarDict['rect'] = wx.Rect2D(x = x, y = y, w = rectSize[0], h = rectSize[1]) self.scalebarDict['where'] = self.scalebarDict['rect'].GetCentre() if self.id not in self.instruction: scalebar = Scalebar(self.id) self.instruction.AddInstruction(scalebar) self.instruction[self.id].SetInstruction(self.scalebarDict) if self.id not in self.parent.objectId: self.parent.objectId.append(self.id) return True def updateDialog(self): """!Update scalebar coordinates, after moving""" x, y = self.scalebarDict['rect'][:2] currUnit = self.unitConv.findUnit(self.panel.units['unitsCtrl'].GetStringSelection()) x = self.unitConv.convert(value = x, fromUnit = 'inch', toUnit = currUnit) y = self.unitConv.convert(value = y, fromUnit = 'inch', toUnit = currUnit) self.panel.position['xCtrl'].SetValue("%5.3f" % x) self.panel.position['yCtrl'].SetValue("%5.3f" % y) class TextDialog(PsmapDialog): def __init__(self, parent, id, settings): PsmapDialog.__init__(self, parent = parent, id = id, title = "Text settings", settings = settings) self.objectType = ('text',) if self.id is not None: self.textDict = self.instruction[id].GetInstruction() else: self.id = wx.NewId() text = Text(self.id) self.textDict = text.GetInstruction() page = self.instruction.FindInstructionByType('page').GetInstruction() self.textDict['where'] = page['Left'], page['Top'] map = self.instruction.FindInstructionByType('map') if not map: map = self.instruction.FindInstructionByType('initMap') self.mapId = map.id self.textDict['east'], self.textDict['north'] = PaperMapCoordinates(map = map, x = self.textDict['where'][0], y = self.textDict['where'][1], paperToMap = True) notebook = wx.Notebook(parent = self, id = wx.ID_ANY, style = wx.BK_DEFAULT) self.textPanel = self._textPanel(notebook) self.positionPanel = self._positionPanel(notebook) self.OnBackground(None) self.OnHighlight(None) self.OnBorder(None) self.OnPositionType(None) self.OnRotation(None) self._layout(notebook) def _textPanel(self, notebook): panel = wx.Panel(parent = notebook, id = wx.ID_ANY, style = wx.TAB_TRAVERSAL) notebook.AddPage(page = panel, text = _("Text")) border = wx.BoxSizer(wx.VERTICAL) # text entry box = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Text")) sizer = wx.StaticBoxSizer(box, wx.HORIZONTAL) textLabel = wx.StaticText(panel, id = wx.ID_ANY, label = _("Enter text:")) self.textCtrl = ExpandoTextCtrl(panel, id = wx.ID_ANY, value = self.textDict['text']) sizer.Add(textLabel, proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL|wx.ALL, border = 5) sizer.Add(self.textCtrl, proportion = 1, flag = wx.ALIGN_CENTER_VERTICAL|wx.ALL, border = 5) border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5) #font box = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Font settings")) sizer = wx.StaticBoxSizer(box, wx.VERTICAL) flexGridSizer = wx.FlexGridSizer (rows = 3, cols = 2, hgap = 5, vgap = 5) flexGridSizer.AddGrowableCol(1) self.AddFont(parent = panel, dialogDict = self.textDict) flexGridSizer.Add(panel.font['fontLabel'], proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL, border = 0) flexGridSizer.Add(panel.font['fontCtrl'], proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL, border = 0) flexGridSizer.Add(panel.font['fontSizeLabel'], proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL, border = 0) flexGridSizer.Add(panel.font['fontSizeCtrl'], proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL, border = 0) flexGridSizer.Add(panel.font['colorLabel'], proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL, border = 0) flexGridSizer.Add(panel.font['colorCtrl'], proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL, border = 0) sizer.Add(item = flexGridSizer, proportion = 1, flag = wx.ALL | wx.EXPAND, border = 1) border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5) #text effects box = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Text effects")) sizer = wx.StaticBoxSizer(box, wx.VERTICAL) gridBagSizer = wx.GridBagSizer (hgap = 5, vgap = 5) self.effect = {} self.effect['backgroundCtrl'] = wx.CheckBox(panel, id = wx.ID_ANY, label = _("text background")) self.effect['backgroundColor'] = wx.ColourPickerCtrl(panel, id = wx.ID_ANY) self.effect['highlightCtrl'] = wx.CheckBox(panel, id = wx.ID_ANY, label = _("highlight")) self.effect['highlightColor'] = wx.ColourPickerCtrl(panel, id = wx.ID_ANY) self.effect['highlightWidth'] = wx.SpinCtrl(panel, id = wx.ID_ANY, size = self.spinCtrlSize, min = 0, max = 5, initial = 1) self.effect['highlightWidthLabel'] = wx.StaticText(panel, id = wx.ID_ANY, label = _("Width (pts):")) self.effect['borderCtrl'] = wx.CheckBox(panel, id = wx.ID_ANY, label = _("text border")) self.effect['borderColor'] = wx.ColourPickerCtrl(panel, id = wx.ID_ANY) self.effect['borderWidth'] = wx.SpinCtrl(panel, id = wx.ID_ANY, size = self.spinCtrlSize, min = 1, max = 25, initial = 1) self.effect['borderWidthLabel'] = wx.StaticText(panel, id = wx.ID_ANY, label = _("Width (pts):")) #set values if self.textDict['background'] == None: self.textDict['background'] = 'none' if self.textDict['background'] != 'none': self.effect['backgroundCtrl'].SetValue(True) self.effect['backgroundColor'].SetColour(convertRGB(self.textDict['background'])) else: self.effect['backgroundCtrl'].SetValue(False) self.effect['backgroundColor'].SetColour(convertRGB('white')) if self.textDict['hcolor'] == None: self.textDict['hcolor'] = 'none' if self.textDict['hcolor'] != 'none': self.effect['highlightCtrl'].SetValue(True) self.effect['highlightColor'].SetColour(convertRGB(self.textDict['hcolor'])) else: self.effect['highlightCtrl'].SetValue(False) self.effect['highlightColor'].SetColour(convertRGB('grey')) self.effect['highlightWidth'].SetValue(float(self.textDict['hwidth'])) if self.textDict['border'] == None: self.textDict['border'] = 'none' if self.textDict['border'] != 'none': self.effect['borderCtrl'].SetValue(True) self.effect['borderColor'].SetColour(convertRGB(self.textDict['border'])) else: self.effect['borderCtrl'].SetValue(False) self.effect['borderColor'].SetColour(convertRGB('black')) self.effect['borderWidth'].SetValue(float(self.textDict['width'])) gridBagSizer.Add(self.effect['backgroundCtrl'], pos = (0,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) gridBagSizer.Add(self.effect['backgroundColor'], pos = (0,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) gridBagSizer.Add(self.effect['highlightCtrl'], pos = (1,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) gridBagSizer.Add(self.effect['highlightColor'], pos = (1,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) gridBagSizer.Add(self.effect['highlightWidthLabel'], pos = (1,2), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) gridBagSizer.Add(self.effect['highlightWidth'], pos = (1,3), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) gridBagSizer.Add(self.effect['borderCtrl'], pos = (2,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) gridBagSizer.Add(self.effect['borderColor'], pos = (2,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) gridBagSizer.Add(self.effect['borderWidthLabel'], pos = (2,2), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) gridBagSizer.Add(self.effect['borderWidth'], pos = (2,3), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) sizer.Add(item = gridBagSizer, proportion = 1, flag = wx.ALL | wx.EXPAND, border = 1) border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5) self.Bind(EVT_ETC_LAYOUT_NEEDED, self.OnRefit, self.textCtrl) self.Bind(wx.EVT_CHECKBOX, self.OnBackground, self.effect['backgroundCtrl']) self.Bind(wx.EVT_CHECKBOX, self.OnHighlight, self.effect['highlightCtrl']) self.Bind(wx.EVT_CHECKBOX, self.OnBorder, self.effect['borderCtrl']) panel.SetSizer(border) panel.Fit() return panel def _positionPanel(self, notebook): panel = wx.Panel(parent = notebook, id = wx.ID_ANY, style = wx.TAB_TRAVERSAL) notebook.AddPage(page = panel, text = _("Position")) border = wx.BoxSizer(wx.VERTICAL) box = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Position")) sizer = wx.StaticBoxSizer(box, wx.HORIZONTAL) gridBagSizer = wx.GridBagSizer(hgap = 5, vgap = 5) gridBagSizer.AddGrowableCol(0) gridBagSizer.AddGrowableCol(1) #Position self.AddExtendedPosition(panel, gridBagSizer, self.textDict) #offset box3 = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " %_("Offset")) sizerO = wx.StaticBoxSizer(box3, wx.VERTICAL) gridBagSizerO = wx.GridBagSizer (hgap = 5, vgap = 5) self.xoffLabel = wx.StaticText(panel, id = wx.ID_ANY, label = _("horizontal (pts):")) self.yoffLabel = wx.StaticText(panel, id = wx.ID_ANY, label = _("vertical (pts):")) self.xoffCtrl = wx.SpinCtrl(panel, id = wx.ID_ANY, size = (50, -1), min = -50, max = 50, initial = 0) self.yoffCtrl = wx.SpinCtrl(panel, id = wx.ID_ANY, size = (50, -1), min = -50, max = 50, initial = 0) self.xoffCtrl.SetValue(self.textDict['xoffset']) self.yoffCtrl.SetValue(self.textDict['yoffset']) gridBagSizerO.Add(self.xoffLabel, pos = (0,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) gridBagSizerO.Add(self.yoffLabel, pos = (1,0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) gridBagSizerO.Add(self.xoffCtrl, pos = (0,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) gridBagSizerO.Add(self.yoffCtrl, pos = (1,1), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) sizerO.Add(gridBagSizerO, proportion = 1, flag = wx.EXPAND|wx.ALL, border = 5) gridBagSizer.Add(sizerO, pos = (3,0), flag = wx.ALIGN_CENTER_HORIZONTAL|wx.EXPAND, border = 0) # reference point box = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " %_(" Reference point")) sizerR = wx.StaticBoxSizer(box, wx.VERTICAL) flexSizer = wx.FlexGridSizer(rows = 3, cols = 3, hgap = 5, vgap = 5) flexSizer.AddGrowableCol(0) flexSizer.AddGrowableCol(1) flexSizer.AddGrowableCol(2) ref = [] for row in ["upper", "center", "lower"]: for col in ["left", "center", "right"]: ref.append(row + " " + col) self.radio = [wx.RadioButton(panel, id = wx.ID_ANY, label = '', style = wx.RB_GROUP, name = ref[0])] self.radio[0].SetValue(False) flexSizer.Add(self.radio[0], proportion = 0, flag = wx.ALIGN_CENTER, border = 0) for i in range(1,9): self.radio.append(wx.RadioButton(panel, id = wx.ID_ANY, label = '', name = ref[i])) self.radio[-1].SetValue(False) flexSizer.Add(self.radio[-1], proportion = 0, flag = wx.ALIGN_CENTER, border = 0) self.FindWindowByName(self.textDict['ref']).SetValue(True) sizerR.Add(flexSizer, proportion = 1, flag = wx.EXPAND, border = 0) gridBagSizer.Add(sizerR, pos = (3,1), flag = wx.ALIGN_LEFT|wx.EXPAND, border = 0) sizer.Add(gridBagSizer, proportion = 1, flag = wx.ALIGN_CENTER_VERTICAL|wx.ALL, border = 5) border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5) #rotation box = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Text rotation")) sizer = wx.StaticBoxSizer(box, wx.HORIZONTAL) self.rotCtrl = wx.CheckBox(panel, id = wx.ID_ANY, label = _("rotate text (counterclockwise)")) self.rotValue = wx.SpinCtrl(panel, wx.ID_ANY, size = (50, -1), min = 0, max = 360, initial = 0) if self.textDict['rotate']: self.rotValue.SetValue(int(self.textDict['rotate'])) self.rotCtrl.SetValue(True) else: self.rotValue.SetValue(0) self.rotCtrl.SetValue(False) sizer.Add(self.rotCtrl, proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT|wx.ALL, border = 5) sizer.Add(self.rotValue, proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT|wx.ALL, border = 5) border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5) panel.SetSizer(border) panel.Fit() self.Bind(wx.EVT_RADIOBUTTON, self.OnPositionType, panel.position['toPaper']) self.Bind(wx.EVT_RADIOBUTTON, self.OnPositionType, panel.position['toMap']) self.Bind(wx.EVT_CHECKBOX, self.OnRotation, self.rotCtrl) return panel def OnRefit(self, event): self.Fit() def OnRotation(self, event): if self.rotCtrl.GetValue(): self.rotValue.Enable() else: self.rotValue.Disable() def OnPositionType(self, event): if self.positionPanel.position['toPaper'].GetValue(): for widget in self.gridBagSizerP.GetChildren(): widget.GetWindow().Enable() for widget in self.gridBagSizerM.GetChildren(): widget.GetWindow().Disable() else: for widget in self.gridBagSizerM.GetChildren(): widget.GetWindow().Enable() for widget in self.gridBagSizerP.GetChildren(): widget.GetWindow().Disable() def OnBackground(self, event): if self.effect['backgroundCtrl'].GetValue(): self.effect['backgroundColor'].Enable() self.update() else: self.effect['backgroundColor'].Disable() def OnHighlight(self, event): if self.effect['highlightCtrl'].GetValue(): self.effect['highlightColor'].Enable() self.effect['highlightWidth'].Enable() self.effect['highlightWidthLabel'].Enable() self.update() else: self.effect['highlightColor'].Disable() self.effect['highlightWidth'].Disable() self.effect['highlightWidthLabel'].Disable() def OnBorder(self, event): if self.effect['borderCtrl'].GetValue(): self.effect['borderColor'].Enable() self.effect['borderWidth'].Enable() self.effect['borderWidthLabel'].Enable() self.update() else: self.effect['borderColor'].Disable() self.effect['borderWidth'].Disable() self.effect['borderWidthLabel'].Disable() def update(self): #text self.textDict['text'] = self.textCtrl.GetValue() if not self.textDict['text']: wx.MessageBox(_("No text entered!"), _("Error")) return False #font self.textDict['font'] = self.textPanel.font['fontCtrl'].GetStringSelection() self.textDict['fontsize'] = self.textPanel.font['fontSizeCtrl'].GetValue() color = self.textPanel.font['colorCtrl'].GetColour() self.textDict['color'] = convertRGB(color) #effects if self.effect['backgroundCtrl'].GetValue(): background = self.effect['backgroundColor'].GetColour() self.textDict['background'] = convertRGB(background) else: self.textDict['background'] = 'none' if self.effect['borderCtrl'].GetValue(): border = self.effect['borderColor'].GetColour() self.textDict['border'] = convertRGB(border) else: self.textDict['border'] = 'none' self.textDict['width'] = self.effect['borderWidth'].GetValue() if self.effect['highlightCtrl'].GetValue(): highlight = self.effect['highlightColor'].GetColour() self.textDict['hcolor'] = convertRGB(highlight) else: self.textDict['hcolor'] = 'none' self.textDict['hwidth'] = self.effect['highlightWidth'].GetValue() #offset self.textDict['xoffset'] = self.xoffCtrl.GetValue() self.textDict['yoffset'] = self.yoffCtrl.GetValue() #position if self.positionPanel.position['toPaper'].GetValue(): self.textDict['XY'] = True currUnit = self.unitConv.findUnit(self.positionPanel.units['unitsCtrl'].GetStringSelection()) self.textDict['unit'] = currUnit if self.positionPanel.position['xCtrl'].GetValue(): x = self.positionPanel.position['xCtrl'].GetValue() else: x = self.textDict['where'][0] if self.positionPanel.position['yCtrl'].GetValue(): y = self.positionPanel.position['yCtrl'].GetValue() else: y = self.textDict['where'][1] x = self.unitConv.convert(value = float(x), fromUnit = currUnit, toUnit = 'inch') y = self.unitConv.convert(value = float(y), fromUnit = currUnit, toUnit = 'inch') self.textDict['where'] = x, y self.textDict['east'], self.textDict['north'] = PaperMapCoordinates(self.instruction[self.mapId], x, y, paperToMap = True) else: self.textDict['XY'] = False if self.positionPanel.position['eCtrl'].GetValue(): self.textDict['east'] = self.positionPanel.position['eCtrl'].GetValue() else: self.textDict['east'] = self.textDict['east'] if self.positionPanel.position['nCtrl'].GetValue(): self.textDict['north'] = self.positionPanel.position['nCtrl'].GetValue() else: self.textDict['north'] = self.textDict['north'] self.textDict['where'] = PaperMapCoordinates(map = self.instruction[self.mapId], x = float(self.textDict['east']), y = float(self.textDict['north']), paperToMap = False) #rotation if self.rotCtrl.GetValue(): self.textDict['rotate'] = self.rotValue.GetValue() else: self.textDict['rotate'] = None #reference point for radio in self.radio: if radio.GetValue() == True: self.textDict['ref'] = radio.GetName() if self.id not in self.instruction: text = Text(self.id) self.instruction.AddInstruction(text) self.instruction[self.id].SetInstruction(self.textDict) if self.id not in self.parent.objectId: self.parent.objectId.append(self.id) # self.updateDialog() return True def updateDialog(self): """!Update text coordinates, after moving""" # XY coordinates x, y = self.textDict['where'][:2] currUnit = self.unitConv.findUnit(self.positionPanel.units['unitsCtrl'].GetStringSelection()) x = self.unitConv.convert(value = x, fromUnit = 'inch', toUnit = currUnit) y = self.unitConv.convert(value = y, fromUnit = 'inch', toUnit = currUnit) self.positionPanel.position['xCtrl'].SetValue("%5.3f" % x) self.positionPanel.position['yCtrl'].SetValue("%5.3f" % y) # EN coordinates e, n = self.textDict['east'], self.textDict['north'] self.positionPanel.position['eCtrl'].SetValue(str(self.textDict['east'])) self.positionPanel.position['nCtrl'].SetValue(str(self.textDict['north'])) class ImageDialog(PsmapDialog): """!Dialog for setting image properties. It's base dialog for North Arrow dialog. """ def __init__(self, parent, id, settings, imagePanelName = _("Image")): PsmapDialog.__init__(self, parent = parent, id = id, title = "Image settings", settings = settings) self.objectType = ('image',) if self.id is not None: self.imageObj = self.instruction[self.id] self.imageDict = self.instruction[id].GetInstruction() else: self.id = wx.NewId() self.imageObj = self._newObject() self.imageDict = self.imageObj.GetInstruction() page = self.instruction.FindInstructionByType('page').GetInstruction() self.imageDict['where'] = page['Left'], page['Top'] map = self.instruction.FindInstructionByType('map') if not map: map = self.instruction.FindInstructionByType('initMap') self.mapId = map.id self.imageDict['east'], self.imageDict['north'] = PaperMapCoordinates(map = map, x = self.imageDict['where'][0], y = self.imageDict['where'][1], paperToMap = True) notebook = wx.Notebook(parent = self, id = wx.ID_ANY, style = wx.BK_DEFAULT) self.imagePanelName = imagePanelName self.imagePanel = self._imagePanel(notebook) self.positionPanel = self._positionPanel(notebook) self.OnPositionType(None) if self.imageDict['epsfile']: self.imagePanel.image['dir'].SetValue(os.path.dirname(self.imageDict['epsfile'])) else: self.imagePanel.image['dir'].SetValue(self._getImageDirectory()) self.OnDirChanged(None) self._layout(notebook) def _newObject(self): """!Create corresponding instruction object""" return Image(self.id, self.instruction) def _imagePanel(self, notebook): panel = wx.Panel(parent = notebook, id = wx.ID_ANY, size = (-1, -1), style = wx.TAB_TRAVERSAL) notebook.AddPage(page = panel, text = self.imagePanelName) border = wx.BoxSizer(wx.VERTICAL) # # choose image # box = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Image")) sizer = wx.StaticBoxSizer(box, wx.VERTICAL) # choose directory panel.image = {} if self.imageDict['epsfile']: startDir = os.path.dirname(self.imageDict['epsfile']) else: startDir = self._getImageDirectory() dir = filebrowse.DirBrowseButton(parent = panel, id = wx.ID_ANY, labelText = _("Choose a directory:"), dialogTitle = _("Choose a directory with images"), buttonText = _('Browse'), startDirectory = startDir, changeCallback = self.OnDirChanged) panel.image['dir'] = dir sizer.Add(item = dir, proportion = 0, flag = wx.EXPAND, border = 0) # image list hSizer = wx.BoxSizer(wx.HORIZONTAL) imageList = wx.ListBox(parent = panel, id = wx.ID_ANY) panel.image['list'] = imageList imageList.Bind(wx.EVT_LISTBOX, self.OnImageSelectionChanged) hSizer.Add(item = imageList, proportion = 1, flag = wx.EXPAND | wx.RIGHT, border = 10) # image preview vSizer = wx.BoxSizer(wx.VERTICAL) self.previewSize = (150, 150) img = wx.EmptyImage(*self.previewSize) panel.image['preview'] = wx.StaticBitmap(parent = panel, id = wx.ID_ANY, bitmap = wx.BitmapFromImage(img)) vSizer.Add(item = panel.image['preview'], proportion = 0, flag = wx.EXPAND | wx.BOTTOM, border = 5) panel.image['sizeInfo'] = wx.StaticText(parent = panel, id = wx.ID_ANY) vSizer.Add(item = panel.image['sizeInfo'], proportion = 0, flag = wx.ALIGN_CENTER, border = 0) hSizer.Add(item = vSizer, proportion = 0, flag = wx.EXPAND, border = 0) sizer.Add(item = hSizer, proportion = 1, flag = wx.EXPAND | wx.ALL, border = 3) epsInfo = wx.StaticText(parent = panel, id = wx.ID_ANY, label = _("Note: only EPS format supported")) sizer.Add(item = epsInfo, proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL | wx.ALL, border = 3) border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5) # # rotation # box = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Scale And Rotation")) sizer = wx.StaticBoxSizer(box, wx.VERTICAL) gridSizer = wx.GridBagSizer(hgap = 5, vgap = 5) scaleLabel = wx.StaticText(parent = panel, id = wx.ID_ANY, label = _("Scale:")) if fs: panel.image['scale'] = fs.FloatSpin(panel, id = wx.ID_ANY, min_val = 0, max_val = 50, increment = 0.5, value = 1, style = fs.FS_RIGHT, size = self.spinCtrlSize) panel.image['scale'].SetFormat("%f") panel.image['scale'].SetDigits(1) else: panel.image['scale'] = wx.TextCtrl(panel, id = wx.ID_ANY, size = self.spinCtrlSize, validator = TCValidator(flag = 'DIGIT_ONLY')) if self.imageDict['scale']: if fs: value = float(self.imageDict['scale']) else: value = str(self.imageDict['scale']) else: if fs: value = 0 else: value = '0' panel.image['scale'].SetValue(value) gridSizer.Add(item = scaleLabel, pos = (0, 0), flag = wx.ALIGN_CENTER_VERTICAL) gridSizer.Add(item = panel.image['scale'], pos = (0, 1), flag = wx.ALIGN_CENTER_VERTICAL) rotLabel = wx.StaticText(parent = panel, id = wx.ID_ANY, label = _("Rotation angle (deg):")) if fs: panel.image['rotate'] = fs.FloatSpin(panel, id = wx.ID_ANY, min_val = 0, max_val = 360, increment = 0.5, value = 0, style = fs.FS_RIGHT, size = self.spinCtrlSize) panel.image['rotate'].SetFormat("%f") panel.image['rotate'].SetDigits(1) else: panel.image['rotate'] = wx.SpinCtrl(parent = panel, id = wx.ID_ANY, size = self.spinCtrlSize, min = 0, max = 359, initial = 0) panel.image['rotate'].SetToolTipString(_("Counterclockwise rotation in degrees")) if self.imageDict['rotate']: panel.image['rotate'].SetValue(int(self.imageDict['rotate'])) else: panel.image['rotate'].SetValue(0) gridSizer.Add(item = rotLabel, pos = (1, 0), flag = wx.ALIGN_CENTER_VERTICAL, border = 0) gridSizer.Add(item = panel.image['rotate'], pos = (1, 1), flag = wx.ALIGN_CENTER_VERTICAL) self._addConvergence(panel = panel, gridBagSizer = gridSizer) sizer.Add(item = gridSizer, proportion = 0, flag = wx.EXPAND | wx.ALL, border = 5) border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5) panel.SetSizer(border) panel.Fit() return panel def _positionPanel(self, notebook): panel = wx.Panel(parent = notebook, id = wx.ID_ANY, size = (-1, -1), style = wx.TAB_TRAVERSAL) notebook.AddPage(page = panel, text = _("Position")) border = wx.BoxSizer(wx.VERTICAL) # # set position # box = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Position")) sizer = wx.StaticBoxSizer(box, wx.VERTICAL) gridBagSizer = wx.GridBagSizer(hgap = 5, vgap = 5) gridBagSizer.AddGrowableCol(0) gridBagSizer.AddGrowableCol(1) self.AddExtendedPosition(panel, gridBagSizer, self.imageDict) self.Bind(wx.EVT_RADIOBUTTON, self.OnPositionType, panel.position['toPaper']) self.Bind(wx.EVT_RADIOBUTTON, self.OnPositionType, panel.position['toMap']) sizer.Add(gridBagSizer, proportion = 1, flag = wx.ALIGN_CENTER_VERTICAL| wx.ALL, border = 5) border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5) panel.SetSizer(border) panel.Fit() return panel def OnDirChanged(self, event): """!Image directory changed""" path = self.imagePanel.image['dir'].GetValue() try: files = os.listdir(path) except OSError: # no such directory files = [] imageList = [] # no setter for startDirectory? try: self.imagePanel.image['dir'].startDirectory = path except AttributeError: # for sure pass for file in files: if os.path.splitext(file)[1].lower() == '.eps': imageList.append(file) imageList.sort() self.imagePanel.image['list'].SetItems(imageList) if self.imageDict['epsfile']: file = os.path.basename(self.imageDict['epsfile']) self.imagePanel.image['list'].SetStringSelection(file) else: self.imagePanel.image['list'].SetSelection(0) self.OnImageSelectionChanged(None) def OnPositionType(self, event): if self.positionPanel.position['toPaper'].GetValue(): for widget in self.gridBagSizerP.GetChildren(): widget.GetWindow().Enable() for widget in self.gridBagSizerM.GetChildren(): widget.GetWindow().Disable() else: for widget in self.gridBagSizerM.GetChildren(): widget.GetWindow().Enable() for widget in self.gridBagSizerP.GetChildren(): widget.GetWindow().Disable() def _getImageDirectory(self): """!Default image directory""" return os.getcwd() def _addConvergence(self, panel, gridBagSizer): pass def OnImageSelectionChanged(self, event): """!Image selected, show preview and size""" if not self.imagePanel.image['dir']: # event is emitted when closing dialog an it causes error return if not havePILImage: self.DrawWarningText(_("PIL\nmissing")) return imageName = self.imagePanel.image['list'].GetStringSelection() if not imageName: self.ClearPreview() return basePath = self.imagePanel.image['dir'].GetValue() file = os.path.join(basePath, imageName) if not os.path.exists(file): return if os.path.splitext(file)[1].lower() == '.eps': try: pImg = PILImage.open(file) img = PilImageToWxImage(pImg) except IOError, e: GError(message = _("Unable to read file %s") % file) self.ClearPreview() return self.SetSizeInfoLabel(img) img = self.ScaleToPreview(img) bitmap = img.ConvertToBitmap() self.DrawBitmap(bitmap) else: # TODO: read other formats and convert by PIL to eps pass def ScaleToPreview(self, img): """!Scale image to preview size""" w = img.GetWidth() h = img.GetHeight() if w <= self.previewSize[0] and h <= self.previewSize[1]: return img if w > h: newW = self.previewSize[0] newH = self.previewSize[0] * h / w else: newH = self.previewSize[0] newW = self.previewSize[0] * w / h return img.Scale(newW, newH, wx.IMAGE_QUALITY_HIGH) def DrawWarningText(self, warning): """!Draw text on preview window""" buffer = wx.EmptyBitmap(*self.previewSize) dc = wx.MemoryDC() dc.SelectObject(buffer) dc.SetBrush(wx.Brush(wx.Color(250, 250, 250))) dc.Clear() extent = dc.GetTextExtent(warning) posX = self.previewSize[0] / 2 - extent[0] / 2 posY = self.previewSize[1] / 2 - extent[1] / 2 dc.DrawText(warning, posX, posY) self.imagePanel.image['preview'].SetBitmap(buffer) dc.SelectObject(wx.NullBitmap) def DrawBitmap(self, bitmap): """!Draw bitmap, center it if smaller than preview size""" if bitmap.GetWidth() <= self.previewSize[0] and bitmap.GetHeight() <= self.previewSize[1]: buffer = wx.EmptyBitmap(*self.previewSize) dc = wx.MemoryDC() dc.SelectObject(buffer) dc.SetBrush(dc.GetBrush()) dc.Clear() posX = self.previewSize[0] / 2 - bitmap.GetWidth() / 2 posY = self.previewSize[1] / 2 - bitmap.GetHeight() / 2 dc.DrawBitmap(bitmap, posX, posY) self.imagePanel.image['preview'].SetBitmap(buffer) dc.SelectObject(wx.NullBitmap) else: self.imagePanel.image['preview'].SetBitmap(bitmap) def SetSizeInfoLabel(self, image): """!Update image size label""" self.imagePanel.image['sizeInfo'].SetLabel(_("size: %s x %s pts") % (image.GetWidth(), image.GetHeight())) self.imagePanel.image['sizeInfo'].GetContainingSizer().Layout() def ClearPreview(self): """!Clear preview window""" buffer = wx.EmptyBitmap(*self.previewSize) dc = wx.MemoryDC() dc.SelectObject(buffer) dc.SetBrush(wx.WHITE_BRUSH) dc.Clear() mask = wx.Mask(buffer, wx.WHITE) buffer.SetMask(mask) self.imagePanel.image['preview'].SetBitmap(buffer) dc.SelectObject(wx.NullBitmap) def update(self): # epsfile selected = self.imagePanel.image['list'].GetStringSelection() basePath = self.imagePanel.image['dir'].GetValue() if not selected: gcmd.GMessage(parent = self, message = _("No image selected.")) return False self.imageDict['epsfile'] = os.path.join(basePath, selected) #position if self.positionPanel.position['toPaper'].GetValue(): self.imageDict['XY'] = True currUnit = self.unitConv.findUnit(self.positionPanel.units['unitsCtrl'].GetStringSelection()) self.imageDict['unit'] = currUnit if self.positionPanel.position['xCtrl'].GetValue(): x = self.positionPanel.position['xCtrl'].GetValue() else: x = self.imageDict['where'][0] if self.positionPanel.position['yCtrl'].GetValue(): y = self.positionPanel.position['yCtrl'].GetValue() else: y = self.imageDict['where'][1] x = self.unitConv.convert(value = float(x), fromUnit = currUnit, toUnit = 'inch') y = self.unitConv.convert(value = float(y), fromUnit = currUnit, toUnit = 'inch') self.imageDict['where'] = x, y else: self.imageDict['XY'] = False if self.positionPanel.position['eCtrl'].GetValue(): e = self.positionPanel.position['eCtrl'].GetValue() else: self.imageDict['east'] = self.imageDict['east'] if self.positionPanel.position['nCtrl'].GetValue(): n = self.positionPanel.position['nCtrl'].GetValue() else: self.imageDict['north'] = self.imageDict['north'] x, y = PaperMapCoordinates(map = self.instruction[self.mapId], x = float(self.imageDict['east']), y = float(self.imageDict['north']), paperToMap = False) #rotation rot = self.imagePanel.image['rotate'].GetValue() if rot == 0: self.imageDict['rotate'] = None else: self.imageDict['rotate'] = rot #scale self.imageDict['scale'] = self.imagePanel.image['scale'].GetValue() # scale w, h = self.imageObj.GetImageOrigSize(self.imageDict['epsfile']) if self.imageDict['rotate']: self.imageDict['size'] = BBoxAfterRotation(w, h, self.imageDict['rotate']) else: self.imageDict['size'] = w, h w = self.unitConv.convert(value = self.imageDict['size'][0], fromUnit = 'point', toUnit = 'inch') h = self.unitConv.convert(value = self.imageDict['size'][1], fromUnit = 'point', toUnit = 'inch') self.imageDict['rect'] = wx.Rect2D(x = x, y = y, w = w * self.imageDict['scale'], h = h * self.imageDict['scale']) if self.id not in self.instruction: image = self._newObject() self.instruction.AddInstruction(image) self.instruction[self.id].SetInstruction(self.imageDict) if self.id not in self.parent.objectId: self.parent.objectId.append(self.id) return True def updateDialog(self): """!Update text coordinates, after moving""" # XY coordinates x, y = self.imageDict['where'][:2] currUnit = self.unitConv.findUnit(self.positionPanel.units['unitsCtrl'].GetStringSelection()) x = self.unitConv.convert(value = x, fromUnit = 'inch', toUnit = currUnit) y = self.unitConv.convert(value = y, fromUnit = 'inch', toUnit = currUnit) self.positionPanel.position['xCtrl'].SetValue("%5.3f" % x) self.positionPanel.position['yCtrl'].SetValue("%5.3f" % y) # EN coordinates e, n = self.imageDict['east'], self.imageDict['north'] self.positionPanel.position['eCtrl'].SetValue(str(self.imageDict['east'])) self.positionPanel.position['nCtrl'].SetValue(str(self.imageDict['north'])) class NorthArrowDialog(ImageDialog): def __init__(self, parent, id, settings): ImageDialog.__init__(self, parent = parent, id = id, settings = settings, imagePanelName = _("North Arrow")) self.objectType = ('northArrow',) self.SetTitle(_("North Arrow settings")) def _newObject(self): return NorthArrow(self.id, self.instruction) def _getImageDirectory(self): gisbase = os.getenv("GISBASE") return os.path.join(gisbase, 'etc', 'paint', 'decorations') def _addConvergence(self, panel, gridBagSizer): convergence = wx.Button(parent = panel, id = wx.ID_ANY, label = _("Compute convergence")) gridBagSizer.Add(item = convergence, pos = (1, 2), flag = wx.ALIGN_CENTER_VERTICAL | wx.EXPAND) convergence.Bind(wx.EVT_BUTTON, self.OnConvergence) panel.image['convergence'] = convergence def OnConvergence(self, event): ret = RunCommand('g.region', read = True, flags = 'ng') if ret: convergence = float(ret.strip().split('=')[1]) if convergence < 0: self.imagePanel.image['rotate'].SetValue(abs(convergence)) else: self.imagePanel.image['rotate'].SetValue(360 - convergence) def convertRGB(rgb): """!Converts wx.Colour(r,g,b,a) to string 'r:g:b' or named color, or named color/r:g:b string to wx.Colour, depending on input""" # transform a wx.Colour tuple into an r:g:b string if type(rgb) == wx.Colour: for name, color in grass.named_colors.items(): if rgb.Red() == int(color[0] * 255) and\ rgb.Green() == int(color[1] * 255) and\ rgb.Blue() == int(color[2] * 255): return name return str(rgb.Red()) + ':' + str(rgb.Green()) + ':' + str(rgb.Blue()) # transform a GRASS named color or an r:g:b string into a wx.Colour tuple else: color = (grass.parse_color(rgb)[0]*255, grass.parse_color(rgb)[1]*255, grass.parse_color(rgb)[2]*255) color = wx.Color(*color) if color.IsOk(): return color else: return None def PaperMapCoordinates(map, x, y, paperToMap = True): """!Converts paper (inch) coordinates -> map coordinates""" unitConv = UnitConversion() currRegionDict = grass.region() cornerEasting, cornerNorthing = currRegionDict['w'], currRegionDict['n'] xMap = map['rect'][0] yMap = map['rect'][1] widthMap = map['rect'][2] * 0.0254 # to meter heightMap = map['rect'][3] * 0.0254 xScale = widthMap / abs(currRegionDict['w'] - currRegionDict['e']) yScale = heightMap / abs(currRegionDict['n'] - currRegionDict['s']) currScale = (xScale + yScale) / 2 if not paperToMap: textEasting, textNorthing = x, y eastingDiff = textEasting - cornerEasting if currRegionDict['w'] > currRegionDict['e']: eastingDiff = - eastingDiff else: eastingDiff = eastingDiff northingDiff = textNorthing - cornerNorthing if currRegionDict['n'] > currRegionDict['s']: northingDiff = - northingDiff else: northingDiff = northingDiff xPaper = xMap + unitConv.convert(value = eastingDiff, fromUnit = 'meter', toUnit = 'inch') * currScale yPaper = yMap + unitConv.convert(value = northingDiff, fromUnit = 'meter', toUnit = 'inch') * currScale return xPaper, yPaper else: if currRegionDict['w'] < currRegionDict['e']: eastingDiff = (x - xMap) else: eastingDiff = (xMap - x) if currRegionDict['n'] < currRegionDict['s']: northingDiff = (y - yMap) else: northingDiff = (yMap - y) textEasting = cornerEasting + unitConv.convert(value = eastingDiff, fromUnit = 'inch', toUnit = 'meter') / currScale textNorthing = cornerNorthing + unitConv.convert(value = northingDiff, fromUnit = 'inch', toUnit = 'meter') / currScale return int(textEasting), int(textNorthing) def AutoAdjust(self, scaleType, rect, map = None, mapType = None, region = None): """!Computes map scale, center and map frame rectangle to fit region (scale is not fixed)""" currRegionDict = {} if scaleType == 0 and map:# automatic, region from raster or vector res = '' if mapType == 'raster': try: res = grass.read_command("g.region", flags = 'gu', rast = map) except grass.ScriptError: pass elif mapType == 'vector': res = grass.read_command("g.region", flags = 'gu', vect = map) currRegionDict = grass.parse_key_val(res, val_type = float) elif scaleType == 1 and region: # saved region res = grass.read_command("g.region", flags = 'gu', region = region) currRegionDict = grass.parse_key_val(res, val_type = float) elif scaleType == 2: # current region env = grass.gisenv() windFilePath = os.path.join(env['GISDBASE'], env['LOCATION_NAME'], env['MAPSET'], 'WIND') try: windFile = open(windFilePath, 'r').read() except IOError: currRegionDict = grass.region() regionDict = grass.parse_key_val(windFile, sep = ':', val_type = float) region = grass.read_command("g.region", flags = 'gu', n = regionDict['north'], s = regionDict['south'], e = regionDict['east'], w = regionDict['west']) currRegionDict = grass.parse_key_val(region, val_type = float) else: return None, None, None if not currRegionDict: return None, None, None rX = rect.x rY = rect.y rW = rect.width rH = rect.height if not hasattr(self, 'unitConv'): self.unitConv = UnitConversion(self) toM = 1 if projInfo()['proj'] != 'xy': toM = float(projInfo()['meters']) mW = self.unitConv.convert(value = (currRegionDict['e'] - currRegionDict['w']) * toM, fromUnit = 'meter', toUnit = 'inch') mH = self.unitConv.convert(value = (currRegionDict['n'] - currRegionDict['s']) * toM, fromUnit = 'meter', toUnit = 'inch') scale = min(rW/mW, rH/mH) if rW/rH > mW/mH: x = rX - (rH*(mW/mH) - rW)/2 y = rY rWNew = rH*(mW/mH) rHNew = rH else: x = rX y = rY - (rW*(mH/mW) - rH)/2 rHNew = rW*(mH/mW) rWNew = rW # center cE = (currRegionDict['w'] + currRegionDict['e'])/2 cN = (currRegionDict['n'] + currRegionDict['s'])/2 return scale, (cE, cN), wx.Rect2D(x, y, rWNew, rHNew) #inch def SetResolution(dpi, width, height): """!If resolution is too high, lower it @param dpi max DPI @param width map frame width @param height map frame height """ region = grass.region() if region['cols'] > width * dpi or region['rows'] > height * dpi: rows = height * dpi cols = width * dpi RunCommand('g.region', rows = rows, cols = cols) def ComputeSetRegion(self, mapDict): """!Computes and sets region from current scale, map center coordinates and map rectangle""" if mapDict['scaleType'] == 3: # fixed scale scale = mapDict['scale'] if not hasattr(self, 'unitConv'): self.unitConv = UnitConversion(self) fromM = 1 if projInfo()['proj'] != 'xy': fromM = float(projInfo()['meters']) rectHalfInch = (mapDict['rect'].width/2, mapDict['rect'].height/2) rectHalfMeter = (self.unitConv.convert(value = rectHalfInch[0], fromUnit = 'inch', toUnit = 'meter')/ fromM /scale, self.unitConv.convert(value = rectHalfInch[1], fromUnit = 'inch', toUnit = 'meter')/ fromM /scale) centerE = mapDict['center'][0] centerN = mapDict['center'][1] raster = self.instruction.FindInstructionByType('raster') if raster: rasterId = raster.id else: rasterId = None if rasterId: RunCommand('g.region', n = ceil(centerN + rectHalfMeter[1]), s = floor(centerN - rectHalfMeter[1]), e = ceil(centerE + rectHalfMeter[0]), w = floor(centerE - rectHalfMeter[0]), rast = self.instruction[rasterId]['raster']) else: RunCommand('g.region', n = ceil(centerN + rectHalfMeter[1]), s = floor(centerN - rectHalfMeter[1]), e = ceil(centerE + rectHalfMeter[0]), w = floor(centerE - rectHalfMeter[0])) def projInfo(): """!Return region projection and map units information, taken from render.py""" projinfo = dict() ret = RunCommand('g.proj', read = True, flags = 'p') if not ret: return projinfo for line in ret.splitlines(): if ':' in line: key, val = line.split(':') projinfo[key.strip()] = val.strip() elif "XY location (unprojected)" in line: projinfo['proj'] = 'xy' projinfo['units'] = '' break return projinfo def GetMapBounds(filename, portrait = True): """!Run ps.map -b to get information about map bounding box @param filename psmap input file @param portrait page orientation""" orient = '' if not portrait: orient = 'r' try: bb = map(float, grass.read_command('ps.map', flags = 'b' + orient, quiet = True, input = filename).strip().split('=')[1].split(',')) except (grass.ScriptError, IndexError): GError(message = _("Unable to run `ps.map -b`")) return None return wx.Rect2D(bb[0], bb[3], bb[2] - bb[0], bb[1] - bb[3]) def getRasterType(map): """!Returns type of raster map (CELL, FCELL, DCELL)""" if map is None: map = '' file = grass.find_file(name = map, element = 'cell') if file['file']: rasterType = grass.raster_info(map)['datatype'] return rasterType else: return None def PilImageToWxImage(pilImage, copyAlpha = True): """!Convert PIL image to wx.Image Based on http://wiki.wxpython.org/WorkingWithImages """ hasAlpha = pilImage.mode[-1] == 'A' if copyAlpha and hasAlpha : # Make sure there is an alpha layer copy. wxImage = wx.EmptyImage( *pilImage.size ) pilImageCopyRGBA = pilImage.copy() pilImageCopyRGB = pilImageCopyRGBA.convert('RGB') # RGBA --> RGB pilImageRgbData = pilImageCopyRGB.tostring() wxImage.SetData(pilImageRgbData) wxImage.SetAlphaData(pilImageCopyRGBA.tostring()[3::4]) # Create layer and insert alpha values. else : # The resulting image will not have alpha. wxImage = wx.EmptyImage(*pilImage.size) pilImageCopy = pilImage.copy() pilImageCopyRGB = pilImageCopy.convert('RGB') # Discard any alpha from the PIL image. pilImageRgbData = pilImageCopyRGB.tostring() wxImage.SetData(pilImageRgbData) return wxImage def BBoxAfterRotation(w, h, angle): """!Compute bounding box or rotated rectangle @param w rectangle width @param h rectangle height @param angle angle (0, 360) in degrees """ angleRad = angle / 180. * pi ct = cos(angleRad) st = sin(angleRad) hct = h * ct wct = w * ct hst = h * st wst = w * st y = x = 0 if 0 < angle <= 90: y_min = y y_max = y + hct + wst x_min = x - hst x_max = x + wct elif 90 < angle <= 180: y_min = y + hct y_max = y + wst x_min = x - hst + wct x_max = x elif 180 < angle <= 270: y_min = y + wst + hct y_max = y x_min = x + wct x_max = x - hst elif 270 < angle <= 360: y_min = y + wst y_max = y + hct x_min = x x_max = x + wct - hst width = int(ceil(abs(x_max) + abs(x_min))) height = int(ceil(abs(y_max) + abs(y_min))) return width, height