306b6fe972
------- Added new controls (Choicebook, Listbook, StatusBar, DatePicker), and completed style flags. Test window is opened for an available parent control if no specific view defined. Better handling of exceptions (highlighting does not 'stick' anymore). Tested on wxGTK 2.6.1.0. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@36156 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
955 lines
38 KiB
Python
955 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 *
|
|
from wxPython.xrc 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'
|
|
]
|
|
|
|
buttonSize = (35,-1) # in dialog units, transformed to pixels in panel ctor
|
|
|
|
# Class that can properly disable children
|
|
class PPanel(wxPanel):
|
|
def __init__(self, parent, name):
|
|
wxPanel.__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)
|
|
#wxPanel.Enable(self, value)
|
|
def SetModified(self):
|
|
self.modified = True
|
|
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 = wxNewId()
|
|
self.ID_BUTTON_CHOICES = wxNewId()
|
|
sizer = wxBoxSizer()
|
|
self.text = wxTextCtrl(self, self.ID_TEXT_CTRL, size=wxSize(200,-1))
|
|
sizer.Add(self.text, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, 5)
|
|
self.button = wxButton(self, self.ID_BUTTON_CHOICES, 'Edit...', size=buttonSize)
|
|
sizer.Add(self.button, 0, wxALIGN_CENTER_VERTICAL)
|
|
self.SetAutoLayout(True)
|
|
self.SetSizer(sizer)
|
|
sizer.Fit(self)
|
|
EVT_BUTTON(self, self.ID_BUTTON_CHOICES, self.OnButtonChoices)
|
|
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 = 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() == wxID_OK:
|
|
value = []
|
|
for i in range(listBox.GetCount()):
|
|
if listBox.IsChecked(i):
|
|
value.append(self.values[i])
|
|
# Add ignored flags
|
|
value.extend(ignored)
|
|
if value:
|
|
self.SetValue(reduce(lambda a,b: a+'|'+b, value))
|
|
else:
|
|
self.SetValue('')
|
|
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]
|
|
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 = XRCCTRL(dlg, 'CHECKLIST_SPECIFIC')
|
|
listBoxSpecific.InsertItems(self.valuesSpecific, 0)
|
|
listBoxGeneric = 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() == wxID_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
|
|
if value:
|
|
self.SetValue(reduce(lambda a,b: a+'|'+b, value))
|
|
else:
|
|
self.SetValue('')
|
|
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)
|
|
self.SetTitle('Extended window styles')
|
|
|
|
class ParamColour(PPanel):
|
|
def __init__(self, parent, name):
|
|
PPanel.__init__(self, parent, name)
|
|
self.ID_TEXT_CTRL = wxNewId()
|
|
self.ID_BUTTON = wxNewId()
|
|
sizer = wxBoxSizer()
|
|
self.text = wxTextCtrl(self, self.ID_TEXT_CTRL, size=(80,-1))
|
|
sizer.Add(self.text, 0, wxALIGN_CENTER_VERTICAL | wxTOP | wxBOTTOM, 2)
|
|
self.button = wxPanel(self, self.ID_BUTTON, wxDefaultPosition, wxSize(20, 20))
|
|
sizer.Add(self.button, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, 5)
|
|
self.SetAutoLayout(True)
|
|
self.SetSizer(sizer)
|
|
sizer.Fit(self)
|
|
self.textModified = False
|
|
EVT_PAINT(self.button, self.OnPaintButton)
|
|
EVT_TEXT(self, self.ID_TEXT_CTRL, self.OnChange)
|
|
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
|
|
colour = wxColour(int(value[1:3], 16), int(value[3:5], 16), int(value[5:7], 16))
|
|
self.button.SetBackgroundColour(colour)
|
|
self.button.Refresh()
|
|
self.freeze = False
|
|
def OnPaintButton(self, evt):
|
|
dc = wxPaintDC(self.button)
|
|
dc.SetBrush(wxTRANSPARENT_BRUSH)
|
|
if self.IsEnabled(): dc.SetPen(wxBLACK_PEN)
|
|
else: dc.SetPen(wxGREY_PEN)
|
|
size = self.button.GetSize()
|
|
dc.DrawRectangle(0, 0, size.width, size.height)
|
|
def OnLeftDown(self, evt):
|
|
data = wxColourData()
|
|
data.SetColour(self.GetValue())
|
|
dlg = wxColourDialog(self, data)
|
|
if dlg.ShowModal() == wxID_OK:
|
|
self.SetValue('#%02X%02X%02X' % dlg.GetColourData().GetColour().Get())
|
|
self.SetModified()
|
|
dlg.Destroy()
|
|
|
|
################################################################################
|
|
|
|
# Mapping from wx constants ro XML strings
|
|
fontFamiliesWx2Xml = {wxDEFAULT: 'default', wxDECORATIVE: 'decorative',
|
|
wxROMAN: 'roman', wxSCRIPT: 'script', wxSWISS: 'swiss',
|
|
wxMODERN: 'modern'}
|
|
fontStylesWx2Xml = {wxNORMAL: 'normal', wxSLANT: 'slant', wxITALIC: 'italic'}
|
|
fontWeightsWx2Xml = {wxNORMAL: 'normal', wxLIGHT: 'light', wxBOLD: '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 = wxNewId()
|
|
self.ID_BUTTON_SELECT = wxNewId()
|
|
sizer = wxBoxSizer()
|
|
self.text = wxTextCtrl(self, self.ID_TEXT_CTRL, size=(200,-1))
|
|
sizer.Add(self.text, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, 5)
|
|
self.button = wxButton(self, self.ID_BUTTON_SELECT, 'Select...', size=buttonSize)
|
|
sizer.Add(self.button, 0, wxALIGN_CENTER_VERTICAL)
|
|
self.SetAutoLayout(True)
|
|
self.SetSizer(sizer)
|
|
sizer.Fit(self)
|
|
self.textModified = False
|
|
EVT_BUTTON(self, self.ID_BUTTON_SELECT, self.OnButtonSelect)
|
|
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:
|
|
wxLogError('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:
|
|
wxLogError('Syntax error in parameter value: ' + self.GetName())
|
|
self.value = self._defaultValue()
|
|
# Make initial font
|
|
# Default values
|
|
size = g._sysFont.GetPointSize()
|
|
family = wxDEFAULT
|
|
style = weight = wxNORMAL
|
|
underlined = 0
|
|
face = ''
|
|
enc = wxFONTENCODING_DEFAULT
|
|
# Fall back to default if exceptions
|
|
error = False
|
|
try:
|
|
try: size = int(self.value[0])
|
|
except ValueError: error = True; wxLogError('Invalid size specification')
|
|
try: family = fontFamiliesXml2wx[self.value[1]]
|
|
except KeyError: error = True; wxLogError('Invalid family specification')
|
|
try: style = fontStylesXml2wx[self.value[2]]
|
|
except KeyError: error = True; wxLogError('Invalid style specification')
|
|
try: weight = fontWeightsXml2wx[self.value[3]]
|
|
except KeyError: error = True; wxLogError('Invalid weight specification')
|
|
try: underlined = bool(self.value[4])
|
|
except ValueError: error = True; wxLogError('Invalid underlined flag specification')
|
|
face = self.value[5]
|
|
except IndexError:
|
|
error = True
|
|
mapper = wxFontMapper()
|
|
if not self.value[6]: enc = mapper.CharsetToEncoding(self.value[6])
|
|
|
|
if error: wxLogError('Invalid font specification')
|
|
if enc == wxFONTENCODING_DEFAULT: enc = wxFONTENCODING_SYSTEM
|
|
font = wxFont(size, family, style, weight, underlined, face, enc)
|
|
data = wxFontData()
|
|
data.SetInitialFont(font)
|
|
dlg = wxFontDialog(self, data)
|
|
if dlg.ShowModal() == wxID_OK:
|
|
font = dlg.GetFontData().GetChosenFont()
|
|
print font.GetEncoding()
|
|
if font.GetEncoding() == wxFONTENCODING_SYSTEM:
|
|
encName = ''
|
|
else:
|
|
encName = wxFontMapper_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 = wxNewId()
|
|
sizer = wxBoxSizer()
|
|
self.spin = wxSpinCtrl(self, self.ID_SPIN_CTRL, size=(60,-1))
|
|
self.spin.SetRange(-2147483648, 2147483647) # min/max integers
|
|
sizer.Add(self.spin)
|
|
self.SetAutoLayout(True)
|
|
self.SetSizer(sizer)
|
|
sizer.Fit(self)
|
|
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 = wxNewId()
|
|
sizer = wxBoxSizer()
|
|
self.spin = wxSpinCtrl(self, self.ID_SPIN_CTRL, size=(60,-1))
|
|
self.spin.SetRange(0, 10000) # min/max integers
|
|
sizer.Add(self.spin)
|
|
self.SetAutoLayout(True)
|
|
self.SetSizer(sizer)
|
|
sizer.Fit(self)
|
|
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 = wxNewId()
|
|
self.ID_SPIN_BUTTON = wxNewId()
|
|
sizer = wxBoxSizer(wxHORIZONTAL)
|
|
self.spin = wxSpinButton(self, self.ID_SPIN_BUTTON, style = wxSP_VERTICAL, size=(-1,1))
|
|
textW = 60 - self.spin.GetSize()[0]
|
|
self.text = wxTextCtrl(self, self.ID_TEXT_CTRL, size=(textW,-1))
|
|
self.spin.SetRange(-10000, 10000)
|
|
sizer.Add(self.text, 0, wxEXPAND)
|
|
sizer.Add(self.spin, 0, wxEXPAND)
|
|
#sizer.SetMinSize((50,-1))
|
|
self.SetAutoLayout(True)
|
|
self.SetSizer(sizer)
|
|
sizer.Fit(self)
|
|
EVT_SPIN_UP(self, self.ID_SPIN_BUTTON, self.OnSpinUp)
|
|
EVT_SPIN_DOWN(self, self.ID_SPIN_BUTTON, self.OnSpinDown)
|
|
def GetValue(self):
|
|
return self.text.GetValue()
|
|
def SetValue(self, value):
|
|
self.freeze = True
|
|
if not value: value = '0'
|
|
self.text.SetValue(value)
|
|
self.freeze = False
|
|
def Change(self, x):
|
|
# 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)
|
|
self.text.SetValue(str(intValue) + units)
|
|
self.SetModified()
|
|
except:
|
|
# !!! Strange, if I use wxLogWarning, event is re-generated
|
|
print 'incorrect unit format'
|
|
def OnSpinUp(self, evt):
|
|
self.Change(1)
|
|
def OnSpinDown(self, evt):
|
|
self.Change(-1)
|
|
|
|
class ParamMultilineText(PPanel):
|
|
def __init__(self, parent, name, textWidth=-1):
|
|
PPanel.__init__(self, parent, name)
|
|
self.ID_TEXT_CTRL = wxNewId()
|
|
self.ID_BUTTON_EDIT = wxNewId()
|
|
sizer = wxBoxSizer()
|
|
self.text = wxTextCtrl(self, self.ID_TEXT_CTRL, size=wxSize(200,-1))
|
|
sizer.Add(self.text, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, 5)
|
|
self.button = wxButton(self, self.ID_BUTTON_EDIT, 'Edit...', size=buttonSize)
|
|
sizer.Add(self.button, 0, wxALIGN_CENTER_VERTICAL)
|
|
self.SetAutoLayout(True)
|
|
self.SetSizer(sizer)
|
|
sizer.Fit(self)
|
|
EVT_BUTTON(self, self.ID_BUTTON_EDIT, self.OnButtonEdit)
|
|
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 = XRCCTRL(dlg, 'TEXT')
|
|
textCtrl.SetValue(self.text.GetValue())
|
|
if dlg.ShowModal() == wxID_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 = wxNewId()
|
|
# We use sizer even here to have the same size of text control
|
|
sizer = wxBoxSizer()
|
|
self.text = wxTextCtrl(self, self.ID_TEXT_CTRL, size=wxSize(textWidth,-1))
|
|
if textWidth == -1: option = 1
|
|
else: option = 0
|
|
sizer.Add(self.text, option, wxALIGN_CENTER_VERTICAL | wxTOP | wxBOTTOM, 2)
|
|
self.SetAutoLayout(True)
|
|
self.SetSizer(sizer)
|
|
sizer.Fit(self)
|
|
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 ContentDialog(wxDialog):
|
|
def __init__(self, parent, value):
|
|
# Load from resource
|
|
pre = wxPreDialog()
|
|
g.frame.res.LoadOnDialog(pre, parent, 'DIALOG_CONTENT')
|
|
self.this = pre.this
|
|
self._setOORInfo(self)
|
|
self.list = 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 = XRCID('BUTTON_APPEND')
|
|
self.ID_BUTTON_REMOVE = XRCID('BUTTON_REMOVE')
|
|
self.ID_BUTTON_UP = XRCID('BUTTON_UP')
|
|
self.ID_BUTTON_DOWN = XRCID('BUTTON_DOWN')
|
|
EVT_BUTTON(self, self.ID_BUTTON_UP, self.OnButtonUp)
|
|
EVT_BUTTON(self, self.ID_BUTTON_DOWN, self.OnButtonDown)
|
|
EVT_BUTTON(self, self.ID_BUTTON_APPEND, self.OnButtonAppend)
|
|
EVT_BUTTON(self, self.ID_BUTTON_REMOVE, self.OnButtonRemove)
|
|
EVT_UPDATE_UI(self, self.ID_BUTTON_UP, self.OnUpdateUI)
|
|
EVT_UPDATE_UI(self, self.ID_BUTTON_DOWN, self.OnUpdateUI)
|
|
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 = wxGetTextFromUser('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(wxDialog):
|
|
def __init__(self, parent, value):
|
|
pre = wxPreDialog()
|
|
g.frame.res.LoadOnDialog(pre, parent, 'DIALOG_CONTENT_CHECKLIST')
|
|
self.this = pre.this
|
|
self._setOORInfo(self)
|
|
self.list = XRCCTRL(self, 'CHECKLIST')
|
|
# 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 = XRCID('BUTTON_APPEND')
|
|
self.ID_BUTTON_REMOVE = XRCID('BUTTON_REMOVE')
|
|
self.ID_BUTTON_UP = XRCID('BUTTON_UP')
|
|
self.ID_BUTTON_DOWN = XRCID('BUTTON_DOWN')
|
|
EVT_CHECKLISTBOX(self, self.list.GetId(), self.OnCheck)
|
|
EVT_BUTTON(self, self.ID_BUTTON_UP, self.OnButtonUp)
|
|
EVT_BUTTON(self, self.ID_BUTTON_DOWN, self.OnButtonDown)
|
|
EVT_BUTTON(self, self.ID_BUTTON_APPEND, self.OnButtonAppend)
|
|
EVT_BUTTON(self, self.ID_BUTTON_REMOVE, self.OnButtonRemove)
|
|
EVT_UPDATE_UI(self, self.ID_BUTTON_UP, self.OnUpdateUI)
|
|
EVT_UPDATE_UI(self, self.ID_BUTTON_DOWN, self.OnUpdateUI)
|
|
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 = wxGetTextFromUser('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 = wxNewId()
|
|
self.ID_BUTTON_EDIT = wxNewId()
|
|
sizer = wxBoxSizer()
|
|
self.text = wxTextCtrl(self, self.ID_TEXT_CTRL, size=wxSize(200,-1))
|
|
sizer.Add(self.text, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, 5)
|
|
self.button = wxButton(self, self.ID_BUTTON_EDIT, 'Edit...', size=buttonSize)
|
|
sizer.Add(self.button, 0, wxALIGN_CENTER_VERTICAL)
|
|
self.SetAutoLayout(True)
|
|
self.SetSizer(sizer)
|
|
sizer.Fit(self)
|
|
self.textModified = False
|
|
EVT_BUTTON(self, self.ID_BUTTON_EDIT, self.OnButtonEdit)
|
|
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 eval(self.text.GetValue())
|
|
except SyntaxError:
|
|
wxLogError('Syntax error in parameter value: ' + self.GetName())
|
|
return []
|
|
return self.value
|
|
def SetValue(self, value):
|
|
self.freeze = True
|
|
if not value: value = []
|
|
self.value = value
|
|
self.text.SetValue(str(value)) # update text ctrl
|
|
self.freeze = False
|
|
def OnButtonEdit(self, evt):
|
|
if self.textModified: # text has newer value
|
|
try:
|
|
self.value = eval(self.text.GetValue())
|
|
except SyntaxError:
|
|
wxLogError('Syntax error in parameter value: ' + self.GetName())
|
|
self.value = []
|
|
dlg = ContentDialog(self, self.value)
|
|
if dlg.ShowModal() == wxID_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()
|
|
|
|
# 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
|
|
try:
|
|
self.value = eval(self.text.GetValue())
|
|
except SyntaxError:
|
|
wxLogError('Syntax error in parameter value: ' + self.GetName())
|
|
self.value = []
|
|
dlg = ContentCheckListDialog(self, self.value)
|
|
if dlg.ShowModal() == wxID_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()
|
|
|
|
class IntListDialog(wxDialog):
|
|
def __init__(self, parent, value):
|
|
pre = wxPreDialog()
|
|
g.frame.res.LoadOnDialog(pre, parent, 'DIALOG_INTLIST')
|
|
self.this = pre.this
|
|
self._setOORInfo(self)
|
|
self.list = XRCCTRL(self, 'LIST')
|
|
# Set list items
|
|
value.sort()
|
|
for v in value:
|
|
if type(v) != IntType:
|
|
wxLogError('Invalid item type')
|
|
else:
|
|
self.list.Append(str(v))
|
|
self.SetAutoLayout(True)
|
|
self.GetSizer().Fit(self)
|
|
# Callbacks
|
|
self.spinCtrl = XRCCTRL(self, 'SPIN')
|
|
EVT_BUTTON(self, XRCID('BUTTON_ADD'), self.OnButtonAdd)
|
|
self.ID_BUTTON_REMOVE = XRCID('BUTTON_REMOVE')
|
|
EVT_BUTTON(self, self.ID_BUTTON_REMOVE, self.OnButtonRemove)
|
|
EVT_BUTTON(self, XRCID('BUTTON_CLEAR'), self.OnButtonClear)
|
|
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:
|
|
wxLogError('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 = eval(self.text.GetValue())
|
|
except SyntaxError:
|
|
wxLogError('Syntax error in parameter value: ' + self.GetName())
|
|
self.value = []
|
|
dlg = IntListDialog(self, self.value)
|
|
if dlg.ShowModal() == wxID_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=wxDefaultPosition, name='radiobox'):
|
|
PPanel.__init__(self, parent, name)
|
|
self.choices = choices
|
|
topSizer = wxBoxSizer()
|
|
for i in choices:
|
|
button = wxRadioButton(self, -1, i, size=(-1,buttonSize[1]), name=i)
|
|
topSizer.Add(button, 0, wxRIGHT, 5)
|
|
EVT_RADIOBUTTON(self, button.GetId(), self.OnRadioChoice)
|
|
self.SetAutoLayout(True)
|
|
self.SetSizer(topSizer)
|
|
topSizer.Fit(self)
|
|
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 = wxNewId()
|
|
self.ID_BUTTON_BROWSE = wxNewId()
|
|
sizer = wxBoxSizer()
|
|
self.text = wxTextCtrl(self, self.ID_TEXT_CTRL, size=wxSize(200,-1))
|
|
sizer.Add(self.text, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, 5)
|
|
self.button = wxButton(self, self.ID_BUTTON_BROWSE, 'Browse...',size=buttonSize)
|
|
sizer.Add(self.button, 0, wxALIGN_CENTER_VERTICAL)
|
|
self.SetAutoLayout(True)
|
|
self.SetSizer(sizer)
|
|
sizer.Fit(self)
|
|
self.textModified = False
|
|
EVT_BUTTON(self, self.ID_BUTTON_BROWSE, self.OnButtonBrowse)
|
|
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 = wxFileDialog(self,
|
|
defaultDir = os.path.abspath(os.path.dirname(self.value)),
|
|
defaultFile = os.path.basename(self.value))
|
|
if dlg.ShowModal() == wxID_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 = wxPrePanel()
|
|
g.frame.res.LoadOnPanel(pre, parent, 'PANEL_BITMAP')
|
|
self.this = pre.this
|
|
self._setOORInfo(self)
|
|
self.modified = self.freeze = False
|
|
self.radio_std = XRCCTRL(self, 'RADIO_STD')
|
|
self.radio_file = XRCCTRL(self, 'RADIO_FILE')
|
|
self.combo = XRCCTRL(self, 'COMBO_STD')
|
|
self.text = XRCCTRL(self, 'TEXT_FILE')
|
|
self.button = XRCCTRL(self, 'BUTTON_BROWSE')
|
|
self.textModified = False
|
|
self.SetAutoLayout(True)
|
|
self.GetSizer().SetMinSize((260, -1))
|
|
self.GetSizer().Fit(self)
|
|
EVT_RADIOBUTTON(self, XRCID('RADIO_STD'), self.OnRadioStd)
|
|
EVT_RADIOBUTTON(self, XRCID('RADIO_FILE'), self.OnRadioFile)
|
|
EVT_BUTTON(self, XRCID('BUTTON_BROWSE'), self.OnButtonBrowse)
|
|
EVT_COMBOBOX(self, XRCID('COMBO_STD'), self.OnCombo)
|
|
EVT_TEXT(self, XRCID('COMBO_STD'), self.OnChange)
|
|
EVT_TEXT(self, 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 = wxFileDialog(self,
|
|
defaultDir = os.path.abspath(os.path.dirname(self.value[1])),
|
|
defaultFile = os.path.basename(self.value[1]))
|
|
if dlg.ShowModal() == wxID_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
|
|
}
|