1"""
2@package psmap.dialogs
3
4@brief dialogs for wxPsMap
5
6Classes:
7 - dialogs::TCValidator
8 - dialogs::PenStyleComboBox
9 - dialogs::CheckListCtrl
10 - dialogs::PsmapDialog
11 - dialogs::PageSetupDialog
12 - dialogs::MapDialog
13 - dialogs::MapFramePanel
14 - dialogs::RasterPanel
15 - dialogs::VectorPanel
16 - dialogs::RasterDialog
17 - dialogs::MainVectorDialog
18 - dialogs::VPropertiesDialog
19 - dialogs::LegendDialog
20 - dialogs::MapinfoDialog
21 - dialogs::ScalebarDialog
22 - dialogs::TextDialog
23 - dialogs::ImageDialog
24 - dialogs::NorthArrowDialog
25 - dialogs::PointDialog
26 - dialogs::RectangleDialog
27
28(C) 2011-2012 by Anna Kratochvilova, and the GRASS Development Team
29
30This program is free software under the GNU General Public License
31(>=v2). Read the file COPYING that comes with GRASS for details.
32
33@author Anna Kratochvilova <kratochanna gmail.com> (bachelor's project)
34@author Martin Landa <landa.martin gmail.com> (mentor)
35"""
36
37import os
38import string
39import sys
40from copy import deepcopy
41
42import wx
43import wx.lib.agw.floatspin as fs
44from wx.lib.mixins.listctrl import ListCtrlAutoWidthMixin
45
46from core import globalvar
47
48if globalvar.wxPythonPhoenix:
49    from wx import Validator
50else:
51    from wx import PyValidator as Validator
52
53import grass.script as grass
54
55from core.utils import PilImageToWxImage
56from dbmgr.vinfo import VectorDBInfo
57from gui_core.gselect import Select
58from core.gcmd import RunCommand, GError, GMessage
59from gui_core.dialogs import SymbolDialog
60from gui_core.wrap import (
61    BitmapButton, BitmapComboBox, BitmapFromImage, Button,
62    CheckBox, Choice, ClientDC, ColourPickerCtrl, Dialog, DirBrowseButton,
63    EmptyBitmap, ExpandoTextCtrl, FileBrowseButton, FloatSpin, ListBox,
64    ListCtrl, Notebook, OwnerDrawnComboBox, Panel, RadioButton,
65    Rect, ScrolledPanel, SpinCtrl, StaticBox, StaticText, TextCtrl,
66    TextEntryDialog, EmptyImage, CheckListCtrlMixin
67)
68from psmap.utils import *
69from psmap.instructions import *
70
71# grass.set_raise_on_error(True)
72
73PSMAP_COLORS = [
74    'aqua',
75    'black',
76    'blue',
77    'brown',
78    'cyan',
79    'gray',
80    'grey',
81    'green',
82    'indigo',
83    'magenta',
84    'orange',
85    'purple',
86    'red',
87    'violet',
88    'white',
89    'yellow']
90
91
92class TCValidator(Validator):
93    """validates input in textctrls, combobox, taken from wxpython demo"""
94
95    def __init__(self, flag=None):
96        Validator.__init__(self)
97        self.flag = flag
98        self.Bind(wx.EVT_CHAR, self.OnChar)
99
100    def Clone(self):
101        return TCValidator(self.flag)
102
103    def Validate(self, win):
104
105        tc = self.GetWindow()
106        val = tc.GetValue()
107
108        if self.flag == 'DIGIT_ONLY':
109            for x in val:
110                if x not in string.digits:
111                    return False
112        return True
113
114    def OnChar(self, event):
115        key = event.GetKeyCode()
116        if key < wx.WXK_SPACE or key == wx.WXK_DELETE or key > 255:
117            event.Skip()
118            return
119        if self.flag == 'DIGIT_ONLY' and chr(key) in string.digits + '.-':
120            event.Skip()
121            return
122# if self.flag == 'SCALE' and chr(key) in string.digits + ':':
123# event.Skip()
124# return
125        if self.flag == 'ZERO_AND_ONE_ONLY' and chr(key) in '01':
126            event.Skip()
127            return
128        if not wx.Validator_IsSilent():
129            wx.Bell()
130        # Returning without calling even.Skip eats the event before it
131        # gets to the text control
132        return
133
134
135class PenStyleComboBox(OwnerDrawnComboBox):
136    """Combo for selecting line style, taken from wxpython demo"""
137
138    # Overridden from OwnerDrawnComboBox, called to draw each
139    # item in the list
140    def OnDrawItem(self, dc, rect, item, flags):
141        if item == wx.NOT_FOUND:
142            # painting the control, but there is no valid item selected yet
143            return
144
145        r = Rect(*rect)  # make a copy
146        r.Deflate(3, 5)
147
148        penStyle = wx.SOLID
149        if item == 1:
150            penStyle = wx.LONG_DASH
151        elif item == 2:
152            penStyle = wx.DOT
153        elif item == 3:
154            penStyle = wx.DOT_DASH
155
156        pen = wx.Pen(dc.GetTextForeground(), 3, penStyle)
157        dc.SetPen(pen)
158
159        # for painting the items in the popup
160        dc.DrawText(self.GetString(item),
161                    r.x + 3,
162                    (r.y + 0) + ((r.height / 2) - dc.GetCharHeight()) / 2
163                    )
164        dc.DrawLine(r.x + 5, r.y + ((r.height / 4) * 3) + 1,
165                    r.x + r.width - 5, r.y + ((r.height / 4) * 3) + 1)
166
167    def OnDrawBackground(self, dc, rect, item, flags):
168        """Overridden from OwnerDrawnComboBox, called for drawing the
169        background area of each item."""
170        # If the item is selected, or its item # iseven, or we are painting the
171        # combo control itself, then use the default rendering.
172        if (item & 1 == 0 or flags & (OwnerDrawnComboBox.ODCB_PAINTING_CONTROL |
173                                      OwnerDrawnComboBox.ODCB_PAINTING_SELECTED)):
174            OwnerDrawnComboBox.OnDrawBackground(
175                self, dc, rect, item, flags)
176            return
177
178        # Otherwise, draw every other background with different colour.
179        bgCol = wx.Colour(240, 240, 250)
180        dc.SetBrush(wx.Brush(bgCol))
181        dc.SetPen(wx.Pen(bgCol))
182        if globalvar.wxPythonPhoenix:
183            dc.DrawRectangle(rect)
184        else:
185            dc.DrawRectangleRect(rect)
186
187    def OnMeasureItem(self, item):
188        """Overridden from OwnerDrawnComboBox, should return the height
189        needed to display an item in the popup, or -1 for default"""
190        return 30
191
192    def OnMeasureItemWidth(self, item):
193        """Overridden from OwnerDrawnComboBox.  Callback for item width, or
194        -1 for default/undetermined"""
195        return -1  # default - will be measured from text width
196
197
198class CheckListCtrl(ListCtrl, CheckListCtrlMixin, ListCtrlAutoWidthMixin):
199    """List control for managing order and labels of vector maps in legend"""
200
201    def __init__(self, parent):
202        ListCtrl.__init__(
203            self, parent, id=wx.ID_ANY, style=wx.LC_REPORT | wx.LC_SINGLE_SEL |
204            wx.BORDER_SUNKEN | wx.LC_VRULES | wx.LC_HRULES)
205        CheckListCtrlMixin.__init__(self)
206        ListCtrlAutoWidthMixin.__init__(self)
207
208
209class PsmapDialog(Dialog):
210
211    def __init__(self, parent, id, title, settings, env, apply=True):
212        Dialog.__init__(self, parent=parent, id=wx.ID_ANY,
213                           title=title, size=wx.DefaultSize,
214                           style=wx.CAPTION | wx.MINIMIZE_BOX | wx.CLOSE_BOX)
215        self.apply = apply
216        self.id = id
217        self.env = env
218        self.parent = parent
219        self.instruction = settings
220        self.objectType = None
221        self.unitConv = UnitConversion(self)
222        self.spinCtrlSize = (65, -1)
223
224        self.Bind(wx.EVT_CLOSE, self.OnClose)
225
226    def AddUnits(self, parent, dialogDict):
227        parent.units = dict()
228        parent.units['unitsLabel'] = StaticText(
229            parent, id=wx.ID_ANY, label=_("Units:"))
230        choices = self.unitConv.getPageUnitsNames()
231        parent.units['unitsCtrl'] = Choice(
232            parent, id=wx.ID_ANY, choices=choices)
233        parent.units['unitsCtrl'].SetStringSelection(
234            self.unitConv.findName(dialogDict['unit']))
235
236    def AddPosition(self, parent, dialogDict):
237        if not hasattr(parent, "position"):
238            parent.position = dict()
239        parent.position['comment'] = StaticText(parent, id=wx.ID_ANY, label=_(
240            "Position of the top left corner\nfrom the top left edge of the paper"))
241        parent.position['xLabel'] = StaticText(
242            parent, id=wx.ID_ANY, label=_("X:"))
243        parent.position['yLabel'] = StaticText(
244            parent, id=wx.ID_ANY, label=_("Y:"))
245        parent.position['xCtrl'] = TextCtrl(
246            parent, id=wx.ID_ANY, value=str(
247                dialogDict['where'][0]), validator=TCValidator(
248                flag='DIGIT_ONLY'))
249        parent.position['yCtrl'] = TextCtrl(
250            parent, id=wx.ID_ANY, value=str(
251                dialogDict['where'][1]), validator=TCValidator(
252                flag='DIGIT_ONLY'))
253        if 'unit' in dialogDict:
254            x = self.unitConv.convert(
255                value=dialogDict['where'][0],
256                fromUnit='inch',
257                toUnit=dialogDict['unit'])
258            y = self.unitConv.convert(
259                value=dialogDict['where'][1],
260                fromUnit='inch',
261                toUnit=dialogDict['unit'])
262            parent.position['xCtrl'].SetValue("%5.3f" % x)
263            parent.position['yCtrl'].SetValue("%5.3f" % y)
264
265    def AddExtendedPosition(self, panel, gridBagSizer, dialogDict):
266        """Add widgets for setting position relative to paper and to map"""
267        panel.position = dict()
268        positionLabel = StaticText(
269            panel, id=wx.ID_ANY, label=_("Position is given:"))
270        panel.position['toPaper'] = RadioButton(
271            panel, id=wx.ID_ANY, label=_("relative to paper"), style=wx.RB_GROUP)
272        panel.position['toMap'] = RadioButton(
273            panel, id=wx.ID_ANY, label=_("by map coordinates"))
274        panel.position['toPaper'].SetValue(dialogDict['XY'])
275        panel.position['toMap'].SetValue(not dialogDict['XY'])
276
277        gridBagSizer.Add(
278            positionLabel, pos=(
279                0, 0), span=(
280                1, 3), flag=wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_LEFT, border=0)
281        gridBagSizer.Add(
282            panel.position['toPaper'],
283            pos=(
284                1,
285                0),
286            flag=wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_LEFT,
287            border=0)
288        gridBagSizer.Add(
289            panel.position['toMap'],
290            pos=(
291                1,
292                1),
293            flag=wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_LEFT,
294            border=0)
295
296        # first box - paper coordinates
297        box1 = StaticBox(parent=panel, id=wx.ID_ANY, label="")
298        sizerP = wx.StaticBoxSizer(box1, wx.VERTICAL)
299        self.gridBagSizerP = wx.GridBagSizer(hgap=5, vgap=5)
300
301        self.AddPosition(parent=panel, dialogDict=dialogDict)
302        panel.position['comment'].SetLabel(
303            _("Position from the top left\nedge of the paper"))
304        self.AddUnits(parent=panel, dialogDict=dialogDict)
305        self.gridBagSizerP.Add(
306            panel.units['unitsLabel'], pos=(
307                0, 0), flag=wx.ALIGN_CENTER_VERTICAL, border=0)
308        self.gridBagSizerP.Add(
309            panel.units['unitsCtrl'], pos=(
310                0, 1), flag=wx.ALIGN_CENTER_VERTICAL, border=0)
311        self.gridBagSizerP.Add(
312            panel.position['xLabel'], pos=(
313                1, 0), flag=wx.ALIGN_CENTER_VERTICAL, border=0)
314        self.gridBagSizerP.Add(panel.position['xCtrl'], pos=(
315            1, 1), flag=wx.ALIGN_CENTER_VERTICAL, border=0)
316        self.gridBagSizerP.Add(
317            panel.position['yLabel'], pos=(
318                2, 0), flag=wx.ALIGN_CENTER_VERTICAL, border=0)
319        self.gridBagSizerP.Add(panel.position['yCtrl'], pos=(
320            2, 1), flag=wx.ALIGN_CENTER_VERTICAL, border=0)
321        self.gridBagSizerP.Add(
322            panel.position['comment'], pos=(
323                3, 0), span=(
324                1, 2), flag=wx.ALIGN_BOTTOM, border=0)
325
326        self.gridBagSizerP.AddGrowableCol(1)
327        self.gridBagSizerP.AddGrowableRow(3)
328        sizerP.Add(
329            self.gridBagSizerP,
330            proportion=1,
331            flag=wx.EXPAND | wx.ALL,
332            border=5)
333        gridBagSizer.Add(
334            sizerP, pos=(
335                2, 0), span=(
336                1, 1), flag=wx.ALIGN_CENTER_HORIZONTAL | wx.EXPAND, border=0)
337
338        # second box - map coordinates
339        box2 = StaticBox(parent=panel, id=wx.ID_ANY, label="")
340        sizerM = wx.StaticBoxSizer(box2, wx.VERTICAL)
341        self.gridBagSizerM = wx.GridBagSizer(hgap=5, vgap=5)
342
343        eastingLabel = StaticText(panel, id=wx.ID_ANY, label="E:")
344        northingLabel = StaticText(panel, id=wx.ID_ANY, label="N:")
345        panel.position['eCtrl'] = TextCtrl(panel, id=wx.ID_ANY, value="")
346        panel.position['nCtrl'] = TextCtrl(panel, id=wx.ID_ANY, value="")
347        east, north = PaperMapCoordinates(
348            mapInstr=self.instruction[self.mapId],
349            x=dialogDict['where'][0],
350            y=dialogDict['where'][1],
351            paperToMap=True,
352            env=self.env)
353        panel.position['eCtrl'].SetValue(str(east))
354        panel.position['nCtrl'].SetValue(str(north))
355
356        self.gridBagSizerM.Add(
357            eastingLabel, pos=(0, 0),
358            flag=wx.ALIGN_CENTER_VERTICAL, border=0)
359        self.gridBagSizerM.Add(
360            northingLabel, pos=(1, 0),
361            flag=wx.ALIGN_CENTER_VERTICAL, border=0)
362        self.gridBagSizerM.Add(panel.position['eCtrl'], pos=(
363            0, 1), flag=wx.ALIGN_CENTER_VERTICAL, border=0)
364        self.gridBagSizerM.Add(panel.position['nCtrl'], pos=(
365            1, 1), flag=wx.ALIGN_CENTER_VERTICAL, border=0)
366
367        self.gridBagSizerM.AddGrowableCol(0)
368        self.gridBagSizerM.AddGrowableCol(1)
369        sizerM.Add(
370            self.gridBagSizerM,
371            proportion=1,
372            flag=wx.EXPAND | wx.ALL,
373            border=5)
374        gridBagSizer.Add(
375            sizerM, pos=(2, 1),
376            flag=wx.ALIGN_LEFT | wx.EXPAND, border=0)
377
378    def AddFont(self, parent, dialogDict, color=True):
379        parent.font = dict()
380##        parent.font['fontLabel'] = wx.StaticText(parent, id = wx.ID_ANY, label = _("Choose font:"))
381##        parent.font['fontCtrl'] = wx.FontPickerCtrl(parent, id = wx.ID_ANY)
382##
383# parent.font['fontCtrl'].SetSelectedFont(
384# wx.FontFromNativeInfoString(dialogDict['font'] + " " + str(dialogDict['fontsize'])))
385# parent.font['fontCtrl'].SetMaxPointSize(50)
386##
387# if color:
388##            parent.font['colorLabel'] = wx.StaticText(parent, id = wx.ID_ANY, label = _("Choose color:"))
389##            parent.font['colorCtrl'] = ColourPickerCtrl(parent, id = wx.ID_ANY, style=wx.FNTP_FONTDESC_AS_LABEL)
390# parent.font['colorCtrl'].SetColour(dialogDict['color'])
391
392# parent.font['colorCtrl'].SetColour(convertRGB(dialogDict['color']))
393
394        parent.font['fontLabel'] = StaticText(
395            parent, id=wx.ID_ANY, label=_("Font:"))
396        parent.font['fontSizeLabel'] = StaticText(
397            parent, id=wx.ID_ANY, label=_("Font size:"))
398        fontChoices = [
399            'Times-Roman',
400            'Times-Italic',
401            'Times-Bold',
402            'Times-BoldItalic',
403            'Helvetica',
404            'Helvetica-Oblique',
405            'Helvetica-Bold',
406            'Helvetica-BoldOblique',
407            'Courier',
408            'Courier-Oblique',
409            'Courier-Bold',
410            'Courier-BoldOblique']
411        parent.font['fontCtrl'] = Choice(
412            parent, id=wx.ID_ANY, choices=fontChoices)
413        if dialogDict['font'] in fontChoices:
414            parent.font['fontCtrl'].SetStringSelection(dialogDict['font'])
415        else:
416            parent.font['fontCtrl'].SetStringSelection('Helvetica')
417        parent.font['fontSizeCtrl'] = SpinCtrl(
418            parent, id=wx.ID_ANY, min=4, max=50, initial=10)
419        parent.font['fontSizeCtrl'].SetValue(dialogDict['fontsize'])
420
421        if color:
422            parent.font['colorLabel'] = StaticText(
423                parent, id=wx.ID_ANY, label=_("Choose color:"))
424            parent.font['colorCtrl'] = ColourPickerCtrl(
425                parent, id=wx.ID_ANY)
426            parent.font['colorCtrl'].SetColour(convertRGB(dialogDict['color']))
427##            parent.font['colorLabel'] = wx.StaticText(parent, id = wx.ID_ANY, label = _("Color:"))
428# colorChoices = [  'aqua', 'black', 'blue', 'brown', 'cyan', 'gray', 'green', 'indigo', 'magenta',\
429# 'orange', 'purple', 'red', 'violet', 'white', 'yellow']
430##            parent.colorCtrl = Choice(parent, id = wx.ID_ANY, choices = colorChoices)
431# parent.colorCtrl.SetStringSelection(parent.rLegendDict['color'])
432##            parent.font['colorCtrl'] = ColourPickerCtrl(parent, id = wx.ID_ANY)
433# parent.font['colorCtrl'].SetColour(dialogDict['color'])
434
435    def OnApply(self, event):
436        ok = self.update()
437        if ok:
438            self.parent.DialogDataChanged(id=self.id)
439            return True
440        else:
441            return False
442
443    def OnOK(self, event):
444        """Apply changes, close dialog"""
445        ok = self.OnApply(event)
446        if ok:
447            self.Close()
448
449    def OnCancel(self, event):
450        """Close dialog"""
451        self.Close()
452
453    def OnClose(self, event):
454        """Destroy dialog and delete it from open dialogs"""
455        if self.objectType:
456            for each in self.objectType:
457                if each in self.parent.openDialogs:
458                    del self.parent.openDialogs[each]
459        event.Skip()
460        self.Destroy()
461
462    def _layout(self, panel):
463        # buttons
464        btnCancel = Button(self, wx.ID_CANCEL)
465        btnOK = Button(self, wx.ID_OK)
466        btnOK.SetDefault()
467        if self.apply:
468            btnApply = Button(self, wx.ID_APPLY)
469
470        # bindigs
471        btnOK.Bind(wx.EVT_BUTTON, self.OnOK)
472        btnOK.SetToolTip(_("Close dialog and apply changes"))
473        #btnCancel.Bind(wx.EVT_BUTTON, self.OnCancel)
474        btnCancel.SetToolTip(_("Close dialog and ignore changes"))
475        btnCancel.Bind(wx.EVT_BUTTON, self.OnCancel)
476        if self.apply:
477            btnApply.Bind(wx.EVT_BUTTON, self.OnApply)
478            btnApply.SetToolTip(_("Apply changes"))
479
480        # sizers
481        btnSizer = wx.StdDialogButtonSizer()
482        btnSizer.AddButton(btnCancel)
483        if self.apply:
484            btnSizer.AddButton(btnApply)
485        btnSizer.AddButton(btnOK)
486        btnSizer.Realize()
487
488        mainSizer = wx.BoxSizer(wx.VERTICAL)
489        mainSizer.Add(
490            panel,
491            proportion=1,
492            flag=wx.EXPAND | wx.ALL,
493            border=5)
494        mainSizer.Add(btnSizer, proportion=0,
495                      flag=wx.EXPAND | wx.ALL, border=5)
496
497        self.SetSizer(mainSizer)
498        mainSizer.Layout()
499        mainSizer.Fit(self)
500
501
502class PageSetupDialog(PsmapDialog):
503
504    def __init__(self, parent, id, settings, env):
505        PsmapDialog.__init__(
506            self,
507            parent=parent,
508            id=id,
509            title="Page setup",
510            settings=settings,
511            env=env)
512
513        self.cat = [
514            'Units',
515            'Format',
516            'Orientation',
517            'Width',
518            'Height',
519            'Left',
520            'Right',
521            'Top',
522            'Bottom']
523        labels = [
524            _('Units'),
525            _('Format'),
526            _('Orientation'),
527            _('Width'),
528            _('Height'),
529            _('Left'),
530            _('Right'),
531            _('Top'),
532            _('Bottom')]
533        self.catsLabels = dict(zip(self.cat, labels))
534        paperString = RunCommand('ps.map', flags='p', read=True, quiet=True)
535        self.paperTable = self._toList(paperString)
536        self.unitsList = self.unitConv.getPageUnitsNames()
537        self.pageSetupDict = settings[id].GetInstruction()
538
539        self._layout()
540
541        if self.pageSetupDict:
542            self.getCtrl('Units').SetStringSelection(
543                self.unitConv.findName(self.pageSetupDict['Units']))
544            if self.pageSetupDict['Format'] == 'custom':
545                self.getCtrl('Format').SetSelection(
546                    self.getCtrl('Format').GetCount() - 1)
547            else:
548                self.getCtrl('Format').SetStringSelection(
549                    self.pageSetupDict['Format'])
550            if self.pageSetupDict['Orientation'] == 'Portrait':
551                self.getCtrl('Orientation').SetSelection(0)
552            else:
553                self.getCtrl('Orientation').SetSelection(1)
554
555            for item in self.cat[3:]:
556                val = self.unitConv.convert(
557                    value=self.pageSetupDict[item],
558                    fromUnit='inch',
559                    toUnit=self.pageSetupDict['Units'])
560                self.getCtrl(item).SetValue("%4.3f" % val)
561
562        if self.getCtrl('Format').GetSelection() != self.getCtrl(
563                'Format').GetCount() - 1:  # custom
564            self.getCtrl('Width').Disable()
565            self.getCtrl('Height').Disable()
566        else:
567            self.getCtrl('Orientation').Disable()
568        # events
569        self.getCtrl('Units').Bind(wx.EVT_CHOICE, self.OnChoice)
570        self.getCtrl('Format').Bind(wx.EVT_CHOICE, self.OnChoice)
571        self.getCtrl('Orientation').Bind(wx.EVT_CHOICE, self.OnChoice)
572        self.btnOk.Bind(wx.EVT_BUTTON, self.OnOK)
573
574    def update(self):
575        self.pageSetupDict['Units'] = self.unitConv.findUnit(
576            self.getCtrl('Units').GetStringSelection())
577        self.pageSetupDict['Format'] = self.paperTable[
578            self.getCtrl('Format').GetSelection()]['Format']
579        if self.getCtrl('Orientation').GetSelection() == 0:
580            self.pageSetupDict['Orientation'] = 'Portrait'
581        else:
582            self.pageSetupDict['Orientation'] = 'Landscape'
583        for item in self.cat[3:]:
584            self.pageSetupDict[item] = self.unitConv.convert(
585                value=float(self.getCtrl(item).GetValue()),
586                fromUnit=self.pageSetupDict['Units'],
587                toUnit='inch')
588
589    def OnOK(self, event):
590        try:
591            self.update()
592        except ValueError:
593            wx.MessageBox(
594                message=_("Literal is not allowed!"),
595                caption=_('Invalid input'),
596                style=wx.OK | wx.ICON_ERROR)
597        else:
598            event.Skip()
599
600    def _layout(self):
601        size = (110, -1)
602        # sizers
603        mainSizer = wx.BoxSizer(wx.VERTICAL)
604        pageBox = StaticBox(
605            self,
606            id=wx.ID_ANY,
607            label=" %s " %
608            _("Page size"))
609        pageSizer = wx.StaticBoxSizer(pageBox, wx.VERTICAL)
610        marginBox = StaticBox(
611            self, id=wx.ID_ANY, label=" %s " %
612            _("Margins"))
613        marginSizer = wx.StaticBoxSizer(marginBox, wx.VERTICAL)
614        horSizer = wx.BoxSizer(wx.HORIZONTAL)
615        #staticText + choice
616        choices = [
617            self.unitsList, [
618                item['Format'] for item in self.paperTable], [
619                _('Portrait'), _('Landscape')]]
620        propor = [0, 1, 1]
621        border = [5, 3, 3]
622        self.hBoxDict = {}
623        for i, item in enumerate(self.cat[:3]):
624            hBox = wx.BoxSizer(wx.HORIZONTAL)
625            stText = StaticText(
626                self, id=wx.ID_ANY, label=self.catsLabels[item] + ':')
627            choice = Choice(
628                self,
629                id=wx.ID_ANY,
630                choices=choices[i],
631                size=size)
632            hBox.Add(
633                stText,
634                proportion=propor[i],
635                flag=wx.ALIGN_CENTER_VERTICAL | wx.ALL,
636                border=border[i])
637            hBox.Add(choice, proportion=0, flag=wx.ALL, border=border[i])
638            if item == 'Units':
639                hBox.Add(size, 1)
640            self.hBoxDict[item] = hBox
641
642        #staticText + TextCtrl
643        for item in self.cat[3:]:
644            hBox = wx.BoxSizer(wx.HORIZONTAL)
645            label = StaticText(
646                self, id=wx.ID_ANY, label=self.catsLabels[item] + ':')
647            textctrl = TextCtrl(self, id=wx.ID_ANY, size=size, value='')
648            hBox.Add(
649                label,
650                proportion=1,
651                flag=wx.ALIGN_CENTER_VERTICAL | wx.ALL,
652                border=3)
653            hBox.Add(
654                textctrl,
655                proportion=0,
656                flag=wx.ALIGN_CENTRE | wx.ALL,
657                border=3)
658            self.hBoxDict[item] = hBox
659
660        sizer = list([mainSizer] + [pageSizer] * 4 + [marginSizer] * 4)
661        for i, item in enumerate(self.cat):
662            sizer[i].Add(
663                self.hBoxDict[item],
664                0, wx.GROW | wx.RIGHT | wx.LEFT, 5)
665        # OK button
666        btnSizer = wx.StdDialogButtonSizer()
667        self.btnOk = Button(self, wx.ID_OK)
668        self.btnOk.SetDefault()
669        btnSizer.AddButton(self.btnOk)
670        btn = Button(self, wx.ID_CANCEL)
671        btnSizer.AddButton(btn)
672        btnSizer.Realize()
673
674        horSizer.Add(
675            pageSizer,
676            proportion=0,
677            flag=wx.LEFT | wx.RIGHT | wx.BOTTOM,
678            border=10)
679        horSizer.Add(marginSizer, proportion=0, flag=wx.LEFT |
680                     wx.RIGHT | wx.BOTTOM | wx.EXPAND, border=10)
681        mainSizer.Add(horSizer, proportion=0, border=10)
682        mainSizer.Add(
683            btnSizer,
684            proportion=0,
685            flag=wx.ALIGN_RIGHT | wx.ALL,
686            border=10)
687        self.SetSizer(mainSizer)
688        mainSizer.Fit(self)
689
690    def OnChoice(self, event):
691        currPaper = self.paperTable[self.getCtrl('Format').GetSelection()]
692        currUnit = self.unitConv.findUnit(
693            self.getCtrl('Units').GetStringSelection())
694        currOrientIdx = self.getCtrl('Orientation').GetSelection()
695        newSize = dict()
696        for item in self.cat[3:]:
697            newSize[item] = self.unitConv.convert(
698                float(currPaper[item]),
699                fromUnit='inch', toUnit=currUnit)
700
701        enable = True
702        if currPaper['Format'] != _('custom'):
703            if currOrientIdx == 1:  # portrait
704                newSize['Width'], newSize['Height'] = newSize[
705                    'Height'], newSize['Width']
706            for item in self.cat[3:]:
707                self.getCtrl(item).ChangeValue("%4.3f" % newSize[item])
708            enable = False
709        self.getCtrl('Width').Enable(enable)
710        self.getCtrl('Height').Enable(enable)
711        self.getCtrl('Orientation').Enable(not enable)
712
713    def getCtrl(self, item):
714        return self.hBoxDict[item].GetItem(1).GetWindow()
715
716    def _toList(self, paperStr):
717
718        sizeList = list()
719        for line in paperStr.strip().split('\n'):
720            d = dict(zip([self.cat[1]] + self.cat[3:], line.split()))
721            sizeList.append(d)
722        d = {}.fromkeys([self.cat[1]] + self.cat[3:], 100)
723        d.update(Format=_('custom'))
724        sizeList.append(d)
725        return sizeList
726
727
728class MapDialog(PsmapDialog):
729    """Dialog for map frame settings and optionally  raster and vector map selection"""
730
731    def __init__(self, parent, id, settings, env, rect=None, notebook=False):
732        PsmapDialog.__init__(
733            self,
734            parent=parent,
735            id=id,
736            title="",
737            settings=settings,
738            env=env)
739
740        self.isNotebook = notebook
741        if self.isNotebook:
742            self.objectType = ('mapNotebook',)
743        else:
744            self.objectType = ('map',)
745
746        # notebook
747        if self.isNotebook:
748            self.notebook = Notebook(
749                parent=self, id=wx.ID_ANY, style=wx.BK_DEFAULT)
750            self.mPanel = MapFramePanel(
751                parent=self.notebook,
752                id=self.id[0],
753                settings=self.instruction,
754                env=env,
755                rect=rect,
756                notebook=True)
757            self.id[0] = self.mPanel.getId()
758            self.rPanel = RasterPanel(
759                parent=self.notebook, id=self.id[1],
760                settings=self.instruction, env=env, notebook=True)
761            self.id[1] = self.rPanel.getId()
762            self.vPanel = VectorPanel(
763                parent=self.notebook, id=self.id[2],
764                settings=self.instruction, env=env, notebook=True)
765            self.id[2] = self.vPanel.getId()
766            self._layout(self.notebook)
767            self.SetTitle(_("Map settings"))
768        else:
769            self.mPanel = MapFramePanel(
770                parent=self,
771                id=self.id[0],
772                settings=self.instruction,
773                env=env,
774                rect=rect,
775                notebook=False)
776            self.id[0] = self.mPanel.getId()
777            self._layout(self.mPanel)
778            self.SetTitle(_("Map frame settings"))
779
780    def OnApply(self, event):
781        """Apply changes"""
782        if self.isNotebook:
783            okV = self.vPanel.update()
784            okR = self.rPanel.update()
785            if okV and self.id[2] in self.instruction:
786                self.parent.DialogDataChanged(id=self.id[2])
787            if okR and self.id[1] in self.instruction:
788                self.parent.DialogDataChanged(id=self.id[1])
789            if not okR or not okV:
790                return False
791
792        ok = self.mPanel.update()
793        if ok:
794            self.parent.DialogDataChanged(id=self.id[0])
795            return True
796
797        return False
798
799    def OnCancel(self, event):
800        """Close dialog and remove tmp red box"""
801        self.parent.canvas.pdcTmp.RemoveId(self.parent.canvas.idZoomBoxTmp)
802        self.parent.canvas.Refresh()
803        self.Close()
804
805    def updateDialog(self):
806        """Update raster and vector information"""
807        if self.mPanel.scaleChoice.GetSelection() == 0:
808            if self.mPanel.rasterTypeRadio.GetValue():
809                if 'raster' in self.parent.openDialogs:
810                    if self.parent.openDialogs['raster'].rPanel.rasterYesRadio.GetValue() and \
811                            self.parent.openDialogs['raster'].rPanel.rasterSelect.GetValue() == self.mPanel.select.GetValue():
812                        self.mPanel.drawMap.SetValue(True)
813                    else:
814                        self.mPanel.drawMap.SetValue(False)
815            else:
816                if 'vector' in self.parent.openDialogs:
817                    found = False
818                    for each in self.parent.openDialogs[
819                            'vector'].vPanel.vectorList:
820                        if each[0] == self.mPanel.select.GetValue():
821                            found = True
822                    self.mPanel.drawMap.SetValue(found)
823
824
825class MapFramePanel(Panel):
826    """Panel with map (scale, region, border) settings"""
827
828    def __init__(self, parent, id, settings, env, rect, notebook=True):
829        Panel.__init__(self, parent, id=wx.ID_ANY, style=wx.TAB_TRAVERSAL)
830
831        self.id = id
832        self.instruction = settings
833        self.env = env
834
835        if notebook:
836            self.book = parent
837            self.book.AddPage(page=self, text=_("Map frame"))
838            self.mapDialog = self.book.GetParent()
839        else:
840            self.mapDialog = parent
841
842        if self.id is not None:
843            self.mapFrameDict = self.instruction[self.id].GetInstruction()
844        else:
845            self.id = NewId()
846            mapFrame = MapFrame(self.id, env=self.env)
847            self.mapFrameDict = mapFrame.GetInstruction()
848            self.mapFrameDict['rect'] = rect
849
850        self._layout()
851
852        self.scale = [None] * 4
853        self.center = [None] * 4
854
855        self.selectedMap = self.mapFrameDict['map']
856        self.selectedRegion = self.mapFrameDict['region']
857        self.scaleType = self.mapFrameDict['scaleType']
858        self.mapType = self.mapFrameDict['mapType']
859        self.scaleChoice.SetSelection(self.mapFrameDict['scaleType'])
860        if self.instruction[self.id]:
861            self.drawMap.SetValue(self.mapFrameDict['drawMap'])
862        else:
863            self.drawMap.SetValue(True)
864        if self.mapFrameDict['scaleType'] == 0 and self.mapFrameDict['map']:
865            self.select.SetValue(self.mapFrameDict['map'])
866            if self.mapFrameDict['mapType'] == 'raster':
867                self.rasterTypeRadio.SetValue(True)
868                self.vectorTypeRadio.SetValue(False)
869            else:
870                self.rasterTypeRadio.SetValue(False)
871                self.vectorTypeRadio.SetValue(True)
872        elif self.mapFrameDict['scaleType'] == 1 and self.mapFrameDict['region']:
873            self.select.SetValue(self.mapFrameDict['region'])
874
875        self.OnMap(None)
876        self.scale[self.mapFrameDict['scaleType']] = self.mapFrameDict['scale']
877        self.center[self.mapFrameDict['scaleType']
878                    ] = self.mapFrameDict['center']
879        self.OnScaleChoice(None)
880        self.OnElementType(None)
881        self.OnBorder(None)
882
883    def _layout(self):
884        """Do layout"""
885        border = wx.BoxSizer(wx.VERTICAL)
886
887        box = StaticBox(
888            parent=self,
889            id=wx.ID_ANY,
890            label=" %s " %
891            _("Map frame"))
892        sizer = wx.StaticBoxSizer(box, wx.HORIZONTAL)
893        gridBagSizer = wx.GridBagSizer(hgap=5, vgap=5)
894
895        # scale options
896        frameText = StaticText(
897            self, id=wx.ID_ANY, label=_("Map frame options:"))
898        scaleChoices = [_("fit frame to match selected map"),
899                        _("fit frame to match saved region"),
900                        _("fit frame to match current computational region"),
901                        _("fixed scale and map center")]
902        self.scaleChoice = Choice(self, id=wx.ID_ANY, choices=scaleChoices)
903
904        gridBagSizer.Add(
905            frameText, pos=(0, 0),
906            flag=wx.ALIGN_CENTER_VERTICAL, border=0)
907        gridBagSizer.Add(
908            self.scaleChoice,
909            pos=(
910                1,
911                0),
912            flag=wx.ALIGN_CENTER_VERTICAL | wx.EXPAND,
913            border=0)
914
915        # map and region selection
916        self.staticBox = StaticBox(
917            parent=self, id=wx.ID_ANY, label=" %s " %
918            _("Map selection"))
919        sizerM = wx.StaticBoxSizer(self.staticBox, wx.HORIZONTAL)
920        self.mapSizer = wx.GridBagSizer(hgap=5, vgap=5)
921
922        self.rasterTypeRadio = RadioButton(
923            self, id=wx.ID_ANY, label=" %s " %
924            _("raster"), style=wx.RB_GROUP)
925        self.vectorTypeRadio = RadioButton(
926            self, id=wx.ID_ANY, label=" %s " %
927            _("vector"))
928        self.drawMap = CheckBox(
929            self, id=wx.ID_ANY, label="add selected map")
930
931        self.mapOrRegionText = [_("Map:"), _("Region:")]
932        dc = ClientDC(self)  # determine size of labels
933        width = max(
934            dc.GetTextExtent(
935                self.mapOrRegionText[0])[0], dc.GetTextExtent(
936                self.mapOrRegionText[1])[0])
937        self.mapText = StaticText(
938            self, id=wx.ID_ANY, label=self.mapOrRegionText[0],
939            size=(width, -1))
940        self.select = Select(
941            self,
942            id=wx.ID_ANY,
943            size=globalvar.DIALOG_GSELECT_SIZE,
944            type='raster',
945            multiple=False,
946            updateOnPopup=True,
947            onPopup=None)
948
949        self.mapSizer.Add(
950            self.rasterTypeRadio, pos=(0, 1),
951            flag=wx.ALIGN_CENTER_VERTICAL, border=0)
952        self.mapSizer.Add(
953            self.vectorTypeRadio, pos=(0, 2),
954            flag=wx.ALIGN_CENTER_VERTICAL, border=0)
955        self.mapSizer.Add(
956            self.drawMap,
957            pos=(
958                0,
959                3),
960            flag=wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT,
961            border=0)
962        self.mapSizer.Add(
963            self.mapText, pos=(1, 0),
964            flag=wx.ALIGN_CENTER_VERTICAL, border=0)
965        self.mapSizer.Add(
966            self.select, pos=(
967                1, 1), span=(
968                1, 3), flag=wx.ALIGN_CENTER_VERTICAL, border=0)
969
970        sizerM.Add(
971            self.mapSizer,
972            proportion=1,
973            flag=wx.EXPAND | wx.ALL,
974            border=5)
975        gridBagSizer.Add(
976            sizerM,
977            pos=(
978                2,
979                0),
980            flag=wx.ALIGN_CENTER_VERTICAL | wx.EXPAND,
981            border=0)
982
983        # map scale and center
984        boxC = StaticBox(
985            parent=self,
986            id=wx.ID_ANY,
987            label=" %s " %
988            _("Map scale and center"))
989        sizerC = wx.StaticBoxSizer(boxC, wx.HORIZONTAL)
990        self.centerSizer = wx.FlexGridSizer(rows=2, cols=5, hgap=5, vgap=5)
991
992        centerText = StaticText(self, id=wx.ID_ANY, label=_("Center:"))
993        self.eastingText = StaticText(self, id=wx.ID_ANY, label=_("E:"))
994        self.northingText = StaticText(self, id=wx.ID_ANY, label=_("N:"))
995        self.eastingTextCtrl = TextCtrl(
996            self, id=wx.ID_ANY, style=wx.TE_RIGHT,
997            validator=TCValidator(flag='DIGIT_ONLY'))
998        self.northingTextCtrl = TextCtrl(
999            self, id=wx.ID_ANY, style=wx.TE_RIGHT,
1000            validator=TCValidator(flag='DIGIT_ONLY'))
1001        scaleText = StaticText(self, id=wx.ID_ANY, label=_("Scale:"))
1002        scalePrefixText = StaticText(self, id=wx.ID_ANY, label=_("1 :"))
1003        self.scaleTextCtrl = TextCtrl(
1004            self, id=wx.ID_ANY, value="", style=wx.TE_RIGHT,
1005            validator=TCValidator('DIGIT_ONLY'))
1006
1007        self.centerSizer.Add(
1008            centerText,
1009            proportion=0,
1010            flag=wx.ALIGN_CENTER_VERTICAL | wx.RIGHT,
1011            border=10)
1012        self.centerSizer.Add(
1013            self.eastingText,
1014            proportion=0,
1015            flag=wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT,
1016            border=0)
1017        self.centerSizer.Add(
1018            self.eastingTextCtrl,
1019            proportion=0,
1020            flag=wx.ALIGN_CENTER_VERTICAL,
1021            border=0)
1022        self.centerSizer.Add(
1023            self.northingText,
1024            proportion=0,
1025            flag=wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT,
1026            border=0)
1027        self.centerSizer.Add(
1028            self.northingTextCtrl,
1029            proportion=0,
1030            flag=wx.ALIGN_CENTER_VERTICAL,
1031            border=0)
1032
1033        self.centerSizer.Add(
1034            scaleText,
1035            proportion=0,
1036            flag=wx.ALIGN_CENTER_VERTICAL | wx.RIGHT,
1037            border=10)
1038        self.centerSizer.Add(
1039            scalePrefixText,
1040            proportion=0,
1041            flag=wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT,
1042            border=0)
1043        self.centerSizer.Add(
1044            self.scaleTextCtrl,
1045            proportion=0,
1046            flag=wx.ALIGN_CENTER_VERTICAL,
1047            border=0)
1048
1049        sizerC.Add(
1050            self.centerSizer,
1051            proportion=1,
1052            flag=wx.EXPAND | wx.ALL,
1053            border=5)
1054        gridBagSizer.Add(
1055            sizerC,
1056            pos=(
1057                3,
1058                0),
1059            flag=wx.ALIGN_CENTER_VERTICAL | wx.EXPAND,
1060            border=0)
1061
1062        # resolution
1063        flexSizer = wx.FlexGridSizer(rows=1, cols=2, hgap=5, vgap=5)
1064
1065        resolutionText = StaticText(
1066            self, id=wx.ID_ANY, label=_("Map max resolution (dpi):"))
1067        self.resolutionSpin = SpinCtrl(
1068            self, id=wx.ID_ANY, min=1, max=1000, initial=300)
1069
1070        flexSizer.Add(
1071            resolutionText,
1072            proportion=0,
1073            flag=wx.ALIGN_CENTER_VERTICAL,
1074            border=0)
1075        flexSizer.Add(
1076            self.resolutionSpin,
1077            proportion=0,
1078            flag=wx.ALIGN_CENTER_VERTICAL,
1079            border=0)
1080        self.resolutionSpin.SetValue(self.mapFrameDict['resolution'])
1081
1082        gridBagSizer.Add(
1083            flexSizer,
1084            pos=(
1085                4,
1086                0),
1087            flag=wx.ALIGN_CENTER_VERTICAL | wx.EXPAND,
1088            border=0)
1089
1090        sizer.Add(
1091            gridBagSizer,
1092            proportion=1,
1093            flag=wx.EXPAND | wx.ALL,
1094            border=5)
1095        border.Add(sizer, proportion=0, flag=wx.ALL | wx.EXPAND, border=5)
1096
1097        # border
1098        # GTC Line around legend or map frame
1099        box = StaticBox(
1100            parent=self,
1101            id=wx.ID_ANY,
1102            label=" %s " %
1103            _("Border"))
1104        sizer = wx.StaticBoxSizer(box, wx.HORIZONTAL)
1105        gridBagSizer = wx.GridBagSizer(hgap=5, vgap=5)
1106
1107        self.borderCheck = CheckBox(
1108            self, id=wx.ID_ANY, label=(
1109                _("draw border around map frame")))
1110        if self.mapFrameDict['border'] == 'y':
1111            self.borderCheck.SetValue(True)
1112        else:
1113            self.borderCheck.SetValue(False)
1114
1115        self.borderColorText = StaticText(
1116            self, id=wx.ID_ANY, label=_("border color:"))
1117        self.borderWidthText = StaticText(
1118            self, id=wx.ID_ANY, label=_("border width (pts):"))
1119        self.borderColourPicker = ColourPickerCtrl(self, id=wx.ID_ANY)
1120        self.borderWidthCtrl = SpinCtrl(
1121            self, id=wx.ID_ANY, min=1, max=100, initial=1)
1122
1123        if self.mapFrameDict['border'] == 'y':
1124            self.borderWidthCtrl.SetValue(int(self.mapFrameDict['width']))
1125            self.borderColourPicker.SetColour(
1126                convertRGB(self.mapFrameDict['color']))
1127
1128        gridBagSizer.Add(
1129            self.borderCheck, pos=(
1130                0, 0), span=(
1131                1, 2), flag=wx.ALIGN_CENTER_VERTICAL | wx.EXPAND, border=0)
1132        gridBagSizer.Add(
1133            self.borderColorText, pos=(1, 1),
1134            flag=wx.ALIGN_CENTER_VERTICAL, border=0)
1135        gridBagSizer.Add(
1136            self.borderWidthText, pos=(2, 1),
1137            flag=wx.ALIGN_CENTER_VERTICAL, border=0)
1138        gridBagSizer.Add(
1139            self.borderColourPicker,
1140            pos=(
1141                1,
1142                2),
1143            flag=wx.ALIGN_CENTER_VERTICAL | wx.EXPAND,
1144            border=0)
1145        gridBagSizer.Add(
1146            self.borderWidthCtrl,
1147            pos=(
1148                2,
1149                2),
1150            flag=wx.ALIGN_CENTER_VERTICAL | wx.EXPAND,
1151            border=0)
1152
1153        sizer.Add(
1154            gridBagSizer,
1155            proportion=1,
1156            flag=wx.EXPAND | wx.ALL,
1157            border=5)
1158        border.Add(sizer, proportion=0, flag=wx.ALL | wx.EXPAND, border=5)
1159
1160        self.SetSizer(border)
1161        self.Fit()
1162
1163        if projInfo()['proj'] == 'll':
1164            self.scaleChoice.SetItems(self.scaleChoice.GetItems()[0:3])
1165            boxC.Hide()
1166            for each in self.centerSizer.GetChildren():
1167                each.GetWindow().Hide()
1168
1169        # bindings
1170        self.scaleChoice.Bind(wx.EVT_CHOICE, self.OnScaleChoice)
1171        self.Bind(wx.EVT_RADIOBUTTON, self.OnElementType, self.vectorTypeRadio)
1172        self.Bind(wx.EVT_RADIOBUTTON, self.OnElementType, self.rasterTypeRadio)
1173        self.Bind(wx.EVT_CHECKBOX, self.OnBorder, self.borderCheck)
1174
1175    def OnMap(self, event):
1176        """Selected map or region changing"""
1177
1178        if self.select.GetValue():
1179            self.selected = self.select.GetValue()
1180        else:
1181            self.selected = None
1182
1183        if self.scaleChoice.GetSelection() == 0:
1184            self.selectedMap = self.selected
1185            if self.rasterTypeRadio.GetValue():
1186                mapType = 'raster'
1187            else:
1188                mapType = 'vector'
1189
1190            self.scale[0], self.center[0], foo = AutoAdjust(
1191                self, scaleType=0, map=self.selected, mapType=mapType,
1192                rect=self.mapFrameDict['rect'], env=self.env)
1193            #self.center[0] = self.RegionCenter(self.RegionDict(scaleType = 0))
1194
1195        elif self.scaleChoice.GetSelection() == 1:
1196            self.selectedRegion = self.selected
1197            self.scale[1], self.center[1], foo = AutoAdjust(
1198                self, scaleType=1, region=self.selected,
1199                rect=self.mapFrameDict['rect'], env=self.env)
1200            #self.center[1] = self.RegionCenter(self.RegionDict(scaleType = 1))
1201        elif self.scaleChoice.GetSelection() == 2:
1202            self.scale[2], self.center[2], foo = AutoAdjust(
1203                self, scaleType=2, rect=self.mapFrameDict['rect'], env=self.env)
1204            #self.center[2] = self.RegionCenter(self.RegionDict(scaleType = 2))
1205
1206        else:
1207            self.scale[3] = None
1208            self.center[3] = None
1209
1210        self.OnScaleChoice(None)
1211
1212    def OnScaleChoice(self, event):
1213        """Selected scale type changing"""
1214
1215        scaleType = self.scaleChoice.GetSelection()
1216        if self.scaleType != scaleType:
1217            self.scaleType = scaleType
1218            self.select.SetValue("")
1219
1220        if scaleType in (
1221                0, 1):  # automatic - region from raster map, saved region
1222            if scaleType == 0:
1223                # set map selection
1224                self.rasterTypeRadio.Show()
1225                self.vectorTypeRadio.Show()
1226                self.drawMap.Show()
1227                self.staticBox.SetLabel(" %s " % _("Map selection"))
1228                if self.rasterTypeRadio.GetValue():
1229                    stype = 'raster'
1230                else:
1231                    stype = 'vector'
1232
1233                self.select.SetElementList(type=stype)
1234                self.mapText.SetLabel(self.mapOrRegionText[0])
1235                self.select.SetToolTip(
1236                    _("Region is set to match this map,\nraster or vector map must be added later"))
1237
1238            if scaleType == 1:
1239                # set region selection
1240                self.rasterTypeRadio.Hide()
1241                self.vectorTypeRadio.Hide()
1242                self.drawMap.Hide()
1243                self.staticBox.SetLabel(" %s " % _("Region selection"))
1244                stype = 'region'
1245                self.select.SetElementList(type=stype)
1246                self.mapText.SetLabel(self.mapOrRegionText[1])
1247                self.select.SetToolTip("")
1248
1249            for each in self.mapSizer.GetChildren():
1250                each.GetWindow().Enable()
1251            for each in self.centerSizer.GetChildren():
1252                each.GetWindow().Disable()
1253
1254            if self.scale[scaleType]:
1255
1256                self.scaleTextCtrl.SetValue(
1257                    "%.0f" % (1 / self.scale[scaleType]))
1258            if self.center[scaleType]:
1259                self.eastingTextCtrl.SetValue(str(self.center[scaleType][0]))
1260                self.northingTextCtrl.SetValue(str(self.center[scaleType][1]))
1261        elif scaleType == 2:
1262            for each in self.mapSizer.GetChildren():
1263                each.GetWindow().Disable()
1264            for each in self.centerSizer.GetChildren():
1265                each.GetWindow().Disable()
1266
1267            if self.scale[scaleType]:
1268                self.scaleTextCtrl.SetValue(
1269                    "%.0f" % (1 / self.scale[scaleType]))
1270            if self.center[scaleType]:
1271                self.eastingTextCtrl.SetValue(str(self.center[scaleType][0]))
1272                self.northingTextCtrl.SetValue(str(self.center[scaleType][1]))
1273        else:  # fixed
1274            for each in self.mapSizer.GetChildren():
1275                each.GetWindow().Disable()
1276            for each in self.centerSizer.GetChildren():
1277                each.GetWindow().Enable()
1278
1279            if self.scale[scaleType]:
1280                self.scaleTextCtrl.SetValue(
1281                    "%.0f" % (1 / self.scale[scaleType]))
1282            if self.center[scaleType]:
1283                self.eastingTextCtrl.SetValue(str(self.center[scaleType][0]))
1284                self.northingTextCtrl.SetValue(str(self.center[scaleType][1]))
1285
1286    def OnElementType(self, event):
1287        """Changes data in map selection tree ctrl popup"""
1288        if self.rasterTypeRadio.GetValue():
1289            mapType = 'raster'
1290        else:
1291            mapType = 'vector'
1292        self.select.SetElementList(type=mapType)
1293        if self.mapType != mapType and event is not None:
1294            self.mapType = mapType
1295            self.select.SetValue('')
1296        self.mapType = mapType
1297
1298    def OnBorder(self, event):
1299        """Enables/disable the part relating to border of map frame"""
1300        for each in (self.borderColorText, self.borderWidthText,
1301                     self.borderColourPicker, self.borderWidthCtrl):
1302            each.Enable(self.borderCheck.GetValue())
1303
1304    def getId(self):
1305        """Returns id of raster map"""
1306        return self.id
1307
1308    def update(self):
1309        """Save changes"""
1310        mapFrameDict = dict(self.mapFrameDict)
1311        # resolution
1312        mapFrameDict['resolution'] = self.resolutionSpin.GetValue()
1313        # scale
1314        scaleType = self.scaleType
1315        mapFrameDict['scaleType'] = scaleType
1316
1317        if mapFrameDict['scaleType'] == 0:
1318            if self.select.GetValue():
1319                mapFrameDict['drawMap'] = self.drawMap.GetValue()
1320                mapFrameDict['map'] = self.select.GetValue()
1321                mapFrameDict['mapType'] = self.mapType
1322                mapFrameDict['region'] = None
1323
1324                if mapFrameDict['drawMap']:
1325
1326                    if mapFrameDict['mapType'] == 'raster':
1327                        mapFile = grass.find_file(
1328                            mapFrameDict['map'],
1329                            element='cell')
1330                        if mapFile['file'] == '':
1331                            GMessage(
1332                                "Raster %s not found" %
1333                                mapFrameDict['map'])
1334                            return False
1335                        raster = self.instruction.FindInstructionByType(
1336                            'raster')
1337                        if raster:
1338                            raster['raster'] = mapFrameDict['map']
1339                        else:
1340                            raster = Raster(NewId(), env=self.env)
1341                            raster['raster'] = mapFrameDict['map']
1342                            raster['isRaster'] = True
1343                            self.instruction.AddInstruction(raster)
1344
1345                    elif mapFrameDict['mapType'] == 'vector':
1346
1347                        mapFile = grass.find_file(
1348                            mapFrameDict['map'],
1349                            element='vector')
1350                        if mapFile['file'] == '':
1351                            GMessage(
1352                                "Vector %s not found" %
1353                                mapFrameDict['map'])
1354                            return False
1355
1356                        vector = self.instruction.FindInstructionByType(
1357                            'vector')
1358                        isAdded = False
1359                        if vector:
1360                            for each in vector['list']:
1361                                if each[0] == mapFrameDict['map']:
1362                                    isAdded = True
1363                        if not isAdded:
1364                            topoInfo = grass.vector_info_topo(
1365                                map=mapFrameDict['map'])
1366                            if topoInfo:
1367                                if bool(topoInfo['areas']):
1368                                    topoType = 'areas'
1369                                elif bool(topoInfo['lines']):
1370                                    topoType = 'lines'
1371                                else:
1372                                    topoType = 'points'
1373                                label = '('.join(
1374                                    mapFrameDict['map'].split('@')) + ')'
1375
1376                                if not vector:
1377                                    vector = Vector(NewId(), env=self.env)
1378                                    vector['list'] = []
1379                                    self.instruction.AddInstruction(vector)
1380                                id = NewId()
1381                                vector['list'].insert(
1382                                    0, [mapFrameDict['map'], topoType, id, 1, label])
1383                                vProp = VProperties(id, topoType, env=self.env)
1384                                vProp['name'], vProp['label'], vProp[
1385                                    'lpos'] = mapFrameDict['map'], label, 1
1386                                self.instruction.AddInstruction(vProp)
1387                            else:
1388                                return False
1389
1390                self.scale[0], self.center[0], self.rectAdjusted = AutoAdjust(
1391                    self, scaleType=0, map=mapFrameDict['map'], env=self.env,
1392                    mapType=self.mapType, rect=self.mapFrameDict['rect'])
1393
1394                if self.rectAdjusted:
1395                    mapFrameDict['rect'] = self.rectAdjusted
1396                else:
1397                    mapFrameDict['rect'] = self.mapFrameDict['rect']
1398
1399                mapFrameDict['scale'] = self.scale[0]
1400
1401                mapFrameDict['center'] = self.center[0]
1402                # set region
1403                if self.mapType == 'raster':
1404                    self.env['GRASS_REGION'] = grass.region_env(raster=mapFrameDict['map'],
1405                                                                env=self.env)
1406                if self.mapType == 'vector':
1407                    raster = self.instruction.FindInstructionByType('raster')
1408                    if raster:
1409                        rasterId = raster.id
1410                    else:
1411                        rasterId = None
1412
1413                    if rasterId:
1414                        self.env['GRASS_REGION'] = grass.region_env(vector=mapFrameDict['map'],
1415                                                                    raster=self.instruction[rasterId]['raster'],
1416                                                                    env=self.env)
1417                    else:
1418                        self.env['GRASS_REGION'] = grass.region_env(vector=mapFrameDict['map'],
1419                                                                    env=self.env)
1420
1421            else:
1422                wx.MessageBox(
1423                    message=_("No map selected!"),
1424                    caption=_('Invalid input'),
1425                    style=wx.OK | wx.ICON_ERROR)
1426                return False
1427
1428        elif mapFrameDict['scaleType'] == 1:
1429            if self.select.GetValue():
1430                mapFrameDict['drawMap'] = False
1431                mapFrameDict['map'] = None
1432                mapFrameDict['mapType'] = None
1433                mapFrameDict['region'] = self.select.GetValue()
1434                self.scale[1], self.center[1], self.rectAdjusted = AutoAdjust(
1435                    self, scaleType=1, region=mapFrameDict['region'],
1436                    rect=self.mapFrameDict['rect'], env=self.env)
1437                if self.rectAdjusted:
1438                    mapFrameDict['rect'] = self.rectAdjusted
1439                else:
1440                    mapFrameDict['rect'] = self.mapFrameDict['rect']
1441
1442                mapFrameDict['scale'] = self.scale[1]
1443                mapFrameDict['center'] = self.center[1]
1444                # set region
1445                self.env['GRASS_REGION'] = grass.region_env(region=mapFrameDict['region'],
1446                                                            env=self.env)
1447            else:
1448                wx.MessageBox(
1449                    message=_("No region selected!"),
1450                    caption=_('Invalid input'),
1451                    style=wx.OK | wx.ICON_ERROR)
1452                return False
1453
1454        elif scaleType == 2:
1455            mapFrameDict['drawMap'] = False
1456            mapFrameDict['map'] = None
1457            mapFrameDict['mapType'] = None
1458            mapFrameDict['region'] = None
1459            self.scale[2], self.center[2], self.rectAdjusted = AutoAdjust(
1460                self, scaleType=2, rect=self.mapFrameDict['rect'], env=self.env)
1461            if self.rectAdjusted:
1462                mapFrameDict['rect'] = self.rectAdjusted
1463            else:
1464                mapFrameDict['rect'] = self.mapFrameDict['rect']
1465
1466            mapFrameDict['scale'] = self.scale[2]
1467            mapFrameDict['center'] = self.center[2]
1468            region = grass.region(env=None)
1469
1470            raster = self.instruction.FindInstructionByType('raster')
1471            if raster:
1472                rasterId = raster.id
1473            else:
1474                rasterId = None
1475
1476            if rasterId:  # because of resolution
1477                self.env['GRASS_REGION'] = grass.region_env(n=region['n'], s=region['s'],
1478                                                            e=region['e'], w=region['w'],
1479                                                            raster=self.instruction[rasterId]['raster'],
1480                                                            env=self.env)
1481            else:
1482                self.env['GRASS_REGION'] = grass.region_env(n=region['n'], s=region['s'],
1483                                                            e=region['e'], w=region['w'],
1484                                                            env=self.env)
1485
1486        elif scaleType == 3:
1487            mapFrameDict['drawMap'] = False
1488            mapFrameDict['map'] = None
1489            mapFrameDict['mapType'] = None
1490            mapFrameDict['region'] = None
1491            mapFrameDict['rect'] = self.mapFrameDict['rect']
1492            try:
1493                scaleNumber = float(self.scaleTextCtrl.GetValue())
1494                centerE = float(self.eastingTextCtrl.GetValue())
1495                centerN = float(self.northingTextCtrl.GetValue())
1496            except (ValueError, SyntaxError):
1497                wx.MessageBox(
1498                    message=_("Invalid scale or map center!"),
1499                    caption=_('Invalid input'),
1500                    style=wx.OK | wx.ICON_ERROR)
1501                return False
1502            mapFrameDict['scale'] = 1 / scaleNumber
1503            mapFrameDict['center'] = centerE, centerN
1504
1505            ComputeSetRegion(self, mapDict=mapFrameDict, env=self.env)
1506
1507        # check resolution
1508        SetResolution(
1509            dpi=mapFrameDict['resolution'],
1510            width=mapFrameDict['rect'].width,
1511            height=mapFrameDict['rect'].height,
1512            env=self.env)
1513        # border
1514        if self.borderCheck.GetValue():
1515            mapFrameDict['border'] = 'y'
1516        else:
1517            mapFrameDict['border'] = 'n'
1518
1519        if mapFrameDict['border'] == 'y':
1520            mapFrameDict['width'] = self.borderWidthCtrl.GetValue()
1521            mapFrameDict['color'] = convertRGB(
1522                self.borderColourPicker.GetColour())
1523
1524        if self.id not in self.instruction:
1525            mapFrame = MapFrame(self.id, env=self.env)
1526            self.instruction.AddInstruction(mapFrame)
1527        self.instruction[self.id].SetInstruction(mapFrameDict)
1528
1529        if self.id not in self.mapDialog.parent.objectId:
1530            self.mapDialog.parent.objectId.insert(
1531                0, self.id)  # map frame is drawn first
1532        return True
1533
1534
1535class RasterPanel(Panel):
1536    """Panel for raster map settings"""
1537
1538    def __init__(self, parent, id, settings, env, notebook=True):
1539        Panel.__init__(self, parent, id=wx.ID_ANY, style=wx.TAB_TRAVERSAL)
1540        self.instruction = settings
1541        self.env = env
1542
1543        if notebook:
1544            self.book = parent
1545            self.book.AddPage(page=self, text=_("Raster map"))
1546            self.mainDialog = self.book.GetParent()
1547        else:
1548            self.mainDialog = parent
1549        if id:
1550            self.id = id
1551            self.rasterDict = self.instruction[self.id].GetInstruction()
1552        else:
1553            self.id = NewId()
1554            raster = Raster(self.id, env=self.env)
1555            self.rasterDict = raster.GetInstruction()
1556
1557        self._layout()
1558        self.OnRaster(None)
1559
1560    def _layout(self):
1561        """Do layout"""
1562        border = wx.BoxSizer(wx.VERTICAL)
1563
1564        # choose raster map
1565
1566        box = StaticBox(
1567            parent=self,
1568            id=wx.ID_ANY,
1569            label=" %s " %
1570            _("Choose raster map"))
1571        sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
1572        gridBagSizer = wx.GridBagSizer(hgap=5, vgap=5)
1573
1574        self.rasterNoRadio = RadioButton(
1575            self, id=wx.ID_ANY, label=_("no raster map"),
1576            style=wx.RB_GROUP)
1577        self.rasterYesRadio = RadioButton(
1578            self, id=wx.ID_ANY, label=_("raster:"))
1579
1580        self.rasterSelect = Select(
1581            self,
1582            id=wx.ID_ANY,
1583            size=globalvar.DIALOG_GSELECT_SIZE,
1584            type='raster',
1585            multiple=False,
1586            updateOnPopup=True,
1587            onPopup=None)
1588        if self.rasterDict['isRaster']:
1589            self.rasterYesRadio.SetValue(True)
1590            self.rasterNoRadio.SetValue(False)
1591            self.rasterSelect.SetValue(self.rasterDict['raster'])
1592        else:
1593            self.rasterYesRadio.SetValue(False)
1594            self.rasterNoRadio.SetValue(True)
1595            mapId = self.instruction.FindInstructionByType('map').id
1596
1597            if self.instruction[mapId]['map'] and self.instruction[
1598                    mapId]['mapType'] == 'raster':
1599                # raster map from map frame dialog if possible
1600                self.rasterSelect.SetValue(self.instruction[mapId]['map'])
1601            else:
1602                self.rasterSelect.SetValue('')
1603        gridBagSizer.Add(
1604            self.rasterNoRadio, pos=(
1605                0, 0), span=(
1606                1, 2), flag=wx.ALIGN_CENTER_VERTICAL, border=0)
1607        gridBagSizer.Add(
1608            self.rasterYesRadio, pos=(1, 0),
1609            flag=wx.ALIGN_CENTER_VERTICAL, border=0)
1610        gridBagSizer.Add(
1611            self.rasterSelect,
1612            pos=(
1613                1,
1614                1),
1615            flag=wx.ALIGN_CENTER_VERTICAL | wx.EXPAND,
1616            border=0)
1617
1618        sizer.Add(
1619            gridBagSizer,
1620            proportion=1,
1621            flag=wx.EXPAND | wx.ALL,
1622            border=5)
1623        border.Add(sizer, proportion=0, flag=wx.ALL | wx.EXPAND, border=5)
1624
1625        #self.rasterSelect.GetTextCtrl().Bind(wx.EVT_TEXT, self.OnRaster)
1626        self.Bind(wx.EVT_RADIOBUTTON, self.OnRaster, self.rasterNoRadio)
1627        self.Bind(wx.EVT_RADIOBUTTON, self.OnRaster, self.rasterYesRadio)
1628
1629        self.SetSizer(border)
1630        self.Fit()
1631
1632    def OnRaster(self, event):
1633        """Enable/disable raster selection"""
1634        self.rasterSelect.Enable(self.rasterYesRadio.GetValue())
1635
1636    def update(self):
1637        # draw raster
1638        mapInstr = self.instruction.FindInstructionByType('map')
1639        if not mapInstr:  # no map frame
1640            GMessage(message=_("Please, create map frame first."))
1641            return
1642
1643        if self.rasterNoRadio.GetValue() or not self.rasterSelect.GetValue():
1644            self.rasterDict['isRaster'] = False
1645            self.rasterDict['raster'] = None
1646            mapInstr['drawMap'] = False
1647            if self.id in self.instruction:
1648                del self.instruction[self.id]
1649
1650        else:
1651            self.rasterDict['isRaster'] = True
1652            self.rasterDict['raster'] = self.rasterSelect.GetValue()
1653            if self.rasterDict['raster'] != mapInstr['drawMap']:
1654                mapInstr['drawMap'] = False
1655
1656            raster = self.instruction.FindInstructionByType('raster')
1657            if not raster:
1658                raster = Raster(self.id, env=self.env)
1659                self.instruction.AddInstruction(raster)
1660                self.instruction[self.id].SetInstruction(self.rasterDict)
1661            else:
1662                self.instruction[raster.id].SetInstruction(self.rasterDict)
1663
1664        if 'map' in self.mainDialog.parent.openDialogs:
1665            self.mainDialog.parent.openDialogs['map'].updateDialog()
1666        return True
1667
1668    def getId(self):
1669        return self.id
1670
1671
1672class VectorPanel(Panel):
1673    """Panel for vector maps settings"""
1674
1675    def __init__(self, parent, id, settings, env, notebook=True):
1676        Panel.__init__(self, parent, id=wx.ID_ANY, style=wx.TAB_TRAVERSAL)
1677
1678        self.parent = parent
1679        self.env = env
1680        self.instruction = settings
1681        self.tmpDialogDict = {}
1682        vectors = self.instruction.FindInstructionByType(
1683            'vProperties', list=True)
1684        for vector in vectors:
1685            self.tmpDialogDict[vector.id] = dict(
1686                self.instruction[vector.id].GetInstruction())
1687
1688        if id:
1689            self.id = id
1690            self.vectorList = deepcopy(self.instruction[id]['list'])
1691        else:
1692            self.id = NewId()
1693            self.vectorList = []
1694
1695        vLegend = self.instruction.FindInstructionByType('vectorLegend')
1696        if vLegend:
1697            self.vLegendId = vLegend.id
1698        else:
1699            self.vLegendId = None
1700
1701        self._layout()
1702
1703        if notebook:
1704            self.parent.AddPage(page=self, text=_("Vector maps"))
1705            self.parent = self.parent.GetParent()
1706
1707    def _layout(self):
1708        """Do layout"""
1709        border = wx.BoxSizer(wx.VERTICAL)
1710
1711        # choose vector map
1712
1713        box = StaticBox(
1714            parent=self,
1715            id=wx.ID_ANY,
1716            label=" %s " %
1717            _("Add map"))
1718        sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
1719        gridBagSizer = wx.GridBagSizer(hgap=5, vgap=5)
1720
1721        text = StaticText(self, id=wx.ID_ANY, label=_("Map:"))
1722        self.select = Select(self, id=wx.ID_ANY,  # size = globalvar.DIALOG_GSELECT_SIZE,
1723                             type='vector', multiple=False,
1724                             updateOnPopup=True, onPopup=None)
1725        topologyTypeTr = [_("points"), _("lines"), _("areas")]
1726        self.topologyTypeList = ["points", "lines", "areas"]
1727        self.vectorType = wx.RadioBox(
1728            self,
1729            id=wx.ID_ANY,
1730            label=" %s " %
1731            _("Data Type"),
1732            choices=topologyTypeTr,
1733            majorDimension=3,
1734            style=wx.RA_SPECIFY_COLS)
1735
1736        self.AddVector = Button(self, id=wx.ID_ANY, label=_("Add"))
1737
1738        gridBagSizer.Add(
1739            text, pos=(0, 0),
1740            flag=wx.ALIGN_CENTER_VERTICAL, border=0)
1741        gridBagSizer.Add(
1742            self.select, pos=(
1743                0, 1), span=(
1744                1, 2), flag=wx.ALIGN_CENTER_VERTICAL, border=0)
1745        gridBagSizer.Add(
1746            self.vectorType, pos=(1, 1),
1747            flag=wx.ALIGN_CENTER, border=0)
1748        gridBagSizer.Add(
1749            self.AddVector, pos=(1, 2),
1750            flag=wx.ALIGN_BOTTOM | wx.ALIGN_RIGHT, border=0)
1751
1752        sizer.Add(
1753            gridBagSizer,
1754            proportion=1,
1755            flag=wx.EXPAND | wx.ALL,
1756            border=5)
1757        border.Add(sizer, proportion=0, flag=wx.ALL | wx.EXPAND, border=5)
1758
1759        # manage vector layers
1760
1761        box = StaticBox(
1762            parent=self,
1763            id=wx.ID_ANY,
1764            label=" %s " %
1765            _("Manage vector maps"))
1766        sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
1767        gridBagSizer = wx.GridBagSizer(hgap=5, vgap=5)
1768
1769        text = StaticText(self, id=wx.ID_ANY, label=_(
1770            "The topmost vector map overlaps the others"))
1771        self.listbox = ListBox(
1772            self, id=wx.ID_ANY, choices=[],
1773            style=wx.LB_SINGLE | wx.LB_NEEDED_SB)
1774        self.btnUp = Button(self, id=wx.ID_ANY, label=_("Up"))
1775        self.btnDown = Button(self, id=wx.ID_ANY, label=_("Down"))
1776        self.btnDel = Button(self, id=wx.ID_ANY, label=_("Delete"))
1777        self.btnProp = Button(self, id=wx.ID_ANY, label=_("Properties..."))
1778
1779        self.updateListBox(selected=0)
1780
1781        gridBagSizer.Add(
1782            text, pos=(0, 0),
1783            flag=wx.ALIGN_CENTER_VERTICAL, border=0)
1784        gridBagSizer.Add(
1785            self.listbox, pos=(
1786                1, 0), span=(
1787                4, 1), flag=wx.ALIGN_CENTER_VERTICAL | wx.EXPAND, border=0)
1788        gridBagSizer.Add(
1789            self.btnUp,
1790            pos=(
1791                1,
1792                1),
1793            flag=wx.ALIGN_CENTER_VERTICAL | wx.EXPAND,
1794            border=0)
1795        gridBagSizer.Add(
1796            self.btnDown,
1797            pos=(
1798                2,
1799                1),
1800            flag=wx.ALIGN_CENTER_VERTICAL | wx.EXPAND,
1801            border=0)
1802        gridBagSizer.Add(
1803            self.btnDel,
1804            pos=(
1805                3,
1806                1),
1807            flag=wx.ALIGN_CENTER_VERTICAL | wx.EXPAND,
1808            border=0)
1809        gridBagSizer.Add(
1810            self.btnProp,
1811            pos=(
1812                4,
1813                1),
1814            flag=wx.ALIGN_CENTER_VERTICAL | wx.EXPAND,
1815            border=0)
1816
1817        gridBagSizer.AddGrowableCol(0, 2)
1818        gridBagSizer.AddGrowableCol(1, 1)
1819        sizer.Add(gridBagSizer, proportion=0, flag=wx.ALL, border=5)
1820        border.Add(sizer, proportion=0, flag=wx.ALL | wx.EXPAND, border=5)
1821
1822        self.Bind(wx.EVT_BUTTON, self.OnAddVector, self.AddVector)
1823        self.Bind(wx.EVT_BUTTON, self.OnDelete, self.btnDel)
1824        self.Bind(wx.EVT_BUTTON, self.OnUp, self.btnUp)
1825        self.Bind(wx.EVT_BUTTON, self.OnDown, self.btnDown)
1826        self.Bind(wx.EVT_BUTTON, self.OnProperties, self.btnProp)
1827        self.select.GetTextCtrl().Bind(wx.EVT_TEXT, self.OnVector)
1828
1829        self.SetSizer(border)
1830        self.Fit()
1831
1832        self.Bind(wx.EVT_LISTBOX_DCLICK, self.OnProperties, self.listbox)
1833
1834    def OnVector(self, event):
1835        """Gets info about toplogy and enables/disables choices point/line/area"""
1836        vmap = self.select.GetValue()
1837        try:
1838            topoInfo = grass.vector_info_topo(map=vmap)
1839        except grass.ScriptError:
1840            return
1841
1842        if topoInfo:
1843            self.vectorType.EnableItem(2, bool(topoInfo['areas']))
1844            self.vectorType.EnableItem(
1845                1, bool(
1846                    topoInfo['boundaries']) or bool(
1847                    topoInfo['lines']))
1848            self.vectorType.EnableItem(
1849                0, bool(
1850                    topoInfo['centroids'] or bool(
1851                        topoInfo['points'])))
1852            for item in range(2, -1, -1):
1853                if self.vectorType.IsItemEnabled(item):
1854                    self.vectorType.SetSelection(item)
1855                    break
1856
1857            self.AddVector.SetFocus()
1858
1859    def OnAddVector(self, event):
1860        """Adds vector map to list"""
1861        vmap = self.select.GetValue()
1862        if vmap:
1863            mapname = vmap.split('@')[0]
1864            try:
1865                mapset = '(' + vmap.split('@')[1] + ')'
1866            except IndexError:
1867                mapset = ''
1868            idx = self.vectorType.GetSelection()
1869            ttype = self.topologyTypeList[idx]
1870            record = "%s - %s" % (vmap, ttype)
1871            id = NewId()
1872            lpos = 1
1873            label = mapname + mapset
1874            self.vectorList.insert(0, [vmap, ttype, id, lpos, label])
1875            self.reposition()
1876            self.listbox.InsertItems([record], 0)
1877
1878            vector = VProperties(id, ttype, env=self.env)
1879            self.tmpDialogDict[id] = vector.GetInstruction()
1880            self.tmpDialogDict[id]['name'] = vmap
1881
1882            self.listbox.SetSelection(0)
1883            self.listbox.EnsureVisible(0)
1884            self.btnProp.SetFocus()
1885            self.enableButtons()
1886
1887    def OnDelete(self, event):
1888        """Deletes vector map from the list"""
1889        if self.listbox.GetSelections():
1890            pos = self.listbox.GetSelection()
1891            id = self.vectorList[pos][2]
1892            del self.vectorList[pos]
1893            del self.tmpDialogDict[id]
1894
1895            for i in range(pos, len(self.vectorList)):
1896                if self.vectorList[i][3]:  # can be 0
1897                    self.vectorList[i][3] -= 1
1898
1899            if pos < len(self.vectorList) - 1:
1900                selected = pos
1901            else:
1902                selected = len(self.vectorList) - 1
1903            self.updateListBox(selected=selected)
1904            if self.listbox.IsEmpty():
1905                self.enableButtons(False)
1906
1907    def OnUp(self, event):
1908        """Moves selected map to top"""
1909        if self.listbox.GetSelections():
1910            pos = self.listbox.GetSelection()
1911            if pos:
1912                self.vectorList.insert(pos - 1, self.vectorList.pop(pos))
1913            if not self.vLegendId:
1914                self.reposition()
1915
1916            if pos > 0:
1917                self.updateListBox(selected=(pos - 1))
1918            else:
1919                self.updateListBox(selected=0)
1920
1921    def OnDown(self, event):
1922        """Moves selected map to bottom"""
1923        if self.listbox.GetSelections():
1924            pos = self.listbox.GetSelection()
1925            if pos != len(self.vectorList) - 1:
1926                self.vectorList.insert(pos + 1, self.vectorList.pop(pos))
1927                if not self.vLegendId:
1928                    self.reposition()
1929            if pos < len(self.vectorList) - 1:
1930                self.updateListBox(selected=(pos + 1))
1931            else:
1932                self.updateListBox(selected=len(self.vectorList) - 1)
1933
1934    def OnProperties(self, event):
1935        """Opens vector map properties dialog"""
1936        if self.listbox.GetSelections():
1937            pos = self.listbox.GetSelection()
1938            id = self.vectorList[pos][2]
1939
1940            dlg = VPropertiesDialog(
1941                self,
1942                id=id,
1943                settings=self.instruction,
1944                env=self.env,
1945                vectors=self.vectorList,
1946                tmpSettings=self.tmpDialogDict[id])
1947            dlg.ShowModal()
1948
1949            self.parent.FindWindowById(wx.ID_OK).SetFocus()
1950
1951    def enableButtons(self, enable=True):
1952        """Enable/disable up, down, properties, delete buttons"""
1953        self.btnUp.Enable(enable)
1954        self.btnDown.Enable(enable)
1955        self.btnProp.Enable(enable)
1956        self.btnDel.Enable(enable)
1957
1958    def updateListBox(self, selected=None):
1959        mapList = ["%s - %s" % (item[0], item[1]) for item in self.vectorList]
1960        self.listbox.Set(mapList)
1961        if self.listbox.IsEmpty():
1962            self.enableButtons(False)
1963        else:
1964            self.enableButtons(True)
1965            if selected is not None:
1966                self.listbox.SetSelection(selected)
1967                self.listbox.EnsureVisible(selected)
1968
1969    def reposition(self):
1970        """Update position in legend, used only if there is no vlegend yet"""
1971        for i in range(len(self.vectorList)):
1972            if self.vectorList[i][3]:
1973                self.vectorList[i][3] = i + 1
1974
1975    def getId(self):
1976        return self.id
1977
1978    def update(self):
1979        vectors = self.instruction.FindInstructionByType(
1980            'vProperties', list=True)
1981
1982        for vector in vectors:
1983            del self.instruction[vector.id]
1984        if self.id in self.instruction:
1985            del self.instruction[self.id]
1986
1987        if len(self.vectorList) > 0:
1988            vector = Vector(self.id, env=self.env)
1989            self.instruction.AddInstruction(vector)
1990
1991            vector.SetInstruction({'list': deepcopy(self.vectorList)})
1992
1993            # save new vectors
1994            for item in self.vectorList:
1995                id = item[2]
1996
1997                vLayer = VProperties(id, item[1], env=self.env)
1998                self.instruction.AddInstruction(vLayer)
1999                vLayer.SetInstruction(self.tmpDialogDict[id])
2000                vLayer['name'] = item[0]
2001                vLayer['label'] = item[4]
2002                vLayer['lpos'] = item[3]
2003
2004        else:
2005            if self.id in self.instruction:
2006                del self.instruction[self.id]
2007
2008        if 'map' in self.parent.parent.openDialogs:
2009            self.parent.parent.openDialogs['map'].updateDialog()
2010
2011        return True
2012
2013
2014class RasterDialog(PsmapDialog):
2015
2016    def __init__(self, parent, id, settings, env):
2017        PsmapDialog.__init__(
2018            self,
2019            parent=parent,
2020            id=id,
2021            title=_("Raster map settings"),
2022            settings=settings,
2023            env=env)
2024        self.objectType = ('raster',)
2025
2026        self.rPanel = RasterPanel(
2027            parent=self,
2028            id=self.id,
2029            settings=self.instruction,
2030            notebook=False,
2031            env=self.env)
2032
2033        self.id = self.rPanel.getId()
2034        self._layout(self.rPanel)
2035
2036    def update(self):
2037        ok = self.rPanel.update()
2038        if ok:
2039            return True
2040        return False
2041
2042    def OnApply(self, event):
2043        ok = self.update()
2044        if not ok:
2045            return False
2046
2047        if self.id in self.instruction:
2048            self.parent.DialogDataChanged(id=self.id)
2049        else:
2050            mapId = self.instruction.FindInstructionByType('map').id
2051            self.parent.DialogDataChanged(id=mapId)
2052        return True
2053
2054    def updateDialog(self):
2055        """Update information (not used)"""
2056        pass
2057# if 'map' in self.parent.openDialogs:
2058# if self.parent.openDialogs['map'].mPanel.rasterTypeRadio.GetValue()\
2059# and self.parent.openDialogs['map'].mPanel.select.GetValue():
2060# if self.parent.openDialogs['map'].mPanel.drawMap.IsChecked():
2061# self.rPanel.rasterSelect.SetValue(self.parent.openDialogs['map'].mPanel.select.GetValue())
2062
2063
2064class MainVectorDialog(PsmapDialog):
2065
2066    def __init__(self, parent, id, settings, env):
2067        PsmapDialog.__init__(
2068            self,
2069            parent=parent,
2070            id=id,
2071            title=_("Vector maps settings"),
2072            settings=settings,
2073            env=env)
2074        self.objectType = ('vector',)
2075        self.vPanel = VectorPanel(
2076            parent=self,
2077            id=self.id,
2078            settings=self.instruction,
2079            env=env,
2080            notebook=False)
2081
2082        self.id = self.vPanel.getId()
2083        self._layout(self.vPanel)
2084
2085    def update(self):
2086        self.vPanel.update()
2087
2088    def OnApply(self, event):
2089        self.update()
2090        if self.id in self.instruction:
2091            self.parent.DialogDataChanged(id=self.id)
2092        else:
2093            mapId = self.instruction.FindInstructionByType('map').id
2094            self.parent.DialogDataChanged(id=mapId)
2095        return True
2096
2097    def updateDialog(self):
2098        """Update information (not used)"""
2099        pass
2100
2101
2102class VPropertiesDialog(PsmapDialog):
2103
2104    def __init__(self, parent, id, settings, vectors, tmpSettings, env):
2105        PsmapDialog.__init__(
2106            self,
2107            parent=parent,
2108            id=id,
2109            title="",
2110            settings=settings,
2111            env=env,
2112            apply=False)
2113
2114        vectorList = vectors
2115        self.vPropertiesDict = tmpSettings
2116
2117        # determine map and its type
2118        for item in vectorList:
2119            if id == item[2]:
2120                self.vectorName = item[0]
2121                self.type = item[1]
2122        self.SetTitle(_("%s properties") % self.vectorName)
2123
2124        # vector map info
2125        self.connection = True
2126        try:
2127            self.mapDBInfo = VectorDBInfo(self.vectorName)
2128            self.layers = self.mapDBInfo.layers.keys()
2129        except grass.ScriptError:
2130            self.connection = False
2131            self.layers = []
2132        if not self.layers:
2133            self.connection = False
2134            self.layers = []
2135
2136        self.currLayer = self.vPropertiesDict['layer']
2137
2138        # path to symbols, patterns
2139        gisbase = os.getenv("GISBASE")
2140        self.symbolPath = os.path.join(gisbase, 'etc', 'symbol')
2141        self.symbols = []
2142        for dir in os.listdir(self.symbolPath):
2143            for symbol in os.listdir(os.path.join(self.symbolPath, dir)):
2144                self.symbols.append(os.path.join(dir, symbol))
2145        self.patternPath = os.path.join(gisbase, 'etc', 'paint', 'patterns')
2146
2147        # notebook
2148        notebook = Notebook(parent=self, id=wx.ID_ANY, style=wx.BK_DEFAULT)
2149        self.DSpanel = self._DataSelectionPanel(notebook)
2150        self.EnableLayerSelection(enable=self.connection)
2151        selectPanel = {
2152            'points': [
2153                self._ColorsPointAreaPanel, self._StylePointPanel], 'lines': [
2154                self._ColorsLinePanel, self._StyleLinePanel], 'areas': [
2155                self._ColorsPointAreaPanel, self._StyleAreaPanel]}
2156        self.ColorsPanel = selectPanel[self.type][0](notebook)
2157
2158        self.OnOutline(None)
2159        if self.type in ('points', 'areas'):
2160            self.OnFill(None)
2161        self.OnColor(None)
2162
2163        self.StylePanel = selectPanel[self.type][1](notebook)
2164        if self.type == 'points':
2165            self.OnSize(None)
2166            self.OnRotation(None)
2167            self.OnSymbology(None)
2168        if self.type == 'areas':
2169            self.OnPattern(None)
2170
2171        self._layout(notebook)
2172
2173    def _DataSelectionPanel(self, notebook):
2174        panel = Panel(
2175            parent=notebook, id=wx.ID_ANY, size=(-1, -1),
2176            style=wx.TAB_TRAVERSAL)
2177        notebook.AddPage(page=panel, text=_("Data selection"))
2178
2179        border = wx.BoxSizer(wx.VERTICAL)
2180
2181        # data type
2182        self.checkType1 = self.checkType2 = None
2183        if self.type in ('lines', 'points'):
2184            box = StaticBox(
2185                parent=panel,
2186                id=wx.ID_ANY,
2187                label=" %s " %
2188                _("Feature type"))
2189            sizer = wx.StaticBoxSizer(box, wx.HORIZONTAL)
2190            gridBagSizer = wx.GridBagSizer(hgap=5, vgap=5)
2191            if self.type == 'points':
2192                label = (_("points"), _("centroids"))
2193            else:
2194                label = (_("lines"), _("boundaries"))
2195            if self.type == 'points':
2196                name = ("point", "centroid")
2197            else:
2198                name = ("line", "boundary")
2199            self.checkType1 = CheckBox(
2200                panel, id=wx.ID_ANY, label=label[0], name=name[0])
2201            self.checkType2 = CheckBox(
2202                panel, id=wx.ID_ANY, label=label[1], name=name[1])
2203            self.checkType1.SetValue(
2204                self.vPropertiesDict['type'].find(
2205                    name[0]) >= 0)
2206            self.checkType2.SetValue(
2207                self.vPropertiesDict['type'].find(
2208                    name[1]) >= 0)
2209
2210            gridBagSizer.Add(
2211                self.checkType1, pos=(0, 0),
2212                flag=wx.ALIGN_CENTER_VERTICAL, border=0)
2213            gridBagSizer.Add(
2214                self.checkType2, pos=(0, 1),
2215                flag=wx.ALIGN_CENTER_VERTICAL, border=0)
2216            sizer.Add(
2217                gridBagSizer,
2218                proportion=1,
2219                flag=wx.EXPAND | wx.ALL,
2220                border=5)
2221            border.Add(
2222                sizer,
2223                proportion=0,
2224                flag=wx.ALL | wx.EXPAND,
2225                border=5)
2226
2227        # layer selection
2228        box = StaticBox(
2229            parent=panel,
2230            id=wx.ID_ANY,
2231            label=" %s " %
2232            _("Layer selection"))
2233        sizer = wx.StaticBoxSizer(box, wx.HORIZONTAL)
2234        self.gridBagSizerL = wx.GridBagSizer(hgap=5, vgap=5)
2235
2236        self.warning = StaticText(panel, id=wx.ID_ANY, label="")
2237        if not self.connection:
2238            self.warning = StaticText(panel, id=wx.ID_ANY, label=_(
2239                "Database connection is not defined in DB file."))
2240        text = StaticText(panel, id=wx.ID_ANY, label=_("Select layer:"))
2241        self.layerChoice = Choice(
2242            panel, id=wx.ID_ANY, choices=[str(each) for each in self.layers],
2243            size=self.spinCtrlSize)
2244
2245        self.layerChoice.SetStringSelection(self.currLayer)
2246
2247        if self.connection:
2248            table = self.mapDBInfo.layers[int(self.currLayer)]['table']
2249        else:
2250            table = ""
2251
2252        self.radioWhere = RadioButton(
2253            panel, id=wx.ID_ANY, label="SELECT * FROM %s WHERE" %
2254            table, style=wx.RB_GROUP)
2255        self.textCtrlWhere = TextCtrl(panel, id=wx.ID_ANY, value="")
2256
2257        if self.connection:
2258            cols = self.mapDBInfo.GetColumns(
2259                self.mapDBInfo.layers[int(self.currLayer)]['table'])
2260        else:
2261            cols = []
2262
2263        self.choiceColumns = Choice(panel, id=wx.ID_ANY, choices=cols)
2264
2265        self.radioCats = RadioButton(
2266            panel, id=wx.ID_ANY, label="Choose categories ")
2267        self.textCtrlCats = TextCtrl(panel, id=wx.ID_ANY, value="")
2268        self.textCtrlCats.SetToolTip(
2269            _("list of categories (e.g. 1,3,5-7)"))
2270
2271        if 'cats' in self.vPropertiesDict:
2272            self.radioCats.SetValue(True)
2273            self.textCtrlCats.SetValue(self.vPropertiesDict['cats'])
2274        if 'where' in self.vPropertiesDict:
2275            self.radioWhere.SetValue(True)
2276            where = self.vPropertiesDict['where'].strip().split(" ", 1)
2277            self.choiceColumns.SetStringSelection(where[0])
2278            self.textCtrlWhere.SetValue(where[1])
2279
2280        row = 0
2281        if not self.connection:
2282            self.gridBagSizerL.Add(
2283                self.warning, pos=(
2284                    0, 0), span=(
2285                    1, 3), flag=wx.ALIGN_CENTER_VERTICAL, border=0)
2286            row = 1
2287        self.gridBagSizerL.Add(
2288            text, pos=(0 + row, 0),
2289            flag=wx.ALIGN_CENTER_VERTICAL, border=0)
2290        self.gridBagSizerL.Add(
2291            self.layerChoice, pos=(0 + row, 1),
2292            flag=wx.ALIGN_CENTER_VERTICAL | wx.EXPAND, border=0)
2293        self.gridBagSizerL.Add(
2294            self.radioWhere, pos=(1 + row, 0),
2295            flag=wx.ALIGN_CENTER_VERTICAL, border=0)
2296        self.gridBagSizerL.Add(
2297            self.choiceColumns, pos=(1 + row, 1),
2298            flag=wx.ALIGN_CENTER_VERTICAL, border=0)
2299        self.gridBagSizerL.Add(
2300            self.textCtrlWhere, pos=(1 + row, 2),
2301            flag=wx.ALIGN_CENTER_VERTICAL, border=0)
2302        self.gridBagSizerL.Add(
2303            self.radioCats, pos=(2 + row, 0),
2304            flag=wx.ALIGN_CENTER_VERTICAL, border=0)
2305        self.gridBagSizerL.Add(
2306            self.textCtrlCats, pos=(2 + row, 1),
2307            span=(1, 2),
2308            flag=wx.ALIGN_CENTER_VERTICAL | wx.EXPAND, border=0)
2309
2310        sizer.Add(
2311            self.gridBagSizerL,
2312            proportion=1,
2313            flag=wx.EXPAND | wx.ALL,
2314            border=5)
2315        border.Add(sizer, proportion=0, flag=wx.ALL | wx.EXPAND, border=5)
2316
2317        # mask
2318        box = StaticBox(
2319            parent=panel,
2320            id=wx.ID_ANY,
2321            label=" %s " %
2322            _("Mask"))
2323        sizer = wx.StaticBoxSizer(box, wx.HORIZONTAL)
2324
2325        self.mask = CheckBox(
2326            panel, id=wx.ID_ANY, label=_("Use current mask"))
2327        if self.vPropertiesDict['masked'] == 'y':
2328            self.mask.SetValue(True)
2329        else:
2330            self.mask.SetValue(False)
2331
2332        sizer.Add(self.mask, proportion=1, flag=wx.EXPAND | wx.ALL, border=5)
2333        border.Add(sizer, proportion=0, flag=wx.ALL | wx.EXPAND, border=5)
2334
2335        self.Bind(wx.EVT_CHOICE, self.OnLayer, self.layerChoice)
2336
2337        panel.SetSizer(border)
2338        panel.Fit()
2339        return panel
2340
2341    def _ColorsPointAreaPanel(self, notebook):
2342        panel = Panel(
2343            parent=notebook, id=wx.ID_ANY, size=(-1, -1),
2344            style=wx.TAB_TRAVERSAL)
2345        notebook.AddPage(page=panel, text=_("Colors"))
2346
2347        border = wx.BoxSizer(wx.VERTICAL)
2348
2349        #colors - outline
2350        box = StaticBox(
2351            parent=panel,
2352            id=wx.ID_ANY,
2353            label=" %s " %
2354            _("Outline"))
2355        sizer = wx.StaticBoxSizer(box, wx.HORIZONTAL)
2356        self.gridBagSizerO = wx.GridBagSizer(hgap=5, vgap=2)
2357
2358        self.outlineCheck = CheckBox(
2359            panel, id=wx.ID_ANY, label=_("draw outline"))
2360        self.outlineCheck.SetValue(self.vPropertiesDict['color'] != 'none')
2361
2362        widthText = StaticText(panel, id=wx.ID_ANY, label=_("Width (pts):"))
2363
2364        self.widthSpin = FloatSpin(
2365            panel,
2366            id=wx.ID_ANY,
2367            min_val=0,
2368            max_val=30,
2369            increment=0.5,
2370            value=1,
2371            style=fs.FS_RIGHT)
2372        self.widthSpin.SetFormat("%f")
2373        self.widthSpin.SetDigits(2)
2374
2375        if self.vPropertiesDict['color'] is None:
2376            self.vPropertiesDict['color'] = 'none'
2377
2378        if self.vPropertiesDict['color'] != 'none':
2379            self.widthSpin.SetValue(self.vPropertiesDict['width'])
2380        else:
2381            self.widthSpin.SetValue(1)
2382
2383        colorText = StaticText(panel, id=wx.ID_ANY, label=_("Color:"))
2384        self.colorPicker = ColourPickerCtrl(panel, id=wx.ID_ANY)
2385        if self.vPropertiesDict['color'] != 'none':
2386            self.colorPicker.SetColour(
2387                convertRGB(self.vPropertiesDict['color']))
2388        else:
2389            self.colorPicker.SetColour(convertRGB('black'))
2390
2391        self.gridBagSizerO.Add(
2392            self.outlineCheck, pos=(
2393                0, 0), span=(
2394                1, 2), flag=wx.ALIGN_CENTER_VERTICAL, border=0)
2395        self.gridBagSizerO.Add(
2396            widthText, pos=(1, 1),
2397            flag=wx.ALIGN_CENTER_VERTICAL, border=0)
2398        self.gridBagSizerO.Add(
2399            self.widthSpin, pos=(1, 2),
2400            flag=wx.ALIGN_CENTER_VERTICAL | wx.EXPAND, border=0)
2401        self.gridBagSizerO.Add(
2402            colorText, pos=(2, 1),
2403            flag=wx.ALIGN_CENTER_VERTICAL, border=0)
2404        self.gridBagSizerO.Add(
2405            self.colorPicker, pos=(2, 2),
2406            flag=wx.ALIGN_CENTER_VERTICAL, border=0)
2407
2408        sizer.Add(
2409            self.gridBagSizerO,
2410            proportion=1,
2411            flag=wx.EXPAND | wx.ALL,
2412            border=5)
2413        border.Add(sizer, proportion=0, flag=wx.ALL | wx.EXPAND, border=5)
2414
2415        self.Bind(wx.EVT_CHECKBOX, self.OnOutline, self.outlineCheck)
2416
2417        #colors - fill
2418        box = StaticBox(
2419            parent=panel,
2420            id=wx.ID_ANY,
2421            label=" %s " %
2422            _("Fill"))
2423        sizer = wx.StaticBoxSizer(box, wx.HORIZONTAL)
2424        self.gridBagSizerF = wx.GridBagSizer(hgap=5, vgap=2)
2425
2426        self.fillCheck = CheckBox(
2427            panel, id=wx.ID_ANY, label=_("fill color"))
2428        self.fillCheck.SetValue(
2429            self.vPropertiesDict['fcolor'] !=
2430            'none' or self.vPropertiesDict['rgbcolumn'] is not None)
2431
2432        self.colorPickerRadio = RadioButton(
2433            panel, id=wx.ID_ANY, label=_("choose color:"), style=wx.RB_GROUP)
2434        # set choose color option if there is no db connection
2435        if self.connection:
2436            self.colorPickerRadio.SetValue(
2437                not self.vPropertiesDict['rgbcolumn'])
2438        else:
2439            self.colorPickerRadio.SetValue(False)
2440        self.fillColorPicker = ColourPickerCtrl(panel, id=wx.ID_ANY)
2441        if self.vPropertiesDict['fcolor'] != 'none':
2442            self.fillColorPicker.SetColour(
2443                convertRGB(self.vPropertiesDict['fcolor']))
2444        else:
2445            self.fillColorPicker.SetColour(convertRGB('red'))
2446
2447        self.colorColRadio = RadioButton(
2448            panel, id=wx.ID_ANY, label=_("color from map table column:"))
2449        self.colorColChoice = self.getColsChoice(parent=panel)
2450        if self.connection:
2451            if self.vPropertiesDict['rgbcolumn']:
2452                self.colorColRadio.SetValue(True)
2453                self.colorColChoice.SetStringSelection(
2454                    self.vPropertiesDict['rgbcolumn'])
2455            else:
2456                self.colorColRadio.SetValue(False)
2457                self.colorColChoice.SetSelection(0)
2458        self.colorColChoice.Enable(self.connection)
2459        self.colorColRadio.Enable(self.connection)
2460
2461        self.gridBagSizerF.Add(
2462            self.fillCheck, pos=(
2463                0, 0), span=(
2464                1, 2), flag=wx.ALIGN_CENTER_VERTICAL, border=0)
2465        self.gridBagSizerF.Add(
2466            self.colorPickerRadio, pos=(1, 1),
2467            flag=wx.ALIGN_CENTER_VERTICAL, border=0)
2468        self.gridBagSizerF.Add(
2469            self.fillColorPicker, pos=(1, 2),
2470            flag=wx.ALIGN_CENTER_VERTICAL, border=0)
2471        self.gridBagSizerF.Add(
2472            self.colorColRadio, pos=(2, 1),
2473            flag=wx.ALIGN_CENTER_VERTICAL, border=0)
2474        self.gridBagSizerF.Add(
2475            self.colorColChoice, pos=(2, 2),
2476            flag=wx.ALIGN_CENTER_VERTICAL | wx.EXPAND, border=0)
2477
2478        sizer.Add(
2479            self.gridBagSizerF,
2480            proportion=1,
2481            flag=wx.EXPAND | wx.ALL,
2482            border=5)
2483        border.Add(sizer, proportion=0, flag=wx.ALL | wx.EXPAND, border=5)
2484
2485        self.Bind(wx.EVT_CHECKBOX, self.OnFill, self.fillCheck)
2486        self.Bind(wx.EVT_RADIOBUTTON, self.OnColor, self.colorColRadio)
2487        self.Bind(wx.EVT_RADIOBUTTON, self.OnColor, self.colorPickerRadio)
2488
2489        panel.SetSizer(border)
2490        panel.Fit()
2491        return panel
2492
2493    def _ColorsLinePanel(self, notebook):
2494        panel = Panel(
2495            parent=notebook, id=wx.ID_ANY, size=(-1, -1),
2496            style=wx.TAB_TRAVERSAL)
2497        notebook.AddPage(page=panel, text=_("Colors"))
2498
2499        border = wx.BoxSizer(wx.VERTICAL)
2500
2501        #colors - outline
2502        box = StaticBox(
2503            parent=panel,
2504            id=wx.ID_ANY,
2505            label=" %s " %
2506            _("Outline"))
2507        sizer = wx.StaticBoxSizer(box, wx.HORIZONTAL)
2508        self.gridBagSizerO = wx.GridBagSizer(hgap=5, vgap=2)
2509
2510        if self.vPropertiesDict['hcolor'] is None:
2511            self.vPropertiesDict['hcolor'] = 'none'
2512        if self.vPropertiesDict['color'] is None:
2513            self.vPropertiesDict['color'] = 'none'
2514
2515        self.outlineCheck = CheckBox(
2516            panel, id=wx.ID_ANY, label=_("draw outline"))
2517        self.outlineCheck.SetValue(self.vPropertiesDict['hcolor'] != 'none')
2518        self.outlineCheck.SetToolTip(
2519            _("No effect for fill color from table column"))
2520
2521        widthText = StaticText(panel, id=wx.ID_ANY, label=_("Width (pts):"))
2522
2523        self.outWidthSpin = FloatSpin(
2524            panel,
2525            id=wx.ID_ANY,
2526            min_val=0,
2527            max_val=30,
2528            increment=0.5,
2529            value=1,
2530            style=fs.FS_RIGHT)
2531        self.outWidthSpin.SetFormat("%f")
2532        self.outWidthSpin.SetDigits(1)
2533
2534        if self.vPropertiesDict['hcolor'] != 'none':
2535            self.outWidthSpin.SetValue(self.vPropertiesDict['hwidth'])
2536        else:
2537            self.outWidthSpin.SetValue(1)
2538
2539        colorText = StaticText(panel, id=wx.ID_ANY, label=_("Color:"))
2540        self.colorPicker = ColourPickerCtrl(panel, id=wx.ID_ANY)
2541        if self.vPropertiesDict['hcolor'] != 'none':
2542            self.colorPicker.SetColour(
2543                convertRGB(self.vPropertiesDict['hcolor']))
2544        else:
2545            self.colorPicker.SetColour(convertRGB('black'))
2546
2547        self.gridBagSizerO.Add(
2548            self.outlineCheck, pos=(
2549                0, 0), span=(
2550                1, 2), flag=wx.ALIGN_CENTER_VERTICAL, border=0)
2551        self.gridBagSizerO.Add(
2552            widthText, pos=(1, 1),
2553            flag=wx.ALIGN_CENTER_VERTICAL, border=0)
2554        self.gridBagSizerO.Add(
2555            self.outWidthSpin, pos=(1, 2),
2556            flag=wx.ALIGN_CENTER_VERTICAL | wx.EXPAND, border=0)
2557        self.gridBagSizerO.Add(
2558            colorText, pos=(2, 1),
2559            flag=wx.ALIGN_CENTER_VERTICAL, border=0)
2560        self.gridBagSizerO.Add(
2561            self.colorPicker, pos=(2, 2),
2562            flag=wx.ALIGN_CENTER_VERTICAL, border=0)
2563
2564        sizer.Add(
2565            self.gridBagSizerO,
2566            proportion=1,
2567            flag=wx.EXPAND | wx.ALL,
2568            border=5)
2569        border.Add(sizer, proportion=0, flag=wx.ALL | wx.EXPAND, border=5)
2570
2571        self.Bind(wx.EVT_CHECKBOX, self.OnOutline, self.outlineCheck)
2572
2573        #colors - fill
2574        box = StaticBox(
2575            parent=panel,
2576            id=wx.ID_ANY,
2577            label=" %s " %
2578            _("Fill"))
2579        sizer = wx.StaticBoxSizer(box, wx.HORIZONTAL)
2580        self.gridBagSizerF = wx.GridBagSizer(hgap=5, vgap=2)
2581
2582        fillText = StaticText(
2583            panel, id=wx.ID_ANY, label=_("Color of lines:"))
2584
2585        self.colorPickerRadio = RadioButton(
2586            panel, id=wx.ID_ANY, label=_("choose color:"), style=wx.RB_GROUP)
2587
2588        # set choose color option if there is no db connection
2589        if self.connection:
2590            self.colorPickerRadio.SetValue(
2591                not self.vPropertiesDict['rgbcolumn'])
2592        else:
2593            self.colorPickerRadio.SetValue(False)
2594        self.fillColorPicker = ColourPickerCtrl(panel, id=wx.ID_ANY)
2595        if self.vPropertiesDict['color'] != 'none':
2596            self.fillColorPicker.SetColour(
2597                convertRGB(self.vPropertiesDict['color']))
2598        else:
2599            self.fillColorPicker.SetColour(convertRGB('black'))
2600
2601        self.colorColRadio = RadioButton(
2602            panel, id=wx.ID_ANY, label=_("color from map table column:"))
2603        self.colorColChoice = self.getColsChoice(parent=panel)
2604        if self.connection:
2605            if self.vPropertiesDict['rgbcolumn']:
2606                self.colorColRadio.SetValue(True)
2607                self.colorColChoice.SetStringSelection(
2608                    self.vPropertiesDict['rgbcolumn'])
2609            else:
2610                self.colorColRadio.SetValue(False)
2611                self.colorColChoice.SetSelection(0)
2612        self.colorColChoice.Enable(self.connection)
2613        self.colorColRadio.Enable(self.connection)
2614
2615        self.gridBagSizerF.Add(
2616            fillText, pos=(
2617                0, 0), span=(
2618                1, 2), flag=wx.ALIGN_CENTER_VERTICAL, border=0)
2619        self.gridBagSizerF.Add(
2620            self.colorPickerRadio, pos=(1, 1),
2621            flag=wx.ALIGN_CENTER_VERTICAL, border=0)
2622        self.gridBagSizerF.Add(
2623            self.fillColorPicker, pos=(1, 2),
2624            flag=wx.ALIGN_CENTER_VERTICAL, border=0)
2625        self.gridBagSizerF.Add(
2626            self.colorColRadio, pos=(2, 1),
2627            flag=wx.ALIGN_CENTER_VERTICAL, border=0)
2628        self.gridBagSizerF.Add(
2629            self.colorColChoice, pos=(2, 2),
2630            flag=wx.ALIGN_CENTER_VERTICAL | wx.EXPAND, border=0)
2631
2632        sizer.Add(
2633            self.gridBagSizerF,
2634            proportion=1,
2635            flag=wx.EXPAND | wx.ALL,
2636            border=5)
2637        border.Add(sizer, proportion=0, flag=wx.ALL | wx.EXPAND, border=5)
2638
2639        self.Bind(wx.EVT_RADIOBUTTON, self.OnColor, self.colorColRadio)
2640        self.Bind(wx.EVT_RADIOBUTTON, self.OnColor, self.colorPickerRadio)
2641
2642        panel.SetSizer(border)
2643        panel.Fit()
2644        return panel
2645
2646    def _StylePointPanel(self, notebook):
2647        panel = Panel(
2648            parent=notebook, id=wx.ID_ANY, size=(-1, -1),
2649            style=wx.TAB_TRAVERSAL)
2650        notebook.AddPage(page=panel, text=_("Size and style"))
2651
2652        border = wx.BoxSizer(wx.VERTICAL)
2653
2654        # symbology
2655        box = StaticBox(
2656            parent=panel,
2657            id=wx.ID_ANY,
2658            label=" %s " %
2659            _("Symbology"))
2660        sizer = wx.StaticBoxSizer(box, wx.HORIZONTAL)
2661        gridBagSizer = wx.GridBagSizer(hgap=5, vgap=5)
2662
2663        self.symbolRadio = RadioButton(
2664            panel, id=wx.ID_ANY, label=_("symbol:"),
2665            style=wx.RB_GROUP)
2666        self.symbolRadio.SetValue(bool(self.vPropertiesDict['symbol']))
2667
2668        self.symbolName = StaticText(panel, id=wx.ID_ANY)
2669        self.symbolName.SetLabel(self.vPropertiesDict['symbol'])
2670        bitmap = wx.Bitmap(
2671            os.path.join(
2672                globalvar.SYMBDIR,
2673                self.vPropertiesDict['symbol']) +
2674            '.png')
2675        self.symbolButton = BitmapButton(panel, id=wx.ID_ANY, bitmap=bitmap)
2676
2677        self.epsRadio = RadioButton(
2678            panel, id=wx.ID_ANY, label=_("eps file:"))
2679        self.epsRadio.SetValue(bool(self.vPropertiesDict['eps']))
2680
2681        self.epsFileCtrl = FileBrowseButton(
2682            panel, id=wx.ID_ANY, labelText='', buttonText=_("Browse"),
2683            toolTip=_("Type filename or click browse to choose file"),
2684            dialogTitle=_("Choose a file"),
2685            startDirectory='', initialValue='',
2686            fileMask="Encapsulated PostScript (*.eps)|*.eps|All files (*.*)|*.*",
2687            fileMode=wx.FD_OPEN)
2688        if not self.vPropertiesDict['eps']:
2689            self.epsFileCtrl.SetValue('')
2690        else:  # eps chosen
2691            self.epsFileCtrl.SetValue(self.vPropertiesDict['eps'])
2692
2693        gridBagSizer.Add(
2694            self.symbolRadio, pos=(0, 0),
2695            flag=wx.ALIGN_CENTER_VERTICAL, border=0)
2696        gridBagSizer.Add(
2697            self.symbolName,
2698            pos=(
2699                0,
2700                1),
2701            flag=wx.ALIGN_CENTER_VERTICAL | wx.LEFT,
2702            border=10)
2703        gridBagSizer.Add(
2704            self.symbolButton, pos=(0, 2),
2705            flag=wx.ALIGN_RIGHT, border=0)
2706        gridBagSizer.Add(
2707            self.epsRadio, pos=(1, 0),
2708            flag=wx.ALIGN_CENTER_VERTICAL, border=0)
2709        gridBagSizer.Add(
2710            self.epsFileCtrl, pos=(
2711                1, 1), span=(
2712                1, 2), flag=wx.ALIGN_CENTER_VERTICAL | wx.EXPAND, border=0)
2713
2714        gridBagSizer.AddGrowableCol(1)
2715        gridBagSizer.AddGrowableCol(2)
2716        sizer.Add(
2717            gridBagSizer,
2718            proportion=1,
2719            flag=wx.EXPAND | wx.ALL,
2720            border=5)
2721        border.Add(sizer, proportion=0, flag=wx.ALL | wx.EXPAND, border=5)
2722
2723        self.Bind(wx.EVT_BUTTON, self.OnSymbolSelection, self.symbolButton)
2724        self.Bind(wx.EVT_RADIOBUTTON, self.OnSymbology, self.symbolRadio)
2725        self.Bind(wx.EVT_RADIOBUTTON, self.OnSymbology, self.epsRadio)
2726
2727        # size
2728
2729        box = StaticBox(
2730            parent=panel,
2731            id=wx.ID_ANY,
2732            label=" %s " %
2733            _("Size"))
2734        sizer = wx.StaticBoxSizer(box, wx.HORIZONTAL)
2735        gridBagSizer = wx.GridBagSizer(hgap=5, vgap=5)
2736
2737        self.sizeRadio = RadioButton(
2738            panel, id=wx.ID_ANY, label=_("size:"),
2739            style=wx.RB_GROUP)
2740        self.sizeSpin = SpinCtrl(
2741            panel, id=wx.ID_ANY, min=1, max=50, initial=1)
2742        self.sizecolumnRadio = RadioButton(
2743            panel, id=wx.ID_ANY, label=_("size from map table column:"))
2744        self.sizeColChoice = self.getColsChoice(panel)
2745        self.scaleText = StaticText(panel, id=wx.ID_ANY, label=_("scale:"))
2746        self.scaleSpin = SpinCtrl(
2747            panel, id=wx.ID_ANY, min=1, max=25, initial=1)
2748
2749        self.sizeRadio.SetValue(self.vPropertiesDict['size'] is not None)
2750        self.sizecolumnRadio.SetValue(bool(self.vPropertiesDict['sizecolumn']))
2751        if self.vPropertiesDict['size']:
2752            self.sizeSpin.SetValue(self.vPropertiesDict['size'])
2753        else:
2754            self.sizeSpin.SetValue(5)
2755        if self.vPropertiesDict['sizecolumn']:
2756            self.scaleSpin.SetValue(self.vPropertiesDict['scale'])
2757            self.sizeColChoice.SetStringSelection(
2758                self.vPropertiesDict['sizecolumn'])
2759        else:
2760            self.scaleSpin.SetValue(1)
2761            self.sizeColChoice.SetSelection(0)
2762        if not self.connection:
2763            for each in (self.sizecolumnRadio, self.sizeColChoice,
2764                         self.scaleSpin, self.scaleText):
2765                each.Disable()
2766
2767        gridBagSizer.Add(
2768            self.sizeRadio, pos=(0, 0),
2769            flag=wx.ALIGN_CENTER_VERTICAL, border=0)
2770        gridBagSizer.Add(
2771            self.sizeSpin, pos=(0, 1),
2772            flag=wx.ALIGN_CENTER_VERTICAL, border=0)
2773        gridBagSizer.Add(
2774            self.sizecolumnRadio, pos=(1, 0),
2775            flag=wx.ALIGN_CENTER_VERTICAL, border=0)
2776        gridBagSizer.Add(
2777            self.sizeColChoice,
2778            pos=(
2779                1,
2780                1),
2781            flag=wx.ALIGN_CENTER_VERTICAL | wx.EXPAND,
2782            border=0)
2783        gridBagSizer.Add(
2784            self.scaleText,
2785            pos=(
2786                2,
2787                0),
2788            flag=wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT,
2789            border=0)
2790        gridBagSizer.Add(
2791            self.scaleSpin, pos=(2, 1),
2792            flag=wx.ALIGN_CENTER_VERTICAL, border=0)
2793
2794        gridBagSizer.AddGrowableCol(0)
2795        sizer.Add(
2796            gridBagSizer,
2797            proportion=1,
2798            flag=wx.EXPAND | wx.ALL,
2799            border=5)
2800        border.Add(sizer, proportion=0, flag=wx.ALL | wx.EXPAND, border=5)
2801
2802        self.Bind(wx.EVT_RADIOBUTTON, self.OnSize, self.sizeRadio)
2803        self.Bind(wx.EVT_RADIOBUTTON, self.OnSize, self.sizecolumnRadio)
2804
2805        # rotation
2806        box = StaticBox(
2807            parent=panel,
2808            id=wx.ID_ANY,
2809            label=" %s " %
2810            _("Rotation"))
2811        sizer = wx.StaticBoxSizer(box, wx.HORIZONTAL)
2812        gridBagSizer = wx.GridBagSizer(hgap=5, vgap=5)
2813
2814        self.rotateCheck = CheckBox(
2815            panel, id=wx.ID_ANY, label=_("rotate symbols:"))
2816        self.rotateRadio = RadioButton(panel, id=wx.ID_ANY, label=_(
2817            "counterclockwise in degrees:"), style=wx.RB_GROUP)
2818        self.rotateSpin = SpinCtrl(
2819            panel, id=wx.ID_ANY, min=0, max=360, initial=0)
2820        self.rotatecolumnRadio = RadioButton(
2821            panel, id=wx.ID_ANY, label=_("from map table column:"))
2822        self.rotateColChoice = self.getColsChoice(panel)
2823
2824        self.rotateCheck.SetValue(self.vPropertiesDict['rotation'])
2825        self.rotateRadio.SetValue(self.vPropertiesDict['rotate'] is not None)
2826        self.rotatecolumnRadio.SetValue(
2827            bool(self.vPropertiesDict['rotatecolumn']))
2828        if self.vPropertiesDict['rotate']:
2829            self.rotateSpin.SetValue(self.vPropertiesDict['rotate'])
2830        else:
2831            self.rotateSpin.SetValue(0)
2832        if self.vPropertiesDict['rotatecolumn']:
2833            self.rotateColChoice.SetStringSelection(
2834                self.vPropertiesDict['rotatecolumn'])
2835        else:
2836            self.rotateColChoice.SetSelection(0)
2837
2838        gridBagSizer.Add(
2839            self.rotateCheck, pos=(
2840                0, 0), span=(
2841                1, 2), flag=wx.ALIGN_CENTER_VERTICAL, border=0)
2842        gridBagSizer.Add(
2843            self.rotateRadio, pos=(1, 1),
2844            flag=wx.ALIGN_CENTER_VERTICAL, border=0)
2845        gridBagSizer.Add(
2846            self.rotateSpin, pos=(1, 2),
2847            flag=wx.ALIGN_CENTER_VERTICAL, border=0)
2848        gridBagSizer.Add(
2849            self.rotatecolumnRadio, pos=(2, 1),
2850            flag=wx.ALIGN_CENTER_VERTICAL, border=0)
2851        gridBagSizer.Add(
2852            self.rotateColChoice,
2853            pos=(
2854                2,
2855                2),
2856            flag=wx.ALIGN_CENTER_VERTICAL | wx.EXPAND,
2857            border=0)
2858
2859        gridBagSizer.AddGrowableCol(1)
2860        sizer.Add(
2861            gridBagSizer,
2862            proportion=1,
2863            flag=wx.EXPAND | wx.ALL,
2864            border=5)
2865        border.Add(sizer, proportion=0, flag=wx.ALL | wx.EXPAND, border=5)
2866
2867        self.Bind(wx.EVT_CHECKBOX, self.OnRotation, self.rotateCheck)
2868        self.Bind(wx.EVT_RADIOBUTTON, self.OnRotationType, self.rotateRadio)
2869        self.Bind(
2870            wx.EVT_RADIOBUTTON,
2871            self.OnRotationType,
2872            self.rotatecolumnRadio)
2873
2874        panel.SetSizer(border)
2875        panel.Fit()
2876        return panel
2877
2878    def _StyleLinePanel(self, notebook):
2879        panel = Panel(
2880            parent=notebook, id=wx.ID_ANY, size=(-1, -1),
2881            style=wx.TAB_TRAVERSAL)
2882        notebook.AddPage(page=panel, text=_("Size and style"))
2883
2884        border = wx.BoxSizer(wx.VERTICAL)
2885
2886        # width
2887        box = StaticBox(
2888            parent=panel,
2889            id=wx.ID_ANY,
2890            label=" %s " %
2891            _("Width"))
2892        sizer = wx.StaticBoxSizer(box, wx.HORIZONTAL)
2893        gridBagSizer = wx.GridBagSizer(hgap=5, vgap=5)
2894
2895        widthText = StaticText(
2896            panel, id=wx.ID_ANY, label=_("Set width (pts):"))
2897
2898        self.widthSpin = FloatSpin(
2899            panel,
2900            id=wx.ID_ANY,
2901            min_val=0,
2902            max_val=30,
2903            increment=0.5,
2904            value=1,
2905            style=fs.FS_RIGHT)
2906        self.widthSpin.SetFormat("%f")
2907        self.widthSpin.SetDigits(1)
2908
2909        self.cwidthCheck = CheckBox(
2910            panel, id=wx.ID_ANY, label=_("multiply width by category value"))
2911
2912        if self.vPropertiesDict['width']:
2913            self.widthSpin.SetValue(self.vPropertiesDict['width'])
2914            self.cwidthCheck.SetValue(False)
2915        else:
2916            self.widthSpin.SetValue(self.vPropertiesDict['cwidth'])
2917            self.cwidthCheck.SetValue(True)
2918
2919        gridBagSizer.Add(
2920            widthText, pos=(0, 0),
2921            flag=wx.ALIGN_CENTER_VERTICAL, border=0)
2922        gridBagSizer.Add(
2923            self.widthSpin, pos=(0, 1),
2924            flag=wx.ALIGN_CENTER_VERTICAL, border=0)
2925        gridBagSizer.Add(
2926            self.cwidthCheck, pos=(
2927                1, 0), span=(
2928                1, 2), flag=wx.ALIGN_CENTER_VERTICAL, border=0)
2929
2930        sizer.Add(
2931            gridBagSizer,
2932            proportion=1,
2933            flag=wx.EXPAND | wx.ALL,
2934            border=5)
2935        border.Add(sizer, proportion=0, flag=wx.ALL | wx.EXPAND, border=5)
2936
2937        # style
2938        box = StaticBox(
2939            parent=panel,
2940            id=wx.ID_ANY,
2941            label=" %s " %
2942            _("Line style"))
2943        sizer = wx.StaticBoxSizer(box, wx.HORIZONTAL)
2944        gridBagSizer = wx.GridBagSizer(hgap=5, vgap=5)
2945
2946        styleText = StaticText(
2947            panel, id=wx.ID_ANY, label=_("Choose line style:"))
2948        penStyles = ["solid", "dashed", "dotted", "dashdotted"]
2949        self.styleCombo = PenStyleComboBox(
2950            panel, choices=penStyles, validator=TCValidator(
2951                flag='ZERO_AND_ONE_ONLY'))
2952# self.styleCombo = wx.ComboBox(panel, id = wx.ID_ANY,
2953##                            choices = ["solid", "dashed", "dotted", "dashdotted"],
2954# validator = TCValidator(flag = 'ZERO_AND_ONE_ONLY'))
2955# self.styleCombo.SetToolTipString(_("It's possible to enter a series of 0's and 1's too. "\
2956##                                    "The first block of repeated zeros or ones represents 'draw', "\
2957##                                    "the second block represents 'blank'. An even number of blocks "\
2958# "will repeat the pattern, an odd number of blocks will alternate the pattern."))
2959        linecapText = StaticText(
2960            panel, id=wx.ID_ANY, label=_("Choose linecap:"))
2961        self.linecapChoice = Choice(
2962            panel, id=wx.ID_ANY, choices=[
2963                "butt", "round", "extended_butt"])
2964
2965        self.styleCombo.SetValue(self.vPropertiesDict['style'])
2966        self.linecapChoice.SetStringSelection(self.vPropertiesDict['linecap'])
2967
2968        gridBagSizer.Add(
2969            styleText, pos=(0, 0),
2970            flag=wx.ALIGN_CENTER_VERTICAL, border=0)
2971        gridBagSizer.Add(
2972            self.styleCombo,
2973            pos=(
2974                0,
2975                1),
2976            flag=wx.ALIGN_CENTER_VERTICAL | wx.EXPAND,
2977            border=0)
2978        gridBagSizer.Add(
2979            linecapText, pos=(1, 0),
2980            flag=wx.ALIGN_CENTER_VERTICAL, border=0)
2981        gridBagSizer.Add(
2982            self.linecapChoice,
2983            pos=(
2984                1,
2985                1),
2986            flag=wx.ALIGN_CENTER_VERTICAL | wx.EXPAND,
2987            border=0)
2988
2989        sizer.Add(
2990            gridBagSizer,
2991            proportion=1,
2992            flag=wx.EXPAND | wx.ALL,
2993            border=5)
2994        border.Add(sizer, proportion=0, flag=wx.ALL | wx.EXPAND, border=5)
2995
2996        panel.SetSizer(border)
2997        panel.Fit()
2998        return panel
2999
3000    def _StyleAreaPanel(self, notebook):
3001        panel = Panel(
3002            parent=notebook, id=wx.ID_ANY, size=(-1, -1),
3003            style=wx.TAB_TRAVERSAL)
3004        notebook.AddPage(page=panel, text=_("Size and style"))
3005
3006        border = wx.BoxSizer(wx.VERTICAL)
3007
3008        # pattern
3009        box = StaticBox(
3010            parent=panel,
3011            id=wx.ID_ANY,
3012            label=" %s " %
3013            _("Pattern"))
3014        sizer = wx.StaticBoxSizer(box, wx.HORIZONTAL)
3015        gridBagSizer = wx.GridBagSizer(hgap=5, vgap=5)
3016
3017        self.patternCheck = CheckBox(
3018            panel, id=wx.ID_ANY, label=_("use pattern:"))
3019        self.patFileCtrl = FileBrowseButton(
3020            panel, id=wx.ID_ANY, labelText=_("Choose pattern file:"),
3021            buttonText=_("Browse"),
3022            toolTip=_("Type filename or click browse to choose file"),
3023            dialogTitle=_("Choose a file"),
3024            startDirectory=self.patternPath, initialValue='',
3025            fileMask="Encapsulated PostScript (*.eps)|*.eps|All files (*.*)|*.*",
3026            fileMode=wx.FD_OPEN)
3027        self.patWidthText = StaticText(
3028            panel, id=wx.ID_ANY, label=_("pattern line width (pts):"))
3029        self.patWidthSpin = SpinCtrl(
3030            panel, id=wx.ID_ANY, min=1, max=25, initial=1)
3031        self.patScaleText = StaticText(
3032            panel, id=wx.ID_ANY, label=_("pattern scale factor:"))
3033        self.patScaleSpin = SpinCtrl(
3034            panel, id=wx.ID_ANY, min=1, max=25, initial=1)
3035
3036        self.patternCheck.SetValue(bool(self.vPropertiesDict['pat']))
3037        if self.patternCheck.GetValue():
3038            self.patFileCtrl.SetValue(self.vPropertiesDict['pat'])
3039            self.patWidthSpin.SetValue(self.vPropertiesDict['pwidth'])
3040            self.patScaleSpin.SetValue(self.vPropertiesDict['scale'])
3041
3042        gridBagSizer.Add(
3043            self.patternCheck, pos=(0, 0),
3044            flag=wx.ALIGN_CENTER_VERTICAL, border=0)
3045        gridBagSizer.Add(
3046            self.patFileCtrl, pos=(
3047                1, 0), span=(
3048                1, 2), flag=wx.ALIGN_CENTER_VERTICAL | wx.EXPAND, border=0)
3049        gridBagSizer.Add(
3050            self.patWidthText, pos=(2, 0),
3051            flag=wx.ALIGN_CENTER_VERTICAL, border=0)
3052        gridBagSizer.Add(
3053            self.patWidthSpin, pos=(2, 1),
3054            flag=wx.ALIGN_CENTER_VERTICAL, border=0)
3055        gridBagSizer.Add(
3056            self.patScaleText, pos=(3, 0),
3057            flag=wx.ALIGN_CENTER_VERTICAL, border=0)
3058        gridBagSizer.Add(
3059            self.patScaleSpin, pos=(3, 1),
3060            flag=wx.ALIGN_CENTER_VERTICAL, border=0)
3061
3062        gridBagSizer.AddGrowableCol(1)
3063        sizer.Add(
3064            gridBagSizer,
3065            proportion=1,
3066            flag=wx.EXPAND | wx.ALL,
3067            border=5)
3068        border.Add(sizer, proportion=0, flag=wx.ALL | wx.EXPAND, border=5)
3069
3070        self.Bind(wx.EVT_CHECKBOX, self.OnPattern, self.patternCheck)
3071
3072        panel.SetSizer(border)
3073        panel.Fit()
3074        return panel
3075
3076    def OnLayer(self, event):
3077        """Change columns on layer change """
3078        if self.layerChoice.GetStringSelection() == self.currLayer:
3079            return
3080        self.currLayer = self.layerChoice.GetStringSelection()
3081        if self.connection:
3082            cols = self.mapDBInfo.GetColumns(
3083                self.mapDBInfo.layers[int(self.currLayer)]['table'])
3084        else:
3085            cols = []
3086
3087        self.choiceColumns.SetItems(cols)
3088
3089        self.choiceColumns.SetSelection(0)
3090        if self.type in ('points', 'lines'):
3091            self.colorColChoice.SetItems(cols)
3092            self.colorColChoice.SetSelection(0)
3093
3094    def OnOutline(self, event):
3095        for widget in self.gridBagSizerO.GetChildren():
3096            if widget.GetWindow() != self.outlineCheck:
3097                widget.GetWindow().Enable(self.outlineCheck.GetValue())
3098
3099    def OnFill(self, event):
3100        enable = self.fillCheck.GetValue()
3101
3102        self.colorColChoice.Enable(enable)
3103        self.colorColRadio.Enable(enable)
3104        self.fillColorPicker.Enable(enable)
3105        self.colorPickerRadio.Enable(enable)
3106        if enable:
3107            self.OnColor(None)
3108        if not self.connection:
3109            self.colorColChoice.Disable()
3110            self.colorColRadio.Disable()
3111
3112    def OnColor(self, event):
3113        self.colorColChoice.Enable(self.colorColRadio.GetValue())
3114        self.fillColorPicker.Enable(self.colorPickerRadio.GetValue())
3115
3116    def OnSize(self, event):
3117        self.sizeSpin.Enable(self.sizeRadio.GetValue())
3118        self.sizeColChoice.Enable(self.sizecolumnRadio.GetValue())
3119        self.scaleText.Enable(self.sizecolumnRadio.GetValue())
3120        self.scaleSpin.Enable(self.sizecolumnRadio.GetValue())
3121
3122    def OnRotation(self, event):
3123        for each in (self.rotateRadio, self.rotatecolumnRadio,
3124                     self.rotateColChoice, self.rotateSpin):
3125            if self.rotateCheck.GetValue():
3126                each.Enable()
3127                self.OnRotationType(event=None)
3128            else:
3129                each.Disable()
3130
3131    def OnRotationType(self, event):
3132        self.rotateSpin.Enable(self.rotateRadio.GetValue())
3133        self.rotateColChoice.Enable(self.rotatecolumnRadio.GetValue())
3134
3135    def OnPattern(self, event):
3136        for each in (self.patFileCtrl, self.patWidthText,
3137                     self.patWidthSpin, self.patScaleText, self.patScaleSpin):
3138            each.Enable(self.patternCheck.GetValue())
3139
3140    def OnSymbology(self, event):
3141        useSymbol = self.symbolRadio.GetValue()
3142
3143        self.symbolButton.Enable(useSymbol)
3144        self.symbolName.Enable(useSymbol)
3145        self.epsFileCtrl.Enable(not useSymbol)
3146
3147    def OnSymbolSelection(self, event):
3148        dlg = SymbolDialog(self, symbolPath=globalvar.SYMBDIR,
3149                           currentSymbol=self.symbolName.GetLabel())
3150        if dlg.ShowModal() == wx.ID_OK:
3151            img = dlg.GetSelectedSymbolPath()
3152            name = dlg.GetSelectedSymbolName()
3153            self.symbolButton.SetBitmapLabel(wx.Bitmap(img + '.png'))
3154            self.symbolName.SetLabel(name)
3155
3156        dlg.Destroy()
3157
3158    def EnableLayerSelection(self, enable=True):
3159        for widget in self.gridBagSizerL.GetChildren():
3160            if widget.GetWindow() != self.warning:
3161                widget.GetWindow().Enable(enable)
3162
3163    def getColsChoice(self, parent):
3164        """Returns a Choice with table columns"""
3165        if self.connection:
3166            cols = self.mapDBInfo.GetColumns(
3167                self.mapDBInfo.layers[int(self.currLayer)]['table'])
3168        else:
3169            cols = []
3170
3171        choice = Choice(parent=parent, id=wx.ID_ANY, choices=cols)
3172        return choice
3173
3174    def update(self):
3175        # feature type
3176        if self.type in ('lines', 'points'):
3177            featureType = None
3178            if self.checkType1.GetValue():
3179                featureType = self.checkType1.GetName()
3180                if self.checkType2.GetValue():
3181                    featureType += " or " + self.checkType2.GetName()
3182            elif self.checkType2.GetValue():
3183                featureType = self.checkType2.GetName()
3184            if featureType:
3185                self.vPropertiesDict['type'] = featureType
3186
3187        # is connection
3188        self.vPropertiesDict['connection'] = self.connection
3189        if self.connection:
3190            self.vPropertiesDict[
3191                'layer'] = self.layerChoice.GetStringSelection()
3192            if self.radioCats.GetValue() and not self.textCtrlCats.IsEmpty():
3193                self.vPropertiesDict['cats'] = self.textCtrlCats.GetValue()
3194            elif self.radioWhere.GetValue() and not self.textCtrlWhere.IsEmpty():
3195                self.vPropertiesDict['where'] = self.choiceColumns.GetStringSelection(
3196                ) + " " + self.textCtrlWhere.GetValue()
3197        # mask
3198        if self.mask.GetValue():
3199            self.vPropertiesDict['masked'] = 'y'
3200        else:
3201            self.vPropertiesDict['masked'] = 'n'
3202
3203        # colors
3204        if self.type in ('points', 'areas'):
3205            if self.outlineCheck.GetValue():
3206                self.vPropertiesDict['color'] = convertRGB(
3207                    self.colorPicker.GetColour())
3208                self.vPropertiesDict['width'] = self.widthSpin.GetValue()
3209            else:
3210                self.vPropertiesDict['color'] = 'none'
3211
3212            if self.fillCheck.GetValue():
3213                if self.colorPickerRadio.GetValue():
3214                    self.vPropertiesDict['fcolor'] = convertRGB(
3215                        self.fillColorPicker.GetColour())
3216                    self.vPropertiesDict['rgbcolumn'] = None
3217                if self.colorColRadio.GetValue():
3218                    # this color is taken in case of no record in rgb column
3219                    self.vPropertiesDict['fcolor'] = 'none'
3220                    self.vPropertiesDict[
3221                        'rgbcolumn'] = self.colorColChoice.GetStringSelection()
3222            else:
3223                self.vPropertiesDict['fcolor'] = 'none'
3224
3225        if self.type == 'lines':
3226                # hcolor only when no rgbcolumn
3227            # and self.fillCheck.GetValue() and self.colorColRadio.GetValue():
3228            if self.outlineCheck.GetValue():
3229                self.vPropertiesDict['hcolor'] = convertRGB(
3230                    self.colorPicker.GetColour())
3231                self.vPropertiesDict['hwidth'] = self.outWidthSpin.GetValue()
3232
3233            else:
3234                self.vPropertiesDict['hcolor'] = 'none'
3235
3236            if self.colorPickerRadio.GetValue():
3237                self.vPropertiesDict['color'] = convertRGB(
3238                    self.fillColorPicker.GetColour())
3239                self.vPropertiesDict['rgbcolumn'] = None
3240            if self.colorColRadio.GetValue():
3241                # this color is taken in case of no record in rgb column
3242                self.vPropertiesDict['color'] = 'none'
3243                self.vPropertiesDict[
3244                    'rgbcolumn'] = self.colorColChoice.GetStringSelection()
3245        #
3246        #size and style
3247        #
3248
3249        if self.type == 'points':
3250            # symbols
3251            if self.symbolRadio.GetValue():
3252                self.vPropertiesDict['symbol'] = self.symbolName.GetLabel()
3253                self.vPropertiesDict['eps'] = None
3254            else:
3255                self.vPropertiesDict['eps'] = self.epsFileCtrl.GetValue()
3256            # size
3257            if self.sizeRadio.GetValue():
3258                self.vPropertiesDict['size'] = self.sizeSpin.GetValue()
3259                self.vPropertiesDict['sizecolumn'] = None
3260                self.vPropertiesDict['scale'] = None
3261            else:
3262                self.vPropertiesDict[
3263                    'sizecolumn'] = self.sizeColChoice.GetStringSelection()
3264                self.vPropertiesDict['scale'] = self.scaleSpin.GetValue()
3265                self.vPropertiesDict['size'] = None
3266
3267            # rotation
3268            self.vPropertiesDict['rotate'] = None
3269            self.vPropertiesDict['rotatecolumn'] = None
3270            self.vPropertiesDict['rotation'] = False
3271            if self.rotateCheck.GetValue():
3272                self.vPropertiesDict['rotation'] = True
3273            if self.rotateRadio.GetValue():
3274                self.vPropertiesDict['rotate'] = self.rotateSpin.GetValue()
3275            else:
3276                self.vPropertiesDict[
3277                    'rotatecolumn'] = self.rotateColChoice.GetStringSelection()
3278
3279        if self.type == 'areas':
3280            # pattern
3281            self.vPropertiesDict['pat'] = None
3282            if self.patternCheck.GetValue() and bool(self.patFileCtrl.GetValue()):
3283                self.vPropertiesDict['pat'] = self.patFileCtrl.GetValue()
3284                self.vPropertiesDict['pwidth'] = self.patWidthSpin.GetValue()
3285                self.vPropertiesDict['scale'] = self.patScaleSpin.GetValue()
3286
3287        if self.type == 'lines':
3288            # width
3289            if self.cwidthCheck.GetValue():
3290                self.vPropertiesDict['cwidth'] = self.widthSpin.GetValue()
3291                self.vPropertiesDict['width'] = None
3292            else:
3293                self.vPropertiesDict['width'] = self.widthSpin.GetValue()
3294                self.vPropertiesDict['cwidth'] = None
3295            # line style
3296            if self.styleCombo.GetValue():
3297                self.vPropertiesDict['style'] = self.styleCombo.GetValue()
3298            else:
3299                self.vPropertiesDict['style'] = 'solid'
3300
3301            self.vPropertiesDict[
3302                'linecap'] = self.linecapChoice.GetStringSelection()
3303
3304    def OnOK(self, event):
3305        self.update()
3306        event.Skip()
3307
3308
3309class LegendDialog(PsmapDialog):
3310
3311    def __init__(self, parent, id, settings, page, env):
3312        PsmapDialog.__init__(
3313            self,
3314            parent=parent,
3315            id=id,
3316            title="Legend settings",
3317            settings=settings,
3318            env=env)
3319        self.objectType = ('rasterLegend', 'vectorLegend')
3320        self.instruction = settings
3321        map = self.instruction.FindInstructionByType('map')
3322        if map:
3323            self.mapId = map.id
3324        else:
3325            self.mapId = None
3326
3327        vector = self.instruction.FindInstructionByType('vector')
3328        if vector:
3329            self.vectorId = vector.id
3330        else:
3331            self.vectorId = None
3332
3333        raster = self.instruction.FindInstructionByType('raster')
3334        if raster:
3335            self.rasterId = raster.id
3336        else:
3337            self.rasterId = None
3338
3339        self.pageId = self.instruction.FindInstructionByType('page').id
3340        currPage = self.instruction[self.pageId].GetInstruction()
3341        # raster legend
3342        if self.id[0] is not None:
3343            self.rasterLegend = self.instruction[self.id[0]]
3344            self.rLegendDict = self.rasterLegend.GetInstruction()
3345        else:
3346            self.id[0] = NewId()
3347            self.rasterLegend = RasterLegend(self.id[0], env=self.env)
3348            self.rLegendDict = self.rasterLegend.GetInstruction()
3349            self.rLegendDict['where'] = currPage['Left'], currPage['Top']
3350
3351        # vector legend
3352        if self.id[1] is not None:
3353            self.vLegendDict = self.instruction[self.id[1]].GetInstruction()
3354        else:
3355            self.id[1] = NewId()
3356            vectorLegend = VectorLegend(self.id[1], env=self.env)
3357            self.vLegendDict = vectorLegend.GetInstruction()
3358            self.vLegendDict['where'] = currPage['Left'], currPage['Top']
3359
3360        if self.rasterId:
3361            self.currRaster = self.instruction[self.rasterId]['raster']
3362        else:
3363            self.currRaster = None
3364
3365        # notebook
3366        self.notebook = Notebook(
3367            parent=self, id=wx.ID_ANY, style=wx.BK_DEFAULT)
3368        self.panelRaster = self._rasterLegend(self.notebook)
3369        self.panelVector = self._vectorLegend(self.notebook)
3370        self.OnRaster(None)
3371        self.OnRange(None)
3372        self.OnIsLegend(None)
3373        self.OnSpan(None)
3374        self.OnBorder(None)
3375
3376        self._layout(self.notebook)
3377        self.notebook.ChangeSelection(page)
3378        self.notebook.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGING, self.OnPageChanging)
3379
3380    def OnPageChanging(self, event):
3381        """Workaround to scroll up to see the checkbox"""
3382        wx.CallAfter(self.FindWindowByName('rasterPanel').ScrollChildIntoView,
3383                     self.FindWindowByName('showRLegend'))
3384        wx.CallAfter(self.FindWindowByName('vectorPanel').ScrollChildIntoView,
3385                     self.FindWindowByName('showVLegend'))
3386
3387    def _rasterLegend(self, notebook):
3388        panel = ScrolledPanel(
3389            parent=notebook, id=wx.ID_ANY, size=(-1, 500),
3390            style=wx.TAB_TRAVERSAL)
3391        panel.SetupScrolling(scroll_x=False, scroll_y=True)
3392        panel.SetName('rasterPanel')
3393        notebook.AddPage(page=panel, text=_("Raster legend"))
3394
3395        border = wx.BoxSizer(wx.VERTICAL)
3396        # is legend
3397        self.isRLegend = CheckBox(
3398            panel, id=wx.ID_ANY, label=_("Show raster legend"))
3399        self.isRLegend.SetValue(self.rLegendDict['rLegend'])
3400        self.isRLegend.SetName("showRLegend")
3401        border.Add(
3402            self.isRLegend,
3403            proportion=0,
3404            flag=wx.ALL | wx.EXPAND,
3405            border=5)
3406
3407        # choose raster
3408        box = StaticBox(
3409            parent=panel,
3410            id=wx.ID_ANY,
3411            label=" %s " %
3412            _("Source raster"))
3413        sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
3414        flexSizer = wx.FlexGridSizer(cols=2, hgap=5, vgap=5)
3415
3416        self.rasterDefault = RadioButton(
3417            panel, id=wx.ID_ANY, label=_("current raster"),
3418            style=wx.RB_GROUP)
3419        self.rasterOther = RadioButton(
3420            panel, id=wx.ID_ANY, label=_("select raster"))
3421        self.rasterDefault.SetValue(self.rLegendDict['rasterDefault'])
3422        self.rasterOther.SetValue(not self.rLegendDict['rasterDefault'])
3423
3424        rasterType = getRasterType(map=self.currRaster)
3425
3426        self.rasterCurrent = StaticText(
3427            panel, id=wx.ID_ANY, label=_("%(rast)s: type %(type)s") %
3428            {'rast': self.currRaster, 'type': rasterType})
3429        self.rasterSelect = Select(
3430            panel,
3431            id=wx.ID_ANY,
3432            size=globalvar.DIALOG_GSELECT_SIZE,
3433            type='raster',
3434            multiple=False,
3435            updateOnPopup=True,
3436            onPopup=None)
3437        if not self.rLegendDict['rasterDefault']:
3438            self.rasterSelect.SetValue(self.rLegendDict['raster'])
3439        else:
3440            self.rasterSelect.SetValue('')
3441        flexSizer.Add(
3442            self.rasterDefault,
3443            proportion=0,
3444            flag=wx.ALIGN_CENTER_VERTICAL,
3445            border=0)
3446        flexSizer.Add(
3447            self.rasterCurrent,
3448            proportion=0,
3449            flag=wx.ALIGN_CENTER_VERTICAL | wx.LEFT,
3450            border=10)
3451        flexSizer.Add(
3452            self.rasterOther,
3453            proportion=0,
3454            flag=wx.ALIGN_CENTER_VERTICAL,
3455            border=0)
3456        flexSizer.Add(
3457            self.rasterSelect,
3458            proportion=0,
3459            flag=wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT,
3460            border=0)
3461        flexSizer.AddGrowableCol(1)
3462
3463        sizer.Add(
3464            flexSizer,
3465            proportion=1,
3466            flag=wx.ALL | wx.EXPAND,
3467            border=1)
3468        border.Add(sizer, proportion=0, flag=wx.ALL | wx.EXPAND, border=5)
3469
3470        # type of legend
3471
3472        box = StaticBox(
3473            parent=panel,
3474            id=wx.ID_ANY,
3475            label=" %s " %
3476            _("Type of legend"))
3477        sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
3478        vbox = wx.BoxSizer(wx.VERTICAL)
3479        self.discrete = RadioButton(
3480            parent=panel, id=wx.ID_ANY, label=" %s " %
3481            _("discrete legend (categorical maps)"),
3482            style=wx.RB_GROUP)
3483        self.continuous = RadioButton(
3484            parent=panel, id=wx.ID_ANY, label=" %s " %
3485            _("continuous color gradient legend (floating point map)"))
3486
3487        vbox.Add(
3488            self.discrete,
3489            proportion=1,
3490            flag=wx.EXPAND | wx.ALL,
3491            border=0)
3492        vbox.Add(
3493            self.continuous,
3494            proportion=1,
3495            flag=wx.EXPAND | wx.ALL,
3496            border=0)
3497        sizer.Add(vbox, proportion=1, flag=wx.ALL | wx.EXPAND, border=1)
3498        border.Add(sizer, proportion=0, flag=wx.ALL | wx.EXPAND, border=5)
3499
3500        # size, position and font
3501        self.sizePositionFont(
3502            legendType='raster',
3503            parent=panel,
3504            mainSizer=border)
3505
3506        # advanced settings
3507        box = StaticBox(
3508            parent=panel,
3509            id=wx.ID_ANY,
3510            label=" %s " %
3511            _("Advanced legend settings"))
3512        sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
3513        gridBagSizer = wx.GridBagSizer(hgap=5, vgap=5)
3514        # no data
3515        self.nodata = CheckBox(
3516            panel, id=wx.ID_ANY, label=_('draw "no data" box'))
3517        if self.rLegendDict['nodata'] == 'y':
3518            self.nodata.SetValue(True)
3519        else:
3520            self.nodata.SetValue(False)
3521        # tickbar
3522        self.ticks = CheckBox(
3523            panel,
3524            id=wx.ID_ANY,
3525            label=_("draw ticks across color table"))
3526        if self.rLegendDict['tickbar'] == 'y':
3527            self.ticks.SetValue(True)
3528        else:
3529            self.ticks.SetValue(False)
3530        # range
3531        if self.rasterId and self.instruction[self.rasterId]['raster']:
3532            rinfo = grass.raster_info(
3533                self.instruction[
3534                    self.rasterId]['raster'])
3535            self.minim, self.maxim = rinfo['min'], rinfo['max']
3536        else:
3537            self.minim, self.maxim = 0, 0
3538        self.range = CheckBox(panel, id=wx.ID_ANY, label=_("range"))
3539        self.range.SetValue(self.rLegendDict['range'])
3540        self.minText = StaticText(
3541            panel,
3542            id=wx.ID_ANY,
3543            label="min (%s)" %
3544            self.minim)
3545        self.maxText = StaticText(
3546            panel,
3547            id=wx.ID_ANY,
3548            label="max (%s)" %
3549            self.maxim)
3550        self.min = TextCtrl(
3551            panel, id=wx.ID_ANY, value=str(
3552                self.rLegendDict['min']))
3553        self.max = TextCtrl(
3554            panel, id=wx.ID_ANY, value=str(
3555                self.rLegendDict['max']))
3556
3557        gridBagSizer.Add(
3558            self.nodata, pos=(
3559                0, 0), span=(
3560                1, 5), flag=wx.ALIGN_CENTER_VERTICAL, border=0)
3561        gridBagSizer.Add(
3562            self.ticks, pos=(
3563                1, 0), span=(
3564                1, 5), flag=wx.ALIGN_CENTER_VERTICAL, border=0)
3565        gridBagSizer.Add(
3566            self.range, pos=(2, 0),
3567            flag=wx.ALIGN_CENTER_VERTICAL, border=0)
3568        gridBagSizer.Add(
3569            self.minText,
3570            pos=(
3571                2,
3572                1),
3573            flag=wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT,
3574            border=0)
3575        gridBagSizer.Add(
3576            self.min, pos=(2, 2),
3577            flag=wx.ALIGN_CENTER_VERTICAL, border=0)
3578        gridBagSizer.Add(
3579            self.maxText,
3580            pos=(
3581                2,
3582                3),
3583            flag=wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT,
3584            border=0)
3585        gridBagSizer.Add(
3586            self.max, pos=(2, 4),
3587            flag=wx.ALIGN_CENTER_VERTICAL, border=0)
3588
3589        sizer.Add(
3590            gridBagSizer,
3591            proportion=0,
3592            border=0)
3593        border.Add(sizer, proportion=0, flag=wx.ALL | wx.EXPAND, border=5)
3594
3595        panel.SetSizer(border)
3596        panel.Fit()
3597
3598        # bindings
3599        self.Bind(wx.EVT_RADIOBUTTON, self.OnRaster, self.rasterDefault)
3600        self.Bind(wx.EVT_RADIOBUTTON, self.OnRaster, self.rasterOther)
3601        self.Bind(wx.EVT_CHECKBOX, self.OnIsLegend, self.isRLegend)
3602        self.Bind(wx.EVT_RADIOBUTTON, self.OnDiscrete, self.discrete)
3603        self.Bind(wx.EVT_RADIOBUTTON, self.OnDiscrete, self.continuous)
3604##        self.Bind(wx.EVT_CHECKBOX, self.OnDefaultSize, panel.defaultSize)
3605        self.Bind(wx.EVT_CHECKBOX, self.OnRange, self.range)
3606        self.rasterSelect.GetTextCtrl().Bind(wx.EVT_TEXT, self.OnRaster)
3607
3608        return panel
3609
3610    def _vectorLegend(self, notebook):
3611        panel = ScrolledPanel(
3612            parent=notebook, id=wx.ID_ANY, size=(-1, 500),
3613            style=wx.TAB_TRAVERSAL)
3614        panel.SetupScrolling(scroll_x=False, scroll_y=True)
3615        panel.SetName('vectorPanel')
3616        notebook.AddPage(page=panel, text=_("Vector legend"))
3617
3618        border = wx.BoxSizer(wx.VERTICAL)
3619        # is legend
3620        self.isVLegend = CheckBox(
3621            panel, id=wx.ID_ANY, label=_("Show vector legend"))
3622        self.isVLegend.SetValue(self.vLegendDict['vLegend'])
3623        self.isVLegend.SetName("showVLegend")
3624        border.Add(
3625            self.isVLegend,
3626            proportion=0,
3627            flag=wx.ALL | wx.EXPAND,
3628            border=5)
3629
3630        # vector maps, their order, labels
3631        box = StaticBox(
3632            parent=panel,
3633            id=wx.ID_ANY,
3634            label=" %s " %
3635            _("Source vector maps"))
3636        sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
3637        gridBagSizer = wx.GridBagSizer(hgap=5, vgap=5)
3638
3639        vectorText = StaticText(panel, id=wx.ID_ANY, label=_(
3640            "Choose vector maps and their order in legend"))
3641
3642        self.vectorListCtrl = CheckListCtrl(panel)
3643
3644        self.vectorListCtrl.InsertColumn(0, _("Vector map"))
3645        self.vectorListCtrl.InsertColumn(1, _("Label"))
3646        if self.vectorId:
3647            vectors = sorted(
3648                self.instruction[
3649                    self.vectorId]['list'],
3650                key=lambda x: x[3])
3651
3652            for vector in vectors:
3653                index = self.vectorListCtrl.InsertItem(
3654                    self.vectorListCtrl.GetItemCount(), vector[0].split('@')[0])
3655                self.vectorListCtrl.SetItem(index, 1, vector[4])
3656                self.vectorListCtrl.SetItemData(index, index)
3657                self.vectorListCtrl.CheckItem(index, True)
3658                if vector[3] == 0:
3659                    self.vectorListCtrl.CheckItem(index, False)
3660        if not self.vectorId:
3661            self.vectorListCtrl.SetColumnWidth(0, 100)
3662        else:
3663            self.vectorListCtrl.SetColumnWidth(0, wx.LIST_AUTOSIZE)
3664        self.vectorListCtrl.SetColumnWidth(1, wx.LIST_AUTOSIZE)
3665
3666        self.btnUp = Button(panel, id=wx.ID_ANY, label=_("Up"))
3667        self.btnDown = Button(panel, id=wx.ID_ANY, label=_("Down"))
3668        self.btnLabel = Button(panel, id=wx.ID_ANY, label=_("Edit label"))
3669
3670        gridBagSizer.Add(
3671            vectorText, pos=(
3672                0, 0), span=(
3673                1, 2), flag=wx.ALIGN_CENTER_VERTICAL, border=0)
3674        gridBagSizer.Add(
3675            self.vectorListCtrl, pos=(
3676                1, 0), span=(
3677                3, 1), flag=wx.ALIGN_CENTER_VERTICAL | wx.EXPAND, border=0)
3678        gridBagSizer.Add(
3679            self.btnUp, pos=(1, 1),
3680            flag=wx.ALIGN_CENTER_VERTICAL, border=0)
3681        gridBagSizer.Add(
3682            self.btnDown, pos=(2, 1),
3683            flag=wx.ALIGN_CENTER_VERTICAL, border=0)
3684        gridBagSizer.Add(
3685            self.btnLabel, pos=(3, 1),
3686            flag=wx.ALIGN_CENTER_VERTICAL, border=0)
3687
3688        gridBagSizer.AddGrowableCol(0, 3)
3689        gridBagSizer.AddGrowableCol(1, 1)
3690        sizer.Add(
3691            gridBagSizer,
3692            proportion=0,
3693            flag=wx.EXPAND,
3694            border=0)
3695        border.Add(sizer, proportion=0, flag=wx.ALL | wx.EXPAND, border=5)
3696
3697        # size, position and font
3698        self.sizePositionFont(
3699            legendType='vector',
3700            parent=panel,
3701            mainSizer=border)
3702
3703        # border
3704        # GTC  Line around legend or map frame
3705        box = StaticBox(
3706            parent=panel,
3707            id=wx.ID_ANY,
3708            label=" %s " %
3709            _("Border"))
3710        sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
3711        flexGridSizer = wx.FlexGridSizer(cols=2, hgap=5, vgap=5)
3712
3713        self.borderCheck = CheckBox(
3714            panel, id=wx.ID_ANY, label=_("draw border around legend"))
3715        self.borderColorCtrl = ColourPickerCtrl(
3716            panel, id=wx.ID_ANY, style=wx.FNTP_FONTDESC_AS_LABEL)
3717        if self.vLegendDict['border'] == 'none':
3718            self.borderColorCtrl.SetColour(wx.BLACK)
3719            self.borderCheck.SetValue(False)
3720        else:
3721            self.borderColorCtrl.SetColour(
3722                convertRGB(self.vLegendDict['border']))
3723            self.borderCheck.SetValue(True)
3724
3725        flexGridSizer.Add(
3726            self.borderCheck,
3727            proportion=0,
3728            flag=wx.ALIGN_CENTER_VERTICAL,
3729            border=0)
3730        flexGridSizer.Add(
3731            self.borderColorCtrl,
3732            proportion=0,
3733            flag=wx.ALIGN_CENTER_VERTICAL,
3734            border=0)
3735        sizer.Add(
3736            flexGridSizer,
3737            proportion=1,
3738            flag=wx.ALL | wx.EXPAND,
3739            border=1)
3740        border.Add(sizer, proportion=0, flag=wx.ALL | wx.EXPAND, border=5)
3741
3742        self.Bind(wx.EVT_BUTTON, self.OnUp, self.btnUp)
3743        self.Bind(wx.EVT_BUTTON, self.OnDown, self.btnDown)
3744        self.Bind(wx.EVT_BUTTON, self.OnEditLabel, self.btnLabel)
3745        self.Bind(wx.EVT_CHECKBOX, self.OnIsLegend, self.isVLegend)
3746        self.Bind(wx.EVT_CHECKBOX, self.OnSpan, panel.spanRadio)
3747        self.Bind(wx.EVT_CHECKBOX, self.OnBorder, self.borderCheck)
3748        self.Bind(
3749            wx.EVT_FONTPICKER_CHANGED,
3750            self.OnFont,
3751            panel.font['fontCtrl'])
3752
3753        panel.SetSizer(border)
3754
3755        panel.Fit()
3756        return panel
3757
3758    def sizePositionFont(self, legendType, parent, mainSizer):
3759        """Insert widgets for size, position and font control"""
3760        if legendType == 'raster':
3761            legendDict = self.rLegendDict
3762        else:
3763            legendDict = self.vLegendDict
3764        panel = parent
3765        border = mainSizer
3766
3767        # size and position
3768        box = StaticBox(
3769            parent=panel,
3770            id=wx.ID_ANY,
3771            label=" %s " %
3772            _("Size and position"))
3773        sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
3774        # unit
3775        self.AddUnits(parent=panel, dialogDict=legendDict)
3776        unitBox = wx.BoxSizer(wx.HORIZONTAL)
3777        unitBox.Add(
3778            panel.units['unitsLabel'],
3779            proportion=0,
3780            flag=wx.ALIGN_CENTER_VERTICAL | wx.LEFT,
3781            border=10)
3782        unitBox.Add(
3783            panel.units['unitsCtrl'],
3784            proportion=1,
3785            flag=wx.ALL,
3786            border=5)
3787        sizer.Add(
3788            unitBox,
3789            proportion=0,
3790            border=0)
3791
3792        hBox = wx.BoxSizer(wx.HORIZONTAL)
3793        posBox = StaticBox(
3794            parent=panel,
3795            id=wx.ID_ANY,
3796            label=" %s " %
3797            _("Position"))
3798        posSizer = wx.StaticBoxSizer(posBox, wx.VERTICAL)
3799        sizeBox = StaticBox(
3800            parent=panel,
3801            id=wx.ID_ANY,
3802            label=" %s " %
3803            _("Size"))
3804        sizeSizer = wx.StaticBoxSizer(sizeBox, wx.VERTICAL)
3805        posGridBagSizer = wx.GridBagSizer(hgap=10, vgap=5)
3806
3807        # position
3808        self.AddPosition(parent=panel, dialogDict=legendDict)
3809
3810        posGridBagSizer.Add(panel.position['xLabel'], pos=(
3811            0, 0), flag=wx.ALIGN_CENTER_VERTICAL, border=0)
3812        posGridBagSizer.Add(panel.position['xCtrl'], pos=(
3813            0, 1), flag=wx.ALIGN_CENTER_VERTICAL, border=0)
3814        posGridBagSizer.Add(panel.position['yLabel'], pos=(
3815            1, 0), flag=wx.ALIGN_CENTER_VERTICAL, border=0)
3816        posGridBagSizer.Add(panel.position['yCtrl'], pos=(
3817            1, 1), flag=wx.ALIGN_CENTER_VERTICAL, border=0)
3818        posGridBagSizer.Add(
3819            panel.position['comment'], pos=(
3820                2, 0), span=(
3821                1, 2), flag=wx.ALIGN_BOTTOM, border=0)
3822        posGridBagSizer.AddGrowableRow(2)
3823        posSizer.Add(
3824            posGridBagSizer,
3825            proportion=1,
3826            flag=wx.EXPAND | wx.ALL,
3827            border=5)
3828
3829        # size
3830        width = StaticText(panel, id=wx.ID_ANY, label=_("Width:"))
3831        if legendDict['width']:
3832            w = self.unitConv.convert(
3833                value=float(legendDict['width']),
3834                fromUnit='inch', toUnit=legendDict['unit'])
3835        else:
3836            w = ''
3837        panel.widthCtrl = TextCtrl(
3838            panel, id=wx.ID_ANY, value=str(w),
3839            validator=TCValidator("DIGIT_ONLY"))
3840        panel.widthCtrl.SetToolTip(
3841            _("Leave the edit field empty, to use default values."))
3842
3843        if legendType == 'raster':
3844            ##            panel.defaultSize = wx.CheckBox(panel, id = wx.ID_ANY, label = _("Use default size"))
3845            # panel.defaultSize.SetValue(legendDict['defaultSize'])
3846
3847            panel.heightOrColumnsLabel = StaticText(
3848                panel, id=wx.ID_ANY, label=_("Height:"))
3849            if legendDict['height']:
3850                h = self.unitConv.convert(
3851                    value=float(legendDict['height']),
3852                    fromUnit='inch', toUnit=legendDict['unit'])
3853            else:
3854                h = ''
3855            panel.heightOrColumnsCtrl = TextCtrl(
3856                panel, id=wx.ID_ANY, value=str(h),
3857                validator=TCValidator("DIGIT_ONLY"))
3858
3859            self.rSizeGBSizer = wx.GridBagSizer(hgap=5, vgap=5)
3860##            self.rSizeGBSizer.Add(panel.defaultSize, pos = (0,0), span = (1,2), flag = wx.ALIGN_CENTER_VERTICAL, border = 0)
3861            self.rSizeGBSizer.Add(
3862                width, pos=(0, 0),
3863                flag=wx.ALIGN_CENTER_VERTICAL, border=0)
3864            self.rSizeGBSizer.Add(
3865                panel.widthCtrl, pos=(0, 1),
3866                flag=wx.ALIGN_CENTER_VERTICAL, border=0)
3867            self.rSizeGBSizer.Add(
3868                panel.heightOrColumnsLabel, pos=(
3869                    1, 0), flag=wx.ALIGN_CENTER_VERTICAL, border=0)
3870            self.rSizeGBSizer.Add(
3871                panel.heightOrColumnsCtrl, pos=(
3872                    1, 1), flag=wx.ALIGN_CENTER_VERTICAL, border=0)
3873            sizeSizer.Add(
3874                self.rSizeGBSizer,
3875                proportion=1,
3876                flag=wx.EXPAND | wx.ALL,
3877                border=5)
3878
3879        if legendType == 'vector':
3880            panel.widthCtrl.SetToolTip(
3881                _("Width of the color symbol (for lines)\nin front of the legend text"))
3882            # columns
3883            minVect, maxVect = 0, 0
3884            if self.vectorId:
3885                minVect = 1
3886                maxVect = min(10, len(self.instruction[self.vectorId]['list']))
3887            cols = StaticText(panel, id=wx.ID_ANY, label=_("Columns:"))
3888            panel.colsCtrl = SpinCtrl(
3889                panel,
3890                id=wx.ID_ANY,
3891                value="",
3892                min=minVect,
3893                max=maxVect,
3894                initial=legendDict['cols'])
3895            # span
3896            panel.spanRadio = CheckBox(
3897                panel, id=wx.ID_ANY, label=_("column span:"))
3898            panel.spanTextCtrl = TextCtrl(panel, id=wx.ID_ANY, value='')
3899            panel.spanTextCtrl.SetToolTip(_("Column separation distance between the left edges\n"
3900                                            "of two columns in a multicolumn legend"))
3901            if legendDict['span']:
3902                panel.spanRadio.SetValue(True)
3903                s = self.unitConv.convert(
3904                    value=float(legendDict['span']),
3905                    fromUnit='inch', toUnit=legendDict['unit'])
3906                panel.spanTextCtrl.SetValue(str(s))
3907            else:
3908                panel.spanRadio.SetValue(False)
3909
3910            self.vSizeGBSizer = wx.GridBagSizer(hgap=5, vgap=5)
3911            self.vSizeGBSizer.Add(
3912                width, pos=(0, 0),
3913                flag=wx.ALIGN_CENTER_VERTICAL, border=0)
3914            self.vSizeGBSizer.Add(
3915                panel.widthCtrl, pos=(0, 1),
3916                flag=wx.ALIGN_CENTER_VERTICAL, border=0)
3917            self.vSizeGBSizer.Add(
3918                cols, pos=(1, 0),
3919                flag=wx.ALIGN_CENTER_VERTICAL, border=0)
3920            self.vSizeGBSizer.Add(
3921                panel.colsCtrl, pos=(1, 1),
3922                flag=wx.ALIGN_CENTER_VERTICAL, border=0)
3923            self.vSizeGBSizer.Add(
3924                panel.spanRadio, pos=(2, 0),
3925                flag=wx.ALIGN_CENTER_VERTICAL, border=0)
3926            self.vSizeGBSizer.Add(
3927                panel.spanTextCtrl, pos=(2, 1),
3928                flag=wx.ALIGN_CENTER_VERTICAL, border=0)
3929            self.vSizeGBSizer.AddGrowableCol(1)
3930            sizeSizer.Add(
3931                self.vSizeGBSizer,
3932                proportion=1,
3933                flag=wx.EXPAND | wx.ALL,
3934                border=5)
3935
3936        hBox.Add(posSizer, proportion=1, flag=wx.EXPAND | wx.ALL, border=3)
3937        hBox.Add(sizeSizer, proportion=1, flag=wx.EXPAND | wx.ALL, border=3)
3938        sizer.Add(hBox, proportion=0, flag=wx.EXPAND, border=0)
3939        border.Add(sizer, proportion=0, flag=wx.ALL | wx.EXPAND, border=5)
3940
3941        # font
3942        box = StaticBox(
3943            parent=panel,
3944            id=wx.ID_ANY,
3945            label=" %s " %
3946            _("Font settings"))
3947        fontSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
3948        flexSizer = wx.FlexGridSizer(cols=2, hgap=5, vgap=5)
3949
3950        if legendType == 'raster':
3951            self.AddFont(parent=panel, dialogDict=legendDict, color=True)
3952        else:
3953            self.AddFont(parent=panel, dialogDict=legendDict, color=False)
3954        flexSizer.Add(
3955            panel.font['fontLabel'],
3956            proportion=0,
3957            flag=wx.ALIGN_CENTER_VERTICAL,
3958            border=0)
3959        flexSizer.Add(
3960            panel.font['fontCtrl'],
3961            proportion=0,
3962            flag=wx.ALIGN_CENTER_VERTICAL,
3963            border=0)
3964        flexSizer.Add(
3965            panel.font['fontSizeLabel'],
3966            proportion=0,
3967            flag=wx.ALIGN_CENTER_VERTICAL,
3968            border=0)
3969        flexSizer.Add(
3970            panel.font['fontSizeCtrl'],
3971            proportion=0,
3972            flag=wx.ALIGN_CENTER_VERTICAL,
3973            border=0)
3974        if legendType == 'raster':
3975            flexSizer.Add(
3976                panel.font['colorLabel'],
3977                proportion=0,
3978                flag=wx.ALIGN_CENTER_VERTICAL,
3979                border=0)
3980            flexSizer.Add(
3981                panel.font['colorCtrl'],
3982                proportion=0,
3983                flag=wx.ALIGN_CENTER_VERTICAL,
3984                border=0)
3985        flexSizer.AddGrowableCol(1)
3986
3987        fontSizer.Add(
3988            flexSizer,
3989            proportion=1,
3990            flag=wx.ALL | wx.EXPAND,
3991            border=1)
3992        border.Add(
3993            fontSizer,
3994            proportion=0,
3995            flag=wx.ALL | wx.EXPAND,
3996            border=5)
3997
3998    #   some enable/disable methods
3999
4000    def OnIsLegend(self, event):
4001        """Enables and disables controls, it depends if raster or vector legend is checked"""
4002        page = self.notebook.GetSelection()
4003        if page == 0 or event is None:
4004            children = self.panelRaster.GetChildren()
4005            if self.isRLegend.GetValue():
4006                for i, widget in enumerate(children):
4007                    widget.Enable()
4008                self.OnRaster(None)
4009                self.OnRange(None)
4010                self.OnDiscrete(None)
4011            else:
4012                for widget in children:
4013                    if widget.GetName() != 'showRLegend':
4014                        widget.Disable()
4015        if page == 1 or event is None:
4016            children = self.panelVector.GetChildren()
4017            if self.isVLegend.GetValue():
4018                for i, widget in enumerate(children):
4019                    widget.Enable()
4020                self.OnSpan(None)
4021                self.OnBorder(None)
4022            else:
4023                for widget in children:
4024                    if widget.GetName() != 'showVLegend':
4025                        widget.Disable()
4026
4027    def OnRaster(self, event):
4028        if self.rasterDefault.GetValue():  # default
4029            self.rasterSelect.Disable()
4030            type = getRasterType(self.currRaster)
4031        else:  # select raster
4032            self.rasterSelect.Enable()
4033            map = self.rasterSelect.GetValue()
4034            type = getRasterType(map)
4035
4036        if type == 'CELL':
4037            self.discrete.SetValue(True)
4038        elif type in ('FCELL', 'DCELL'):
4039            self.continuous.SetValue(True)
4040        if event is None:
4041            if self.rLegendDict['discrete'] == 'y':
4042                self.discrete.SetValue(True)
4043            elif self.rLegendDict['discrete'] == 'n':
4044                self.continuous.SetValue(True)
4045        self.OnDiscrete(None)
4046
4047    def OnDiscrete(self, event):
4048        """Change control according to the type of legend"""
4049        enabledSize = self.panelRaster.heightOrColumnsCtrl.IsEnabled()
4050        self.panelRaster.heightOrColumnsCtrl.Destroy()
4051        if self.discrete.GetValue():
4052            self.panelRaster.heightOrColumnsLabel.SetLabel(_("Columns:"))
4053            self.panelRaster.heightOrColumnsCtrl = SpinCtrl(
4054                self.panelRaster, id=wx.ID_ANY, value="", min=1, max=10,
4055                initial=self.rLegendDict['cols'])
4056            self.panelRaster.heightOrColumnsCtrl.Enable(enabledSize)
4057            self.nodata.Enable()
4058            self.range.Disable()
4059            self.min.Disable()
4060            self.max.Disable()
4061            self.minText.Disable()
4062            self.maxText.Disable()
4063            self.ticks.Disable()
4064        else:
4065            self.panelRaster.heightOrColumnsLabel.SetLabel(_("Height:"))
4066            if self.rLegendDict['height']:
4067                h = self.unitConv.convert(
4068                    value=float(
4069                        self.rLegendDict['height']),
4070                    fromUnit='inch',
4071                    toUnit=self.rLegendDict['unit'])
4072            else:
4073                h = ''
4074            self.panelRaster.heightOrColumnsCtrl = TextCtrl(
4075                self.panelRaster, id=wx.ID_ANY, value=str(h),
4076                validator=TCValidator("DIGIT_ONLY"))
4077            self.panelRaster.heightOrColumnsCtrl.Enable(enabledSize)
4078            self.nodata.Disable()
4079            self.range.Enable()
4080            if self.range.GetValue():
4081                self.minText.Enable()
4082                self.maxText.Enable()
4083                self.min.Enable()
4084                self.max.Enable()
4085            self.ticks.Enable()
4086
4087        self.rSizeGBSizer.Add(
4088            self.panelRaster.heightOrColumnsCtrl, pos=(
4089                1, 1), flag=wx.ALIGN_CENTER_VERTICAL, border=0)
4090        self.panelRaster.Layout()
4091        self.panelRaster.Fit()
4092
4093    def OnRange(self, event):
4094        if not self.range.GetValue():
4095            self.min.Disable()
4096            self.max.Disable()
4097            self.minText.Disable()
4098            self.maxText.Disable()
4099        else:
4100            self.min.Enable()
4101            self.max.Enable()
4102            self.minText.Enable()
4103            self.maxText.Enable()
4104
4105    def OnUp(self, event):
4106        """Moves selected map up, changes order in vector legend"""
4107        if self.vectorListCtrl.GetFirstSelected() != -1:
4108            pos = self.vectorListCtrl.GetFirstSelected()
4109            if pos:
4110                idx1 = self.vectorListCtrl.GetItemData(pos) - 1
4111                idx2 = self.vectorListCtrl.GetItemData(pos - 1) + 1
4112                self.vectorListCtrl.SetItemData(pos, idx1)
4113                self.vectorListCtrl.SetItemData(pos - 1, idx2)
4114                self.vectorListCtrl.SortItems(cmp)
4115                if pos > 0:
4116                    selected = (pos - 1)
4117                else:
4118                    selected = 0
4119
4120                self.vectorListCtrl.Select(selected)
4121
4122    def OnDown(self, event):
4123        """Moves selected map down, changes order in vector legend"""
4124        if self.vectorListCtrl.GetFirstSelected() != -1:
4125            pos = self.vectorListCtrl.GetFirstSelected()
4126            if pos != self.vectorListCtrl.GetItemCount() - 1:
4127                idx1 = self.vectorListCtrl.GetItemData(pos) + 1
4128                idx2 = self.vectorListCtrl.GetItemData(pos + 1) - 1
4129                self.vectorListCtrl.SetItemData(pos, idx1)
4130                self.vectorListCtrl.SetItemData(pos + 1, idx2)
4131                self.vectorListCtrl.SortItems(cmp)
4132                if pos < self.vectorListCtrl.GetItemCount() - 1:
4133                    selected = (pos + 1)
4134                else:
4135                    selected = self.vectorListCtrl.GetItemCount() - 1
4136
4137                self.vectorListCtrl.Select(selected)
4138
4139    def OnEditLabel(self, event):
4140        """Change legend label of vector map"""
4141        if self.vectorListCtrl.GetFirstSelected() != -1:
4142            idx = self.vectorListCtrl.GetFirstSelected()
4143            default = self.vectorListCtrl.GetItem(idx, 1).GetText()
4144            dlg = TextEntryDialog(
4145                self,
4146                message=_("Edit legend label:"),
4147                caption=_("Edit label"),
4148                value=default,
4149                style=wx.OK | wx.CANCEL | wx.CENTRE)
4150            if dlg.ShowModal() == wx.ID_OK:
4151                new = dlg.GetValue()
4152                self.vectorListCtrl.SetItem(idx, 1, new)
4153            dlg.Destroy()
4154
4155    def OnSpan(self, event):
4156        self.panelVector.spanTextCtrl.Enable(
4157            self.panelVector.spanRadio.GetValue())
4158
4159    def OnFont(self, event):
4160        """Changes default width according to fontsize, width [inch] = fontsize[pt]/24"""
4161##        fontsize = self.panelVector.font['fontCtrl'].GetSelectedFont().GetPointSize()
4162        fontsize = self.panelVector.font['fontSizeCtrl'].GetValue()
4163        unit = self.unitConv.findUnit(
4164            self.panelVector.units['unitsCtrl'].GetStringSelection())
4165        w = fontsize / 24.
4166        width = self.unitConv.convert(value=w, fromUnit='inch', toUnit=unit)
4167        self.panelVector.widthCtrl.SetValue("%3.2f" % width)
4168
4169    def OnBorder(self, event):
4170        """Enables/disables colorPickerCtrl for border"""
4171        self.borderColorCtrl.Enable(self.borderCheck.GetValue())
4172
4173    def updateRasterLegend(self):
4174        """Save information from raster legend dialog to dictionary"""
4175
4176        # is raster legend
4177        if not self.isRLegend.GetValue():
4178            self.rLegendDict['rLegend'] = False
4179        else:
4180            self.rLegendDict['rLegend'] = True
4181        # units
4182        currUnit = self.unitConv.findUnit(
4183            self.panelRaster.units['unitsCtrl'].GetStringSelection())
4184        self.rLegendDict['unit'] = currUnit
4185        # raster
4186        if self.rasterDefault.GetValue():
4187            self.rLegendDict['rasterDefault'] = True
4188            self.rLegendDict['raster'] = self.currRaster
4189        else:
4190            self.rLegendDict['rasterDefault'] = False
4191            self.rLegendDict['raster'] = self.rasterSelect.GetValue()
4192        if self.rLegendDict['rLegend'] and not self.rLegendDict['raster']:
4193            wx.MessageBox(message=_("No raster map selected!"),
4194                          caption=_('No raster'), style=wx.OK | wx.ICON_ERROR)
4195            return False
4196
4197        if self.rLegendDict['raster']:
4198            # type and range of map
4199            rasterType = getRasterType(self.rLegendDict['raster'])
4200            if rasterType is None:
4201                return False
4202            self.rLegendDict['type'] = rasterType
4203
4204            # discrete
4205            if self.discrete.GetValue():
4206                self.rLegendDict['discrete'] = 'y'
4207            else:
4208                self.rLegendDict['discrete'] = 'n'
4209
4210            # font
4211            self.rLegendDict['font'] = self.panelRaster.font[
4212                'fontCtrl'].GetStringSelection()
4213            self.rLegendDict['fontsize'] = self.panelRaster.font[
4214                'fontSizeCtrl'].GetValue()
4215            color = self.panelRaster.font['colorCtrl'].GetColour()
4216            self.rLegendDict['color'] = convertRGB(color)
4217
4218            # position
4219            x = self.unitConv.convert(
4220                value=float(
4221                    self.panelRaster.position
4222                    ['xCtrl'].GetValue()),
4223                fromUnit=currUnit, toUnit='inch')
4224            y = self.unitConv.convert(
4225                value=float(
4226                    self.panelRaster.position
4227                    ['yCtrl'].GetValue()),
4228                fromUnit=currUnit, toUnit='inch')
4229            self.rLegendDict['where'] = (x, y)
4230            # estimated size
4231            width = self.panelRaster.widthCtrl.GetValue()
4232            try:
4233                width = float(width)
4234                width = self.unitConv.convert(
4235                    value=width, fromUnit=currUnit, toUnit='inch')
4236            except ValueError:
4237                width = None
4238            self.rLegendDict['width'] = width
4239            if self.rLegendDict['discrete'] == 'n':
4240                height = self.panelRaster.heightOrColumnsCtrl.GetValue()
4241                try:
4242                    height = float(height)
4243                    height = self.unitConv.convert(
4244                        value=height, fromUnit=currUnit, toUnit='inch')
4245                except ValueError:
4246                    height = None
4247                self.rLegendDict['height'] = height
4248            else:
4249                cols = self.panelRaster.heightOrColumnsCtrl.GetValue()
4250                self.rLegendDict['cols'] = cols
4251            drawHeight = self.rasterLegend.EstimateHeight(
4252                raster=self.rLegendDict['raster'],
4253                discrete=self.rLegendDict['discrete'],
4254                fontsize=self.rLegendDict['fontsize'],
4255                cols=self.rLegendDict['cols'],
4256                height=self.rLegendDict['height'])
4257            drawWidth = self.rasterLegend.EstimateWidth(
4258                raster=self.rLegendDict['raster'],
4259                discrete=self.rLegendDict['discrete'],
4260                fontsize=self.rLegendDict['fontsize'],
4261                cols=self.rLegendDict['cols'],
4262                width=self.rLegendDict['width'],
4263                paperInstr=self.instruction[self.pageId])
4264            self.rLegendDict['rect'] = Rect2D(
4265                x=x, y=y, width=drawWidth, height=drawHeight)
4266
4267            # no data
4268            if self.rLegendDict['discrete'] == 'y':
4269                if self.nodata.GetValue():
4270                    self.rLegendDict['nodata'] = 'y'
4271                else:
4272                    self.rLegendDict['nodata'] = 'n'
4273            # tickbar
4274            elif self.rLegendDict['discrete'] == 'n':
4275                if self.ticks.GetValue():
4276                    self.rLegendDict['tickbar'] = 'y'
4277                else:
4278                    self.rLegendDict['tickbar'] = 'n'
4279            # range
4280                if self.range.GetValue():
4281                    self.rLegendDict['range'] = True
4282                    self.rLegendDict['min'] = self.min.GetValue()
4283                    self.rLegendDict['max'] = self.max.GetValue()
4284                else:
4285                    self.rLegendDict['range'] = False
4286
4287        if not self.id[0] in self.instruction:
4288            rasterLegend = RasterLegend(self.id[0], env=self.env)
4289            self.instruction.AddInstruction(rasterLegend)
4290        self.instruction[self.id[0]].SetInstruction(self.rLegendDict)
4291
4292        if self.id[0] not in self.parent.objectId:
4293            self.parent.objectId.append(self.id[0])
4294        return True
4295
4296    def updateVectorLegend(self):
4297        """Save information from vector legend dialog to dictionary"""
4298
4299        vector = self.instruction.FindInstructionByType('vector')
4300        if vector:
4301            self.vectorId = vector.id
4302        else:
4303            self.vectorId = None
4304
4305        # is vector legend
4306        if not self.isVLegend.GetValue():
4307            self.vLegendDict['vLegend'] = False
4308        else:
4309            self.vLegendDict['vLegend'] = True
4310        if self.vLegendDict['vLegend'] == True and self.vectorId is not None:
4311            # labels
4312            # reindex order
4313            idx = 1
4314            for item in range(self.vectorListCtrl.GetItemCount()):
4315                if self.vectorListCtrl.IsItemChecked(item):
4316                    self.vectorListCtrl.SetItemData(item, idx)
4317                    idx += 1
4318                else:
4319                    self.vectorListCtrl.SetItemData(item, 0)
4320            if idx == 1:
4321                self.vLegendDict['vLegend'] = False
4322            else:
4323                vList = self.instruction[self.vectorId]['list']
4324                for i, vector in enumerate(vList):
4325                    item = self.vectorListCtrl.FindItem(
4326                        start=-1, str=vector[0].split('@')[0])
4327                    vList[i][3] = self.vectorListCtrl.GetItemData(item)
4328                    vList[i][4] = self.vectorListCtrl.GetItem(
4329                        item, 1).GetText()
4330                vmaps = self.instruction.FindInstructionByType(
4331                    'vProperties', list=True)
4332                for vmap, vector in zip(vmaps, vList):
4333                    self.instruction[vmap.id]['lpos'] = vector[3]
4334                    self.instruction[vmap.id]['label'] = vector[4]
4335                # units
4336                currUnit = self.unitConv.findUnit(
4337                    self.panelVector.units['unitsCtrl'].GetStringSelection())
4338                self.vLegendDict['unit'] = currUnit
4339                # position
4340                x = self.unitConv.convert(
4341                    value=float(
4342                        self.panelVector.position['xCtrl'].GetValue()),
4343                    fromUnit=currUnit,
4344                    toUnit='inch')
4345                y = self.unitConv.convert(
4346                    value=float(
4347                        self.panelVector.position['yCtrl'].GetValue()),
4348                    fromUnit=currUnit,
4349                    toUnit='inch')
4350                self.vLegendDict['where'] = (x, y)
4351
4352                # font
4353                self.vLegendDict['font'] = self.panelVector.font[
4354                    'fontCtrl'].GetStringSelection()
4355                self.vLegendDict['fontsize'] = self.panelVector.font[
4356                    'fontSizeCtrl'].GetValue()
4357                dc = ClientDC(self)
4358                dc.SetFont(
4359                    wx.Font(
4360                        pointSize=self.vLegendDict['fontsize'],
4361                        family=wx.FONTFAMILY_DEFAULT,
4362                        style=wx.FONTSTYLE_NORMAL,
4363                        weight=wx.FONTWEIGHT_NORMAL))
4364                # size
4365                width = self.unitConv.convert(
4366                    value=float(self.panelVector.widthCtrl.GetValue()),
4367                    fromUnit=currUnit, toUnit='inch')
4368                self.vLegendDict['width'] = width
4369                self.vLegendDict['cols'] = self.panelVector.colsCtrl.GetValue()
4370                if self.panelVector.spanRadio.GetValue() and self.panelVector.spanTextCtrl.GetValue():
4371                    self.vLegendDict[
4372                        'span'] = self.panelVector.spanTextCtrl.GetValue()
4373                else:
4374                    self.vLegendDict['span'] = None
4375
4376                # size estimation
4377                vectors = self.instruction[self.vectorId]['list']
4378                labels = [vector[4] for vector in vectors if vector[3] != 0]
4379                extent = dc.GetTextExtent(max(labels, key=len))
4380                wExtent = self.unitConv.convert(
4381                    value=extent[0], fromUnit='pixel', toUnit='inch')
4382                hExtent = self.unitConv.convert(
4383                    value=extent[1], fromUnit='pixel', toUnit='inch')
4384                w = (width + wExtent) * self.vLegendDict['cols']
4385                h = len(labels) * hExtent / self.vLegendDict['cols']
4386                h *= 1.1
4387                self.vLegendDict['rect'] = Rect2D(x, y, w, h)
4388
4389                # border
4390                if self.borderCheck.GetValue():
4391                    color = self.borderColorCtrl.GetColour()
4392                    self.vLegendDict['border'] = convertRGB(color)
4393
4394                else:
4395                    self.vLegendDict['border'] = 'none'
4396
4397        if not self.id[1] in self.instruction:
4398            vectorLegend = VectorLegend(self.id[1], env=self.env)
4399            self.instruction.AddInstruction(vectorLegend)
4400        self.instruction[self.id[1]].SetInstruction(self.vLegendDict)
4401        if self.id[1] not in self.parent.objectId:
4402            self.parent.objectId.append(self.id[1])
4403        return True
4404
4405    def update(self):
4406        okR = self.updateRasterLegend()
4407        okV = self.updateVectorLegend()
4408        if okR and okV:
4409            return True
4410        return False
4411
4412    def updateDialog(self):
4413        """Update legend coordinates after moving"""
4414
4415        # raster legend
4416        if 'rect' in self.rLegendDict:
4417            x, y = self.rLegendDict['rect'][:2]
4418            currUnit = self.unitConv.findUnit(
4419                self.panelRaster.units['unitsCtrl'].GetStringSelection())
4420            x = self.unitConv.convert(
4421                value=x, fromUnit='inch', toUnit=currUnit)
4422            y = self.unitConv.convert(
4423                value=y, fromUnit='inch', toUnit=currUnit)
4424            self.panelRaster.position['xCtrl'].SetValue("%5.3f" % x)
4425            self.panelRaster.position['yCtrl'].SetValue("%5.3f" % y)
4426        # update name and type of raster
4427        raster = self.instruction.FindInstructionByType('raster')
4428        if raster:
4429            self.rasterId = raster.id
4430        else:
4431            self.rasterId = None
4432
4433        if raster:
4434            currRaster = raster['raster']
4435        else:
4436            currRaster = None
4437
4438        rasterType = getRasterType(map=currRaster)
4439        self.rasterCurrent.SetLabel(
4440            _("%(rast)s: type %(type)s") %
4441            {'rast': currRaster, 'type': str(rasterType)})
4442
4443        # vector legend
4444        if 'rect' in self.vLegendDict:
4445            x, y = self.vLegendDict['rect'][:2]
4446            currUnit = self.unitConv.findUnit(
4447                self.panelVector.units['unitsCtrl'].GetStringSelection())
4448            x = self.unitConv.convert(
4449                value=x, fromUnit='inch', toUnit=currUnit)
4450            y = self.unitConv.convert(
4451                value=y, fromUnit='inch', toUnit=currUnit)
4452            self.panelVector.position['xCtrl'].SetValue("%5.3f" % x)
4453            self.panelVector.position['yCtrl'].SetValue("%5.3f" % y)
4454        # update vector maps
4455        if self.instruction.FindInstructionByType('vector'):
4456            vectors = sorted(
4457                self.instruction.FindInstructionByType('vector')['list'],
4458                key=lambda x: x[3])
4459            self.vectorListCtrl.DeleteAllItems()
4460            for vector in vectors:
4461                index = self.vectorListCtrl.InsertItem(
4462                    self.vectorListCtrl.GetItemCount(), vector[0].split('@')[0])
4463                self.vectorListCtrl.SetItem(index, 1, vector[4])
4464                self.vectorListCtrl.SetItemData(index, index)
4465                self.vectorListCtrl.CheckItem(index, True)
4466                if vector[3] == 0:
4467                    self.vectorListCtrl.CheckItem(index, False)
4468            self.panelVector.colsCtrl.SetRange(
4469                1, min(10, len(self.instruction.FindInstructionByType('vector')['list'])))
4470            self.panelVector.colsCtrl.SetValue(1)
4471        else:
4472            self.vectorListCtrl.DeleteAllItems()
4473            self.panelVector.colsCtrl.SetRange(0, 0)
4474            self.panelVector.colsCtrl.SetValue(0)
4475
4476
4477class MapinfoDialog(PsmapDialog):
4478
4479    def __init__(self, parent, id, settings, env):
4480        PsmapDialog.__init__(
4481            self,
4482            parent=parent,
4483            id=id,
4484            title=_("Mapinfo settings"),
4485            settings=settings,
4486            env=env)
4487
4488        self.objectType = ('mapinfo',)
4489        if self.id is not None:
4490            self.mapinfo = self.instruction[self.id]
4491            self.mapinfoDict = self.mapinfo.GetInstruction()
4492        else:
4493            self.id = NewId()
4494            self.mapinfo = Mapinfo(self.id, env=self.env)
4495            self.mapinfoDict = self.mapinfo.GetInstruction()
4496            page = self.instruction.FindInstructionByType(
4497                'page').GetInstruction()
4498            self.mapinfoDict['where'] = page['Left'], page['Top']
4499
4500        self.panel = self._mapinfoPanel()
4501
4502        self._layout(self.panel)
4503        self.OnIsBackground(None)
4504        self.OnIsBorder(None)
4505
4506    def _mapinfoPanel(self):
4507        panel = Panel(
4508            parent=self, id=wx.ID_ANY, size=(-1, -1),
4509            style=wx.TAB_TRAVERSAL)
4510        #panel.SetupScrolling(scroll_x = False, scroll_y = True)
4511        border = wx.BoxSizer(wx.VERTICAL)
4512
4513        # position
4514        box = StaticBox(
4515            parent=panel,
4516            id=wx.ID_ANY,
4517            label=" %s " %
4518            _("Position"))
4519        sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
4520        gridBagSizer = wx.GridBagSizer(hgap=5, vgap=5)
4521
4522        self.AddPosition(parent=panel, dialogDict=self.mapinfoDict)
4523        self.AddUnits(parent=panel, dialogDict=self.mapinfoDict)
4524        gridBagSizer.Add(panel.units['unitsLabel'], pos=(
4525            0, 0), flag=wx.ALIGN_CENTER_VERTICAL, border=0)
4526        gridBagSizer.Add(panel.units['unitsCtrl'], pos=(
4527            0, 1), flag=wx.ALIGN_CENTER_VERTICAL, border=0)
4528        gridBagSizer.Add(panel.position['xLabel'], pos=(
4529            1, 0), flag=wx.ALIGN_CENTER_VERTICAL, border=0)
4530        gridBagSizer.Add(panel.position['xCtrl'], pos=(
4531            1, 1), flag=wx.ALIGN_CENTER_VERTICAL, border=0)
4532        gridBagSizer.Add(panel.position['yLabel'], pos=(
4533            2, 0), flag=wx.ALIGN_CENTER_VERTICAL, border=0)
4534        gridBagSizer.Add(panel.position['yCtrl'], pos=(
4535            2, 1), flag=wx.ALIGN_CENTER_VERTICAL, border=0)
4536        gridBagSizer.Add(
4537            panel.position['comment'], pos=(
4538                3, 0), span=(
4539                1, 2), flag=wx.ALIGN_BOTTOM, border=0)
4540
4541        gridBagSizer.AddGrowableCol(1)
4542        sizer.Add(
4543            gridBagSizer,
4544            proportion=1,
4545            flag=wx.EXPAND | wx.ALL,
4546            border=5)
4547        border.Add(sizer, proportion=0, flag=wx.ALL | wx.EXPAND, border=5)
4548
4549        # font
4550        box = StaticBox(
4551            parent=panel,
4552            id=wx.ID_ANY,
4553            label=" %s " %
4554            _("Font settings"))
4555        sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
4556        gridBagSizer = wx.GridBagSizer(hgap=5, vgap=5)
4557
4558        # creates font color too, used below
4559        self.AddFont(parent=panel, dialogDict=self.mapinfoDict)
4560
4561        gridBagSizer.Add(panel.font['fontLabel'], pos=(
4562            0, 0), flag=wx.ALIGN_CENTER_VERTICAL, border=0)
4563        gridBagSizer.Add(
4564            panel.font['fontCtrl'],
4565            pos=(0, 1),
4566            flag=wx.ALIGN_CENTER_VERTICAL, border=0)
4567        gridBagSizer.Add(panel.font['fontSizeLabel'], pos=(
4568            1, 0), flag=wx.ALIGN_CENTER_VERTICAL, border=0)
4569        gridBagSizer.Add(panel.font['fontSizeCtrl'], pos=(
4570            1, 1), flag=wx.ALIGN_CENTER_VERTICAL, border=0)
4571        gridBagSizer.Add(panel.font['colorLabel'], pos=(
4572            2, 0), flag=wx.ALIGN_CENTER_VERTICAL, border=0)
4573        gridBagSizer.Add(panel.font['colorCtrl'], pos=(
4574            2, 1), flag=wx.ALIGN_CENTER_VERTICAL, border=0)
4575
4576        gridBagSizer.AddGrowableCol(1)
4577        sizer.Add(
4578            gridBagSizer,
4579            proportion=1,
4580            flag=wx.ALL | wx.EXPAND,
4581            border=1)
4582        border.Add(sizer, proportion=0, flag=wx.ALL | wx.EXPAND, border=5)
4583
4584        # colors
4585        box = StaticBox(
4586            parent=panel,
4587            id=wx.ID_ANY,
4588            label=" %s " %
4589            _("Color settings"))
4590        sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
4591        flexSizer = wx.FlexGridSizer(cols=2, hgap=5, vgap=5)
4592
4593        self.colors = {}
4594        self.colors['borderCtrl'] = CheckBox(
4595            panel, id=wx.ID_ANY, label=_("use border color:"))
4596        self.colors['backgroundCtrl'] = CheckBox(
4597            panel, id=wx.ID_ANY, label=_("use background color:"))
4598        self.colors['borderColor'] = ColourPickerCtrl(panel, id=wx.ID_ANY)
4599        self.colors['backgroundColor'] = ColourPickerCtrl(
4600            panel, id=wx.ID_ANY)
4601
4602        if self.mapinfoDict['border'] is None:
4603            self.mapinfoDict['border'] = 'none'
4604        if self.mapinfoDict['border'] != 'none':
4605            self.colors['borderCtrl'].SetValue(True)
4606            self.colors['borderColor'].SetColour(
4607                convertRGB(self.mapinfoDict['border']))
4608        else:
4609            self.colors['borderCtrl'].SetValue(False)
4610            self.colors['borderColor'].SetColour(convertRGB('black'))
4611
4612        if self.mapinfoDict['background'] is None:
4613            self.mapinfoDict['background'] == 'none'
4614        if self.mapinfoDict['background'] != 'none':
4615            self.colors['backgroundCtrl'].SetValue(True)
4616            self.colors['backgroundColor'].SetColour(
4617                convertRGB(self.mapinfoDict['background']))
4618        else:
4619            self.colors['backgroundCtrl'].SetValue(False)
4620            self.colors['backgroundColor'].SetColour(convertRGB('white'))
4621
4622        flexSizer.Add(
4623            self.colors['borderCtrl'],
4624            proportion=0,
4625            flag=wx.ALIGN_CENTER_VERTICAL,
4626            border=0)
4627        flexSizer.Add(
4628            self.colors['borderColor'],
4629            proportion=0,
4630            flag=wx.ALIGN_CENTER_VERTICAL,
4631            border=0)
4632        flexSizer.Add(
4633            self.colors['backgroundCtrl'],
4634            proportion=0,
4635            flag=wx.ALIGN_CENTER_VERTICAL,
4636            border=0)
4637        flexSizer.Add(
4638            self.colors['backgroundColor'],
4639            proportion=0,
4640            flag=wx.ALIGN_CENTER_VERTICAL,
4641            border=0)
4642        flexSizer.AddGrowableCol(1)
4643
4644        sizer.Add(
4645            flexSizer,
4646            proportion=1,
4647            flag=wx.ALL | wx.EXPAND,
4648            border=1)
4649        border.Add(sizer, proportion=0, flag=wx.ALL | wx.EXPAND, border=5)
4650
4651        panel.SetSizer(border)
4652
4653        self.Bind(wx.EVT_CHECKBOX, self.OnIsBorder, self.colors['borderCtrl'])
4654        self.Bind(
4655            wx.EVT_CHECKBOX,
4656            self.OnIsBackground,
4657            self.colors['backgroundCtrl'])
4658
4659        return panel
4660
4661    def OnIsBackground(self, event):
4662        if self.colors['backgroundCtrl'].GetValue():
4663            self.colors['backgroundColor'].Enable()
4664            self.update()
4665        else:
4666            self.colors['backgroundColor'].Disable()
4667
4668    def OnIsBorder(self, event):
4669        if self.colors['borderCtrl'].GetValue():
4670            self.colors['borderColor'].Enable()
4671            self.update()
4672        else:
4673            self.colors['borderColor'].Disable()
4674
4675    def update(self):
4676
4677        # units
4678        currUnit = self.unitConv.findUnit(
4679            self.panel.units['unitsCtrl'].GetStringSelection())
4680        self.mapinfoDict['unit'] = currUnit
4681
4682        # position
4683        if self.panel.position['xCtrl'].GetValue():
4684            x = self.panel.position['xCtrl'].GetValue()
4685        else:
4686            x = self.mapinfoDict['where'][0]
4687
4688        if self.panel.position['yCtrl'].GetValue():
4689            y = self.panel.position['yCtrl'].GetValue()
4690        else:
4691            y = self.mapinfoDict['where'][1]
4692
4693        x = self.unitConv.convert(
4694            value=float(
4695                self.panel.position['xCtrl'].GetValue()),
4696            fromUnit=currUnit,
4697            toUnit='inch')
4698        y = self.unitConv.convert(
4699            value=float(
4700                self.panel.position['yCtrl'].GetValue()),
4701            fromUnit=currUnit,
4702            toUnit='inch')
4703        self.mapinfoDict['where'] = (x, y)
4704
4705        # font
4706        self.mapinfoDict['font'] = self.panel.font[
4707            'fontCtrl'].GetStringSelection()
4708        self.mapinfoDict['fontsize'] = self.panel.font[
4709            'fontSizeCtrl'].GetValue()
4710
4711        # colors
4712        color = self.panel.font['colorCtrl'].GetColour()
4713        self.mapinfoDict['color'] = convertRGB(color)
4714
4715        if self.colors['backgroundCtrl'].GetValue():
4716            background = self.colors['backgroundColor'].GetColour()
4717            self.mapinfoDict['background'] = convertRGB(background)
4718        else:
4719            self.mapinfoDict['background'] = 'none'
4720
4721        if self.colors['borderCtrl'].GetValue():
4722            border = self.colors['borderColor'].GetColour()
4723            self.mapinfoDict['border'] = convertRGB(border)
4724        else:
4725            self.mapinfoDict['border'] = 'none'
4726
4727        # estimation of size
4728        self.mapinfoDict['rect'] = self.mapinfo.EstimateRect(self.mapinfoDict)
4729
4730        if self.id not in self.instruction:
4731            mapinfo = Mapinfo(self.id, env=self.env)
4732            self.instruction.AddInstruction(mapinfo)
4733
4734        self.instruction[self.id].SetInstruction(self.mapinfoDict)
4735
4736        if self.id not in self.parent.objectId:
4737            self.parent.objectId.append(self.id)
4738
4739        self.updateDialog()
4740
4741        return True
4742
4743    def updateDialog(self):
4744        """Update mapinfo coordinates, after moving"""
4745        x, y = self.mapinfoDict['where']
4746        currUnit = self.unitConv.findUnit(
4747            self.panel.units['unitsCtrl'].GetStringSelection())
4748        x = self.unitConv.convert(value=x, fromUnit='inch', toUnit=currUnit)
4749        y = self.unitConv.convert(value=y, fromUnit='inch', toUnit=currUnit)
4750        self.panel.position['xCtrl'].SetValue("%5.3f" % x)
4751        self.panel.position['yCtrl'].SetValue("%5.3f" % y)
4752
4753
4754class ScalebarDialog(PsmapDialog):
4755    """Dialog for scale bar"""
4756
4757    def __init__(self, parent, id, settings, env):
4758        PsmapDialog.__init__(
4759            self,
4760            parent=parent,
4761            id=id,
4762            title="Scale bar settings",
4763            settings=settings,
4764            env=env)
4765        self.objectType = ('scalebar',)
4766        if self.id is not None:
4767            self.scalebar = self.instruction[id]
4768            self.scalebarDict = self.scalebar.GetInstruction()
4769        else:
4770            self.id = NewId()
4771            self.scalebar = Scalebar(self.id, env=self.env)
4772            self.scalebarDict = self.scalebar.GetInstruction()
4773            page = self.instruction.FindInstructionByType(
4774                'page').GetInstruction()
4775            self.scalebarDict['where'] = page['Left'], page['Top']
4776
4777        self.panel = self._scalebarPanel()
4778
4779        self._layout(self.panel)
4780
4781        self.mapUnit = projInfo()['units'].lower()
4782        if projInfo()['proj'] == 'xy':
4783            self.mapUnit = 'meters'
4784        if self.mapUnit not in self.unitConv.getAllUnits():
4785            self.mapUnit = 'meters'
4786
4787    def _scalebarPanel(self):
4788        panel = Panel(parent=self, id=wx.ID_ANY, style=wx.TAB_TRAVERSAL)
4789        border = wx.BoxSizer(wx.VERTICAL)
4790        #
4791        # position
4792        #
4793        box = StaticBox(
4794            parent=panel,
4795            id=wx.ID_ANY,
4796            label=" %s " %
4797            _("Position"))
4798        sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
4799        gridBagSizer = wx.GridBagSizer(hgap=5, vgap=5)
4800
4801        self.AddUnits(parent=panel, dialogDict=self.scalebarDict)
4802        self.AddPosition(parent=panel, dialogDict=self.scalebarDict)
4803
4804        if self.scalebarDict[
4805                'rect']:  # set position, ref point is center and not left top corner
4806
4807            x = self.unitConv.convert(
4808                value=self.scalebarDict['where'][0] -
4809                self.scalebarDict['rect'].Get()[2] /
4810                2,
4811                fromUnit='inch',
4812                toUnit=self.scalebarDict['unit'])
4813            y = self.unitConv.convert(
4814                value=self.scalebarDict['where'][1] -
4815                self.scalebarDict['rect'].Get()[3] /
4816                2,
4817                fromUnit='inch',
4818                toUnit=self.scalebarDict['unit'])
4819            panel.position['xCtrl'].SetValue("%5.3f" % x)
4820            panel.position['yCtrl'].SetValue("%5.3f" % y)
4821
4822        gridBagSizer.Add(panel.units['unitsLabel'], pos=(
4823            0, 0), flag=wx.ALIGN_CENTER_VERTICAL, border=0)
4824        gridBagSizer.Add(panel.units['unitsCtrl'], pos=(
4825            0, 1), flag=wx.ALIGN_CENTER_VERTICAL, border=0)
4826        gridBagSizer.Add(panel.position['xLabel'], pos=(
4827            1, 0), flag=wx.ALIGN_CENTER_VERTICAL, border=0)
4828        gridBagSizer.Add(panel.position['xCtrl'], pos=(
4829            1, 1), flag=wx.ALIGN_CENTER_VERTICAL, border=0)
4830        gridBagSizer.Add(panel.position['yLabel'], pos=(
4831            2, 0), flag=wx.ALIGN_CENTER_VERTICAL, border=0)
4832        gridBagSizer.Add(panel.position['yCtrl'], pos=(
4833            2, 1), flag=wx.ALIGN_CENTER_VERTICAL, border=0)
4834        gridBagSizer.Add(
4835            panel.position['comment'], pos=(
4836                3, 0), span=(
4837                1, 2), flag=wx.ALIGN_BOTTOM, border=0)
4838
4839        gridBagSizer.AddGrowableCol(1)
4840        sizer.Add(
4841            gridBagSizer,
4842            proportion=1,
4843            flag=wx.EXPAND | wx.ALL,
4844            border=5)
4845        border.Add(sizer, proportion=0, flag=wx.ALL | wx.EXPAND, border=5)
4846        #
4847        # size
4848        #
4849        box = StaticBox(
4850            parent=panel,
4851            id=wx.ID_ANY,
4852            label=" %s " %
4853            _("Size"))
4854        sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
4855        gridBagSizer = wx.GridBagSizer(hgap=5, vgap=5)
4856
4857        lengthText = StaticText(panel, id=wx.ID_ANY, label=_("Length:"))
4858        heightText = StaticText(panel, id=wx.ID_ANY, label=_("Height:"))
4859
4860        self.lengthTextCtrl = TextCtrl(
4861            panel, id=wx.ID_ANY, validator=TCValidator('DIGIT_ONLY'))
4862        self.lengthTextCtrl.SetToolTip(
4863            _("Scalebar length is given in map units"))
4864
4865        self.heightTextCtrl = TextCtrl(
4866            panel, id=wx.ID_ANY, validator=TCValidator('DIGIT_ONLY'))
4867        self.heightTextCtrl.SetToolTip(
4868            _("Scalebar height is real height on paper"))
4869
4870        choices = [_('default')] + self.unitConv.getMapUnitsNames()
4871        self.unitsLength = Choice(panel, id=wx.ID_ANY, choices=choices)
4872        choices = self.unitConv.getPageUnitsNames()
4873        self.unitsHeight = Choice(panel, id=wx.ID_ANY, choices=choices)
4874
4875        # set values
4876        unitName = self.unitConv.findName(self.scalebarDict['unitsLength'])
4877        if unitName:
4878            self.unitsLength.SetStringSelection(unitName)
4879        else:
4880            if self.scalebarDict['unitsLength'] == 'auto':
4881                self.unitsLength.SetSelection(0)
4882            elif self.scalebarDict['unitsLength'] == 'nautmiles':
4883                self.unitsLength.SetStringSelection(
4884                    self.unitConv.findName("nautical miles"))
4885        self.unitsHeight.SetStringSelection(
4886            self.unitConv.findName(
4887                self.scalebarDict['unitsHeight']))
4888        if self.scalebarDict['length']:
4889            self.lengthTextCtrl.SetValue(str(self.scalebarDict['length']))
4890        else:  # estimate default
4891            reg = grass.region(env=self.env)
4892            w = int((reg['e'] - reg['w']) / 3)
4893            w = round(w, -len(str(w)) + 2)  # 12345 -> 12000
4894            self.lengthTextCtrl.SetValue(str(w))
4895
4896        h = self.unitConv.convert(
4897            value=self.scalebarDict['height'],
4898            fromUnit='inch',
4899            toUnit=self.scalebarDict['unitsHeight'])
4900        self.heightTextCtrl.SetValue(str(h))
4901
4902        gridBagSizer.Add(
4903            lengthText, pos=(0, 0),
4904            flag=wx.ALIGN_CENTER_VERTICAL, border=0)
4905        gridBagSizer.Add(
4906            self.lengthTextCtrl, pos=(0, 1),
4907            flag=wx.ALIGN_CENTER_VERTICAL, border=0)
4908        gridBagSizer.Add(
4909            self.unitsLength,
4910            pos=(
4911                0,
4912                2),
4913            flag=wx.ALIGN_CENTER_VERTICAL | wx.EXPAND,
4914            border=0)
4915        gridBagSizer.Add(
4916            heightText, pos=(1, 0),
4917            flag=wx.ALIGN_CENTER_VERTICAL, border=0)
4918        gridBagSizer.Add(
4919            self.heightTextCtrl, pos=(1, 1),
4920            flag=wx.ALIGN_CENTER_VERTICAL, border=0)
4921        gridBagSizer.Add(
4922            self.unitsHeight,
4923            pos=(
4924                1,
4925                2),
4926            flag=wx.ALIGN_CENTER_VERTICAL | wx.EXPAND,
4927            border=0)
4928
4929        gridBagSizer.AddGrowableCol(1)
4930        sizer.Add(
4931            gridBagSizer,
4932            proportion=1,
4933            flag=wx.EXPAND | wx.ALL,
4934            border=5)
4935        border.Add(sizer, proportion=0, flag=wx.ALL | wx.EXPAND, border=5)
4936        #
4937        # style
4938        #
4939        box = StaticBox(
4940            parent=panel,
4941            id=wx.ID_ANY,
4942            label=" %s " %
4943            _("Style"))
4944        sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
4945        gridBagSizer = wx.GridBagSizer(hgap=5, vgap=5)
4946
4947        sbTypeText = StaticText(panel, id=wx.ID_ANY, label=_("Type:"))
4948        self.sbCombo = BitmapComboBox(panel, style=wx.CB_READONLY)
4949        # only temporary, images must be moved away
4950        imagePath = os.path.join(
4951            globalvar.IMGDIR, "scalebar-fancy.png"), os.path.join(
4952            globalvar.IMGDIR, "scalebar-simple.png")
4953        for item, path in zip(['fancy', 'simple'], imagePath):
4954            if not os.path.exists(path):
4955                bitmap = EmptyBitmap(0, 0)
4956            else:
4957                bitmap = wx.Bitmap(path)
4958            self.sbCombo.Append(item='', bitmap=bitmap, clientData=item[0])
4959        #self.sbCombo.Append(item = 'simple', bitmap = wx.Bitmap("./images/scalebar-simple.png"), clientData = 's')
4960        if self.scalebarDict['scalebar'] == 'f':
4961            self.sbCombo.SetSelection(0)
4962        elif self.scalebarDict['scalebar'] == 's':
4963            self.sbCombo.SetSelection(1)
4964
4965        sbSegmentsText = StaticText(
4966            panel, id=wx.ID_ANY, label=_("Number of segments:"))
4967        self.sbSegmentsCtrl = SpinCtrl(
4968            panel, id=wx.ID_ANY, min=1, max=30, initial=4)
4969        self.sbSegmentsCtrl.SetValue(self.scalebarDict['segment'])
4970
4971        sbLabelsText1 = StaticText(
4972            panel, id=wx.ID_ANY, label=_("Label every "))
4973        sbLabelsText2 = StaticText(panel, id=wx.ID_ANY, label=_("segments"))
4974        self.sbLabelsCtrl = SpinCtrl(
4975            panel, id=wx.ID_ANY, min=1, max=30, initial=1)
4976        self.sbLabelsCtrl.SetValue(self.scalebarDict['numbers'])
4977
4978        # font
4979        fontsizeText = StaticText(
4980            panel, id=wx.ID_ANY, label=_("Font size:"))
4981        self.fontsizeCtrl = SpinCtrl(
4982            panel, id=wx.ID_ANY, min=4, max=30, initial=10)
4983        self.fontsizeCtrl.SetValue(self.scalebarDict['fontsize'])
4984
4985        self.backgroundCheck = CheckBox(
4986            panel, id=wx.ID_ANY, label=_("transparent text background"))
4987        if self.scalebarDict['background'] == 'y':
4988            self.backgroundCheck.SetValue(False)
4989        else:
4990            self.backgroundCheck.SetValue(True)
4991
4992        gridBagSizer.Add(
4993            sbTypeText, pos=(0, 0),
4994            flag=wx.ALIGN_CENTER_VERTICAL, border=0)
4995        gridBagSizer.Add(
4996            self.sbCombo, pos=(
4997                0, 1), span=(
4998                1, 2), flag=wx.ALIGN_CENTER_VERTICAL | wx.EXPAND, border=0)
4999        gridBagSizer.Add(
5000            sbSegmentsText, pos=(1, 0),
5001            flag=wx.ALIGN_CENTER_VERTICAL, border=0)
5002        gridBagSizer.Add(
5003            self.sbSegmentsCtrl, pos=(1, 1),
5004            flag=wx.ALIGN_CENTER_VERTICAL, border=0)
5005        gridBagSizer.Add(
5006            sbLabelsText1, pos=(2, 0),
5007            flag=wx.ALIGN_CENTER_VERTICAL, border=0)
5008        gridBagSizer.Add(
5009            self.sbLabelsCtrl, pos=(2, 1),
5010            flag=wx.ALIGN_CENTER_VERTICAL, border=0)
5011        gridBagSizer.Add(
5012            sbLabelsText2, pos=(2, 2),
5013            flag=wx.ALIGN_CENTER_VERTICAL, border=0)
5014        gridBagSizer.Add(
5015            fontsizeText, pos=(3, 0),
5016            flag=wx.ALIGN_CENTER_VERTICAL, border=0)
5017        gridBagSizer.Add(
5018            self.fontsizeCtrl, pos=(3, 1),
5019            flag=wx.ALIGN_CENTER_VERTICAL, border=0)
5020        gridBagSizer.Add(
5021            self.backgroundCheck, pos=(
5022                4, 0), span=(
5023                1, 3), flag=wx.ALIGN_CENTER_VERTICAL, border=0)
5024
5025        sizer.Add(
5026            gridBagSizer,
5027            proportion=1,
5028            border=5)
5029        border.Add(sizer, proportion=0, flag=wx.ALL | wx.EXPAND, border=5)
5030
5031        panel.SetSizer(border)
5032
5033        return panel
5034
5035    def update(self):
5036        """Save information from dialog"""
5037
5038        # units
5039        currUnit = self.unitConv.findUnit(
5040            self.panel.units['unitsCtrl'].GetStringSelection())
5041        self.scalebarDict['unit'] = currUnit
5042        # position
5043        if self.panel.position['xCtrl'].GetValue():
5044            x = self.panel.position['xCtrl'].GetValue()
5045        else:
5046            x = self.scalebarDict['where'][0]
5047
5048        if self.panel.position['yCtrl'].GetValue():
5049            y = self.panel.position['yCtrl'].GetValue()
5050        else:
5051            y = self.scalebarDict['where'][1]
5052
5053        x = self.unitConv.convert(
5054            value=float(
5055                self.panel.position['xCtrl'].GetValue()),
5056            fromUnit=currUnit,
5057            toUnit='inch')
5058        y = self.unitConv.convert(
5059            value=float(
5060                self.panel.position['yCtrl'].GetValue()),
5061            fromUnit=currUnit,
5062            toUnit='inch')
5063
5064        # style
5065        self.scalebarDict['scalebar'] = self.sbCombo.GetClientData(
5066            self.sbCombo.GetSelection())
5067        self.scalebarDict['segment'] = self.sbSegmentsCtrl.GetValue()
5068        self.scalebarDict['numbers'] = self.sbLabelsCtrl.GetValue()
5069        self.scalebarDict['fontsize'] = self.fontsizeCtrl.GetValue()
5070        if self.backgroundCheck.GetValue():
5071            self.scalebarDict['background'] = 'n'
5072        else:
5073            self.scalebarDict['background'] = 'y'
5074
5075        # size
5076
5077        # height
5078        self.scalebarDict['unitsHeight'] = self.unitConv.findUnit(
5079            self.unitsHeight.GetStringSelection())
5080        try:
5081            height = float(self.heightTextCtrl.GetValue())
5082            height = self.unitConv.convert(
5083                value=height,
5084                fromUnit=self.scalebarDict['unitsHeight'],
5085                toUnit='inch')
5086        except (ValueError, SyntaxError):
5087            height = 0.1  # default in inch
5088        self.scalebarDict['height'] = height
5089
5090        # length
5091        if self.unitsLength.GetSelection() == 0:
5092            selected = 'auto'
5093        else:
5094            selected = self.unitConv.findUnit(
5095                self.unitsLength.GetStringSelection())
5096            if selected == 'nautical miles':
5097                selected = 'nautmiles'
5098        self.scalebarDict['unitsLength'] = selected
5099        try:
5100            length = float(self.lengthTextCtrl.GetValue())
5101        except (ValueError, SyntaxError):
5102            wx.MessageBox(
5103                message=_("Length of scale bar is not defined"),
5104                caption=_('Invalid input'),
5105                style=wx.OK | wx.ICON_ERROR)
5106            return False
5107        self.scalebarDict['length'] = length
5108
5109        # estimation of size
5110        map = self.instruction.FindInstructionByType('map')
5111        if not map:
5112            map = self.instruction.FindInstructionByType('initMap')
5113        mapId = map.id
5114
5115        rectSize = self.scalebar.EstimateSize(
5116            scalebarDict=self.scalebarDict,
5117            scale=self.instruction[mapId]['scale'])
5118        self.scalebarDict['rect'] = Rect2D(
5119            x=x, y=y, width=rectSize[0], height=rectSize[1])
5120        self.scalebarDict['where'] = self.scalebarDict['rect'].GetCentre()
5121
5122        if self.id not in self.instruction:
5123            scalebar = Scalebar(self.id, env=self.env)
5124            self.instruction.AddInstruction(scalebar)
5125        self.instruction[self.id].SetInstruction(self.scalebarDict)
5126        if self.id not in self.parent.objectId:
5127            self.parent.objectId.append(self.id)
5128
5129        return True
5130
5131    def updateDialog(self):
5132        """Update scalebar coordinates, after moving"""
5133        x, y = self.scalebarDict['rect'][:2]
5134        currUnit = self.unitConv.findUnit(
5135            self.panel.units['unitsCtrl'].GetStringSelection())
5136        x = self.unitConv.convert(value=x, fromUnit='inch', toUnit=currUnit)
5137        y = self.unitConv.convert(value=y, fromUnit='inch', toUnit=currUnit)
5138        self.panel.position['xCtrl'].SetValue("%5.3f" % x)
5139        self.panel.position['yCtrl'].SetValue("%5.3f" % y)
5140
5141
5142class TextDialog(PsmapDialog):
5143
5144    def __init__(self, parent, id, settings, env):
5145        PsmapDialog.__init__(
5146            self,
5147            parent=parent,
5148            id=id,
5149            title="Text settings",
5150            settings=settings,
5151            env=env)
5152        self.objectType = ('text',)
5153        if self.id is not None:
5154            self.textDict = self.instruction[id].GetInstruction()
5155        else:
5156            self.id = NewId()
5157            text = Text(self.id, env=self.env)
5158            self.textDict = text.GetInstruction()
5159            page = self.instruction.FindInstructionByType(
5160                'page').GetInstruction()
5161            self.textDict['where'] = page['Left'], page['Top']
5162
5163        map = self.instruction.FindInstructionByType('map')
5164        if not map:
5165            map = self.instruction.FindInstructionByType('initMap')
5166        self.mapId = map.id
5167
5168        self.textDict['east'], self.textDict['north'] = PaperMapCoordinates(
5169            mapInstr=map, x=self.textDict['where'][0],
5170            y=self.textDict['where'][1],
5171            paperToMap=True,
5172            env=self.env)
5173
5174        notebook = Notebook(parent=self, id=wx.ID_ANY, style=wx.BK_DEFAULT)
5175        self.textPanel = self._textPanel(notebook)
5176        self.positionPanel = self._positionPanel(notebook)
5177        self.OnBackground(None)
5178        self.OnHighlight(None)
5179        self.OnBorder(None)
5180        self.OnPositionType(None)
5181        self.OnRotation(None)
5182
5183        self._layout(notebook)
5184
5185    def _textPanel(self, notebook):
5186        panel = Panel(parent=notebook, id=wx.ID_ANY, style=wx.TAB_TRAVERSAL)
5187        notebook.AddPage(page=panel, text=_("Text"))
5188
5189        border = wx.BoxSizer(wx.VERTICAL)
5190
5191        # text entry
5192        box = StaticBox(
5193            parent=panel,
5194            id=wx.ID_ANY,
5195            label=" %s " %
5196            _("Text"))
5197        sizer = wx.StaticBoxSizer(box, wx.HORIZONTAL)
5198
5199        textLabel = StaticText(panel, id=wx.ID_ANY, label=_("Enter text:"))
5200        self.textCtrl = ExpandoTextCtrl(
5201            panel, id=wx.ID_ANY, value=self.textDict['text'])
5202
5203        sizer.Add(
5204            textLabel,
5205            proportion=0,
5206            flag=wx.ALIGN_CENTER_VERTICAL | wx.ALL,
5207            border=5)
5208        sizer.Add(
5209            self.textCtrl,
5210            proportion=1,
5211            flag=wx.ALIGN_CENTER_VERTICAL | wx.ALL,
5212            border=5)
5213        border.Add(sizer, proportion=0, flag=wx.ALL | wx.EXPAND, border=5)
5214
5215        # font
5216        box = StaticBox(
5217            parent=panel,
5218            id=wx.ID_ANY,
5219            label=" %s " %
5220            _("Font settings"))
5221        sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
5222        flexGridSizer = wx.FlexGridSizer(rows=3, cols=2, hgap=5, vgap=5)
5223
5224        self.AddFont(parent=panel, dialogDict=self.textDict)
5225
5226        flexGridSizer.Add(
5227            panel.font['fontLabel'],
5228            proportion=0,
5229            flag=wx.ALIGN_CENTER_VERTICAL,
5230            border=0)
5231        flexGridSizer.Add(
5232            panel.font['fontCtrl'],
5233            proportion=0,
5234            flag=wx.ALIGN_CENTER_VERTICAL,
5235            border=0)
5236        flexGridSizer.Add(
5237            panel.font['fontSizeLabel'],
5238            proportion=0,
5239            flag=wx.ALIGN_CENTER_VERTICAL,
5240            border=0)
5241        flexGridSizer.Add(
5242            panel.font['fontSizeCtrl'],
5243            proportion=0,
5244            flag=wx.ALIGN_CENTER_VERTICAL,
5245            border=0)
5246        flexGridSizer.Add(
5247            panel.font['colorLabel'],
5248            proportion=0,
5249            flag=wx.ALIGN_CENTER_VERTICAL,
5250            border=0)
5251        flexGridSizer.Add(
5252            panel.font['colorCtrl'],
5253            proportion=0,
5254            flag=wx.ALIGN_CENTER_VERTICAL,
5255            border=0)
5256        flexGridSizer.AddGrowableCol(1)
5257
5258        sizer.Add(
5259            flexGridSizer,
5260            proportion=1,
5261            flag=wx.ALL | wx.EXPAND,
5262            border=1)
5263        border.Add(sizer, proportion=0, flag=wx.ALL | wx.EXPAND, border=5)
5264
5265        # text effects
5266        box = StaticBox(
5267            parent=panel,
5268            id=wx.ID_ANY,
5269            label=" %s " %
5270            _("Text effects"))
5271        sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
5272        gridBagSizer = wx.GridBagSizer(hgap=5, vgap=5)
5273
5274        self.effect = {}
5275        self.effect['backgroundCtrl'] = CheckBox(
5276            panel, id=wx.ID_ANY, label=_("text background"))
5277        self.effect['backgroundColor'] = ColourPickerCtrl(
5278            panel, id=wx.ID_ANY)
5279
5280        self.effect['highlightCtrl'] = CheckBox(
5281            panel, id=wx.ID_ANY, label=_("highlight"))
5282        self.effect['highlightColor'] = ColourPickerCtrl(
5283            panel, id=wx.ID_ANY)
5284        self.effect['highlightWidth'] = SpinCtrl(
5285            panel, id=wx.ID_ANY, size=self.spinCtrlSize, min=0, max=5, initial=1)
5286        self.effect['highlightWidthLabel'] = StaticText(
5287            panel, id=wx.ID_ANY, label=_("Width (pts):"))
5288
5289        self.effect['borderCtrl'] = CheckBox(
5290            panel, id=wx.ID_ANY, label=_("text border"))
5291        self.effect['borderColor'] = ColourPickerCtrl(panel, id=wx.ID_ANY)
5292        self.effect['borderWidth'] = SpinCtrl(
5293            panel, id=wx.ID_ANY, size=self.spinCtrlSize, min=1, max=25, initial=1)
5294        self.effect['borderWidthLabel'] = StaticText(
5295            panel, id=wx.ID_ANY, label=_("Width (pts):"))
5296
5297        # set values
5298        if self.textDict['background'] is None:
5299            self.textDict['background'] = 'none'
5300        if self.textDict['background'] != 'none':
5301            self.effect['backgroundCtrl'].SetValue(True)
5302            self.effect['backgroundColor'].SetColour(
5303                convertRGB(self.textDict['background']))
5304        else:
5305            self.effect['backgroundCtrl'].SetValue(False)
5306            self.effect['backgroundColor'].SetColour(convertRGB('white'))
5307
5308        if self.textDict['hcolor'] is None:
5309            self.textDict['hcolor'] = 'none'
5310        if self.textDict['hcolor'] != 'none':
5311            self.effect['highlightCtrl'].SetValue(True)
5312            self.effect['highlightColor'].SetColour(
5313                convertRGB(self.textDict['hcolor']))
5314        else:
5315            self.effect['highlightCtrl'].SetValue(False)
5316            self.effect['highlightColor'].SetColour(convertRGB('grey'))
5317
5318        self.effect['highlightWidth'].SetValue(float(self.textDict['hwidth']))
5319
5320        if self.textDict['border'] is None:
5321            self.textDict['border'] = 'none'
5322        if self.textDict['border'] != 'none':
5323            self.effect['borderCtrl'].SetValue(True)
5324            self.effect['borderColor'].SetColour(
5325                convertRGB(self.textDict['border']))
5326        else:
5327            self.effect['borderCtrl'].SetValue(False)
5328            self.effect['borderColor'].SetColour(convertRGB('black'))
5329
5330        self.effect['borderWidth'].SetValue(float(self.textDict['width']))
5331
5332        gridBagSizer.Add(self.effect['backgroundCtrl'], pos=(
5333            0, 0), flag=wx.ALIGN_CENTER_VERTICAL, border=0)
5334        gridBagSizer.Add(self.effect['backgroundColor'], pos=(
5335            0, 1), flag=wx.ALIGN_CENTER_VERTICAL, border=0)
5336        gridBagSizer.Add(self.effect['highlightCtrl'], pos=(
5337            1, 0), flag=wx.ALIGN_CENTER_VERTICAL, border=0)
5338        gridBagSizer.Add(self.effect['highlightColor'], pos=(
5339            1, 1), flag=wx.ALIGN_CENTER_VERTICAL, border=0)
5340        gridBagSizer.Add(
5341            self.effect['highlightWidthLabel'], pos=(
5342                1, 2), flag=wx.ALIGN_CENTER_VERTICAL, border=0)
5343        gridBagSizer.Add(self.effect['highlightWidth'], pos=(
5344            1, 3), flag=wx.ALIGN_CENTER_VERTICAL, border=0)
5345        gridBagSizer.Add(self.effect['borderCtrl'], pos=(
5346            2, 0), flag=wx.ALIGN_CENTER_VERTICAL, border=0)
5347        gridBagSizer.Add(self.effect['borderColor'], pos=(
5348            2, 1), flag=wx.ALIGN_CENTER_VERTICAL, border=0)
5349        gridBagSizer.Add(self.effect['borderWidthLabel'], pos=(
5350            2, 2), flag=wx.ALIGN_CENTER_VERTICAL, border=0)
5351        gridBagSizer.Add(self.effect['borderWidth'], pos=(
5352            2, 3), flag=wx.ALIGN_CENTER_VERTICAL, border=0)
5353
5354        sizer.Add(
5355            gridBagSizer,
5356            proportion=1,
5357            flag=wx.ALL | wx.EXPAND,
5358            border=1)
5359        border.Add(sizer, proportion=0, flag=wx.ALL | wx.EXPAND, border=5)
5360
5361        self.Bind(ExpandoTextCtrl.EVT_ETC_LAYOUT_NEEDED, self.OnRefit, self.textCtrl)
5362        self.Bind(
5363            wx.EVT_CHECKBOX,
5364            self.OnBackground,
5365            self.effect['backgroundCtrl'])
5366        self.Bind(
5367            wx.EVT_CHECKBOX,
5368            self.OnHighlight,
5369            self.effect['highlightCtrl'])
5370        self.Bind(wx.EVT_CHECKBOX, self.OnBorder, self.effect['borderCtrl'])
5371
5372        panel.SetSizer(border)
5373        panel.Fit()
5374
5375        return panel
5376
5377    def _positionPanel(self, notebook):
5378        panel = Panel(parent=notebook, id=wx.ID_ANY, style=wx.TAB_TRAVERSAL)
5379        notebook.AddPage(page=panel, text=_("Position"))
5380
5381        border = wx.BoxSizer(wx.VERTICAL)
5382
5383        box = StaticBox(
5384            parent=panel,
5385            id=wx.ID_ANY,
5386            label=" %s " %
5387            _("Position"))
5388        sizer = wx.StaticBoxSizer(box, wx.HORIZONTAL)
5389        gridBagSizer = wx.GridBagSizer(hgap=5, vgap=5)
5390
5391        # Position
5392        self.AddExtendedPosition(panel, gridBagSizer, self.textDict)
5393
5394        # offset
5395        box3 = StaticBox(
5396            parent=panel,
5397            id=wx.ID_ANY,
5398            label=" %s " %
5399            _("Offset"))
5400        sizerO = wx.StaticBoxSizer(box3, wx.VERTICAL)
5401        gridBagSizerO = wx.GridBagSizer(hgap=5, vgap=5)
5402        self.xoffLabel = StaticText(
5403            panel, id=wx.ID_ANY, label=_("horizontal (pts):"))
5404        self.yoffLabel = StaticText(
5405            panel, id=wx.ID_ANY, label=_("vertical (pts):"))
5406        self.xoffCtrl = SpinCtrl(
5407            panel, id=wx.ID_ANY, size=(50, -1),
5408            min=-50, max=50, initial=0)
5409        self.yoffCtrl = SpinCtrl(
5410            panel, id=wx.ID_ANY, size=(50, -1),
5411            min=-50, max=50, initial=0)
5412        self.xoffCtrl.SetValue(self.textDict['xoffset'])
5413        self.yoffCtrl.SetValue(self.textDict['yoffset'])
5414        gridBagSizerO.Add(
5415            self.xoffLabel, pos=(0, 0),
5416            flag=wx.ALIGN_CENTER_VERTICAL, border=0)
5417        gridBagSizerO.Add(
5418            self.yoffLabel, pos=(1, 0),
5419            flag=wx.ALIGN_CENTER_VERTICAL, border=0)
5420        gridBagSizerO.Add(
5421            self.xoffCtrl, pos=(0, 1),
5422            flag=wx.ALIGN_CENTER_VERTICAL, border=0)
5423        gridBagSizerO.Add(
5424            self.yoffCtrl, pos=(1, 1),
5425            flag=wx.ALIGN_CENTER_VERTICAL, border=0)
5426
5427        sizerO.Add(
5428            gridBagSizerO,
5429            proportion=1,
5430            flag=wx.EXPAND | wx.ALL,
5431            border=5)
5432        gridBagSizer.Add(
5433            sizerO,
5434            pos=(
5435                3,
5436                0),
5437            flag=wx.ALIGN_CENTER_HORIZONTAL | wx.EXPAND,
5438            border=0)
5439        # reference point
5440        box = StaticBox(
5441            parent=panel,
5442            id=wx.ID_ANY,
5443            label=" %s " %
5444            _(" Reference point"))
5445        sizerR = wx.StaticBoxSizer(box, wx.VERTICAL)
5446        flexSizer = wx.FlexGridSizer(rows=3, cols=3, hgap=5, vgap=5)
5447        ref = []
5448        for row in ["upper", "center", "lower"]:
5449            for col in ["left", "center", "right"]:
5450                ref.append(row + " " + col)
5451        self.radio = [
5452            RadioButton(
5453                panel,
5454                id=wx.ID_ANY,
5455                label='',
5456                style=wx.RB_GROUP,
5457                name=ref[0])]
5458        self.radio[0].SetValue(False)
5459        flexSizer.Add(
5460            self.radio[0],
5461            proportion=0,
5462            flag=wx.ALIGN_CENTER,
5463            border=0)
5464        for i in range(1, 9):
5465            self.radio.append(
5466                RadioButton(
5467                    panel,
5468                    id=wx.ID_ANY,
5469                    label='',
5470                    name=ref[i]))
5471            self.radio[-1].SetValue(False)
5472            flexSizer.Add(self.radio[-1], proportion=0,
5473                          flag=wx.ALIGN_CENTER, border=0)
5474        self.FindWindowByName(self.textDict['ref']).SetValue(True)
5475        flexSizer.AddGrowableCol(0)
5476        flexSizer.AddGrowableCol(1)
5477        flexSizer.AddGrowableCol(2)
5478
5479        sizerR.Add(flexSizer, proportion=1, flag=wx.EXPAND, border=0)
5480        gridBagSizer.Add(
5481            sizerR, pos=(3, 1),
5482            flag=wx.ALIGN_LEFT | wx.EXPAND, border=0)
5483        gridBagSizer.AddGrowableCol(0)
5484        gridBagSizer.AddGrowableCol(1)
5485
5486        sizer.Add(
5487            gridBagSizer,
5488            proportion=1,
5489            flag=wx.ALIGN_CENTER_VERTICAL | wx.ALL,
5490            border=5)
5491        border.Add(sizer, proportion=0, flag=wx.ALL | wx.EXPAND, border=5)
5492
5493        # rotation
5494        box = StaticBox(
5495            parent=panel,
5496            id=wx.ID_ANY,
5497            label=" %s " %
5498            _("Text rotation"))
5499        sizer = wx.StaticBoxSizer(box, wx.HORIZONTAL)
5500
5501        self.rotCtrl = CheckBox(
5502            panel,
5503            id=wx.ID_ANY,
5504            label=_("rotate text (counterclockwise)"))
5505        self.rotValue = SpinCtrl(
5506            panel, wx.ID_ANY, size=(50, -1),
5507            min=0, max=360, initial=0)
5508        if self.textDict['rotate']:
5509            self.rotValue.SetValue(int(self.textDict['rotate']))
5510            self.rotCtrl.SetValue(True)
5511        else:
5512            self.rotValue.SetValue(0)
5513            self.rotCtrl.SetValue(False)
5514        sizer.Add(
5515            self.rotCtrl,
5516            proportion=0,
5517            flag=wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_LEFT | wx.ALL,
5518            border=5)
5519        sizer.Add(
5520            self.rotValue,
5521            proportion=0,
5522            flag=wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_LEFT | wx.ALL,
5523            border=5)
5524
5525        border.Add(sizer, proportion=0, flag=wx.ALL | wx.EXPAND, border=5)
5526
5527        panel.SetSizer(border)
5528        panel.Fit()
5529
5530        self.Bind(
5531            wx.EVT_RADIOBUTTON,
5532            self.OnPositionType,
5533            panel.position['toPaper'])
5534        self.Bind(
5535            wx.EVT_RADIOBUTTON,
5536            self.OnPositionType,
5537            panel.position['toMap'])
5538        self.Bind(wx.EVT_CHECKBOX, self.OnRotation, self.rotCtrl)
5539
5540        return panel
5541
5542    def OnRefit(self, event):
5543        self.Fit()
5544
5545    def OnRotation(self, event):
5546        if self.rotCtrl.GetValue():
5547            self.rotValue.Enable()
5548        else:
5549            self.rotValue.Disable()
5550
5551    def OnPositionType(self, event):
5552        if self.positionPanel.position['toPaper'].GetValue():
5553            for widget in self.gridBagSizerP.GetChildren():
5554                widget.GetWindow().Enable()
5555            for widget in self.gridBagSizerM.GetChildren():
5556                widget.GetWindow().Disable()
5557        else:
5558            for widget in self.gridBagSizerM.GetChildren():
5559                widget.GetWindow().Enable()
5560            for widget in self.gridBagSizerP.GetChildren():
5561                widget.GetWindow().Disable()
5562
5563    def OnBackground(self, event):
5564        if self.effect['backgroundCtrl'].GetValue():
5565            self.effect['backgroundColor'].Enable()
5566            self.update()
5567        else:
5568            self.effect['backgroundColor'].Disable()
5569
5570    def OnHighlight(self, event):
5571        if self.effect['highlightCtrl'].GetValue():
5572            self.effect['highlightColor'].Enable()
5573            self.effect['highlightWidth'].Enable()
5574            self.effect['highlightWidthLabel'].Enable()
5575            self.update()
5576        else:
5577            self.effect['highlightColor'].Disable()
5578            self.effect['highlightWidth'].Disable()
5579            self.effect['highlightWidthLabel'].Disable()
5580
5581    def OnBorder(self, event):
5582        if self.effect['borderCtrl'].GetValue():
5583            self.effect['borderColor'].Enable()
5584            self.effect['borderWidth'].Enable()
5585            self.effect['borderWidthLabel'].Enable()
5586            self.update()
5587        else:
5588            self.effect['borderColor'].Disable()
5589            self.effect['borderWidth'].Disable()
5590            self.effect['borderWidthLabel'].Disable()
5591
5592    def update(self):
5593        # text
5594        self.textDict['text'] = self.textCtrl.GetValue()
5595        if not self.textDict['text']:
5596            wx.MessageBox(_("No text entered!"), _("Error"))
5597            return False
5598
5599        # font
5600        self.textDict['font'] = self.textPanel.font[
5601            'fontCtrl'].GetStringSelection()
5602        self.textDict['fontsize'] = self.textPanel.font[
5603            'fontSizeCtrl'].GetValue()
5604        color = self.textPanel.font['colorCtrl'].GetColour()
5605        self.textDict['color'] = convertRGB(color)
5606
5607        # effects
5608        if self.effect['backgroundCtrl'].GetValue():
5609            background = self.effect['backgroundColor'].GetColour()
5610            self.textDict['background'] = convertRGB(background)
5611        else:
5612            self.textDict['background'] = 'none'
5613
5614        if self.effect['borderCtrl'].GetValue():
5615            border = self.effect['borderColor'].GetColour()
5616            self.textDict['border'] = convertRGB(border)
5617        else:
5618            self.textDict['border'] = 'none'
5619
5620        self.textDict['width'] = self.effect['borderWidth'].GetValue()
5621
5622        if self.effect['highlightCtrl'].GetValue():
5623            highlight = self.effect['highlightColor'].GetColour()
5624            self.textDict['hcolor'] = convertRGB(highlight)
5625        else:
5626            self.textDict['hcolor'] = 'none'
5627
5628        self.textDict['hwidth'] = self.effect['highlightWidth'].GetValue()
5629
5630        # offset
5631        self.textDict['xoffset'] = self.xoffCtrl.GetValue()
5632        self.textDict['yoffset'] = self.yoffCtrl.GetValue()
5633
5634        # position
5635        if self.positionPanel.position['toPaper'].GetValue():
5636            self.textDict['XY'] = True
5637            currUnit = self.unitConv.findUnit(
5638                self.positionPanel.units['unitsCtrl'].GetStringSelection())
5639            self.textDict['unit'] = currUnit
5640            if self.positionPanel.position['xCtrl'].GetValue():
5641                x = self.positionPanel.position['xCtrl'].GetValue()
5642            else:
5643                x = self.textDict['where'][0]
5644
5645            if self.positionPanel.position['yCtrl'].GetValue():
5646                y = self.positionPanel.position['yCtrl'].GetValue()
5647            else:
5648                y = self.textDict['where'][1]
5649
5650            x = self.unitConv.convert(
5651                value=float(x), fromUnit=currUnit, toUnit='inch')
5652            y = self.unitConv.convert(
5653                value=float(y), fromUnit=currUnit, toUnit='inch')
5654            self.textDict['where'] = x, y
5655            self.textDict['east'], self.textDict['north'] = PaperMapCoordinates(
5656                self.instruction[self.mapId], x, y, paperToMap=True, env=self.env)
5657        else:
5658            self.textDict['XY'] = False
5659            if self.positionPanel.position['eCtrl'].GetValue():
5660                self.textDict['east'] = self.positionPanel.position[
5661                    'eCtrl'].GetValue()
5662            else:
5663                self.textDict['east'] = self.textDict['east']
5664
5665            if self.positionPanel.position['nCtrl'].GetValue():
5666                self.textDict['north'] = self.positionPanel.position[
5667                    'nCtrl'].GetValue()
5668            else:
5669                self.textDict['north'] = self.textDict['north']
5670
5671            self.textDict['where'] = PaperMapCoordinates(
5672                mapInstr=self.instruction[
5673                    self.mapId], x=float(
5674                    self.textDict['east']), y=float(
5675                    self.textDict['north']), paperToMap=False,
5676                    env=self.env)
5677        # rotation
5678        if self.rotCtrl.GetValue():
5679            self.textDict['rotate'] = self.rotValue.GetValue()
5680        else:
5681            self.textDict['rotate'] = None
5682        # reference point
5683        for radio in self.radio:
5684            if radio.GetValue() == True:
5685                self.textDict['ref'] = radio.GetName()
5686
5687        if self.id not in self.instruction:
5688            text = Text(self.id, env=self.env)
5689            self.instruction.AddInstruction(text)
5690        self.instruction[self.id].SetInstruction(self.textDict)
5691
5692        if self.id not in self.parent.objectId:
5693            self.parent.objectId.append(self.id)
5694
5695#        self.updateDialog()
5696
5697        return True
5698
5699    def updateDialog(self):
5700        """Update text coordinates, after moving"""
5701        # XY coordinates
5702        x, y = self.textDict['where'][:2]
5703        currUnit = self.unitConv.findUnit(
5704            self.positionPanel.units['unitsCtrl'].GetStringSelection())
5705        x = self.unitConv.convert(value=x, fromUnit='inch', toUnit=currUnit)
5706        y = self.unitConv.convert(value=y, fromUnit='inch', toUnit=currUnit)
5707        self.positionPanel.position['xCtrl'].SetValue("%5.3f" % x)
5708        self.positionPanel.position['yCtrl'].SetValue("%5.3f" % y)
5709        # EN coordinates
5710        e, n = self.textDict['east'], self.textDict['north']
5711        self.positionPanel.position['eCtrl'].SetValue(
5712            str(self.textDict['east']))
5713        self.positionPanel.position['nCtrl'].SetValue(
5714            str(self.textDict['north']))
5715
5716
5717class ImageDialog(PsmapDialog):
5718    """Dialog for setting image properties.
5719
5720    It's base dialog for North Arrow dialog.
5721    """
5722
5723    def __init__(self, parent, id, settings, env, imagePanelName=_("Image")):
5724        PsmapDialog.__init__(
5725            self,
5726            parent=parent,
5727            id=id,
5728            title="Image settings",
5729            settings=settings,
5730            env=env)
5731
5732        self.objectType = ('image',)
5733        if self.id is not None:
5734            self.imageObj = self.instruction[self.id]
5735            self.imageDict = self.instruction[id].GetInstruction()
5736        else:
5737            self.id = NewId()
5738            self.imageObj = self._newObject()
5739            self.imageDict = self.imageObj.GetInstruction()
5740            page = self.instruction.FindInstructionByType(
5741                'page').GetInstruction()
5742            self.imageDict['where'] = page['Left'], page['Top']
5743
5744        map = self.instruction.FindInstructionByType('map')
5745        if not map:
5746            map = self.instruction.FindInstructionByType('initMap')
5747        self.mapId = map.id
5748
5749        self.imageDict['east'], self.imageDict['north'] = PaperMapCoordinates(
5750            mapInstr=map, x=self.imageDict['where'][0],
5751            y=self.imageDict['where'][1],
5752            paperToMap=True, env=self.env)
5753
5754        notebook = Notebook(parent=self, id=wx.ID_ANY, style=wx.BK_DEFAULT)
5755        self.imagePanelName = imagePanelName
5756        self.imagePanel = self._imagePanel(notebook)
5757        self.positionPanel = self._positionPanel(notebook)
5758        self.OnPositionType(None)
5759
5760        if self.imageDict['epsfile']:
5761            self.imagePanel.image['dir'].SetValue(
5762                os.path.dirname(self.imageDict['epsfile']))
5763        else:
5764            self.imagePanel.image['dir'].SetValue(self._getImageDirectory())
5765        self.OnDirChanged(None)
5766
5767        self._layout(notebook)
5768
5769    def _newObject(self):
5770        """Create corresponding instruction object"""
5771        return Image(self.id, self.instruction, env=self.env)
5772
5773    def _imagePanel(self, notebook):
5774        panel = Panel(
5775            parent=notebook, id=wx.ID_ANY, size=(-1, -1),
5776            style=wx.TAB_TRAVERSAL)
5777        notebook.AddPage(page=panel, text=self.imagePanelName)
5778        border = wx.BoxSizer(wx.VERTICAL)
5779        #
5780        # choose image
5781        #
5782        box = StaticBox(
5783            parent=panel,
5784            id=wx.ID_ANY,
5785            label=" %s " %
5786            _("Image"))
5787        sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
5788
5789        # choose directory
5790        panel.image = {}
5791        if self.imageDict['epsfile']:
5792            startDir = os.path.dirname(self.imageDict['epsfile'])
5793        else:
5794            startDir = self._getImageDirectory()
5795        dir = DirBrowseButton(
5796            parent=panel,
5797            id=wx.ID_ANY,
5798            labelText=_("Choose a directory:"),
5799            dialogTitle=_("Choose a directory with images"),
5800            buttonText=_('Browse'),
5801            startDirectory=startDir,
5802            changeCallback=self.OnDirChanged)
5803        panel.image['dir'] = dir
5804
5805        sizer.Add(dir, proportion=0, flag=wx.EXPAND, border=0)
5806
5807        # image list
5808        hSizer = wx.BoxSizer(wx.HORIZONTAL)
5809
5810        imageList = ListBox(parent=panel, id=wx.ID_ANY)
5811        panel.image['list'] = imageList
5812        imageList.Bind(wx.EVT_LISTBOX, self.OnImageSelectionChanged)
5813
5814        hSizer.Add(
5815            imageList,
5816            proportion=1,
5817            flag=wx.EXPAND | wx.RIGHT,
5818            border=10)
5819
5820        # image preview
5821        vSizer = wx.BoxSizer(wx.VERTICAL)
5822        self.previewSize = (150, 150)
5823        img = EmptyImage(*self.previewSize)
5824        panel.image['preview'] = wx.StaticBitmap(
5825            panel, wx.ID_ANY, BitmapFromImage(img))
5826        vSizer.Add(
5827            panel.image['preview'],
5828            proportion=0,
5829            flag=wx.EXPAND | wx.BOTTOM,
5830            border=5)
5831        panel.image['sizeInfo'] = StaticText(parent=panel, id=wx.ID_ANY)
5832        vSizer.Add(
5833            panel.image['sizeInfo'],
5834            proportion=0,
5835            flag=wx.ALIGN_CENTER,
5836            border=0)
5837
5838        hSizer.Add(vSizer, proportion=0, flag=wx.EXPAND, border=0)
5839        sizer.Add(hSizer, proportion=1, flag=wx.EXPAND | wx.ALL, border=3)
5840
5841        epsInfo = StaticText(parent=panel, id=wx.ID_ANY,
5842                                label=_("Note: only EPS format supported"))
5843        sizer.Add(
5844            epsInfo,
5845            proportion=0,
5846            flag=wx.ALL,
5847            border=3)
5848
5849        border.Add(sizer, proportion=0, flag=wx.ALL | wx.EXPAND, border=5)
5850
5851        #
5852        # rotation
5853        #
5854        box = StaticBox(
5855            parent=panel,
5856            id=wx.ID_ANY,
5857            label=" %s " %
5858            _("Scale And Rotation"))
5859        sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
5860
5861        gridSizer = wx.GridBagSizer(hgap=5, vgap=5)
5862
5863        scaleLabel = StaticText(
5864            parent=panel, id=wx.ID_ANY, label=_("Scale:"))
5865
5866        panel.image['scale'] = FloatSpin(
5867            panel, id=wx.ID_ANY, min_val=0, max_val=50, increment=0.5,
5868            value=1, style=fs.FS_RIGHT)
5869        panel.image['scale'].SetFormat("%f")
5870        panel.image['scale'].SetDigits(1)
5871
5872        if self.imageDict['scale']:
5873            value = float(self.imageDict['scale'])
5874        else:
5875            value = 0
5876
5877        panel.image['scale'].SetValue(value)
5878
5879        gridSizer.Add(
5880            scaleLabel, pos=(0, 0),
5881            flag=wx.ALIGN_CENTER_VERTICAL)
5882        gridSizer.Add(
5883            panel.image['scale'],
5884            pos=(0, 1),
5885            flag=wx.ALIGN_CENTER_VERTICAL)
5886
5887        rotLabel = StaticText(
5888            parent=panel,
5889            id=wx.ID_ANY,
5890            label=_("Rotation angle (deg):"))
5891        panel.image['rotate'] = FloatSpin(
5892            panel, id=wx.ID_ANY, min_val=0, max_val=360, increment=0.5,
5893            value=0, style=fs.FS_RIGHT)
5894        panel.image['rotate'].SetFormat("%f")
5895        panel.image['rotate'].SetDigits(1)
5896
5897        panel.image['rotate'].SetToolTip(
5898            _("Counterclockwise rotation in degrees"))
5899        if self.imageDict['rotate']:
5900            panel.image['rotate'].SetValue(int(self.imageDict['rotate']))
5901        else:
5902            panel.image['rotate'].SetValue(0)
5903
5904        gridSizer.Add(
5905            rotLabel,
5906            pos=(
5907                1,
5908                0),
5909            flag=wx.ALIGN_CENTER_VERTICAL,
5910            border=0)
5911        gridSizer.Add(
5912            panel.image['rotate'], pos=(
5913                1, 1), flag=wx.ALIGN_CENTER_VERTICAL)
5914
5915        self._addConvergence(panel=panel, gridBagSizer=gridSizer)
5916        sizer.Add(
5917            gridSizer,
5918            proportion=0,
5919            flag=wx.EXPAND | wx.ALL,
5920            border=5)
5921        border.Add(sizer, proportion=0, flag=wx.ALL | wx.EXPAND, border=5)
5922
5923        panel.SetSizer(border)
5924        panel.Fit()
5925
5926        return panel
5927
5928    def _positionPanel(self, notebook):
5929        panel = Panel(
5930            parent=notebook, id=wx.ID_ANY, size=(-1, -1),
5931            style=wx.TAB_TRAVERSAL)
5932        notebook.AddPage(page=panel, text=_("Position"))
5933        border = wx.BoxSizer(wx.VERTICAL)
5934        #
5935        # set position
5936        #
5937        box = StaticBox(
5938            parent=panel,
5939            id=wx.ID_ANY,
5940            label=" %s " %
5941            _("Position"))
5942        sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
5943
5944        gridBagSizer = wx.GridBagSizer(hgap=5, vgap=5)
5945
5946        self.AddExtendedPosition(panel, gridBagSizer, self.imageDict)
5947
5948        self.Bind(
5949            wx.EVT_RADIOBUTTON,
5950            self.OnPositionType,
5951            panel.position['toPaper'])
5952        self.Bind(
5953            wx.EVT_RADIOBUTTON,
5954            self.OnPositionType,
5955            panel.position['toMap'])
5956
5957        gridBagSizer.AddGrowableCol(0)
5958        gridBagSizer.AddGrowableCol(1)
5959        sizer.Add(
5960            gridBagSizer,
5961            proportion=1,
5962            flag=wx.ALL,
5963            border=5)
5964        border.Add(sizer, proportion=0, flag=wx.ALL | wx.EXPAND, border=5)
5965
5966        panel.SetSizer(border)
5967        panel.Fit()
5968
5969        return panel
5970
5971    def OnDirChanged(self, event):
5972        """Image directory changed"""
5973        path = self.imagePanel.image['dir'].GetValue()
5974        try:
5975            files = os.listdir(path)
5976        except OSError:  # no such directory
5977            files = []
5978        imageList = []
5979
5980        # no setter for startDirectory?
5981        try:
5982            self.imagePanel.image['dir'].startDirectory = path
5983        except AttributeError:  # for sure
5984            pass
5985        for file in files:
5986            if os.path.splitext(file)[1].lower() == '.eps':
5987                imageList.append(file)
5988
5989        imageList.sort()
5990        self.imagePanel.image['list'].SetItems(imageList)
5991        if self.imageDict['epsfile']:
5992            file = os.path.basename(self.imageDict['epsfile'])
5993            self.imagePanel.image['list'].SetStringSelection(file)
5994        elif imageList:
5995            self.imagePanel.image['list'].SetSelection(0)
5996        self.OnImageSelectionChanged(None)
5997
5998    def OnPositionType(self, event):
5999        if self.positionPanel.position['toPaper'].GetValue():
6000            for widget in self.gridBagSizerP.GetChildren():
6001                widget.GetWindow().Enable()
6002            for widget in self.gridBagSizerM.GetChildren():
6003                widget.GetWindow().Disable()
6004        else:
6005            for widget in self.gridBagSizerM.GetChildren():
6006                widget.GetWindow().Enable()
6007            for widget in self.gridBagSizerP.GetChildren():
6008                widget.GetWindow().Disable()
6009
6010    def _getImageDirectory(self):
6011        """Default image directory"""
6012        return os.getcwd()
6013
6014    def _addConvergence(self, panel, gridBagSizer):
6015        pass
6016
6017    def OnImageSelectionChanged(self, event):
6018        """Image selected, show preview and size"""
6019        if not self.imagePanel.image[
6020                'dir']:  # event is emitted when closing dialog an it causes error
6021            return
6022
6023        if not havePILImage:
6024            self.DrawWarningText(_("PIL\nmissing"))
6025            return
6026
6027        imageName = self.imagePanel.image['list'].GetStringSelection()
6028        if not imageName:
6029            self.ClearPreview()
6030            return
6031        basePath = self.imagePanel.image['dir'].GetValue()
6032        file = os.path.join(basePath, imageName)
6033        if not os.path.exists(file):
6034            return
6035
6036        if os.path.splitext(file)[1].lower() == '.eps':
6037            try:
6038                pImg = PILImage.open(file)
6039                if sys.platform == 'win32':
6040                    import types
6041                    pImg.load = types.MethodType(loadPSForWindows, pImg)
6042                img = PilImageToWxImage(pImg)
6043            except IOError as e:
6044                GError(message=_("Unable to read file %s") % file)
6045                self.ClearPreview()
6046                return
6047            self.SetSizeInfoLabel(img)
6048            img = self.ScaleToPreview(img)
6049            bitmap = img.ConvertToBitmap()
6050            self.DrawBitmap(bitmap)
6051
6052        else:
6053            # TODO: read other formats and convert by PIL to eps
6054            pass
6055
6056    def ScaleToPreview(self, img):
6057        """Scale image to preview size"""
6058        w = img.GetWidth()
6059        h = img.GetHeight()
6060        if w <= self.previewSize[0] and h <= self.previewSize[1]:
6061            return img
6062        if w > h:
6063            newW = self.previewSize[0]
6064            newH = self.previewSize[0] * h / w
6065        else:
6066            newH = self.previewSize[0]
6067            newW = self.previewSize[0] * w / h
6068        return img.Scale(newW, newH, wx.IMAGE_QUALITY_HIGH)
6069
6070    def DrawWarningText(self, warning):
6071        """Draw text on preview window"""
6072        buffer = EmptyBitmap(*self.previewSize)
6073        dc = wx.MemoryDC()
6074        dc.SelectObject(buffer)
6075        dc.SetBrush(wx.Brush(wx.Colour(250, 250, 250)))
6076        dc.Clear()
6077        extent = dc.GetTextExtent(warning)
6078        posX = self.previewSize[0] / 2 - extent[0] / 2
6079        posY = self.previewSize[1] / 2 - extent[1] / 2
6080        dc.DrawText(warning, posX, posY)
6081        self.imagePanel.image['preview'].SetBitmap(buffer)
6082        dc.SelectObject(wx.NullBitmap)
6083
6084    def DrawBitmap(self, bitmap):
6085        """Draw bitmap, center it if smaller than preview size"""
6086        if bitmap.GetWidth() <= self.previewSize[
6087                0] and bitmap.GetHeight() <= self.previewSize[1]:
6088            buffer = EmptyBitmap(*self.previewSize)
6089            dc = wx.MemoryDC()
6090            dc.SelectObject(buffer)
6091            dc.SetBrush(dc.GetBrush())
6092            dc.Clear()
6093            posX = self.previewSize[0] / 2 - bitmap.GetWidth() / 2
6094            posY = self.previewSize[1] / 2 - bitmap.GetHeight() / 2
6095            dc.DrawBitmap(bitmap, posX, posY)
6096            self.imagePanel.image['preview'].SetBitmap(buffer)
6097            dc.SelectObject(wx.NullBitmap)
6098        else:
6099            self.imagePanel.image['preview'].SetBitmap(bitmap)
6100        self.imagePanel.Refresh()
6101
6102    def SetSizeInfoLabel(self, image):
6103        """Update image size label"""
6104        self.imagePanel.image['sizeInfo'].SetLabel(
6105            _("size: %(width)s x %(height)s pts") %
6106            {'width': image.GetWidth(),
6107             'height': image.GetHeight()})
6108        self.imagePanel.image['sizeInfo'].GetContainingSizer().Layout()
6109
6110    def ClearPreview(self):
6111        """Clear preview window"""
6112        buffer = EmptyBitmap(*self.previewSize)
6113        dc = wx.MemoryDC()
6114        dc.SelectObject(buffer)
6115        dc.SetBrush(wx.WHITE_BRUSH)
6116        dc.Clear()
6117        dc.SelectObject(wx.NullBitmap)
6118        mask = wx.Mask(buffer, wx.WHITE)
6119        buffer.SetMask(mask)
6120        self.imagePanel.image['preview'].SetBitmap(buffer)
6121
6122    def update(self):
6123        # epsfile
6124        selected = self.imagePanel.image['list'].GetStringSelection()
6125        basePath = self.imagePanel.image['dir'].GetValue()
6126        if not selected:
6127            GMessage(parent=self, message=_("No image selected."))
6128            return False
6129
6130        self.imageDict['epsfile'] = os.path.join(basePath, selected)
6131
6132        # position
6133        if self.positionPanel.position['toPaper'].GetValue():
6134            self.imageDict['XY'] = True
6135            currUnit = self.unitConv.findUnit(
6136                self.positionPanel.units['unitsCtrl'].GetStringSelection())
6137            self.imageDict['unit'] = currUnit
6138            if self.positionPanel.position['xCtrl'].GetValue():
6139                x = self.positionPanel.position['xCtrl'].GetValue()
6140            else:
6141                x = self.imageDict['where'][0]
6142
6143            if self.positionPanel.position['yCtrl'].GetValue():
6144                y = self.positionPanel.position['yCtrl'].GetValue()
6145            else:
6146                y = self.imageDict['where'][1]
6147
6148            x = self.unitConv.convert(
6149                value=float(x), fromUnit=currUnit, toUnit='inch')
6150            y = self.unitConv.convert(
6151                value=float(y), fromUnit=currUnit, toUnit='inch')
6152            self.imageDict['where'] = x, y
6153
6154        else:
6155            self.imageDict['XY'] = False
6156            if self.positionPanel.position['eCtrl'].GetValue():
6157                e = self.positionPanel.position['eCtrl'].GetValue()
6158            else:
6159                self.imageDict['east'] = self.imageDict['east']
6160
6161            if self.positionPanel.position['nCtrl'].GetValue():
6162                n = self.positionPanel.position['nCtrl'].GetValue()
6163            else:
6164                self.imageDict['north'] = self.imageDict['north']
6165
6166            x, y = PaperMapCoordinates(
6167                mapInstr=self.instruction[
6168                    self.mapId], x=float(
6169                    self.imageDict['east']), y=float(
6170                    self.imageDict['north']), paperToMap=False,
6171                    env=self.env)
6172
6173        # rotation
6174        rot = self.imagePanel.image['rotate'].GetValue()
6175        if rot == 0:
6176            self.imageDict['rotate'] = None
6177        else:
6178            self.imageDict['rotate'] = rot
6179
6180        # scale
6181        self.imageDict['scale'] = self.imagePanel.image['scale'].GetValue()
6182
6183        # scale
6184        w, h = self.imageObj.GetImageOrigSize(self.imageDict['epsfile'])
6185        if self.imageDict['rotate']:
6186            self.imageDict['size'] = BBoxAfterRotation(
6187                w, h, self.imageDict['rotate'])
6188        else:
6189            self.imageDict['size'] = w, h
6190
6191        w = self.unitConv.convert(value=self.imageDict['size'][0],
6192                                  fromUnit='point', toUnit='inch')
6193        h = self.unitConv.convert(value=self.imageDict['size'][1],
6194                                  fromUnit='point', toUnit='inch')
6195
6196        self.imageDict['rect'] = Rect2D(x=x, y=y,
6197                                        width=w * self.imageDict['scale'],
6198                                        height=h * self.imageDict['scale'])
6199
6200        if self.id not in self.instruction:
6201            image = self._newObject()
6202            self.instruction.AddInstruction(image)
6203        self.instruction[self.id].SetInstruction(self.imageDict)
6204
6205        if self.id not in self.parent.objectId:
6206            self.parent.objectId.append(self.id)
6207
6208        return True
6209
6210    def updateDialog(self):
6211        """Update text coordinates, after moving"""
6212        # XY coordinates
6213        x, y = self.imageDict['where'][:2]
6214        currUnit = self.unitConv.findUnit(
6215            self.positionPanel.units['unitsCtrl'].GetStringSelection())
6216        x = self.unitConv.convert(value=x, fromUnit='inch', toUnit=currUnit)
6217        y = self.unitConv.convert(value=y, fromUnit='inch', toUnit=currUnit)
6218        self.positionPanel.position['xCtrl'].SetValue("%5.3f" % x)
6219        self.positionPanel.position['yCtrl'].SetValue("%5.3f" % y)
6220        # EN coordinates
6221        e, n = self.imageDict['east'], self.imageDict['north']
6222        self.positionPanel.position['eCtrl'].SetValue(
6223            str(self.imageDict['east']))
6224        self.positionPanel.position['nCtrl'].SetValue(
6225            str(self.imageDict['north']))
6226
6227
6228class NorthArrowDialog(ImageDialog):
6229
6230    def __init__(self, parent, id, settings, env):
6231        ImageDialog.__init__(self, parent=parent, id=id, settings=settings,
6232                             imagePanelName=_("North Arrow"), env=env)
6233
6234        self.objectType = ('northArrow',)
6235        self.SetTitle(_("North Arrow settings"))
6236
6237    def _newObject(self):
6238        return NorthArrow(self.id, self.instruction, env=self.env)
6239
6240    def _getImageDirectory(self):
6241        gisbase = os.getenv("GISBASE")
6242        return os.path.join(gisbase, 'etc', 'paint', 'decorations')
6243
6244    def _addConvergence(self, panel, gridBagSizer):
6245        convergence = Button(parent=panel, id=wx.ID_ANY,
6246                             label=_("Compute convergence"))
6247        gridBagSizer.Add(convergence, pos=(1, 2),
6248                         flag=wx.ALIGN_CENTER_VERTICAL | wx.EXPAND)
6249        convergence.Bind(wx.EVT_BUTTON, self.OnConvergence)
6250        panel.image['convergence'] = convergence
6251
6252    def OnConvergence(self, event):
6253        ret = RunCommand('g.region', read=True, flags='nug', env=self.env)
6254        if ret:
6255            convergence = float(ret.strip().split('=')[1])
6256            if convergence < 0:
6257                self.imagePanel.image['rotate'].SetValue(abs(convergence))
6258            else:
6259                self.imagePanel.image['rotate'].SetValue(360 - convergence)
6260
6261
6262class PointDialog(PsmapDialog):
6263    """Dialog for setting point properties."""
6264
6265    def __init__(
6266            self, parent, id, settings, env, coordinates=None,
6267            pointPanelName=_("Point")):
6268        PsmapDialog.__init__(
6269            self,
6270            parent=parent,
6271            id=id,
6272            title="Point settings",
6273            settings=settings,
6274            env=env)
6275
6276        self.objectType = ('point',)
6277        if self.id is not None:
6278            self.pointObj = self.instruction[self.id]
6279            self.pointDict = self.instruction[id].GetInstruction()
6280        else:
6281            self.id = NewId()
6282            self.pointObj = Point(self.id, env=self.env)
6283            self.pointDict = self.pointObj.GetInstruction()
6284            self.pointDict['where'] = coordinates
6285        self.defaultDict = self.pointObj.defaultInstruction
6286
6287        mapObj = self.instruction.FindInstructionByType('map')
6288        if not mapObj:
6289            mapObj = self.instruction.FindInstructionByType('initMap')
6290        self.mapId = mapObj.id
6291
6292        self.pointDict['east'], self.pointDict['north'] = PaperMapCoordinates(
6293            mapInstr=mapObj, x=self.pointDict['where'][0],
6294            y=self.pointDict['where'][1],
6295            paperToMap=True,
6296            env=self.env)
6297
6298        notebook = Notebook(parent=self, id=wx.ID_ANY, style=wx.BK_DEFAULT)
6299        self.pointPanelName = pointPanelName
6300        self.pointPanel = self._pointPanel(notebook)
6301        self.positionPanel = self._positionPanel(notebook)
6302        self.OnPositionType(None)
6303
6304        self._layout(notebook)
6305
6306    def _pointPanel(self, notebook):
6307        panel = Panel(
6308            parent=notebook, id=wx.ID_ANY, size=(-1, -1),
6309            style=wx.TAB_TRAVERSAL)
6310        notebook.AddPage(page=panel, text=self.pointPanelName)
6311        border = wx.BoxSizer(wx.VERTICAL)
6312        #
6313        # choose image
6314        #
6315        box = StaticBox(
6316            parent=panel,
6317            id=wx.ID_ANY,
6318            label=" %s " %
6319            _("Symbol"))
6320        sizer = wx.StaticBoxSizer(box, wx.HORIZONTAL)
6321
6322        gridSizer = wx.GridBagSizer(hgap=5, vgap=5)
6323
6324        gridSizer.Add(
6325            StaticText(
6326                parent=panel, id=wx.ID_ANY, label=_("Select symbol:")), pos=(
6327                0, 0), flag=wx.ALIGN_CENTER_VERTICAL)
6328
6329        self.symbolLabel = StaticText(parent=panel, id=wx.ID_ANY,
6330                                      label=self.pointDict['symbol'])
6331        gridSizer.Add(self.symbolLabel, pos=(0, 1),
6332                      flag=wx.ALIGN_CENTER_VERTICAL)
6333        bitmap = wx.Bitmap(os.path.join(globalvar.SYMBDIR,
6334                           self.pointDict['symbol']) + '.png')
6335        self.symbolButton = BitmapButton(panel, id=wx.ID_ANY, bitmap=bitmap)
6336        self.symbolButton.Bind(wx.EVT_BUTTON, self.OnSymbolSelection)
6337
6338        gridSizer.Add(
6339            self.symbolButton, pos=(0, 2),
6340            flag=wx.ALIGN_CENTER_VERTICAL)
6341        self.noteLabel = StaticText(
6342            parent=panel, id=wx.ID_ANY, label=_(
6343                "Note: Selected symbol is not displayed\n"
6344                "in draft mode (only in preview mode)"))
6345        gridSizer.Add(
6346            self.noteLabel, pos=(
6347                1, 0), span=(
6348                1, 2), flag=wx.ALIGN_CENTER_VERTICAL)
6349
6350        gridSizer.AddGrowableCol(1)
6351        sizer.Add(
6352            gridSizer,
6353            proportion=1,
6354            flag=wx.EXPAND | wx.ALL,
6355            border=5)
6356
6357        border.Add(sizer, proportion=0, flag=wx.ALL | wx.EXPAND, border=5)
6358
6359        #
6360        # outline/fill color
6361        #
6362
6363        # outline
6364        box = StaticBox(
6365            parent=panel,
6366            id=wx.ID_ANY,
6367            label=" %s " %
6368            _("Color"))
6369        sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
6370
6371        gridSizer = wx.GridBagSizer(hgap=5, vgap=5)
6372
6373        outlineLabel = StaticText(
6374            parent=panel,
6375            id=wx.ID_ANY,
6376            label=_("Outline color:"))
6377        self.outlineColorCtrl = ColourPickerCtrl(panel, id=wx.ID_ANY)
6378        self.outlineTranspCtrl = CheckBox(
6379            panel, id=wx.ID_ANY, label=_("transparent"))
6380
6381        if self.pointDict['color'] != 'none':
6382            self.outlineTranspCtrl.SetValue(False)
6383            self.outlineColorCtrl.SetColour(
6384                convertRGB(self.pointDict['color']))
6385        else:
6386            self.outlineTranspCtrl.SetValue(True)
6387            self.outlineColorCtrl.SetColour(
6388                convertRGB(self.defaultDict['color']))
6389
6390        gridSizer.Add(
6391            outlineLabel, pos=(0, 0),
6392            flag=wx.ALIGN_CENTER_VERTICAL)
6393        gridSizer.Add(
6394            self.outlineColorCtrl, pos=(
6395                0, 1), flag=wx.ALIGN_CENTER_VERTICAL)
6396        gridSizer.Add(
6397            self.outlineTranspCtrl, pos=(
6398                0, 2), flag=wx.ALIGN_CENTER_VERTICAL)
6399
6400        fillLabel = StaticText(
6401            parent=panel,
6402            id=wx.ID_ANY,
6403            label=_("Fill color:"))
6404        self.fillColorCtrl = ColourPickerCtrl(panel, id=wx.ID_ANY)
6405        self.fillTranspCtrl = CheckBox(
6406            panel, id=wx.ID_ANY, label=_("transparent"))
6407
6408        if self.pointDict['fcolor'] != 'none':
6409            self.fillTranspCtrl.SetValue(False)
6410            self.fillColorCtrl.SetColour(convertRGB(self.pointDict['fcolor']))
6411        else:
6412            self.fillTranspCtrl.SetValue(True)
6413            self.fillColorCtrl.SetColour(
6414                convertRGB(self.defaultDict['fcolor']))
6415
6416        gridSizer.Add(
6417            fillLabel, pos=(1, 0),
6418            flag=wx.ALIGN_CENTER_VERTICAL)
6419        gridSizer.Add(
6420            self.fillColorCtrl, pos=(
6421                1, 1), flag=wx.ALIGN_CENTER_VERTICAL)
6422        gridSizer.Add(
6423            self.fillTranspCtrl, pos=(
6424                1, 2), flag=wx.ALIGN_CENTER_VERTICAL)
6425
6426        sizer.Add(
6427            gridSizer,
6428            proportion=0,
6429            flag=wx.EXPAND | wx.ALL,
6430            border=5)
6431        border.Add(sizer, proportion=0, flag=wx.ALL | wx.EXPAND, border=5)
6432
6433        #
6434        # size and rotation
6435        #
6436
6437        # size
6438        box = StaticBox(
6439            parent=panel,
6440            id=wx.ID_ANY,
6441            label=" %s " %
6442            _("Size and Rotation"))
6443        sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
6444
6445        gridSizer = wx.GridBagSizer(hgap=5, vgap=5)
6446
6447        sizeLabel = StaticText(
6448            parent=panel,
6449            id=wx.ID_ANY,
6450            label=_("Size (pt):"))
6451        self.sizeCtrl = SpinCtrl(
6452            panel, id=wx.ID_ANY, size=self.spinCtrlSize)
6453        self.sizeCtrl.SetToolTip(_("Symbol size in points"))
6454        self.sizeCtrl.SetValue(self.pointDict['size'])
6455
6456        gridSizer.Add(
6457            sizeLabel, pos=(0, 0),
6458            flag=wx.ALIGN_CENTER_VERTICAL)
6459        gridSizer.Add(
6460            self.sizeCtrl, pos=(
6461                0, 1), flag=wx.ALIGN_CENTER_VERTICAL)
6462
6463        # rotation
6464        rotLabel = StaticText(
6465            parent=panel,
6466            id=wx.ID_ANY,
6467            label=_("Rotation angle (deg):"))
6468
6469        self.rotCtrl = FloatSpin(
6470            panel,
6471            id=wx.ID_ANY,
6472            min_val=-360,
6473            max_val=360,
6474            increment=1,
6475            value=0,
6476            style=fs.FS_RIGHT)
6477        self.rotCtrl.SetFormat("%f")
6478        self.rotCtrl.SetDigits(1)
6479
6480        self.rotCtrl.SetToolTip(
6481            _("Counterclockwise rotation in degrees"))
6482        self.rotCtrl.SetValue(float(self.pointDict['rotate']))
6483
6484        gridSizer.Add(
6485            rotLabel,
6486            pos=(
6487                1,
6488                0),
6489            flag=wx.ALIGN_CENTER_VERTICAL,
6490            border=0)
6491        gridSizer.Add(
6492            self.rotCtrl, pos=(1, 1),
6493            flag=wx.ALIGN_CENTER_VERTICAL)
6494
6495        sizer.Add(
6496            gridSizer,
6497            proportion=0,
6498            flag=wx.EXPAND | wx.ALL,
6499            border=5)
6500        border.Add(sizer, proportion=0, flag=wx.ALL | wx.EXPAND, border=5)
6501
6502        panel.SetSizer(border)
6503        panel.Fit()
6504
6505        return panel
6506
6507    def _positionPanel(self, notebook):
6508        panel = Panel(
6509            parent=notebook, id=wx.ID_ANY, size=(-1, -1),
6510            style=wx.TAB_TRAVERSAL)
6511        notebook.AddPage(page=panel, text=_("Position"))
6512        border = wx.BoxSizer(wx.VERTICAL)
6513        #
6514        # set position
6515        #
6516        box = StaticBox(
6517            parent=panel,
6518            id=wx.ID_ANY,
6519            label=" %s " %
6520            _("Position"))
6521        sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
6522
6523        gridBagSizer = wx.GridBagSizer(hgap=5, vgap=5)
6524
6525        self.AddExtendedPosition(panel, gridBagSizer, self.pointDict)
6526
6527        self.Bind(
6528            wx.EVT_RADIOBUTTON,
6529            self.OnPositionType,
6530            panel.position['toPaper'])
6531        self.Bind(
6532            wx.EVT_RADIOBUTTON,
6533            self.OnPositionType,
6534            panel.position['toMap'])
6535
6536        gridBagSizer.AddGrowableCol(0)
6537        gridBagSizer.AddGrowableCol(1)
6538        sizer.Add(
6539            gridBagSizer,
6540            proportion=1,
6541            flag=wx.ALL,
6542            border=5)
6543        border.Add(sizer, proportion=0, flag=wx.ALL | wx.EXPAND, border=5)
6544
6545        panel.SetSizer(border)
6546        panel.Fit()
6547
6548        return panel
6549
6550    def OnPositionType(self, event):
6551        if self.positionPanel.position['toPaper'].GetValue():
6552            for widget in self.gridBagSizerP.GetChildren():
6553                widget.GetWindow().Enable()
6554            for widget in self.gridBagSizerM.GetChildren():
6555                widget.GetWindow().Disable()
6556        else:
6557            for widget in self.gridBagSizerM.GetChildren():
6558                widget.GetWindow().Enable()
6559            for widget in self.gridBagSizerP.GetChildren():
6560                widget.GetWindow().Disable()
6561
6562    def OnSymbolSelection(self, event):
6563        dlg = SymbolDialog(self, symbolPath=globalvar.SYMBDIR,
6564                           currentSymbol=self.symbolLabel.GetLabel())
6565        if dlg.ShowModal() == wx.ID_OK:
6566            img = dlg.GetSelectedSymbolPath()
6567            name = dlg.GetSelectedSymbolName()
6568            self.symbolButton.SetBitmapLabel(wx.Bitmap(img + '.png'))
6569            self.symbolLabel.SetLabel(name)
6570
6571        dlg.Destroy()
6572
6573    def update(self):
6574        # symbol
6575        self.pointDict['symbol'] = self.symbolLabel.GetLabel()
6576
6577        # position
6578        if self.positionPanel.position['toPaper'].GetValue():
6579            self.pointDict['XY'] = True
6580            currUnit = self.unitConv.findUnit(
6581                self.positionPanel.units['unitsCtrl'].GetStringSelection())
6582            self.pointDict['unit'] = currUnit
6583            if self.positionPanel.position['xCtrl'].GetValue():
6584                x = self.positionPanel.position['xCtrl'].GetValue()
6585            else:
6586                x = self.pointDict['where'][0]
6587
6588            if self.positionPanel.position['yCtrl'].GetValue():
6589                y = self.positionPanel.position['yCtrl'].GetValue()
6590            else:
6591                y = self.pointDict['where'][1]
6592
6593            x = self.unitConv.convert(
6594                value=float(x), fromUnit=currUnit, toUnit='inch')
6595            y = self.unitConv.convert(
6596                value=float(y), fromUnit=currUnit, toUnit='inch')
6597            self.pointDict['where'] = x, y
6598
6599        else:
6600            self.pointDict['XY'] = False
6601            if self.positionPanel.position['eCtrl'].GetValue():
6602                e = self.positionPanel.position['eCtrl'].GetValue()
6603            else:
6604                self.pointDict['east'] = self.pointDict['east']
6605
6606            if self.positionPanel.position['nCtrl'].GetValue():
6607                n = self.positionPanel.position['nCtrl'].GetValue()
6608            else:
6609                self.pointDict['north'] = self.pointDict['north']
6610
6611            x, y = PaperMapCoordinates(
6612                mapInstr=self.instruction[
6613                    self.mapId], x=float(
6614                    self.pointDict['east']), y=float(
6615                    self.pointDict['north']), paperToMap=False,
6616                    env=self.env)
6617
6618        # rotation
6619        self.pointDict['rotate'] = self.rotCtrl.GetValue()
6620
6621        # size
6622        self.pointDict['size'] = self.sizeCtrl.GetValue()
6623
6624        w = h = self.unitConv.convert(value=self.pointDict['size'],
6625                                      fromUnit='point', toUnit='inch')
6626
6627        # outline color
6628        if self.outlineTranspCtrl.GetValue():
6629            self.pointDict['color'] = 'none'
6630        else:
6631            self.pointDict['color'] = convertRGB(
6632                self.outlineColorCtrl.GetColour())
6633
6634        # fill color
6635        if self.fillTranspCtrl.GetValue():
6636            self.pointDict['fcolor'] = 'none'
6637        else:
6638            self.pointDict['fcolor'] = convertRGB(
6639                self.fillColorCtrl.GetColour())
6640
6641        self.pointDict['rect'] = Rect2D(
6642            x=x - w / 2, y=y - h / 2, width=w, height=h)
6643
6644        if self.id not in self.instruction:
6645            point = Point(self.id, env=self.env)
6646            self.instruction.AddInstruction(point)
6647        self.instruction[self.id].SetInstruction(self.pointDict)
6648
6649        if self.id not in self.parent.objectId:
6650            self.parent.objectId.append(self.id)
6651
6652        return True
6653
6654    def updateDialog(self):
6655        """Update text coordinates, after moving"""
6656        # XY coordinates
6657        x, y = self.pointDict['where'][:2]
6658        currUnit = self.unitConv.findUnit(
6659            self.positionPanel.units['unitsCtrl'].GetStringSelection())
6660        x = self.unitConv.convert(value=x, fromUnit='inch', toUnit=currUnit)
6661        y = self.unitConv.convert(value=y, fromUnit='inch', toUnit=currUnit)
6662        self.positionPanel.position['xCtrl'].SetValue("%5.3f" % x)
6663        self.positionPanel.position['yCtrl'].SetValue("%5.3f" % y)
6664        # EN coordinates
6665        e, n = self.pointDict['east'], self.pointDict['north']
6666        self.positionPanel.position['eCtrl'].SetValue(
6667            str(self.pointDict['east']))
6668        self.positionPanel.position['nCtrl'].SetValue(
6669            str(self.pointDict['north']))
6670
6671
6672class RectangleDialog(PsmapDialog):
6673
6674    def __init__(self, parent, id, settings, env,
6675                 type='rectangle', coordinates=None):
6676        """
6677
6678        :param coordinates: begin and end point coordinate (wx.Point, wx.Point)
6679        """
6680        if type == 'rectangle':
6681            title = _("Rectangle settings")
6682        else:
6683            title = _("Line settings")
6684        PsmapDialog.__init__(
6685            self,
6686            parent=parent,
6687            id=id,
6688            title=title,
6689            settings=settings,
6690            env=env)
6691
6692        self.objectType = (type,)
6693
6694        if self.id is not None:
6695            self.rectObj = self.instruction[self.id]
6696            self.rectDict = self.rectObj.GetInstruction()
6697        else:
6698            self.id = NewId()
6699            if type == 'rectangle':
6700                self.rectObj = Rectangle(self.id, env=self.env)
6701            else:
6702                self.rectObj = Line(self.id, env=self.env)
6703            self.rectDict = self.rectObj.GetInstruction()
6704
6705            self.rectDict['rect'] = Rect2DPP(coordinates[0], coordinates[1])
6706            self.rectDict['where'] = coordinates
6707
6708        self.defaultDict = self.rectObj.defaultInstruction
6709        self.panel = self._rectPanel()
6710
6711        self._layout(self.panel)
6712
6713    def _rectPanel(self):
6714        panel = Panel(parent=self, id=wx.ID_ANY, style=wx.TAB_TRAVERSAL)
6715        border = wx.BoxSizer(wx.VERTICAL)
6716
6717        # color
6718        box = StaticBox(
6719            parent=panel,
6720            id=wx.ID_ANY,
6721            label=" %s " %
6722            _("Color"))
6723        sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
6724        gridSizer = wx.GridBagSizer(hgap=5, vgap=5)
6725
6726        outlineLabel = StaticText(
6727            parent=panel,
6728            id=wx.ID_ANY,
6729            label=_("Outline color:"))
6730        self.outlineColorCtrl = ColourPickerCtrl(panel, id=wx.ID_ANY)
6731        self.outlineTranspCtrl = CheckBox(
6732            panel, id=wx.ID_ANY, label=_("transparent"))
6733
6734        if self.rectDict['color'] != 'none':
6735            self.outlineTranspCtrl.SetValue(False)
6736            self.outlineColorCtrl.SetColour(convertRGB(self.rectDict['color']))
6737        else:
6738            self.outlineTranspCtrl.SetValue(True)
6739            self.outlineColorCtrl.SetColour(
6740                convertRGB(self.defaultDict['color']))
6741
6742        # transparent outline makes sense only for rectangle
6743        if self.objectType == ('line',):
6744            self.outlineTranspCtrl.Hide()
6745
6746        gridSizer.Add(
6747            outlineLabel, pos=(0, 0),
6748            flag=wx.ALIGN_CENTER_VERTICAL)
6749        gridSizer.Add(
6750            self.outlineColorCtrl, pos=(
6751                0, 1), flag=wx.ALIGN_CENTER_VERTICAL)
6752        gridSizer.Add(
6753            self.outlineTranspCtrl, pos=(
6754                0, 2), flag=wx.ALIGN_CENTER_VERTICAL)
6755
6756        # fill color only in rectangle
6757        if self.objectType == ('rectangle',):
6758            fillLabel = StaticText(
6759                parent=panel, id=wx.ID_ANY, label=_("Fill color:"))
6760            self.fillColorCtrl = ColourPickerCtrl(panel, id=wx.ID_ANY)
6761            self.fillTranspCtrl = CheckBox(
6762                panel, id=wx.ID_ANY, label=_("transparent"))
6763
6764            if self.rectDict['fcolor'] != 'none':
6765                self.fillTranspCtrl.SetValue(False)
6766                self.fillColorCtrl.SetColour(
6767                    convertRGB(self.rectDict['fcolor']))
6768            else:
6769                self.fillTranspCtrl.SetValue(True)
6770                self.fillColorCtrl.SetColour(wx.WHITE)
6771
6772            gridSizer.Add(
6773                fillLabel, pos=(1, 0),
6774                flag=wx.ALIGN_CENTER_VERTICAL)
6775            gridSizer.Add(
6776                self.fillColorCtrl, pos=(
6777                    1, 1), flag=wx.ALIGN_CENTER_VERTICAL)
6778            gridSizer.Add(
6779                self.fillTranspCtrl, pos=(
6780                    1, 2), flag=wx.ALIGN_CENTER_VERTICAL)
6781
6782        sizer.Add(gridSizer, proportion=1, flag=wx.EXPAND | wx.ALL, border=5)
6783        border.Add(sizer, proportion=0, flag=wx.ALL | wx.EXPAND, border=5)
6784        gridSizer = wx.GridBagSizer(hgap=5, vgap=5)
6785
6786        # width
6787        box = StaticBox(
6788            parent=panel,
6789            id=wx.ID_ANY,
6790            label=" %s " %
6791            _("Line style"))
6792        sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
6793
6794        widthLabel = StaticText(
6795            parent=panel,
6796            id=wx.ID_ANY,
6797            label=_("Line width:"))
6798
6799        self.widthCtrl = FloatSpin(
6800            panel,
6801            id=wx.ID_ANY,
6802            min_val=0,
6803            max_val=50,
6804            increment=1,
6805            value=0,
6806            style=fs.FS_RIGHT)
6807        self.widthCtrl.SetFormat("%f")
6808        self.widthCtrl.SetDigits(1)
6809
6810        self.widthCtrl.SetToolTip(_("Line width in points"))
6811        self.widthCtrl.SetValue(float(self.rectDict['width']))
6812
6813        gridSizer.Add(
6814            widthLabel, pos=(0, 0),
6815            flag=wx.ALIGN_CENTER_VERTICAL)
6816        gridSizer.Add(
6817            self.widthCtrl, pos=(
6818                0, 1), flag=wx.ALIGN_CENTER_VERTICAL)
6819
6820        sizer.Add(gridSizer, proportion=1, flag=wx.EXPAND | wx.ALL, border=5)
6821        border.Add(sizer, proportion=0, flag=wx.ALL | wx.EXPAND, border=5)
6822
6823        panel.SetSizer(border)
6824
6825        return panel
6826
6827    def update(self):
6828        mapInstr = self.instruction.FindInstructionByType('map')
6829        if not mapInstr:
6830            mapInstr = self.instruction.FindInstructionByType('initMap')
6831        self.mapId = mapInstr.id
6832        point1 = self.rectDict['where'][0]
6833        point2 = self.rectDict['where'][1]
6834        self.rectDict['east1'], self.rectDict['north1'] = PaperMapCoordinates(
6835            mapInstr=mapInstr, x=point1[0], y=point1[1], paperToMap=True,
6836            env=self.env)
6837        self.rectDict['east2'], self.rectDict['north2'] = PaperMapCoordinates(
6838            mapInstr=mapInstr, x=point2[0], y=point2[1], paperToMap=True,
6839            env=self.env)
6840        # width
6841        self.rectDict['width'] = self.widthCtrl.GetValue()
6842
6843        # outline color
6844        if self.outlineTranspCtrl.GetValue():
6845            self.rectDict['color'] = 'none'
6846        else:
6847            self.rectDict['color'] = convertRGB(
6848                self.outlineColorCtrl.GetColour())
6849
6850        # fill color
6851        if self.objectType == ('rectangle',):
6852            if self.fillTranspCtrl.GetValue():
6853                self.rectDict['fcolor'] = 'none'
6854            else:
6855                self.rectDict['fcolor'] = convertRGB(
6856                    self.fillColorCtrl.GetColour())
6857
6858        if self.id not in self.instruction:
6859            if self.objectType == ('rectangle',):
6860                rect = Rectangle(self.id, env=self.env)
6861            else:
6862                rect = Line(self.id, env=self.env)
6863            self.instruction.AddInstruction(rect)
6864
6865        self.instruction[self.id].SetInstruction(self.rectDict)
6866
6867        if self.id not in self.parent.objectId:
6868            self.parent.objectId.append(self.id)
6869
6870        self.updateDialog()
6871
6872        return True
6873
6874    def updateDialog(self):
6875        """Update text coordinates, after moving"""
6876        pass
6877
6878
6879class LabelsDialog(PsmapDialog):
6880
6881    def __init__(self, parent, id, settings, env):
6882        PsmapDialog.__init__(
6883            self,
6884            parent=parent,
6885            id=id,
6886            title=_("Vector labels"),
6887            settings=settings,
6888            env=env)
6889        self.objectType = ('labels',)
6890        if self.id is not None:
6891            self.labels = self.instruction[self.id]
6892        else:
6893            self.id = NewId()
6894            self.labels = Labels(self.id, env=self.env)
6895        self.labelsDict = self.labels.GetInstruction()
6896        self.panel = self._labelPanel()
6897
6898        self._layout(self.panel)
6899
6900    def _labelPanel(self):
6901        panel = Panel(parent=self, id=wx.ID_ANY, style=wx.TAB_TRAVERSAL)
6902
6903        border = wx.BoxSizer(wx.VERTICAL)
6904
6905        box = StaticBox(
6906            parent=panel, id=wx.ID_ANY, label=" %s " %
6907            _("Vector label files created beforehand by v.label module"))
6908        sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
6909
6910        self.select = Select(
6911            parent=panel,
6912            multiple=True,
6913            type='label',
6914            fullyQualified=False)
6915        self.select.SetValue(','.join(self.labelsDict['labels']))
6916        self.select.SetFocus()
6917        sizer.Add(
6918            self.select,
6919            proportion=1,
6920            flag=wx.EXPAND | wx.ALL,
6921            border=5)
6922        helpText = StaticText(
6923            panel, id=wx.ID_ANY,
6924            label=_("You can select multiple label files."))
6925        helpText.SetForegroundColour(
6926            wx.SystemSettings.GetColour(
6927                wx.SYS_COLOUR_GRAYTEXT))
6928        sizer.Add(
6929            helpText,
6930            proportion=0,
6931            flag=wx.EXPAND | wx.LEFT | wx.RIGHT,
6932            border=5)
6933
6934        border.Add(sizer, proportion=1, flag=wx.EXPAND | wx.ALL, border=5)
6935        panel.SetSizer(border)
6936
6937        return panel
6938
6939    def update(self):
6940        value = self.select.GetValue()
6941        if not value:
6942            self.labelsDict['labels'] = []
6943        else:
6944            self.labelsDict['labels'] = value.split(',')
6945        if self.id not in self.instruction:
6946            labels = Labels(self.id, env=self.env)
6947            self.instruction.AddInstruction(labels)
6948
6949        self.instruction[self.id].SetInstruction(self.labelsDict)
6950
6951        return True
6952