are not Elements) had to add xxxObject.isElement flag and changed xxxObject.element variable to xxxObject.node (xxxComment is derived from xxxObject to minimize changes in processing). More testing is still needed to verify that things didn't break. Use previous commit (0.1.8-4 release on 2007/03/10) if you need a stable version. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@44764 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
936 lines
38 KiB
Python
936 lines
38 KiB
Python
# Name: params.py
|
|
# Purpose: Classes for parameter introduction
|
|
# Author: Roman Rolinsky <rolinsky@mema.ucl.ac.be>
|
|
# Created: 22.08.2001
|
|
# RCS-ID: $Id$
|
|
|
|
import string
|
|
import os.path
|
|
from globals import *
|
|
from types import *
|
|
|
|
genericStyles = [
|
|
'wxSIMPLE_BORDER', 'wxSUNKEN_BORDER', 'wxDOUBLE_BORDER',
|
|
'wxRAISED_BORDER', 'wxSTATIC_BORDER', 'wxNO_BORDER',
|
|
'wxCLIP_CHILDREN', 'wxTRANSPARENT_WINDOW', 'wxWANTS_CHARS',
|
|
'wxNO_FULL_REPAINT_ON_RESIZE', 'wxFULL_REPAINT_ON_RESIZE'
|
|
]
|
|
|
|
genericExStyles = [
|
|
'wxWS_EX_VALIDATE_RECURSIVELY',
|
|
'wxWS_EX_BLOCK_EVENTS',
|
|
'wxWS_EX_TRANSIENT',
|
|
'wxFRAME_EX_CONTEXTHELP',
|
|
'wxWS_EX_PROCESS_IDLE',
|
|
'wxWS_EX_PROCESS_UI_UPDATES'
|
|
]
|
|
|
|
# Global var initialized in Panel.__init__ for button size in screen pixels
|
|
buttonSize = None
|
|
# Button size in dialog units
|
|
buttonSizeD = (35,-1)
|
|
|
|
# Class that can properly disable children
|
|
class PPanel(wx.Panel):
|
|
def __init__(self, parent, name):
|
|
wx.Panel.__init__(self, parent, -1, name=name)
|
|
self.modified = self.freeze = False
|
|
def Enable(self, value):
|
|
# Something strange is going on with enable so we make sure...
|
|
for w in self.GetChildren():
|
|
w.Enable(value)
|
|
#wx.Panel.Enable(self, value)
|
|
def SetModified(self, state=True):
|
|
self.modified = state
|
|
if state: g.panel.SetModified(True)
|
|
# Common method to set modified state
|
|
def OnChange(self, evt):
|
|
if self.freeze: return
|
|
self.SetModified()
|
|
evt.Skip()
|
|
|
|
class ParamBinaryOr(PPanel):
|
|
def __init__(self, parent, name):
|
|
PPanel.__init__(self, parent, name)
|
|
self.ID_TEXT_CTRL = wx.NewId()
|
|
self.ID_BUTTON_CHOICES = wx.NewId()
|
|
sizer = wx.BoxSizer()
|
|
self.text = wx.TextCtrl(self, self.ID_TEXT_CTRL, size=wx.Size(200,-1))
|
|
sizer.Add(self.text, 0, wx.RIGHT | wx.ALIGN_CENTER_VERTICAL, 5)
|
|
self.button = wx.Button(self, self.ID_BUTTON_CHOICES, 'Edit...', size=buttonSize)
|
|
sizer.Add(self.button, 0, wx.ALIGN_CENTER_VERTICAL)
|
|
self.SetSizer(sizer)
|
|
wx.EVT_BUTTON(self, self.ID_BUTTON_CHOICES, self.OnButtonChoices)
|
|
wx.EVT_TEXT(self, self.ID_TEXT_CTRL, self.OnChange)
|
|
def GetValue(self):
|
|
return self.text.GetValue()
|
|
def SetValue(self, value):
|
|
self.freeze = True
|
|
self.text.SetValue(value)
|
|
self.freeze = False
|
|
def OnButtonChoices(self, evt):
|
|
dlg = g.frame.res.LoadDialog(self, 'DIALOG_CHOICES')
|
|
if self.GetName() == 'flag': dlg.SetTitle('Sizer item flags')
|
|
elif self.GetName() == 'style': dlg.SetTitle('Window styles')
|
|
elif self.GetName() == 'exstyle': dlg.SetTitle('Extended window styles')
|
|
listBox = xrc.XRCCTRL(dlg, 'CHECKLIST')
|
|
listBox.InsertItems(self.values, 0)
|
|
value = map(string.strip, self.text.GetValue().split('|'))
|
|
if value == ['']: value = []
|
|
ignored = []
|
|
for i in value:
|
|
try:
|
|
listBox.Check(self.values.index(i))
|
|
except ValueError:
|
|
# Try to find equal
|
|
if self.equal.has_key(i):
|
|
listBox.Check(self.values.index(self.equal[i]))
|
|
else:
|
|
print 'WARNING: unknown flag: %s: ignored.' % i
|
|
ignored.append(i)
|
|
if dlg.ShowModal() == wx.ID_OK:
|
|
value = []
|
|
for i in range(listBox.GetCount()):
|
|
if listBox.IsChecked(i):
|
|
value.append(self.values[i])
|
|
# Add ignored flags
|
|
value.extend(ignored)
|
|
self.SetValue('|'.join(value))
|
|
self.SetModified()
|
|
dlg.Destroy()
|
|
|
|
class ParamFlag(ParamBinaryOr):
|
|
values = ['wxTOP', 'wxBOTTOM', 'wxLEFT', 'wxRIGHT', 'wxALL',
|
|
'wxEXPAND', 'wxGROW', 'wxSHAPED', 'wxSTRETCH_NOT',
|
|
'wxALIGN_CENTRE', 'wxALIGN_LEFT', 'wxALIGN_RIGHT',
|
|
'wxALIGN_TOP', 'wxALIGN_BOTTOM',
|
|
'wxALIGN_CENTRE_VERTICAL', 'wxALIGN_CENTRE_HORIZONTAL',
|
|
'wxADJUST_MINSIZE', 'wxFIXED_MINSIZE'
|
|
]
|
|
equal = {'wxALIGN_CENTER': 'wxALIGN_CENTRE',
|
|
'wxALIGN_CENTER_VERTICAL': 'wxALIGN_CENTRE_VERTICAL',
|
|
'wxALIGN_CENTER_HORIZONTAL': 'wxALIGN_CENTRE_HORIZONTAL',
|
|
'wxUP': 'wxTOP', 'wxDOWN': 'wxBOTTOM', 'wxNORTH': 'wxTOP',
|
|
'wxSOUTH': 'wxBOTTOM', 'wxWEST': 'wxLEFT', 'wxEAST': 'wxRIGHT'}
|
|
def __init__(self, parent, name):
|
|
ParamBinaryOr.__init__(self, parent, name)
|
|
|
|
class ParamNonGenericStyle(ParamBinaryOr):
|
|
def __init__(self, parent, name):
|
|
self.values = g.currentXXX.winStyles
|
|
ParamBinaryOr.__init__(self, parent, name)
|
|
|
|
class ParamStyle(ParamBinaryOr):
|
|
equal = {'wxALIGN_CENTER': 'wxALIGN_CENTRE'}
|
|
def __init__(self, parent, name):
|
|
ParamBinaryOr.__init__(self, parent, name)
|
|
self.valuesSpecific = g.currentXXX.winStyles
|
|
if self.valuesSpecific: # override if using specific styles
|
|
# Remove duplicates
|
|
self.valuesGeneric = [s for s in genericStyles
|
|
if s not in self.valuesSpecific]
|
|
wx.EVT_BUTTON(self, self.ID_BUTTON_CHOICES, self.OnButtonChoicesBoth)
|
|
else:
|
|
self.values = genericStyles
|
|
def OnButtonChoicesBoth(self, evt):
|
|
dlg = g.frame.res.LoadDialog(self, 'DIALOG_STYLES')
|
|
listBoxSpecific = xrc.XRCCTRL(dlg, 'CHECKLIST_SPECIFIC')
|
|
listBoxSpecific.InsertItems(self.valuesSpecific, 0)
|
|
listBoxGeneric = xrc.XRCCTRL(dlg, 'CHECKLIST_GENERIC')
|
|
listBoxGeneric.InsertItems(self.valuesGeneric, 0)
|
|
value = map(string.strip, self.text.GetValue().split('|'))
|
|
if value == ['']: value = []
|
|
# Set specific styles
|
|
value2 = [] # collect generic and ignored here
|
|
for i in value:
|
|
try:
|
|
listBoxSpecific.Check(self.valuesSpecific.index(i))
|
|
except ValueError:
|
|
# Try to find equal
|
|
if self.equal.has_key(i):
|
|
listBoxSpecific.Check(self.valuesSpecific.index(self.equal[i]))
|
|
else:
|
|
value2.append(i)
|
|
ignored = []
|
|
# Set generic styles, collect non-standart values
|
|
for i in value2:
|
|
try:
|
|
listBoxGeneric.Check(self.valuesGeneric.index(i))
|
|
except ValueError:
|
|
# Try to find equal
|
|
if self.equal.has_key(i):
|
|
listBoxGeneric.Check(self.valuesGeneric.index(self.equal[i]))
|
|
else:
|
|
print 'WARNING: unknown flag: %s: ignored.' % i
|
|
ignored.append(i)
|
|
if dlg.ShowModal() == wx.ID_OK:
|
|
value = [self.valuesSpecific[i]
|
|
for i in range(listBoxSpecific.GetCount())
|
|
if listBoxSpecific.IsChecked(i)] + \
|
|
[self.valuesGeneric[i]
|
|
for i in range(listBoxGeneric.GetCount())
|
|
if listBoxGeneric.IsChecked(i)] + ignored
|
|
self.SetValue('|'.join(value))
|
|
self.SetModified()
|
|
dlg.Destroy()
|
|
|
|
class ParamExStyle(ParamBinaryOr):
|
|
def __init__(self, parent, name):
|
|
if g.currentXXX:
|
|
self.values = g.currentXXX.exStyles + genericExStyles
|
|
else:
|
|
self.values = []
|
|
ParamBinaryOr.__init__(self, parent, name)
|
|
|
|
class ParamColour(PPanel):
|
|
def __init__(self, parent, name):
|
|
PPanel.__init__(self, parent, name)
|
|
self.ID_TEXT_CTRL = wx.NewId()
|
|
self.ID_BUTTON = wx.NewId()
|
|
sizer = wx.BoxSizer()
|
|
self.text = wx.TextCtrl(self, self.ID_TEXT_CTRL, size=(80,-1))
|
|
sizer.Add(self.text, 0, wx.ALIGN_CENTER_VERTICAL | wx.TOP | wx.BOTTOM, 2)
|
|
self.button = wx.Panel(self, self.ID_BUTTON, wx.DefaultPosition, wx.Size(20, 20))
|
|
sizer.Add(self.button, 0, wx.ALIGN_CENTER_VERTICAL | wx.LEFT, 5)
|
|
self.SetSizer(sizer)
|
|
self.textModified = False
|
|
wx.EVT_PAINT(self.button, self.OnPaintButton)
|
|
wx.EVT_TEXT(self, self.ID_TEXT_CTRL, self.OnChange)
|
|
wx.EVT_LEFT_DOWN(self.button, self.OnLeftDown)
|
|
def GetValue(self):
|
|
return self.text.GetValue()
|
|
def SetValue(self, value):
|
|
self.freeze = True
|
|
if not value: value = '#FFFFFF'
|
|
self.text.SetValue(str(value)) # update text ctrl
|
|
try:
|
|
colour = wx.Colour(int(value[1:3], 16), int(value[3:5], 16), int(value[5:7], 16))
|
|
self.button.SetBackgroundColour(colour)
|
|
except: # ignore errors
|
|
pass
|
|
self.button.Refresh()
|
|
self.freeze = False
|
|
def OnPaintButton(self, evt):
|
|
dc = wx.PaintDC(self.button)
|
|
dc.SetBrush(wx.TRANSPARENT_BRUSH)
|
|
if self.IsEnabled(): dc.SetPen(wx.BLACK_PEN)
|
|
else: dc.SetPen(wx.GREY_PEN)
|
|
size = self.button.GetSize()
|
|
dc.DrawRectangle(0, 0, size.width, size.height)
|
|
def OnLeftDown(self, evt):
|
|
data = wx.ColourData()
|
|
data.SetColour(self.GetValue())
|
|
dlg = wx.ColourDialog(self, data)
|
|
if dlg.ShowModal() == wx.ID_OK:
|
|
self.SetValue('#%02X%02X%02X' % dlg.GetColourData().GetColour().Get())
|
|
self.SetModified()
|
|
dlg.Destroy()
|
|
|
|
################################################################################
|
|
|
|
# Mapping from wx constants to XML strings
|
|
fontFamiliesWx2Xml = {wx.DEFAULT: 'default', wx.DECORATIVE: 'decorative',
|
|
wx.ROMAN: 'roman', wx.SCRIPT: 'script', wx.SWISS: 'swiss',
|
|
wx.MODERN: 'modern'}
|
|
fontStylesWx2Xml = {wx.NORMAL: 'normal', wx.SLANT: 'slant', wx.ITALIC: 'italic'}
|
|
fontWeightsWx2Xml = {wx.NORMAL: 'normal', wx.LIGHT: 'light', wx.BOLD: 'bold'}
|
|
def ReverseMap(m):
|
|
rm = {}
|
|
for k,v in m.items(): rm[v] = k
|
|
return rm
|
|
fontFamiliesXml2wx = ReverseMap(fontFamiliesWx2Xml)
|
|
fontStylesXml2wx = ReverseMap(fontStylesWx2Xml)
|
|
fontWeightsXml2wx = ReverseMap(fontWeightsWx2Xml)
|
|
|
|
class ParamFont(PPanel):
|
|
def __init__(self, parent, name):
|
|
PPanel.__init__(self, parent, name)
|
|
self.ID_TEXT_CTRL = wx.NewId()
|
|
self.ID_BUTTON_SELECT = wx.NewId()
|
|
sizer = wx.BoxSizer()
|
|
self.text = wx.TextCtrl(self, self.ID_TEXT_CTRL, size=(200,-1))
|
|
sizer.Add(self.text, 0, wx.RIGHT | wx.ALIGN_CENTER_VERTICAL, 5)
|
|
self.button = wx.Button(self, self.ID_BUTTON_SELECT, 'Select...', size=buttonSize)
|
|
sizer.Add(self.button, 0, wx.ALIGN_CENTER_VERTICAL)
|
|
self.SetSizer(sizer)
|
|
self.textModified = False
|
|
wx.EVT_BUTTON(self, self.ID_BUTTON_SELECT, self.OnButtonSelect)
|
|
wx.EVT_TEXT(self, self.ID_TEXT_CTRL, self.OnChange)
|
|
def OnChange(self, evt):
|
|
PPanel.OnChange(self, evt)
|
|
self.textModified = True
|
|
def _defaultValue(self):
|
|
return [`g._sysFont.GetPointSize()`, 'default', 'normal', 'normal', '0', '', '']
|
|
def GetValue(self):
|
|
if self.textModified: # text has newer value
|
|
try:
|
|
return eval(self.text.GetValue())
|
|
except SyntaxError:
|
|
wx.LogError('Syntax error in parameter value: ' + self.GetName())
|
|
return self._defaultValue()
|
|
return self.value
|
|
def SetValue(self, value):
|
|
self.freeze = True # disable other handlers
|
|
if not value: value = self._defaultValue()
|
|
self.value = value
|
|
self.text.SetValue(str(value)) # update text ctrl
|
|
self.freeze = False
|
|
def OnButtonSelect(self, evt):
|
|
if self.textModified: # text has newer value
|
|
try:
|
|
self.value = eval(self.text.GetValue())
|
|
except SyntaxError:
|
|
wx.LogError('Syntax error in parameter value: ' + self.GetName())
|
|
self.value = self._defaultValue()
|
|
# Make initial font
|
|
# Default values
|
|
size = g._sysFont.GetPointSize()
|
|
family = wx.DEFAULT
|
|
style = weight = wx.NORMAL
|
|
underlined = 0
|
|
face = ''
|
|
enc = wx.FONTENCODING_DEFAULT
|
|
# Fall back to default if exceptions
|
|
error = False
|
|
try:
|
|
try: size = int(self.value[0])
|
|
except ValueError: error = True; wx.LogError('Invalid size specification')
|
|
try: family = fontFamiliesXml2wx[self.value[1]]
|
|
except KeyError: error = True; wx.LogError('Invalid family specification')
|
|
try: style = fontStylesXml2wx[self.value[2]]
|
|
except KeyError: error = True; wx.LogError('Invalid style specification')
|
|
try: weight = fontWeightsXml2wx[self.value[3]]
|
|
except KeyError: error = True; wx.LogError('Invalid weight specification')
|
|
try: underlined = bool(self.value[4])
|
|
except ValueError: error = True; wx.LogError('Invalid underlined flag specification')
|
|
face = self.value[5]
|
|
except IndexError:
|
|
error = True
|
|
mapper = wx.FontMapper()
|
|
if not self.value[6]: enc = mapper.CharsetToEncoding(self.value[6])
|
|
|
|
if error: wx.LogError('Invalid font specification')
|
|
if enc == wx.FONTENCODING_DEFAULT: enc = wx.FONTENCODING_SYSTEM
|
|
font = wx.Font(size, family, style, weight, underlined, face, enc)
|
|
data = wx.FontData()
|
|
data.SetInitialFont(font)
|
|
dlg = wx.FontDialog(self, data)
|
|
if dlg.ShowModal() == wx.ID_OK:
|
|
font = dlg.GetFontData().GetChosenFont()
|
|
if font.GetEncoding() == wx.FONTENCODING_SYSTEM:
|
|
encName = ''
|
|
else:
|
|
encName = wx.FontMapper.GetEncodingName(font.GetEncoding()).encode()
|
|
value = [str(font.GetPointSize()),
|
|
fontFamiliesWx2Xml.get(font.GetFamily(), "default"),
|
|
fontStylesWx2Xml.get(font.GetStyle(), "normal"),
|
|
fontWeightsWx2Xml.get(font.GetWeight(), "normal"),
|
|
str(int(font.GetUnderlined())),
|
|
font.GetFaceName().encode(),
|
|
encName
|
|
]
|
|
self.SetValue(value)
|
|
self.SetModified()
|
|
self.textModified = False
|
|
dlg.Destroy()
|
|
|
|
################################################################################
|
|
|
|
class ParamInt(PPanel):
|
|
def __init__(self, parent, name):
|
|
PPanel.__init__(self, parent, name)
|
|
self.ID_SPIN_CTRL = wx.NewId()
|
|
sizer = wx.BoxSizer()
|
|
self.spin = wx.SpinCtrl(self, self.ID_SPIN_CTRL, size=(60,-1))
|
|
self.spin.SetRange(-2147483648, 2147483647) # min/max integers
|
|
sizer.Add(self.spin)
|
|
self.SetSizer(sizer)
|
|
wx.EVT_SPINCTRL(self, self.ID_SPIN_CTRL, self.OnChange)
|
|
def GetValue(self):
|
|
return str(self.spin.GetValue())
|
|
def SetValue(self, value):
|
|
self.freeze = True
|
|
if not value: value = 0
|
|
self.spin.SetValue(int(value))
|
|
self.freeze = False
|
|
|
|
# Non-negative number
|
|
class ParamIntNN(PPanel):
|
|
def __init__(self, parent, name):
|
|
PPanel.__init__(self, parent, name)
|
|
self.ID_SPIN_CTRL = wx.NewId()
|
|
sizer = wx.BoxSizer()
|
|
self.spin = wx.SpinCtrl(self, self.ID_SPIN_CTRL, size=(60,-1))
|
|
self.spin.SetRange(0, 10000) # min/max integers
|
|
sizer.Add(self.spin)
|
|
self.SetSizer(sizer)
|
|
wx.EVT_SPINCTRL(self, self.ID_SPIN_CTRL, self.OnChange)
|
|
def GetValue(self):
|
|
return str(self.spin.GetValue())
|
|
def SetValue(self, value):
|
|
self.freeze = True
|
|
if not value: value = 0
|
|
self.spin.SetValue(int(value))
|
|
self.freeze = False
|
|
|
|
# Same as int but allows dialog units (XXXd)
|
|
class ParamUnit(PPanel):
|
|
def __init__(self, parent, name):
|
|
PPanel.__init__(self, parent, name)
|
|
self.ID_TEXT_CTRL = wx.NewId()
|
|
self.ID_SPIN_BUTTON = wx.NewId()
|
|
sizer = wx.BoxSizer(wx.HORIZONTAL)
|
|
self.spin = wx.SpinButton(self, self.ID_SPIN_BUTTON, style = wx.SP_VERTICAL, size=(-1,0))
|
|
textW = 60 - self.spin.GetSize()[0]
|
|
self.text = wx.TextCtrl(self, self.ID_TEXT_CTRL, size=(textW,-1))
|
|
self.spin.SetRange(-10000, 10000)
|
|
sizer.Add(self.text, 0, wx.EXPAND)
|
|
sizer.Add(self.spin, 0, wx.EXPAND)
|
|
self.SetSizer(sizer)
|
|
self.spin.Bind(wx.EVT_SPIN_UP, self.OnSpinUp)
|
|
self.spin.Bind(wx.EVT_SPIN_DOWN, self.OnSpinDown)
|
|
def GetValue(self):
|
|
return self.text.GetValue()
|
|
def SetValue(self, value):
|
|
if not value: value = '0'
|
|
self.text.SetValue(value)
|
|
self.Change(0)
|
|
def Change(self, x):
|
|
self.freeze = True
|
|
# Check if we are working with dialog units
|
|
value = self.text.GetValue()
|
|
units = ''
|
|
if value[-1].upper() == 'D':
|
|
units = value[-1]
|
|
value = value[:-1]
|
|
try:
|
|
intValue = int(value) + x
|
|
self.spin.SetValue(intValue)
|
|
if x: # 0 can be passed to update spin value only
|
|
self.text.SetValue(str(intValue) + units)
|
|
self.SetModified()
|
|
except:
|
|
# !!! Strange, if I use wx.LogWarning, event is re-generated
|
|
print 'ERROR: incorrect unit format'
|
|
self.freeze = False
|
|
def OnSpinUp(self, evt):
|
|
self.freeze = True
|
|
self.Change(1)
|
|
def OnSpinDown(self, evt):
|
|
if self.freeze: return
|
|
self.freeze = True
|
|
self.Change(-1)
|
|
|
|
class ParamMultilineText(PPanel):
|
|
def __init__(self, parent, name, textWidth=-1):
|
|
PPanel.__init__(self, parent, name)
|
|
self.ID_TEXT_CTRL = wx.NewId()
|
|
self.ID_BUTTON_EDIT = wx.NewId()
|
|
sizer = wx.BoxSizer()
|
|
self.text = wx.TextCtrl(self, self.ID_TEXT_CTRL, size=wx.Size(200,-1))
|
|
sizer.Add(self.text, 0, wx.RIGHT | wx.ALIGN_CENTER_VERTICAL, 5)
|
|
self.button = wx.Button(self, self.ID_BUTTON_EDIT, 'Edit...', size=buttonSize)
|
|
sizer.Add(self.button, 0, wx.ALIGN_CENTER_VERTICAL)
|
|
self.SetSizerAndFit(sizer)
|
|
wx.EVT_BUTTON(self, self.ID_BUTTON_EDIT, self.OnButtonEdit)
|
|
wx.EVT_TEXT(self, self.ID_TEXT_CTRL, self.OnChange)
|
|
def GetValue(self):
|
|
return self.text.GetValue()
|
|
def SetValue(self, value):
|
|
self.freeze = True # disable other handlers
|
|
self.text.SetValue(value)
|
|
self.freeze = False # disable other handlers
|
|
def OnButtonEdit(self, evt):
|
|
dlg = g.frame.res.LoadDialog(self, 'DIALOG_TEXT')
|
|
textCtrl = xrc.XRCCTRL(dlg, 'TEXT')
|
|
textCtrl.SetValue(self.text.GetValue())
|
|
if dlg.ShowModal() == wx.ID_OK:
|
|
self.text.SetValue(textCtrl.GetValue())
|
|
self.SetModified()
|
|
dlg.Destroy()
|
|
|
|
class ParamText(PPanel):
|
|
def __init__(self, parent, name, textWidth=-1):
|
|
PPanel.__init__(self, parent, name)
|
|
self.ID_TEXT_CTRL = wx.NewId()
|
|
# We use sizer even here to have the same size of text control
|
|
sizer = wx.BoxSizer()
|
|
self.text = wx.TextCtrl(self, self.ID_TEXT_CTRL, size=wx.Size(textWidth,-1))
|
|
if textWidth == -1: option = 1
|
|
else: option = 0
|
|
sizer.Add(self.text, option, wx.ALIGN_CENTER_VERTICAL | wx.TOP | wx.BOTTOM, 2)
|
|
self.SetSizer(sizer)
|
|
wx.EVT_TEXT(self, self.ID_TEXT_CTRL, self.OnChange)
|
|
def GetValue(self):
|
|
return self.text.GetValue()
|
|
def SetValue(self, value):
|
|
self.freeze = True # disable other handlers
|
|
self.text.SetValue(value)
|
|
self.freeze = False # disable other handlers
|
|
|
|
class ParamAccel(ParamText):
|
|
def __init__(self, parent, name):
|
|
ParamText.__init__(self, parent, name, 100)
|
|
|
|
class ParamPosSize(ParamText):
|
|
def __init__(self, parent, name):
|
|
ParamText.__init__(self, parent, name, 80)
|
|
|
|
class ParamLabel(ParamText):
|
|
def __init__(self, parent, name):
|
|
ParamText.__init__(self, parent, name, 200)
|
|
|
|
class ParamEncoding(ParamText):
|
|
def __init__(self, parent, name):
|
|
ParamText.__init__(self, parent, name, 100)
|
|
|
|
class ParamComment(ParamText):
|
|
def __init__(self, parent, name):
|
|
ParamText.__init__(self, parent, name, 330 + buttonSize[0])
|
|
|
|
class ContentDialog(wx.Dialog):
|
|
def __init__(self, parent, value):
|
|
# Load from resource
|
|
pre = wx.PreDialog()
|
|
g.frame.res.LoadOnDialog(pre, parent, 'DIALOG_CONTENT')
|
|
self.PostCreate(pre)
|
|
self.list = xrc.XRCCTRL(self, 'LIST')
|
|
# Set list items
|
|
for v in value:
|
|
self.list.Append(v)
|
|
self.SetAutoLayout(True)
|
|
self.GetSizer().Fit(self)
|
|
# Callbacks
|
|
self.ID_BUTTON_APPEND = xrc.XRCID('BUTTON_APPEND')
|
|
self.ID_BUTTON_REMOVE = xrc.XRCID('BUTTON_REMOVE')
|
|
self.ID_BUTTON_UP = xrc.XRCID('BUTTON_UP')
|
|
self.ID_BUTTON_DOWN = xrc.XRCID('BUTTON_DOWN')
|
|
wx.EVT_BUTTON(self, self.ID_BUTTON_UP, self.OnButtonUp)
|
|
wx.EVT_BUTTON(self, self.ID_BUTTON_DOWN, self.OnButtonDown)
|
|
wx.EVT_BUTTON(self, self.ID_BUTTON_APPEND, self.OnButtonAppend)
|
|
wx.EVT_BUTTON(self, self.ID_BUTTON_REMOVE, self.OnButtonRemove)
|
|
wx.EVT_UPDATE_UI(self, self.ID_BUTTON_UP, self.OnUpdateUI)
|
|
wx.EVT_UPDATE_UI(self, self.ID_BUTTON_DOWN, self.OnUpdateUI)
|
|
wx.EVT_UPDATE_UI(self, self.ID_BUTTON_REMOVE, self.OnUpdateUI)
|
|
def OnButtonUp(self, evt):
|
|
i = self.list.GetSelection()
|
|
str = self.list.GetString(i)
|
|
self.list.Delete(i)
|
|
self.list.InsertItems([str], i-1)
|
|
self.list.SetSelection(i-1)
|
|
def OnButtonDown(self, evt):
|
|
i = self.list.GetSelection()
|
|
str = self.list.GetString(i)
|
|
self.list.Delete(i)
|
|
self.list.InsertItems([str], i+1)
|
|
self.list.SetSelection(i+1)
|
|
def OnButtonAppend(self, evt):
|
|
str = wx.GetTextFromUser('Enter new item:', 'Append', '', self)
|
|
self.list.Append(str)
|
|
def OnButtonRemove(self, evt):
|
|
self.list.Delete(self.list.GetSelection())
|
|
def OnUpdateUI(self, evt):
|
|
if evt.GetId() == self.ID_BUTTON_REMOVE:
|
|
evt.Enable(self.list.GetSelection() != -1)
|
|
elif evt.GetId() == self.ID_BUTTON_UP:
|
|
evt.Enable(self.list.GetSelection() > 0)
|
|
elif evt.GetId() == self.ID_BUTTON_DOWN:
|
|
evt.Enable(self.list.GetSelection() != -1 and \
|
|
self.list.GetSelection() < self.list.GetCount() - 1)
|
|
|
|
class ContentCheckListDialog(wx.Dialog):
|
|
def __init__(self, parent, value):
|
|
pre = wx.PreDialog()
|
|
g.frame.res.LoadOnDialog(pre, parent, 'DIALOG_CONTENT_CHECKLIST')
|
|
self.PostCreate(pre)
|
|
self.list = xrc.XRCCTRL(self, 'CHECK_LIST')
|
|
# Set list items
|
|
i = 0
|
|
for v,ch in value:
|
|
self.list.Append(v)
|
|
self.list.Check(i, ch)
|
|
i += 1
|
|
self.SetAutoLayout(True)
|
|
self.GetSizer().Fit(self)
|
|
# Callbacks
|
|
self.ID_BUTTON_APPEND = xrc.XRCID('BUTTON_APPEND')
|
|
self.ID_BUTTON_REMOVE = xrc.XRCID('BUTTON_REMOVE')
|
|
self.ID_BUTTON_UP = xrc.XRCID('BUTTON_UP')
|
|
self.ID_BUTTON_DOWN = xrc.XRCID('BUTTON_DOWN')
|
|
wx.EVT_CHECKLISTBOX(self, self.list.GetId(), self.OnCheck)
|
|
wx.EVT_BUTTON(self, self.ID_BUTTON_UP, self.OnButtonUp)
|
|
wx.EVT_BUTTON(self, self.ID_BUTTON_DOWN, self.OnButtonDown)
|
|
wx.EVT_BUTTON(self, self.ID_BUTTON_APPEND, self.OnButtonAppend)
|
|
wx.EVT_BUTTON(self, self.ID_BUTTON_REMOVE, self.OnButtonRemove)
|
|
wx.EVT_UPDATE_UI(self, self.ID_BUTTON_UP, self.OnUpdateUI)
|
|
wx.EVT_UPDATE_UI(self, self.ID_BUTTON_DOWN, self.OnUpdateUI)
|
|
wx.EVT_UPDATE_UI(self, self.ID_BUTTON_REMOVE, self.OnUpdateUI)
|
|
def OnCheck(self, evt):
|
|
# !!! Wrong wxGTK (wxMSW?) behavior: toggling selection if checking
|
|
self.list.Deselect(evt.GetSelection())
|
|
def OnButtonUp(self, evt):
|
|
i = self.list.GetSelection()
|
|
str, ch = self.list.GetString(i), self.list.IsChecked(i)
|
|
self.list.Delete(i)
|
|
self.list.InsertItems([str], i-1)
|
|
self.list.Check(i-1, ch)
|
|
self.list.SetSelection(i-1)
|
|
def OnButtonDown(self, evt):
|
|
i = self.list.GetSelection()
|
|
str, ch = self.list.GetString(i), self.list.IsChecked(i)
|
|
self.list.Delete(i)
|
|
self.list.InsertItems([str], i+1)
|
|
self.list.Check(i+1, ch)
|
|
self.list.SetSelection(i+1)
|
|
def OnButtonAppend(self, evt):
|
|
str = wx.GetTextFromUser('Enter new item:', 'Append', '', self)
|
|
self.list.Append(str)
|
|
def OnButtonRemove(self, evt):
|
|
self.list.Delete(self.list.GetSelection())
|
|
def OnUpdateUI(self, evt):
|
|
if evt.GetId() == self.ID_BUTTON_REMOVE:
|
|
evt.Enable(self.list.GetSelection() != -1)
|
|
elif evt.GetId() == self.ID_BUTTON_UP:
|
|
evt.Enable(self.list.GetSelection() > 0)
|
|
elif evt.GetId() == self.ID_BUTTON_DOWN:
|
|
evt.Enable(self.list.GetSelection() != -1 and \
|
|
self.list.GetSelection() < self.list.GetCount() - 1)
|
|
|
|
class ParamContent(PPanel):
|
|
def __init__(self, parent, name):
|
|
PPanel.__init__(self, parent, name)
|
|
self.ID_TEXT_CTRL = wx.NewId()
|
|
self.ID_BUTTON_EDIT = wx.NewId()
|
|
sizer = wx.BoxSizer()
|
|
self.text = wx.TextCtrl(self, self.ID_TEXT_CTRL, size=wx.Size(200,-1))
|
|
sizer.Add(self.text, 0, wx.RIGHT | wx.ALIGN_CENTER_VERTICAL, 5)
|
|
self.button = wx.Button(self, self.ID_BUTTON_EDIT, 'Edit...', size=buttonSize)
|
|
sizer.Add(self.button, 0, wx.ALIGN_CENTER_VERTICAL)
|
|
self.SetSizer(sizer)
|
|
self.textModified = False
|
|
wx.EVT_BUTTON(self, self.ID_BUTTON_EDIT, self.OnButtonEdit)
|
|
wx.EVT_TEXT(self, self.ID_TEXT_CTRL, self.OnChange)
|
|
def OnChange(self, evt):
|
|
PPanel.OnChange(self, evt)
|
|
self.textModified = True
|
|
def GetValue(self):
|
|
if self.textModified: # text has newer value
|
|
try:
|
|
return self.text.GetValue().split('|')
|
|
except ValueError:
|
|
return []
|
|
return self.value
|
|
def SetValue(self, value):
|
|
self.freeze = True
|
|
if not value: value = []
|
|
self.value = value
|
|
repr_ = '|'.join(map(str, value))
|
|
self.text.SetValue(repr_) # update text ctrl
|
|
self.freeze = False
|
|
def OnButtonEdit(self, evt):
|
|
if self.textModified: # text has newer value
|
|
self.value = self.GetValue()
|
|
dlg = ContentDialog(self, self.value)
|
|
if dlg.ShowModal() == wx.ID_OK:
|
|
value = []
|
|
for i in range(dlg.list.GetCount()):
|
|
value.append(dlg.list.GetString(i))
|
|
self.SetValue(value)
|
|
self.SetModified()
|
|
self.textModified = False
|
|
dlg.Destroy()
|
|
def SetModified(self, state=True):
|
|
PPanel.SetModified(self, state)
|
|
self.textModified = False
|
|
|
|
# CheckList content
|
|
class ParamContentCheckList(ParamContent):
|
|
def __init__(self, parent, name):
|
|
ParamContent.__init__(self, parent, name)
|
|
def OnButtonEdit(self, evt):
|
|
if self.textModified: # text has newer value
|
|
self.value = self.GetValue()
|
|
dlg = ContentCheckListDialog(self, self.value)
|
|
if dlg.ShowModal() == wx.ID_OK:
|
|
value = []
|
|
for i in range(dlg.list.GetCount()):
|
|
value.append((dlg.list.GetString(i), int(dlg.list.IsChecked(i))))
|
|
self.SetValue(value)
|
|
self.SetModified()
|
|
self.textModified = False
|
|
dlg.Destroy()
|
|
def SetValue(self, value):
|
|
self.freeze = True
|
|
if not value: value = []
|
|
self.value = value
|
|
repr_ = '|'.join(map(str,value))
|
|
self.text.SetValue(repr_) # update text ctrl
|
|
self.freeze = False
|
|
|
|
class IntListDialog(wx.Dialog):
|
|
def __init__(self, parent, value):
|
|
pre = wx.PreDialog()
|
|
g.frame.res.LoadOnDialog(pre, parent, 'DIALOG_INTLIST')
|
|
self.PostCreate(pre)
|
|
self.list = xrc.XRCCTRL(self, 'LIST')
|
|
# Set list items
|
|
value.sort()
|
|
for v in value:
|
|
if type(v) != IntType:
|
|
wx.LogError('Invalid item type')
|
|
else:
|
|
self.list.Append(str(v))
|
|
self.SetAutoLayout(True)
|
|
self.GetSizer().Fit(self)
|
|
# Callbacks
|
|
self.spinCtrl = xrc.XRCCTRL(self, 'SPIN')
|
|
wx.EVT_BUTTON(self, xrc.XRCID('BUTTON_ADD'), self.OnButtonAdd)
|
|
self.ID_BUTTON_REMOVE = xrc.XRCID('BUTTON_REMOVE')
|
|
wx.EVT_BUTTON(self, self.ID_BUTTON_REMOVE, self.OnButtonRemove)
|
|
wx.EVT_BUTTON(self, xrc.XRCID('BUTTON_CLEAR'), self.OnButtonClear)
|
|
wx.EVT_UPDATE_UI(self, self.ID_BUTTON_REMOVE, self.OnUpdateUI)
|
|
def OnButtonAdd(self, evt):
|
|
# Check that it's unique
|
|
try:
|
|
v = self.spinCtrl.GetValue()
|
|
s = str(v) # to be sure
|
|
i = self.list.FindString(s)
|
|
if i == -1: # ignore non-unique
|
|
# Find place to insert
|
|
found = False
|
|
for i in range(self.list.GetCount()):
|
|
if int(self.list.GetString(i)) > v:
|
|
found = True
|
|
break
|
|
if found: self.list.InsertItems([s], i)
|
|
else: self.list.Append(s)
|
|
except ValueError:
|
|
wx.LogError('List item is not an int!')
|
|
def OnButtonRemove(self, evt):
|
|
self.list.Delete(self.list.GetSelection())
|
|
def OnButtonClear(self, evt):
|
|
self.list.Clear()
|
|
def OnUpdateUI(self, evt):
|
|
if evt.GetId() == self.ID_BUTTON_REMOVE:
|
|
evt.Enable(self.list.GetSelection() != -1)
|
|
|
|
# For growable list
|
|
class ParamIntList(ParamContent):
|
|
def __init__(self, parent, name):
|
|
ParamContent.__init__(self, parent, name)
|
|
def OnButtonEdit(self, evt):
|
|
if self.textModified: # text has newer value
|
|
try:
|
|
self.value = map(int, self.text.GetValue().split('|'))
|
|
except ValueError:
|
|
self.value = []
|
|
dlg = IntListDialog(self, self.value)
|
|
if dlg.ShowModal() == wx.ID_OK:
|
|
value = []
|
|
for i in range(dlg.list.GetCount()):
|
|
value.append(int(dlg.list.GetString(i)))
|
|
self.SetValue(value)
|
|
self.SetModified()
|
|
self.textModified = False
|
|
dlg.Destroy()
|
|
|
|
# Boxless radiobox
|
|
class RadioBox(PPanel):
|
|
def __init__(self, parent, id, choices,
|
|
pos=wx.DefaultPosition, name='radiobox'):
|
|
PPanel.__init__(self, parent, name)
|
|
self.choices = choices
|
|
topSizer = wx.BoxSizer()
|
|
for i in choices:
|
|
button = wx.RadioButton(self, -1, i, size=(-1,buttonSize[1]), name=i)
|
|
topSizer.Add(button, 0, wx.RIGHT, 5)
|
|
wx.EVT_RADIOBUTTON(self, button.GetId(), self.OnRadioChoice)
|
|
self.SetSizer(topSizer)
|
|
def SetStringSelection(self, value):
|
|
self.freeze = True
|
|
for i in self.choices:
|
|
self.FindWindowByName(i).SetValue(i == value)
|
|
self.value = value
|
|
self.freeze = False
|
|
def OnRadioChoice(self, evt):
|
|
if self.freeze: return
|
|
if evt.GetSelection():
|
|
self.value = evt.GetEventObject().GetName()
|
|
self.SetModified()
|
|
def GetStringSelection(self):
|
|
return self.value
|
|
|
|
class ParamBool(RadioBox):
|
|
values = {'yes': '1', 'no': '0'}
|
|
seulav = {'1': 'yes', '0': 'no'}
|
|
def __init__(self, parent, name):
|
|
RadioBox.__init__(self, parent, -1, choices=self.values.keys(), name=name)
|
|
def GetValue(self):
|
|
return self.values[self.GetStringSelection()]
|
|
def SetValue(self, value):
|
|
if not value: value = '1'
|
|
self.SetStringSelection(self.seulav[value])
|
|
|
|
class ParamOrient(RadioBox):
|
|
values = {'horizontal': 'wxHORIZONTAL', 'vertical': 'wxVERTICAL'}
|
|
seulav = {'wxHORIZONTAL': 'horizontal', 'wxVERTICAL': 'vertical'}
|
|
def __init__(self, parent, name):
|
|
RadioBox.__init__(self, parent, -1, choices=self.values.keys(), name=name)
|
|
def GetValue(self):
|
|
return self.values[self.GetStringSelection()]
|
|
def SetValue(self, value):
|
|
if not value: value = 'wxHORIZONTAL'
|
|
self.SetStringSelection(self.seulav[value])
|
|
|
|
class ParamOrientation(RadioBox):
|
|
values = {'horizontal': 'horizontal', 'vertical': 'vertical'}
|
|
seulav = {'horizontal': 'horizontal', 'vertical': 'vertical'}
|
|
def __init__(self, parent, name):
|
|
RadioBox.__init__(self, parent, -1, choices=self.values.keys(), name=name)
|
|
def GetValue(self):
|
|
return self.values[self.GetStringSelection()]
|
|
def SetValue(self, value):
|
|
if not value: value = 'vertical'
|
|
self.SetStringSelection(self.seulav[value])
|
|
|
|
class ParamFile(PPanel):
|
|
def __init__(self, parent, name):
|
|
PPanel.__init__(self, parent, name)
|
|
self.ID_TEXT_CTRL = wx.NewId()
|
|
self.ID_BUTTON_BROWSE = wx.NewId()
|
|
sizer = wx.BoxSizer()
|
|
self.text = wx.TextCtrl(self, self.ID_TEXT_CTRL, size=wx.Size(200,-1))
|
|
sizer.Add(self.text, 0, wx.RIGHT | wx.ALIGN_CENTER_VERTICAL, 5)
|
|
self.button = wx.Button(self, self.ID_BUTTON_BROWSE, 'Browse...',size=buttonSize)
|
|
sizer.Add(self.button, 0, wx.ALIGN_CENTER_VERTICAL)
|
|
self.SetSizer(sizer)
|
|
self.textModified = False
|
|
wx.EVT_BUTTON(self, self.ID_BUTTON_BROWSE, self.OnButtonBrowse)
|
|
wx.EVT_TEXT(self, self.ID_TEXT_CTRL, self.OnChange)
|
|
def OnChange(self, evt):
|
|
PPanel.OnChange(self, evt)
|
|
self.textModified = True
|
|
def GetValue(self):
|
|
if self.textModified: # text has newer value
|
|
return self.text.GetValue()
|
|
return self.value
|
|
def SetValue(self, value):
|
|
self.freeze = True
|
|
self.value = value
|
|
self.text.SetValue(value) # update text ctrl
|
|
self.freeze = False
|
|
def OnButtonBrowse(self, evt):
|
|
if self.textModified: # text has newer value
|
|
self.value = self.text.GetValue()
|
|
dlg = wx.FileDialog(self,
|
|
defaultDir = os.path.abspath(os.path.dirname(self.value)),
|
|
defaultFile = os.path.basename(self.value))
|
|
if dlg.ShowModal() == wx.ID_OK:
|
|
# Get common part of selected path and current
|
|
if g.frame.dataFile:
|
|
curpath = os.path.abspath(g.frame.dataFile)
|
|
else:
|
|
curpath = os.path.join(os.getcwd(), '')
|
|
common = os.path.commonprefix([curpath, dlg.GetPath()])
|
|
self.SetValue(dlg.GetPath()[len(common):])
|
|
self.SetModified()
|
|
self.textModified = False
|
|
dlg.Destroy()
|
|
|
|
class ParamBitmap(PPanel):
|
|
def __init__(self, parent, name):
|
|
pre = wx.PrePanel()
|
|
g.frame.res.LoadOnPanel(pre, parent, 'PANEL_BITMAP')
|
|
self.PostCreate(pre)
|
|
self.modified = self.freeze = False
|
|
self.radio_std = xrc.XRCCTRL(self, 'RADIO_STD')
|
|
self.radio_file = xrc.XRCCTRL(self, 'RADIO_FILE')
|
|
self.combo = xrc.XRCCTRL(self, 'COMBO_STD')
|
|
self.text = xrc.XRCCTRL(self, 'TEXT_FILE')
|
|
self.button = xrc.XRCCTRL(self, 'BUTTON_BROWSE')
|
|
self.textModified = False
|
|
self.SetAutoLayout(True)
|
|
self.GetSizer().SetMinSize((260, -1))
|
|
self.GetSizer().Fit(self)
|
|
wx.EVT_RADIOBUTTON(self, xrc.XRCID('RADIO_STD'), self.OnRadioStd)
|
|
wx.EVT_RADIOBUTTON(self, xrc.XRCID('RADIO_FILE'), self.OnRadioFile)
|
|
wx.EVT_BUTTON(self, xrc.XRCID('BUTTON_BROWSE'), self.OnButtonBrowse)
|
|
wx.EVT_COMBOBOX(self, xrc.XRCID('COMBO_STD'), self.OnCombo)
|
|
wx.EVT_TEXT(self, xrc.XRCID('COMBO_STD'), self.OnChange)
|
|
wx.EVT_TEXT(self, xrc.XRCID('TEXT_FILE'), self.OnChange)
|
|
def OnRadioStd(self, evt):
|
|
self.SetModified()
|
|
self.SetValue(['wxART_MISSING_IMAGE',''])
|
|
def OnRadioFile(self, evt):
|
|
self.SetModified()
|
|
self.SetValue(['',''])
|
|
def updateRadios(self):
|
|
if self.value[0]:
|
|
self.radio_std.SetValue(True)
|
|
self.radio_file.SetValue(False)
|
|
self.text.Enable(False)
|
|
self.button.Enable(False)
|
|
self.combo.Enable(True)
|
|
else:
|
|
self.radio_std.SetValue(False)
|
|
self.radio_file.SetValue(True)
|
|
self.text.Enable(True)
|
|
self.button.Enable(True)
|
|
self.combo.Enable(False)
|
|
def OnChange(self, evt):
|
|
PPanel.OnChange(self, evt)
|
|
self.textModified = True
|
|
def OnCombo(self, evt):
|
|
PPanel.OnChange(self, evt)
|
|
self.value[0] = self.combo.GetValue()
|
|
def GetValue(self):
|
|
if self.textModified: # text has newer value
|
|
return [self.combo.GetValue(), self.text.GetValue()]
|
|
return self.value
|
|
def SetValue(self, value):
|
|
self.freeze = True
|
|
if not value:
|
|
self.value = ['', '']
|
|
else:
|
|
self.value = value
|
|
self.combo.SetValue(self.value[0])
|
|
self.text.SetValue(self.value[1]) # update text ctrl
|
|
self.updateRadios()
|
|
self.freeze = False
|
|
def OnButtonBrowse(self, evt):
|
|
if self.textModified: # text has newer value
|
|
self.value[1] = self.text.GetValue()
|
|
dlg = wx.FileDialog(self,
|
|
defaultDir = os.path.abspath(os.path.dirname(self.value[1])),
|
|
defaultFile = os.path.basename(self.value[1]))
|
|
if dlg.ShowModal() == wx.ID_OK:
|
|
# Get common part of selected path and current
|
|
if g.frame.dataFile:
|
|
curpath = os.path.abspath(g.frame.dataFile)
|
|
else:
|
|
curpath = os.path.join(os.getcwd(), '')
|
|
common = os.path.commonprefix([curpath, dlg.GetPath()])
|
|
self.SetValue(['', dlg.GetPath()[len(common):]])
|
|
self.SetModified()
|
|
self.textModified = False
|
|
dlg.Destroy()
|
|
|
|
paramDict = {
|
|
'flag': ParamFlag,
|
|
'style': ParamStyle, 'exstyle': ParamExStyle,
|
|
'pos': ParamPosSize, 'size': ParamPosSize,
|
|
'cellpos': ParamPosSize, 'cellspan': ParamPosSize,
|
|
'border': ParamUnit, 'cols': ParamIntNN, 'rows': ParamIntNN,
|
|
'vgap': ParamUnit, 'hgap': ParamUnit,
|
|
'checkable': ParamBool, 'checked': ParamBool, 'radio': ParamBool,
|
|
'accel': ParamAccel,
|
|
'label': ParamMultilineText, 'title': ParamText, 'value': ParamText,
|
|
'content': ParamContent, 'selection': ParamIntNN,
|
|
'min': ParamInt, 'max': ParamInt,
|
|
'fg': ParamColour, 'bg': ParamColour, 'font': ParamFont,
|
|
'enabled': ParamBool, 'focused': ParamBool, 'hidden': ParamBool,
|
|
'tooltip': ParamText, 'bitmap': ParamBitmap, 'icon': ParamBitmap,
|
|
'encoding': ParamEncoding, 'borders': ParamUnit,
|
|
'comment': ParamComment
|
|
}
|