Läuft die Voice Acoustic VA-Remotecontrol (AllDSP AllControl) nativ unter Linux auf echtem wxGTK 3.0 — ohne Wine und ohne dekompilierten App-Code. Ausgeführt wird das unveränderte Python-2.7-Bytecode aus dem macOS-.app; C-Extensions (wxGTK/numpy/ scipy/PortAudio) kommen nativ aus Debian stretch. Enthält: va/ (Original-.pyc + pure-Python-Libs + Assets + launch.py mit den drei Linux-Fixes), Dockerfile/run.sh/entrypoint.sh, reference/ (dekompilierter Quellcode zum Debuggen) und README/STATUS. img.cache (378 MB, regenerierbar) ist per .gitignore ausgeschlossen. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
4036 lines
155 KiB
Python
4036 lines
155 KiB
Python
# uncompyle6 version 3.9.3
|
|
# Python bytecode version base 2.6 (62161)
|
|
# Decompiled from: Python 3.9.25 (main, Oct 31 2025, 23:16:49)
|
|
# [GCC 14.2.0]
|
|
# Embedded file name: svg_panel.pyc
|
|
# Compiled at: 2025-05-23 10:33:00
|
|
import types, os.path, sys, xml.etree.cElementTree as etree, math, threading, random, mytime, data_model, wx, one_unit, svg, svg.document, future, control_panel, string, copy, traceback, protocol, inspect, wx.lib.scrolledpanel, dialog
|
|
from definitions import *
|
|
mac_names = 'posix'
|
|
|
|
def getString(strID):
|
|
return one_unit.getString(strID)
|
|
|
|
|
|
class SVG_Panel(wx.Panel):
|
|
"""wxPanel rendering SVG graphics in the background, and allowing
|
|
to position some controls precisely over some background elements"""
|
|
|
|
def __init__(self, parent, id=-1, pos=(-1, -1), size=(-1, -1), style=0, name='svg_panel', svg_doc=None, svg_id=None):
|
|
size = (0, 0)
|
|
self.render_keys = {}
|
|
self.render_elements = {}
|
|
self.parent = parent
|
|
self.load_impedances = {}
|
|
self.default_load_impedance = 4.0
|
|
self.name = name
|
|
self.size = (-1, -1)
|
|
self.timestamp = 0
|
|
super(SVG_Panel, self).__init__(parent, id, pos, size, style, name)
|
|
self.Show(True)
|
|
self.local_init(svg_doc, svg_id)
|
|
self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)
|
|
self.moved_screen = False
|
|
self.needs_rendering = True
|
|
self.gc = None
|
|
return self
|
|
|
|
def render_me(self, element):
|
|
if self.full_screen_diagram:
|
|
return False
|
|
else:
|
|
if element in self.fixed_render:
|
|
return self.fixed_render[element]
|
|
try:
|
|
if element in self.channelFlagShow:
|
|
mask = self.channelFlagShow[element]
|
|
if mask == 'always':
|
|
return True
|
|
except:
|
|
traceback.print_exc(file=sys.stdout)
|
|
|
|
if element not in self.render_keys:
|
|
s_element = element
|
|
for s in ('_off', '_on', '_over', '_bg', '_max', '_min'):
|
|
s_element = s_element.replace(s, '')
|
|
|
|
for s in ('', '_slider', '_knob'):
|
|
try:
|
|
(ctrl, key, var_name) = self.controls[s_element + s]
|
|
break
|
|
except:
|
|
key = None
|
|
|
|
if key == None:
|
|
if s_element in self.custom_access_key:
|
|
key = s_element
|
|
self.render_keys[element] = key
|
|
self.render_elements[element] = s_element
|
|
if s_element in self.fixed_render:
|
|
self.fixed_render[element] = self.fixed_render[s_element]
|
|
return self.fixed_render[s_element]
|
|
else:
|
|
key = self.render_keys[element]
|
|
element = self.render_elements[element]
|
|
try:
|
|
if element in self.channelFlagMask:
|
|
mask = self.channelFlagMask[element]
|
|
for channel in mask:
|
|
if channel in self.parent.userBits:
|
|
if mask[channel] & self.parent.userBits[channel] > 0:
|
|
return False
|
|
|
|
except:
|
|
traceback.print_exc(file=sys.stdout)
|
|
|
|
try:
|
|
if element in self.channelFlagShow:
|
|
mask = self.channelFlagShow[element]
|
|
if mask == 'never':
|
|
return False
|
|
for channel in mask:
|
|
if channel in self.parent.userBits:
|
|
if mask[channel] & self.parent.userBits[channel] > 0:
|
|
return True
|
|
|
|
except:
|
|
traceback.print_exc(file=sys.stdout)
|
|
|
|
if key == None:
|
|
if element.startswith('cs_') == True:
|
|
try:
|
|
element = self.render_elements[element]
|
|
except:
|
|
pass
|
|
|
|
(accessrights, current_user) = self.parent.get_access()
|
|
if element.lower().find('xover') != -1:
|
|
if accessrights & protocol.arOutChannel == 0:
|
|
return False
|
|
if element.lower().find('cs_out') != -1:
|
|
if accessrights & protocol.arOutChannel == 0:
|
|
return False
|
|
channel = int(element.lower().replace('cs_out', '').replace('_', '').strip()) + 127
|
|
if channel in self.parent.enabled_channels and self.parent.enabled_channels[channel] == False:
|
|
return False
|
|
if channel in self.parent.hideBridgedChannel and self.parent.hideBridgedChannel[channel] == True:
|
|
return False
|
|
if element.lower().find('cs_in') != -1:
|
|
if accessrights & protocol.arInChannel == 0:
|
|
return False
|
|
try:
|
|
channel = int(element.lower().replace('cs_in', '').replace('_', '').strip()) - 1
|
|
except:
|
|
try:
|
|
channel = ord(element.lower().replace('cs_in', '').replace('_', '').strip()) - ord('a')
|
|
except:
|
|
channel = None
|
|
print mytime.displayTime(), 'sp.rm.failed to extract channel from', element
|
|
traceback.print_exc(file=sys.stdout)
|
|
|
|
else:
|
|
if channel in self.parent.enabled_channels and self.parent.enabled_channels[channel] == False:
|
|
return False
|
|
if channel in self.parent.hideBridgedChannel and self.parent.hideBridgedChannel[channel] == True:
|
|
return False
|
|
if element in self.visibility_key:
|
|
testkey = self.visibility_key[element]
|
|
testval = self.visibility_value[element]
|
|
testmask = self.visibility_mask[element]
|
|
val = self.parent.model.get(testkey)
|
|
try:
|
|
if int(val) & testmask == testval:
|
|
return not self.visibility_invert[element]
|
|
else:
|
|
return self.visibility_invert[element]
|
|
except:
|
|
return False
|
|
|
|
return True
|
|
else:
|
|
return True
|
|
if isinstance(key, str):
|
|
channel = None
|
|
try:
|
|
if key.find('select_speaker') >= 0:
|
|
channel = int(key[key.rfind('_') + 1:])
|
|
channel += 128
|
|
else:
|
|
try:
|
|
channel = int(key[key.find('(') + 1:key.find(')')])
|
|
except:
|
|
traceback.print_exc(file=sys.stdout)
|
|
raise
|
|
|
|
except:
|
|
print mytime.displayTime(), 'sp.rm.Hoe krijg ik het kanaal van deze string?', key, key[key.rfind('_') + 1:]
|
|
traceback.print_exc(file=sys.stdout)
|
|
|
|
elif key.channel == -1:
|
|
channel = self.current_channel
|
|
else:
|
|
channel = key.channel
|
|
if key.member_id == protocol.MEMBER_ID_THRESHOLD_LIMIT:
|
|
channel += 128
|
|
if channel in self.parent.enabled_channels and self.parent.enabled_channels[channel] == False and key.channel >= 0:
|
|
return False
|
|
if channel in self.parent.hideBridgedChannel and self.parent.hideBridgedChannel[channel] == True and key.channel >= 0:
|
|
return False
|
|
if key.struct_id == protocol.STRUCT_ID_LINK and channel + 1 in self.parent.hideBridgedChannel and self.parent.hideBridgedChannel[channel + 1] == True and key.channel >= 0:
|
|
return False
|
|
try:
|
|
if key.struct_id == protocol.STRUCT_ID_MIXER and key.num in self.parent.enabled_channels and self.parent.enabled_channels[key.num] == False:
|
|
return False
|
|
except:
|
|
pass
|
|
|
|
if element in self.visibility_key:
|
|
testkey = self.visibility_key[element]
|
|
testval = self.visibility_value[element]
|
|
testmask = self.visibility_mask[element]
|
|
val = self.parent.model.get(testkey)
|
|
try:
|
|
if int(val) & testmask == testval:
|
|
return not self.visibility_invert[element]
|
|
else:
|
|
return self.visibility_invert[element]
|
|
except:
|
|
return False
|
|
|
|
if key in self.custom_access_key:
|
|
if self.parent.preset_accessrights & self.custom_access_key[key] == 0:
|
|
return self.invert_custom_access_key[key]
|
|
else:
|
|
return not self.invert_custom_access_key[key]
|
|
if isinstance(key, str):
|
|
return True
|
|
if key.struct_id == protocol.STRUCT_ID_LINK:
|
|
if channel & 254 in self.parent.enabled_channels and self.parent.enabled_channels[channel & 254] == False or channel | 1 in self.parent.enabled_channels and self.parent.enabled_channels[channel | 1] == False and key.channel >= 0:
|
|
return False
|
|
if key in self.parent.model.min_build_number:
|
|
if self.parent.active_unit.BuildNumber < self.parent.model.min_build_number[key]:
|
|
return False
|
|
if self.key_with_current_channel(key) in self.parent.model.min_build_number:
|
|
if self.parent.active_unit.BuildNumber < self.parent.model.min_build_number[self.key_with_current_channel(key)]:
|
|
return False
|
|
if key.struct_id in (protocol.STRUCT_ID_GLOBAL, protocol.STRUCT_ID_PRESET_GLOBAL, protocol.STRUCT_ID_COMMAND):
|
|
return True
|
|
if self.parent.preset_accessrights & 1 == 0 and channel < 128:
|
|
return False
|
|
if self.parent.preset_accessrights & 2 == 0 and channel >= 128:
|
|
return False
|
|
if key in self.select_rendering_by_channel:
|
|
if channel in self.select_rendering_by_channel[key]:
|
|
return True
|
|
else:
|
|
return False
|
|
return True
|
|
|
|
def parse_to_cache(self, doc_name):
|
|
entrytime = mytime.clock()
|
|
if not self.parent.svg_doc_cache.has_key(doc_name):
|
|
tree = etree.parse(doc_name)
|
|
svg_doc = svg.document.SVGDocument(tree.getroot(), 'file:' + doc_name, self)
|
|
self.parent.svg_doc_cache[doc_name] = svg_doc
|
|
return self.parent.svg_doc_cache[doc_name]
|
|
|
|
def Create(*args, **kwargs):
|
|
self = args[0]
|
|
wx.Panel.Create(*args, **kwargs)
|
|
SVG_Panel.local_init(*args, **kwargs)
|
|
return
|
|
|
|
def local_init(self, svg_doc, svg_id):
|
|
self.svg_doc = None
|
|
self.svg_id = None
|
|
self.rendercount = 0
|
|
self.svg_scale_x = self.parent.svg_scale_x
|
|
self.svg_scale_y = self.parent.svg_scale_y
|
|
self.dummy_focus = wx.TextCtrl(self, wx.ID_ANY, '')
|
|
self.dummy_focus.SetSize((1, 1))
|
|
self.dummy_focus.SetPosition((0, -10))
|
|
font = wx.Font(8, wx.FONTFAMILY_SWISS, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD)
|
|
self.SetFont(font)
|
|
self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)
|
|
self.Bind(wx.EVT_PAINT, self.OnPaint)
|
|
self.Bind(wx.EVT_MOTION, self.OnMotion)
|
|
self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
|
|
self.Bind(wx.EVT_LEFT_DCLICK, self.OnLeftDClick)
|
|
self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
|
|
self.Bind(wx.EVT_RIGHT_DOWN, self.OnRightDown)
|
|
self.svg_controls = []
|
|
self.inserted_ops = {}
|
|
self.currentPoint = [
|
|
0, 0]
|
|
self.ctrl_with_focus = None
|
|
self.ctrl_mouse_over = None
|
|
if svg_doc is None:
|
|
svg_doc = os.path.join(parent.next_skin_path, svg_id + '.svg')
|
|
if isinstance(svg_doc, svg.document.SVGDocument):
|
|
self.svg_doc = svg_doc
|
|
elif isinstance(svg_doc, types.StringTypes):
|
|
try:
|
|
self.svg_doc = self.parent.svg_doc_cache[svg_doc]
|
|
except KeyError:
|
|
self.svg_doc = self.parse_to_cache(svg_doc)
|
|
|
|
else:
|
|
raise TypeError('svg.document.SVGDocument expected for svg_doc')
|
|
if svg_id is None or isinstance(svg_id, types.StringTypes):
|
|
self.svg_id = svg_id
|
|
else:
|
|
raise TypeError('string expected for svg_id')
|
|
if svg_id is None:
|
|
self.svg_id = self.GetName()
|
|
self.svg_id = None
|
|
return
|
|
|
|
def hideByChannelFlag(self, e):
|
|
section = self.name + '|' + str(self.current_channel) + '|' + self.contextControlName
|
|
print mytime.displayTime(), 's_p.hBCF.channel flag mask:', self.channelFlagMask, self.name
|
|
if section in self.channelFlagMaskConfig.sections():
|
|
try:
|
|
bits = eval(self.channelFlagMaskConfig.get(section, 'channelFlagMask'))
|
|
except:
|
|
bits = {}
|
|
|
|
else:
|
|
bits = {}
|
|
for channel in self.parent.unit_channels:
|
|
if channel not in bits:
|
|
bits[channel] = 0
|
|
|
|
print mytime.displayTime(), 's_p.hBCF.bits:', bits
|
|
dial = dialog.mapOutputToInput(self.parent, bits, getString('ltcf') + ': ' + self.contextControlName)
|
|
dial.ShowModal()
|
|
res = dial.res
|
|
response = dial.response
|
|
dial.Destroy()
|
|
if response != 'OK':
|
|
return
|
|
zero = True
|
|
for channel in self.parent.unit_channels:
|
|
if res[channel] != 0:
|
|
zero = False
|
|
else:
|
|
del res[channel]
|
|
|
|
if zero:
|
|
self.channelFlagMaskConfig.remove_section(section)
|
|
elif section not in self.channelFlagMaskConfig.sections():
|
|
self.channelFlagMaskConfig.add_section(section)
|
|
self.channelFlagMaskConfig.set(section, 'channelFlagMask', res)
|
|
self.saveChannelFlagMaskConfig()
|
|
self.readChannelFlagMask()
|
|
return
|
|
|
|
def showByChannelFlag(self, e):
|
|
section = self.name + '|' + str(self.current_channel) + '|' + self.contextControlName
|
|
if section in self.channelFlagMaskConfig.sections():
|
|
try:
|
|
bits = eval(self.channelFlagMaskConfig.get(section, 'channelFlagShow'))
|
|
except:
|
|
bits = {}
|
|
|
|
else:
|
|
bits = {}
|
|
for channel in self.parent.unit_channels:
|
|
if channel not in bits:
|
|
bits[channel] = 0
|
|
|
|
dial = dialog.mapOutputToInput(self.parent, bits, getString('sbcf') + ': ' + self.contextControlName)
|
|
dial.ShowModal()
|
|
res = dial.res
|
|
response = dial.response
|
|
dial.Destroy()
|
|
if response != 'OK':
|
|
return
|
|
zero = True
|
|
for channel in self.parent.unit_channels:
|
|
if res[channel] != 0:
|
|
zero = False
|
|
else:
|
|
del res[channel]
|
|
|
|
if section not in self.channelFlagMaskConfig.sections():
|
|
self.channelFlagMaskConfig.add_section(section)
|
|
self.channelFlagMaskConfig.set(section, 'channelFlagShow', res)
|
|
self.saveChannelFlagMaskConfig()
|
|
self.readChannelFlagMask()
|
|
return
|
|
|
|
def showAlways(self, e):
|
|
section = self.name + '|' + str(self.current_channel) + '|' + self.contextControlName
|
|
if section not in self.channelFlagMaskConfig.sections():
|
|
self.channelFlagMaskConfig.add_section(section)
|
|
self.channelFlagMaskConfig.set(section, 'channelFlagShow', 'always')
|
|
self.saveChannelFlagMaskConfig()
|
|
self.readChannelFlagMask()
|
|
return
|
|
|
|
def hideAlways(self, e):
|
|
section = self.name + '|' + str(self.current_channel) + '|' + self.contextControlName
|
|
if section not in self.channelFlagMaskConfig.sections():
|
|
self.channelFlagMaskConfig.add_section(section)
|
|
self.channelFlagMaskConfig.set(section, 'channelFlagShow', 'never')
|
|
self.saveChannelFlagMaskConfig()
|
|
self.readChannelFlagMask()
|
|
return
|
|
|
|
def removeChannelFlags(self, e):
|
|
dlgMessage = getString('rcfm1') + ' ' + self.contextControlName + ' ' + getString('rcfm2')
|
|
dlgTitle = getString('rcft')
|
|
res = wx.MessageBox(dlgMessage, dlgTitle, wx.OK | wx.CANCEL)
|
|
if res != wx.OK:
|
|
return
|
|
section = self.name + '|' + str(self.current_channel) + '|' + self.contextControlName
|
|
print mytime.displayTime(), 's_p.rCF.channel flag mask:', self.channelFlagMask, self.name
|
|
print mytime.displayTime(), 's_p.rCF.channel flag show:', self.channelFlagShow, self.name
|
|
self.channelFlagMaskConfig.remove_section(section)
|
|
self.saveChannelFlagMaskConfig()
|
|
self.readChannelFlagMask()
|
|
return
|
|
|
|
def showContextMenu(self, item):
|
|
topMenu = wx.Menu()
|
|
if self.current_channel >= 0:
|
|
copy = wx.MenuItem(topMenu, wx.NewId(), getString('cpy'))
|
|
topMenu.AppendItem(copy)
|
|
self.Bind(wx.EVT_MENU, self.parent.OnCopy, copy)
|
|
paste = wx.MenuItem(topMenu, wx.NewId(), getString('pas'))
|
|
topMenu.AppendItem(paste)
|
|
self.Bind(wx.EVT_MENU, self.parent.OnPaste, paste)
|
|
makeSnapshot = wx.MenuItem(topMenu, wx.NewId(), getString('hsm'))
|
|
topMenu.AppendItem(makeSnapshot)
|
|
self.Bind(wx.EVT_MENU, self.parent.setManualHistoryMarker, makeSnapshot)
|
|
if item is not None and self.enableContextMenu == True:
|
|
print 'sp.making context menu'
|
|
customizeMenu = wx.Menu()
|
|
showHideMenu = wx.Menu()
|
|
if self.name.startswith('cs_') == False:
|
|
rstdef = wx.MenuItem(customizeMenu, wx.NewId(), getString('rstdef'))
|
|
customizeMenu.AppendItem(rstdef)
|
|
selkeys = wx.MenuItem(customizeMenu, wx.NewId(), getString('selkeys'))
|
|
customizeMenu.AppendItem(selkeys)
|
|
self.Bind(wx.EVT_MENU, self.OnResetLinkedKeysToDefault, rstdef)
|
|
self.Bind(wx.EVT_MENU, self.selectLinkedKeys, selkeys)
|
|
hideByFlag = wx.MenuItem(showHideMenu, wx.NewId(), getString('ltcf'))
|
|
showHideMenu.AppendItem(hideByFlag)
|
|
showByFlag = wx.MenuItem(showHideMenu, wx.NewId(), getString('sbcf'))
|
|
showHideMenu.AppendItem(showByFlag)
|
|
showAlways = wx.MenuItem(showHideMenu, wx.NewId(), getString('sa'))
|
|
showHideMenu.AppendItem(showAlways)
|
|
hideAlways = wx.MenuItem(showHideMenu, wx.NewId(), getString('ha'))
|
|
showHideMenu.AppendItem(hideAlways)
|
|
showHideAuto = wx.MenuItem(showHideMenu, wx.NewId(), getString('sha'))
|
|
showHideMenu.AppendItem(showHideAuto)
|
|
customizeMenu.AppendMenu(-1, getString('sh'), showHideMenu)
|
|
self.Bind(wx.EVT_MENU, self.hideByChannelFlag, hideByFlag)
|
|
self.Bind(wx.EVT_MENU, self.showByChannelFlag, showByFlag)
|
|
self.Bind(wx.EVT_MENU, self.showAlways, showAlways)
|
|
self.Bind(wx.EVT_MENU, self.hideAlways, hideAlways)
|
|
self.Bind(wx.EVT_MENU, self.removeChannelFlags, showHideAuto)
|
|
topMenu.AppendMenu(1, getString('cu'), customizeMenu)
|
|
if os.name in mac_names:
|
|
menuPos = (
|
|
self.currentPoint[0] + 10, self.currentPoint[1] + 10)
|
|
else:
|
|
menuPos = (
|
|
self.currentPoint[0] + 1, self.currentPoint[1] + 3)
|
|
self.PopupMenu(topMenu, menuPos)
|
|
return
|
|
|
|
def OnResetLinkedKeysToDefault(self, e):
|
|
print mytime.displayTime(), 'sp.reset linked keys'
|
|
section = self.name + '|' + str(self.current_channel) + '|' + self.contextControlName
|
|
try:
|
|
del self.customElementKeys[section]
|
|
self.elementConfig.remove_section(section)
|
|
self.saveElementConfig()
|
|
self.readCustomElementKeys()
|
|
except:
|
|
pass
|
|
|
|
return
|
|
|
|
def selectLinkedKeys(self, e):
|
|
controlName = self.contextControlName
|
|
if one_unit.app.enableRightClickButtonConfiguration:
|
|
try:
|
|
print mytime.displayTime(), 'sp.TB.ORD', controlName
|
|
myKey = self.controls[controlName][1]
|
|
print mytime.displayTime(), 'My default key:', myKey
|
|
myType = self.parent.GL.loaded_skin
|
|
print mytime.displayTime(), 'My type:', myType
|
|
section = self.name + '|' + str(self.current_channel) + '|' + controlName
|
|
if section in self.customElementKeys:
|
|
allMyKeys = self.customElementKeys[section]
|
|
else:
|
|
allMyKeys = [
|
|
myKey]
|
|
newKeys = []
|
|
print mytime.displayTime(), 'sp.TB.sLK. all my keys 1:', allMyKeys
|
|
for key in allMyKeys:
|
|
print mytime.displayTime(), 'sp.TB.sLK.creating key with current channel for', key
|
|
newKeys.append(self.key_with_current_channel(key))
|
|
|
|
print mytime.displayTime(), 'sp.TB.sLK. keys with current channel:', newKeys
|
|
allMyKeys = []
|
|
for key in newKeys:
|
|
if key != None:
|
|
if key.channel < 0:
|
|
key = data_model.Key(key.struct_id, key.member_id, 0, key.num)
|
|
allMyKeys.append(key)
|
|
|
|
print mytime.displayTime(), 'sp.TB.sLK. all my keys 2:', allMyKeys
|
|
control = self.controls[controlName][0]
|
|
if isinstance(control, Button):
|
|
dataType = 'bool'
|
|
if isinstance(control, Slider):
|
|
dataType = None
|
|
if isinstance(control, Knob):
|
|
dataType = None
|
|
if isinstance(control, TextValueCtrl):
|
|
dataType = None
|
|
if len(allMyKeys) > 0:
|
|
dataType = protocol.get_member_data_type(allMyKeys[0].member_id)
|
|
import select_keys
|
|
dial = select_keys.Dialog(self, -1, 'Select Linked Keys for ' + controlName, ' ', unit_type=myType, existing_links=allMyKeys, restrictDataType=dataType)
|
|
dial.ShowModal()
|
|
if dial.response == 'OK':
|
|
allMyKeys = dial.result
|
|
print mytime.displayTime(), 'Selected keys:', allMyKeys
|
|
if len(allMyKeys) > 0:
|
|
if myKey not in allMyKeys:
|
|
myKey = allMyKeys[0]
|
|
allMyKeys.remove(myKey)
|
|
allMyKeys.insert(0, myKey)
|
|
print mytime.displayTime(), 'res:', allMyKeys
|
|
self.customElementKeys[section] = allMyKeys
|
|
else:
|
|
self.customElementKeys[section] = []
|
|
if section not in self.elementConfig.sections():
|
|
self.elementConfig.add_section(section)
|
|
self.elementConfig.set(section, 'customElementKeys', allMyKeys)
|
|
self.saveElementConfig()
|
|
dial.Destroy()
|
|
except:
|
|
traceback.print_exc(file=sys.stdout)
|
|
|
|
else:
|
|
print mytime.displayTime(), 'sp.TB.sLK.Disabled!'
|
|
return
|
|
|
|
def OnRightDown(self, event):
|
|
self.parent.clickTime = mytime.clock()
|
|
try:
|
|
self.ctrl_with_focus.on_lost_focus()
|
|
except:
|
|
pass
|
|
|
|
self.currentPoint = self.getEventCoordinates(event)
|
|
item = self.getCurrentShape(event)
|
|
self.executeOnRightDown(item)
|
|
return
|
|
|
|
def renderAll(self):
|
|
self.update_controls()
|
|
self.svg_doc.set_element_render_all()
|
|
self.OLU_Refresh()
|
|
return
|
|
|
|
def executeOnRightDown(self, item):
|
|
if item == None:
|
|
self.showContextMenu(item)
|
|
return
|
|
else:
|
|
if self.render_me(item.name) == False:
|
|
print mytime.displayTime() + ' Render me returned False for', item.name
|
|
return
|
|
if self.ctrl_with_focus != None:
|
|
try:
|
|
self.ctrl_with_focus.on_lost_focus()
|
|
except:
|
|
pass
|
|
|
|
try:
|
|
if not isinstance(item, Indicator) and item.name not in ('link_status',
|
|
'available_units',
|
|
'recall_preset',
|
|
'preset_name',
|
|
'unit_name'):
|
|
self.contextControlName = item.name
|
|
print mytime.displayTime(), 'sp.eORD.executing context menu'
|
|
self.showContextMenu(item)
|
|
else:
|
|
print mytime.displayTime(), 'sp.eORD. not executing context menu', self.enableContextMenu, isinstance(item, Indicator), item.name
|
|
except:
|
|
traceback.print_exc(file=sys.stdout)
|
|
|
|
self.svg_doc.set_element_render_all()
|
|
self.rendercount = 0
|
|
self.svg_doc.set_element_render(item.name)
|
|
self.ctrl_with_focus = item
|
|
self.Refresh()
|
|
return
|
|
|
|
def SetMinSize(self, size):
|
|
(def_width, def_height) = size
|
|
self.svg_scale_x = self.parent.svg_scale_x
|
|
self.svg_scale_y = self.parent.svg_scale_y
|
|
height = def_height
|
|
width = def_width
|
|
self.size = (
|
|
width, height)
|
|
self.display_buffer = wx.EmptyBitmap(width, height)
|
|
self.svg_doc.set_element_render_all()
|
|
return super(SVG_Panel, self).SetMinSize((width, height))
|
|
|
|
def OnPaint(self, evt):
|
|
if self.full_screen_diagram == True:
|
|
dc = wx.PaintDC(self)
|
|
return
|
|
dc = wx.BufferedPaintDC(self, buffer=self.display_buffer)
|
|
gc = wx.GraphicsContext_Create(dc)
|
|
self.svg_doc.render(gc, self.svg_id)
|
|
if os.name in mac_names:
|
|
try:
|
|
dc.Blit(self.tempPos[0], self.tempPos[1], 30, 11, self.tempDC, 0, 0)
|
|
except:
|
|
pass
|
|
|
|
return
|
|
|
|
def add_control(self, ctrl):
|
|
rc = ctrl.on_add(self)
|
|
if rc == 0:
|
|
self.svg_controls.append(ctrl)
|
|
return rc
|
|
|
|
def insert_ops(self, id, extra_ops):
|
|
if self.inserted_ops.has_key(id):
|
|
print mytime.displayTime() + ' already inserted, doing nothing'
|
|
return
|
|
if len(extra_ops) == 0:
|
|
return
|
|
ops_index = self.svg_doc.ops_index
|
|
(start, end) = ops_index[id]
|
|
ops = self.svg_doc.ops
|
|
self.svg_doc.ops = ops[:start + 1] + [(wx.GraphicsContext.PushState, ())] + extra_ops + ops[start + 1:end - 1] + [(wx.GraphicsContext.PopState, ())] + ops[end - 1:]
|
|
self.inserted_ops[id] = (
|
|
start, start + len(extra_ops) + 2)
|
|
start_off = len(extra_ops) + 1
|
|
end_off = start_off + 1
|
|
my_id = id
|
|
for id in ops_index:
|
|
(s, e) = ops_index[id]
|
|
if my_id == id:
|
|
e += end_off
|
|
else:
|
|
if s >= end:
|
|
s += end_off
|
|
elif s >= start:
|
|
s += start_off
|
|
if e > end:
|
|
e += end_off
|
|
elif e > start:
|
|
e += start_off
|
|
ops_index[id] = (
|
|
s, e)
|
|
(op, args) = self.svg_doc.ops[s]
|
|
if op != svg.document.do_nothing or args[0] != id or args[1] != 'start':
|
|
print mytime.displayTime() + " start positioning error for '%s' in self.ops" % id
|
|
i = -5
|
|
while i <= 5:
|
|
print i, self.svg_doc.ops[s + i]
|
|
i += 1
|
|
|
|
(op, args) = self.svg_doc.ops[e - 1]
|
|
if op != svg.document.do_nothing or args[0] != id or args[1] != 'end':
|
|
print mytime.displayTime() + " end positioning error for '%s' in self.ops" % id
|
|
i = -10
|
|
while i <= 10:
|
|
print i, self.svg_doc.ops[end - 1 + i]
|
|
i += 1
|
|
|
|
(start, end) = self.svg_doc.ops_index[id]
|
|
return
|
|
|
|
def OnLeftDown(self, event):
|
|
self.currentPoint = self.getEventCoordinates(event)
|
|
item = self.getCurrentShape(event)
|
|
self.executeOnLeftDown(item, event)
|
|
return
|
|
|
|
def executeOnLeftDown(self, item=None, event=None):
|
|
self.parent.clickTime = mytime.clock()
|
|
try:
|
|
self.ctrl_with_focus.on_lost_focus()
|
|
except:
|
|
pass
|
|
|
|
if item is None:
|
|
self.dummy_focus.SetFocus()
|
|
self.ctrl_with_focus = None
|
|
if event != None:
|
|
self.getOrReleaseMouseCapture(True)
|
|
self.mouse_down = True
|
|
return
|
|
else:
|
|
if self.render_me(item.name) == False:
|
|
print mytime.displayTime() + ' Render me returned False for', item.name
|
|
return
|
|
if self.ctrl_with_focus != None:
|
|
try:
|
|
self.ctrl_with_focus.on_lost_focus()
|
|
except:
|
|
pass
|
|
|
|
item.OnLeftDown(event)
|
|
self.ctrl_with_focus = item
|
|
return
|
|
|
|
def OnLeftDClick(self, event):
|
|
self.currentPoint = self.getEventCoordinates(event)
|
|
item = self.getCurrentShape(event)
|
|
if item is None:
|
|
self.ctrl_with_focus = None
|
|
return
|
|
else:
|
|
if self.render_me(item.name) == False:
|
|
return
|
|
self.svg_doc.set_element_render_all()
|
|
self.svg_doc.set_element_render(item.name)
|
|
item.OnLeftDClick(event)
|
|
self.ctrl_with_focus = item
|
|
self.OLU_Refresh()
|
|
self.last_repaint_time = 0
|
|
self.timer.Stop()
|
|
self.timer.Start(500)
|
|
self.repaint_time = mytime.clock()
|
|
return
|
|
|
|
def OnLeftUp(self, event):
|
|
item = self.getCurrentShape(event)
|
|
self.executeOnLeftUp(item, event)
|
|
return
|
|
|
|
def executeOnLeftUp(self, item=None, event=None):
|
|
if self.ctrl_with_focus != None:
|
|
if item is None:
|
|
try:
|
|
self.ctrl_with_focus.on_lost_focus()
|
|
except:
|
|
pass
|
|
|
|
self.mouse_down = False
|
|
self.getOrReleaseMouseCapture(False)
|
|
self.svg_doc.dragging = False
|
|
self.svg_doc.set_element_render_all()
|
|
try:
|
|
item.OnLeftUp(event)
|
|
except:
|
|
pass
|
|
|
|
self.last_repaint_time = 0
|
|
if item == None:
|
|
self.OLU_Refresh()
|
|
self.last_repaint_time = 0
|
|
self.timer.Stop()
|
|
self.timer.Start(500)
|
|
self.repaint_time = mytime.clock()
|
|
return
|
|
|
|
def simulateMouseClick(self, delay):
|
|
future.Future(delay, self.executeOnLeftDown)
|
|
future.Future(delay + 0.1, self.executeOnLeftUp)
|
|
return
|
|
|
|
def OLU_Refresh(self):
|
|
if self.parent.progress != None:
|
|
calframe = inspect.getouterframes(inspect.currentframe(), 2)
|
|
print mytime.displayTime(), 'sp.skipping OLU_R 1', calframe[2][3], calframe[1][3], calframe[0][3]
|
|
return
|
|
else:
|
|
if self.parent.dial != None:
|
|
calframe = inspect.getouterframes(inspect.currentframe(), 2)
|
|
print mytime.displayTime(), 'sp.skipping OLU_R 2', calframe[2][3], calframe[1][3], calframe[0][3]
|
|
return
|
|
try:
|
|
self.ctrl_with_focus.on_lost_focus()
|
|
except:
|
|
pass
|
|
|
|
self.ctrl_with_focus = None
|
|
self.dummy_focus.SetFocus()
|
|
self.parent.Refresh()
|
|
calframe = inspect.getouterframes(inspect.currentframe(), 2)
|
|
self.dummy_focus.SetFocus()
|
|
self.ctrl_with_focus = None
|
|
self.update_all_controls_counter = 8
|
|
self.Refresh()
|
|
return
|
|
|
|
def OnMotion(self, event):
|
|
self.timestamp = mytime.clock()
|
|
point = self.getEventCoordinates(event)
|
|
if event.Dragging():
|
|
x = point[0]
|
|
y = point[1]
|
|
ctrl = self.ctrl_with_focus
|
|
if ctrl is not None:
|
|
self.svg_doc.set_element_render(ctrl.name)
|
|
self.svg_doc.dragging = True
|
|
self.currentPoint = point
|
|
ctrl.move(x, y, event)
|
|
self.Refresh()
|
|
return
|
|
if self.mouse_down == True and self.parent.IsMaximized() == False:
|
|
screen = self.parent.GetPosition()
|
|
screenpoint = (screen[0] + point[0] - self.currentPoint[0], screen[1] + point[1] - self.currentPoint[1])
|
|
self.parent.SetPosition(screenpoint)
|
|
self.moved_screen = True
|
|
return
|
|
self.mouse_down = False
|
|
old_mouse_over = self.ctrl_mouse_over
|
|
if old_mouse_over is not None and not old_mouse_over.HitTest(*point):
|
|
if hasattr(old_mouse_over, 'on_mouse_leave'):
|
|
old_mouse_over.on_mouse_leave()
|
|
self.svg_doc.set_element_render(old_mouse_over.name)
|
|
self.ctrl_mouse_over = None
|
|
old_mouse_over = None
|
|
for c in self.svg_controls:
|
|
if c.HitTest(*point):
|
|
self.ctrl_mouse_over = c
|
|
self.svg_doc.set_element_render(c.name)
|
|
if c != old_mouse_over and hasattr(c, 'on_mouse_enter'):
|
|
if old_mouse_over is not None and hasattr(old_mouse_over, 'on_mouse_leave'):
|
|
old_mouse_over.on_mouse_leave()
|
|
c.on_mouse_enter()
|
|
elif hasattr(c, 'on_mouse_leave'):
|
|
c.on_mouse_leave()
|
|
|
|
return
|
|
|
|
def getCurrentShape(self, event):
|
|
point = self.getEventCoordinates(event)
|
|
for item in self.svg_controls:
|
|
if item.HitTest(point[0], point[1]) and self.render_me(item.name):
|
|
return item
|
|
|
|
return
|
|
|
|
def getEventCoordinates(self, event):
|
|
return (
|
|
event.GetX(), event.GetY())
|
|
|
|
def getOrReleaseMouseCapture(self, capture):
|
|
"""
|
|
Captures the mouse for this class object (which keeps a wxWidgets frame or a compatible
|
|
wxWidgets object). The mouse will only be captured or released if the class object hasCapture
|
|
method returns the correct value.
|
|
|
|
@param self: The class object itself
|
|
@param capture: True or false. True get the mouse capture for this class, false release it
|
|
"""
|
|
if capture and not self.HasCapture():
|
|
self.CaptureMouse()
|
|
if not capture and self.HasCapture():
|
|
self.ReleaseMouse()
|
|
return
|
|
|
|
|
|
def TranslateVsPanel(context, x, y):
|
|
"""executed from render()"""
|
|
matrix = context.GetTransform()
|
|
(a, b, c, d, tx, ty) = matrix.Get()
|
|
tx += x
|
|
ty += y
|
|
matrix.Set(a, b, c, d, tx, ty)
|
|
context.SetTransform(matrix)
|
|
return
|
|
|
|
|
|
def RotateVsPanel(context, angle, x=0, y=0, offset=0):
|
|
"""executed from render()"""
|
|
matrix = context.GetTransform()
|
|
(a, b, c, d, tx, ty) = matrix.Get()
|
|
matrix.Invert()
|
|
(x1, y1) = matrix.TransformPoint(x, y)
|
|
y2 = 2 * ty - offset
|
|
if os.name in mac_names:
|
|
y1 = y2 - y1 - 1
|
|
context.Translate(x1, y1)
|
|
context.Rotate(angle)
|
|
context.Translate(-x1, -y1)
|
|
return
|
|
|
|
|
|
class SVG_control():
|
|
|
|
def __init__(self, name, change_handler=None):
|
|
self.name = name
|
|
self.parent = None
|
|
self.ops = []
|
|
self.x = 0
|
|
self.y = 0
|
|
self.svg_action = None
|
|
self.last_click = mytime.clock()
|
|
self.default = 0
|
|
self.width = 0
|
|
self.name = name
|
|
self.height = 0
|
|
self.change_handler = change_handler
|
|
return
|
|
|
|
def get_svg_labels(self):
|
|
"""return all SVG labels, i.e., the names of the SVG elements,
|
|
that can be used by this control, as a list"""
|
|
return [
|
|
self.name]
|
|
|
|
def set_change_handler(self, change_handler):
|
|
self.change_handler = change_handler
|
|
return
|
|
|
|
def on_add(self, parent):
|
|
self.parent = parent
|
|
bb = parent.svg_doc.get_bb(self.name)
|
|
if bb is None:
|
|
return -1
|
|
else:
|
|
if os.name in mac_names:
|
|
self.x = bb.left * parent.svg_scale_x
|
|
self.y = -bb.top * parent.svg_scale_y
|
|
self.width = (bb.right - bb.left) * parent.svg_scale_x
|
|
self.height = (bb.bottom - bb.top) * parent.svg_scale_y
|
|
else:
|
|
self.x = bb.left * parent.svg_scale_x
|
|
self.y = bb.top * parent.svg_scale_y
|
|
self.width = (bb.right - bb.left) * parent.svg_scale_x
|
|
self.height = (bb.bottom - bb.top) * parent.svg_scale_y
|
|
parent.insert_ops(self.name, self.ops)
|
|
return 0
|
|
|
|
def OnLeftDClick(self, evt):
|
|
try:
|
|
if float(self.var_value) == float(self.default):
|
|
self.reset_minimum()
|
|
return
|
|
except:
|
|
pass
|
|
|
|
self.reset_default()
|
|
return
|
|
|
|
def OnLeftDown(self, evt):
|
|
try:
|
|
self.parent.ctrl_with_focus.on_lost_focus()
|
|
except:
|
|
pass
|
|
|
|
self.parent.ctrl_with_focus = self
|
|
return
|
|
|
|
def reset_minimum(self):
|
|
if self.lower_limit is not None:
|
|
self.set_value(self.lower_limit)
|
|
if callable(self.change_handler):
|
|
self.change_handler(self)
|
|
if hasattr(self, 'update_ops') and callable(self.update_ops):
|
|
self.update_ops()
|
|
return
|
|
|
|
def reset_default(self):
|
|
if self.default is not None and not isinstance(self, Color_gauge):
|
|
self.set_value(self.default)
|
|
if callable(self.change_handler):
|
|
self.change_handler(self)
|
|
if hasattr(self, 'update_ops') and callable(self.update_ops):
|
|
self.update_ops()
|
|
return
|
|
|
|
def set_default(self, val):
|
|
self.default = val
|
|
return
|
|
|
|
def OnLeftUp(self, evt):
|
|
if self.parent.ctrl_with_focus != None:
|
|
try:
|
|
self.parent.ctrl_with_focus.on_lost_focus()
|
|
except:
|
|
pass
|
|
|
|
return
|
|
|
|
def move(self, x, y, event):
|
|
return
|
|
|
|
def HitTest(self, x, y):
|
|
"""Check if the point (x, y) is contained within the shape."""
|
|
if x < self.x or x > self.x + self.width:
|
|
return False
|
|
if os.name in mac_names and (y < self.y or y > self.y + self.height):
|
|
return False
|
|
elif y < self.y or y > self.y + self.height:
|
|
return False
|
|
return True
|
|
|
|
def set_change_handler(self, new_handler):
|
|
old_handler = self.change_handler
|
|
self.change_handler = new_handler
|
|
return old_handler
|
|
|
|
def Refresh(self):
|
|
if self.parent.full_screen_diagram == False:
|
|
self.parent.Refresh()
|
|
return
|
|
|
|
|
|
class Knob(SVG_control):
|
|
LOW_LIMIT = -150
|
|
HI_LIMIT = 150
|
|
|
|
def __init__(self, name, change_handler=None):
|
|
SVG_control.__init__(self, name, change_handler)
|
|
self.angle = 0
|
|
self.cx = 0
|
|
self.cy = 0
|
|
self.last_click = mytime.clock()
|
|
self.value = -100000
|
|
self.lower_limit = -100
|
|
self.higher_limit = 100
|
|
self.name = name
|
|
self.last_angle = 0
|
|
self.offset = 0
|
|
self.translate_params = [
|
|
self.angle, self.cx, self.cy, self.offset]
|
|
self.ops = [(RotateVsPanel, self.translate_params)]
|
|
return
|
|
|
|
def get_angle(self):
|
|
"""Get the angle the knob is rotated in degrees"""
|
|
return self.angle
|
|
|
|
def Show(self, val):
|
|
return
|
|
|
|
def get_value(self):
|
|
return self.value
|
|
|
|
def set_angle(self, angle=0):
|
|
"""Set the angle the knob is rotated in degrees"""
|
|
self.angle = angle
|
|
self.update_ops()
|
|
self.parent.Refresh()
|
|
return
|
|
|
|
def set_value(self, value):
|
|
"""Set the angle the knob is rotated in degrees"""
|
|
try:
|
|
value = value * 1.0
|
|
except:
|
|
value = 0
|
|
|
|
self.value = value
|
|
if self.lower_limit == 19 or self.higher_limit == 20000:
|
|
if value < self.lower_limit:
|
|
value = self.lower_limit
|
|
if value > self.higher_limit:
|
|
value = self.higher_limit
|
|
if value < 1:
|
|
value = 1
|
|
value = float(value)
|
|
angle = -150 + 100.0 * math.log10(value / 20)
|
|
else:
|
|
angle = -150 + 300.0 * (value - self.lower_limit) / (self.higher_limit - self.lower_limit)
|
|
self.set_angle(angle)
|
|
return
|
|
|
|
def set_limits(self, lower, higher):
|
|
curframe = inspect.currentframe()
|
|
calframe = inspect.getouterframes(curframe, 2)
|
|
self.lower_limit = lower
|
|
self.higher_limit = higher
|
|
return
|
|
|
|
def OnLeftDown(self, event):
|
|
try:
|
|
self.parent.ctrl_with_focus.on_lost_focus()
|
|
except:
|
|
pass
|
|
|
|
self.parent.ctrl_with_focus = self
|
|
self.rawMove(self.parent.getEventCoordinates(event))
|
|
self.Refresh()
|
|
return
|
|
|
|
def HitTest(self, x, y):
|
|
"""Check if the point (x, y) is contained within the shape."""
|
|
if os.name in mac_names:
|
|
y += self.height / 2 + 4.5
|
|
if x < self.x or x > self.x + self.width:
|
|
return False
|
|
if y < self.y or y > self.y + self.height:
|
|
return False
|
|
return True
|
|
|
|
def move(self, x, y, event):
|
|
self.rawMove((x, y))
|
|
return
|
|
|
|
def rawMove(self, (x, y)):
|
|
dx = x - self.cx
|
|
dy = self.cy - y
|
|
if dy == 0:
|
|
dy = 0.1
|
|
if dy < 0 and dx < 0:
|
|
angle = 180 / 3.14 * math.atan(dx / dy) - 180
|
|
elif dy < 0 and dx > 0:
|
|
angle = 180 / 3.14 * math.atan(dx / dy) + 180
|
|
else:
|
|
angle = 180 / 3.14 * math.atan(dx / dy)
|
|
self.last_angle = angle
|
|
if math.fabs(angle - self.angle) > 180:
|
|
return
|
|
if angle < self.LOW_LIMIT:
|
|
angle = self.LOW_LIMIT
|
|
if angle > self.HI_LIMIT:
|
|
angle = self.HI_LIMIT
|
|
if self.angle != angle:
|
|
self.angle = float(angle)
|
|
if self.lower_limit == 19 or self.higher_limit == 20000:
|
|
self.value = 20 * pow(10, (self.angle + 150) / 100)
|
|
else:
|
|
self.value = (self.angle + 150.0) / 300.0 * (self.higher_limit - self.lower_limit) + self.lower_limit
|
|
self.update_ops()
|
|
if callable(self.change_handler):
|
|
self.change_handler(self)
|
|
for ctrl_name in self.parent.controls:
|
|
if ctrl_name == self.name:
|
|
(c, my_key, var_name) = self.parent.controls[ctrl_name]
|
|
break
|
|
|
|
for ctrl_name in self.parent.controls:
|
|
(c, key, var_name) = self.parent.controls[ctrl_name]
|
|
if key == my_key and ctrl_name != self.name:
|
|
wx.CallAfter(self.parent.update_control, ctrl_name)
|
|
self.parent.svg_doc.set_element_render(ctrl_name)
|
|
|
|
return
|
|
|
|
def on_add(self, parent):
|
|
rc = SVG_control.on_add(self, parent)
|
|
if rc != 0:
|
|
return rc
|
|
bb = parent.svg_doc.get_bb(self.name)
|
|
if os.name in mac_names:
|
|
self.cx = (bb.left + bb.right) / 2.0 * parent.svg_scale_x
|
|
self.cy = -(bb.top + bb.bottom) / 2.0 * parent.svg_scale_y
|
|
else:
|
|
self.cx = (bb.left + bb.right) / 2.0 * parent.svg_scale_x
|
|
self.cy = (bb.top + bb.bottom) / 2.0 * parent.svg_scale_y
|
|
self.offset = parent.size[1] - 17
|
|
self.update_ops()
|
|
return 0
|
|
|
|
def update_ops(self):
|
|
self.translate_params[0] = math.radians(self.angle)
|
|
self.translate_params[1] = self.cx
|
|
self.translate_params[2] = self.cy
|
|
self.translate_params[3] = self.offset
|
|
return
|
|
|
|
|
|
class Slider(SVG_control):
|
|
|
|
def __init__(self, parent, name, top_name, bottom_name, change_handler=None):
|
|
SVG_control.__init__(self, name, change_handler)
|
|
self.top_name = top_name
|
|
self.bottom_name = bottom_name
|
|
self.value = 0.0
|
|
self.var_value = None
|
|
self.init_pos = (0, 0)
|
|
self.translate_params = [0, 0]
|
|
self.ops = [(TranslateVsPanel, self.translate_params)]
|
|
self.slider_len = 1.0
|
|
self.lower_limit = 0.0
|
|
self.higher_limit = 1.0
|
|
self.scale = 'linear'
|
|
self.bottom_pos = None
|
|
self.top_pos = None
|
|
self.last_move = 0
|
|
self.name = name
|
|
self.parent = parent
|
|
try:
|
|
self.grid = eval(parent.parent.config.get(parent.name, self.name + '_grid'))
|
|
print displayTime(), 's_p.slider.grid voor', self.name, ':', self.grid
|
|
except:
|
|
self.grid = None
|
|
|
|
return
|
|
|
|
def set_unit(self, unit):
|
|
return
|
|
|
|
def Show(self, val):
|
|
return
|
|
|
|
def get_svg_labels(self):
|
|
"""return all SVG labels, i.e., the names of the SVG elements,
|
|
that can be used by this control, as a list"""
|
|
return [
|
|
self.name, self.top_name, self.bottom_name, self.name + '_bg']
|
|
|
|
def get_value(self):
|
|
"""Get the angle the knob is rotated in degrees"""
|
|
return self.var_value
|
|
|
|
def set_value(self, value=0):
|
|
"""Set the position of the slider between 0.0 (bottom) and 1.0 (top)"""
|
|
try:
|
|
value = value * 1.0
|
|
except:
|
|
value = 0
|
|
|
|
self.var_value = value
|
|
if value > self.higher_limit:
|
|
value = self.higher_limit
|
|
elif value < self.lower_limit:
|
|
value = self.lower_limit
|
|
value = (value - self.lower_limit) / float(self.higher_limit - self.lower_limit)
|
|
if self.scale == 'pow':
|
|
value = (math.pow(10, value) - 1) / 9.0 / 1.414
|
|
elif self.scale == 'pow_pk':
|
|
value = (math.pow(10, value) - 1) / 9.0
|
|
elif self.scale == 'log':
|
|
value *= 999
|
|
value += 1
|
|
value = math.log10(value) / 3
|
|
elif self.scale[:3] == 'exp':
|
|
try:
|
|
exponent = float(self.scale[4:])
|
|
value = math.log(1 + value * (exponent - 1), exponent)
|
|
except:
|
|
traceback.print_exc(file=sys.stdout)
|
|
|
|
self.value = value
|
|
self.update_ops()
|
|
if self.parent is not None:
|
|
self.parent.Refresh()
|
|
return
|
|
|
|
def set_limits(self, lower, higher):
|
|
self.lower_limit = lower
|
|
self.higher_limit = higher
|
|
return
|
|
|
|
def move(self, x, y, event):
|
|
if os.name in mac_names:
|
|
y -= 17.0
|
|
if x > self.top_pos[0]:
|
|
x = self.top_pos[0]
|
|
if x < self.bottom_pos[0]:
|
|
x = self.bottom_pos[0]
|
|
if y < self.top_pos[1]:
|
|
y = self.top_pos[1]
|
|
if y > self.bottom_pos[1]:
|
|
y = self.bottom_pos[1]
|
|
new_value = ((x - self.bottom_pos[0]) * self.x_len + (y - self.bottom_pos[1]) * self.y_len) / self.slider_len2
|
|
if self.value == new_value:
|
|
return
|
|
else:
|
|
self.value = new_value
|
|
self.update_ops()
|
|
if self.scale == 'pow':
|
|
new_value = new_value * 9 + 1
|
|
new_value = math.log10(new_value) * 1.414
|
|
elif self.scale == 'pow_pk':
|
|
new_value = new_value * 9 + 1
|
|
new_value = math.log10(new_value)
|
|
elif self.scale == 'log':
|
|
new_value = (math.pow(10, new_value * 3) - 1) / 999.0
|
|
elif self.scale[:3] == 'exp':
|
|
try:
|
|
exponent = float(self.scale[4:])
|
|
new_value = (math.pow(exponent, new_value) - 1) / (exponent - 1)
|
|
except:
|
|
traceback.print_exc(file=sys.stdout)
|
|
|
|
self.var_value = self.lower_limit + new_value * (self.higher_limit - self.lower_limit)
|
|
if self.grid != None:
|
|
self.var_value = float(int(self.var_value / self.grid)) * self.grid
|
|
wx.CallAfter(self.set_value, self.var_value)
|
|
if callable(self.change_handler):
|
|
self.change_handler(self)
|
|
for ctrl_name in self.parent.controls:
|
|
if ctrl_name == self.name:
|
|
(c, my_key, var_name) = self.parent.controls[ctrl_name]
|
|
break
|
|
|
|
for ctrl_name in self.parent.controls:
|
|
(c, key, var_name) = self.parent.controls[ctrl_name]
|
|
if key == my_key and ctrl_name != self.name:
|
|
wx.CallAfter(self.parent.update_control, ctrl_name)
|
|
self.parent.svg_doc.set_element_render(ctrl_name)
|
|
|
|
return
|
|
|
|
def on_add(self, parent):
|
|
doc = parent.svg_doc
|
|
rc = SVG_control.on_add(self, parent)
|
|
if rc != 0:
|
|
return rc
|
|
else:
|
|
bb = doc.get_bb(self.name)
|
|
slider_height = bb.top - bb.bottom
|
|
try:
|
|
correct_top_pos = eval(self.parent.parent.config.get(self.parent.name, self.name + '_correct_top_pos'))
|
|
except:
|
|
correct_top_pos = (0, 0)
|
|
|
|
try:
|
|
correct_bot_pos = eval(self.parent.parent.config.get(self.parent.name, self.name + '_correct_bot_pos'))
|
|
except:
|
|
correct_bot_pos = (0, 0)
|
|
|
|
bb = doc.get_bb(self.top_name)
|
|
if bb == None:
|
|
bb = doc.get_bb(self.top_name.replace('_slider', ''))
|
|
if os.name in mac_names:
|
|
if bb == None:
|
|
bb = doc.get_bb(self.name.replace('slider', 'bg'))
|
|
if bb == None:
|
|
dial = wx.MessageDialog(None, os.path.join('No bg position of the slider:', self.name), 'Error', wx.OK | wx.ICON_ERROR)
|
|
dial.ShowModal()
|
|
return -1
|
|
offset = doc.offset[self.name.replace('slider', 'bg')]
|
|
scale_by = doc.scale_by[self.name.replace('slider', 'bg')]
|
|
print mytime.displayTime() + ' offset and scale:', self.name, offset, scale_by
|
|
self.bottom_pos = (((bb.left + bb.right) / 2.0 + offset[0]) * parent.svg_scale_x + correct_top_pos[0], -(bb.top * scale_by - slider_height / 2 + offset[1]) * parent.svg_scale_y + correct_top_pos[1])
|
|
else:
|
|
self.top_pos = (
|
|
(bb.left + bb.right) / 2.0 * parent.svg_scale_x + correct_top_pos[0], -(bb.top + bb.bottom) / 2.0 * parent.svg_scale_y + correct_top_pos[1])
|
|
bb = doc.get_bb(self.bottom_name)
|
|
if bb == None:
|
|
bb = doc.get_bb(self.bottom_name.replace('_slider', ''))
|
|
if bb == None:
|
|
bb = doc.get_bb(self.name.replace('slider', 'bg'))
|
|
offset = doc.offset[self.name.replace('slider', 'bg')]
|
|
scale_by = doc.scale_by[self.name.replace('slider', 'bg')]
|
|
self.top_pos = (((bb.left + bb.right) / 2.0 + offset[0]) * parent.svg_scale_x + correct_bot_pos[0], -(bb.bottom / scale_by + slider_height / 2 + offset[1]) * parent.svg_scale_y + correct_bot_pos[1])
|
|
else:
|
|
self.bottom_pos = (
|
|
(bb.left + bb.right) / 2.0 * parent.svg_scale_x + correct_bot_pos[0], -(bb.top + bb.bottom) / 2.0 * parent.svg_scale_y + correct_bot_pos[1])
|
|
bb = doc.get_bb(self.name)
|
|
current_pos = ((bb.left + bb.right) / 2.0 * parent.svg_scale_x,
|
|
-(bb.top + bb.bottom) / 2.0 * parent.svg_scale_y)
|
|
self.init_pos = current_pos
|
|
self.slider_len = euclid_distance(self.top_pos, self.bottom_pos)
|
|
self.value = euclid_distance(current_pos, self.bottom_pos) / self.slider_len
|
|
else:
|
|
if bb == None:
|
|
bb = doc.get_bb(self.name.replace('slider', 'bg'))
|
|
if bb == None:
|
|
dial = wx.MessageDialog(None, os.path.join('No bg position of the slider:', self.name), 'Error', wx.OK | wx.ICON_ERROR)
|
|
dial.ShowModal()
|
|
return -1
|
|
offset = doc.offset[self.name.replace('slider', 'bg')]
|
|
scale_by = doc.scale_by[self.name.replace('slider', 'bg')]
|
|
self.top_pos = (((bb.left + bb.right) / 2.0 + offset[0]) * parent.svg_scale_x + correct_top_pos[0], (bb.top / scale_by - slider_height / 2 - offset[1]) * parent.svg_scale_y + correct_top_pos[1])
|
|
else:
|
|
self.top_pos = (
|
|
(bb.left + bb.right) / 2.0 * parent.svg_scale_x + correct_top_pos[0], (bb.top + bb.bottom) / 2.0 * parent.svg_scale_y + correct_top_pos[1])
|
|
bb = doc.get_bb(self.bottom_name)
|
|
if bb == None:
|
|
bb = doc.get_bb(self.bottom_name.replace('_slider', ''))
|
|
if bb == None:
|
|
bb = doc.get_bb(self.name.replace('slider', 'bg'))
|
|
offset = doc.offset[self.name.replace('slider', 'bg')]
|
|
scale_by = doc.scale_by[self.name.replace('slider', 'bg')]
|
|
self.bottom_pos = (((bb.left + bb.right) / 2.0 + offset[0]) * parent.svg_scale_x + correct_bot_pos[0], (bb.bottom * scale_by + slider_height / 2 - offset[1]) * parent.svg_scale_y + correct_bot_pos[1])
|
|
else:
|
|
self.bottom_pos = (
|
|
(bb.left + bb.right) / 2.0 * parent.svg_scale_x + correct_bot_pos[0], (bb.top + bb.bottom) / 2.0 * parent.svg_scale_y + correct_bot_pos[1])
|
|
bb = doc.get_bb(self.name)
|
|
current_pos = ((bb.left + bb.right) / 2.0 * parent.svg_scale_x,
|
|
(bb.top + bb.bottom) / 2.0 * parent.svg_scale_y)
|
|
self.init_pos = current_pos
|
|
self.slider_len = euclid_distance(self.top_pos, self.bottom_pos)
|
|
self.value = euclid_distance(current_pos, self.bottom_pos) / self.slider_len
|
|
if self.value < 0.0:
|
|
self.value = 0.0
|
|
elif self.value > 1.0:
|
|
self.value = 1.0
|
|
self.x_len = self.top_pos[0] - self.bottom_pos[0]
|
|
self.y_len = self.top_pos[1] - self.bottom_pos[1]
|
|
self.slider_len2 = self.slider_len * self.slider_len
|
|
self.update_ops()
|
|
if self.lower_limit == 19 or self.lower_limit == 20 or self.higher_limit == 20000 or self.higher_limit == 20001:
|
|
self.scale = 'log'
|
|
try:
|
|
self.scale = self.parent.parent.config.get(self.parent.name, self.name + '_scale')
|
|
print displayTime(), 's_p.slider.set scale for', self.name, 'to', self.scale
|
|
except:
|
|
pass
|
|
|
|
return 0
|
|
|
|
def update_ops(self):
|
|
if self.bottom_pos is None or self.top_pos is None:
|
|
return
|
|
else:
|
|
if os.name in mac_names:
|
|
self.x = self.bottom_pos[0] * (1 - self.value) + self.top_pos[0] * self.value
|
|
self.y = self.bottom_pos[1] * (1 - self.value) + self.top_pos[1] * self.value
|
|
self.translate_params[0] = self.x - self.init_pos[0]
|
|
self.translate_params[1] = -(self.y - self.init_pos[1])
|
|
else:
|
|
self.x = self.bottom_pos[0] * (1 - self.value) + self.top_pos[0] * self.value
|
|
self.y = self.bottom_pos[1] * (1 - self.value) + self.top_pos[1] * self.value
|
|
self.translate_params[0] = self.x - self.init_pos[0]
|
|
self.translate_params[1] = self.y - self.init_pos[1]
|
|
return
|
|
|
|
def HitTest(self, x, y):
|
|
"""Check if the point (x, y) is contained within the shape."""
|
|
if os.name in mac_names:
|
|
y -= 16 - self.height / 2.0
|
|
else:
|
|
y += self.height / 2.0
|
|
x += self.width / 2.0
|
|
if x < self.x or x > self.x + self.width:
|
|
return False
|
|
if y < self.y or y > self.y + self.height:
|
|
return False
|
|
return True
|
|
|
|
|
|
def euclid_distance(p1, p2):
|
|
(x1, y1) = p1
|
|
(x2, y2) = p2
|
|
return math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2))
|
|
|
|
|
|
class Button(SVG_control):
|
|
STATES = ('off', 'on', 'over', 'on_over', 'sync')
|
|
|
|
def __init__(self, parent, name, action=None, state='off'):
|
|
SVG_control.__init__(self, name)
|
|
self.translate_params = {}
|
|
self.change_handler = action
|
|
self.state = None
|
|
self.parent = parent
|
|
self.svg_action = None
|
|
self.last_state = None
|
|
self.name = name
|
|
self.hidden = False
|
|
self.highlight_peq_select = False
|
|
self.highlight_peq_index = 0
|
|
try:
|
|
self.highlight_peq_select = eval(self.parent.config.get('DEFAULT', 'highlight_peq_select'))
|
|
if self.name.find('peq_sw') < 0:
|
|
self.highlight_peq_select = False
|
|
else:
|
|
self.highlight_peq_index = int(self.name[-1])
|
|
except:
|
|
pass
|
|
|
|
if self.highlight_peq_select == True:
|
|
self.panel = wx.Panel(parent, -1, size=(1, 1))
|
|
self.panel.Bind(wx.EVT_PAINT, self.onPaint)
|
|
return
|
|
|
|
def Show(self, val):
|
|
if val == self.hidden:
|
|
self.hidden = not val
|
|
state = self.state
|
|
self.state = None
|
|
self.set_state(state)
|
|
return
|
|
|
|
def get_svg_labels(self):
|
|
return [_[1] for s in Button.STATES]
|
|
|
|
def exec_svg(self):
|
|
if self.svg_action:
|
|
locals = {'self': self, 'app': (wx.GetApp()), 'parent': (self.parent),
|
|
'frame': (self.parent.parent)}
|
|
exec self.svg_action in globals(), locals
|
|
self.parent.Refresh()
|
|
self.Refresh()
|
|
return
|
|
|
|
def OnLeftDown(self, evt):
|
|
try:
|
|
self.parent.ctrl_with_focus.on_lost_focus()
|
|
except:
|
|
pass
|
|
|
|
self.parent.ctrl_with_focus = self
|
|
self.exec_svg()
|
|
if callable(self.change_handler):
|
|
self.change_handler(self)
|
|
return
|
|
|
|
def on_mouse_enter(self):
|
|
if self.name == 'link_status':
|
|
return
|
|
else:
|
|
if self.translate_params.has_key('over') and self.state in ('off', None):
|
|
self.last_state = self.state
|
|
self.set_state('over')
|
|
return
|
|
if self.translate_params.has_key('on_over') and self.state in ('on', None):
|
|
self.last_state = self.state
|
|
self.set_state('on_over')
|
|
return
|
|
return
|
|
|
|
def on_mouse_leave(self):
|
|
if self.name == 'link_status':
|
|
return
|
|
if self.translate_params.has_key('over') and self.state == 'over':
|
|
self.set_state(self.last_state)
|
|
if self.translate_params.has_key('on_over') and self.state == 'on_over':
|
|
self.set_state(self.last_state)
|
|
return
|
|
|
|
def on_add(self, parent):
|
|
self.parent = parent
|
|
names = [_[1] for s in Button.STATES]
|
|
doc = parent.svg_doc
|
|
for i in range(len(Button.STATES)):
|
|
state = Button.STATES[i]
|
|
name = names[i]
|
|
bb = doc.get_bb(name)
|
|
try:
|
|
if bb is not None:
|
|
self.translate_params[state] = [0, 0]
|
|
if os.name in mac_names:
|
|
self.x = bb.left * parent.svg_scale_x
|
|
self.y = 19 - bb.bottom * parent.svg_scale_y
|
|
self.width = (bb.right - bb.left) * parent.svg_scale_x
|
|
self.height = (bb.bottom - bb.top) * parent.svg_scale_y * 0.85
|
|
else:
|
|
self.x = bb.left * parent.svg_scale_x
|
|
self.y = bb.top * parent.svg_scale_y
|
|
self.width = (bb.right - bb.left) * parent.svg_scale_x
|
|
self.height = (bb.bottom - bb.top) * parent.svg_scale_y
|
|
except:
|
|
pass
|
|
|
|
if not self.translate_params:
|
|
print mytime.clock(), 's_p.Could not find needed elements for button', self.name
|
|
self.set_state(self.state)
|
|
for state in self.translate_params.keys():
|
|
name = names[Button.STATES.index(state)]
|
|
parent.insert_ops(name, [
|
|
(
|
|
TranslateVsPanel, self.translate_params[state])])
|
|
|
|
for element in doc.tree.getiterator():
|
|
if element.get('id', None) != self.name + '_on':
|
|
continue
|
|
self.svg_action = element.get('onclick', None)
|
|
|
|
if self.highlight_peq_select == True:
|
|
self.panel.SetPosition((self.x, self.y))
|
|
return 0
|
|
|
|
def set_state(self, state, force=False):
|
|
if state == self.state and force == False:
|
|
return
|
|
self.state = state
|
|
self.hidden = not self.parent.render_me(self.name)
|
|
if not self.translate_params.has_key(self.state):
|
|
if self.state == 'sync':
|
|
self.state = 'on'
|
|
if not self.translate_params.has_key(self.state):
|
|
for state in Button.STATES:
|
|
if self.translate_params.has_key(state):
|
|
self.state = state
|
|
break
|
|
|
|
i = 1000
|
|
for state in self.translate_params.keys():
|
|
i += 1
|
|
params = self.translate_params[state]
|
|
if state == self.state and self.hidden == False:
|
|
params[0] = params[1] = 0
|
|
else:
|
|
params[0] = params[1] = -10000 - i
|
|
|
|
self.parent.svg_doc.set_element_render(self.name)
|
|
self.Refresh()
|
|
return
|
|
|
|
set_value = set_state
|
|
|
|
def get_state(self):
|
|
if self.parent.render_me(self.name) == False:
|
|
self.Show(False)
|
|
else:
|
|
self.Show(True)
|
|
return self.state
|
|
|
|
def onPaint(self, e):
|
|
self.panel.Freeze()
|
|
dc = wx.PaintDC(self.panel)
|
|
if self.highlight_peq_select == True and self.highlight_peq_index == self.parent.index:
|
|
dc = wx.ClientDC(self.parent)
|
|
dc.SetPen(wx.Pen('white', width=3))
|
|
dc.SetBrush(wx.Brush('grey', wx.TRANSPARENT))
|
|
if os.name in mac_names:
|
|
dc.DrawRectangle(self.x - 1, self.y - 3, self.width + 2, self.height + 6)
|
|
else:
|
|
dc.DrawRectangle(self.x, self.y - 1, self.width, self.height + 2)
|
|
self.panel.Thaw()
|
|
e.Skip()
|
|
return
|
|
|
|
get_value = get_state
|
|
|
|
|
|
class ToggleButton(Button):
|
|
|
|
def __init__(self, parent, name, action=None, state='off'):
|
|
Button.__init__(self, parent, name, action, state)
|
|
self.prev_state = None
|
|
return
|
|
|
|
def OnLeftDown(self, evt):
|
|
try:
|
|
self.parent.ctrl_with_focus.on_lost_focus()
|
|
except:
|
|
pass
|
|
|
|
self.parent.ctrl_with_focus = self
|
|
if self.name == 'link_status':
|
|
return
|
|
else:
|
|
if self.prev_state in ('off', None):
|
|
self.set_state('on')
|
|
self.prev_state = 'on'
|
|
self.exec_svg()
|
|
elif self.prev_state == 'on':
|
|
self.set_state('off')
|
|
self.prev_state = 'off'
|
|
self.exec_svg()
|
|
if callable(self.change_handler):
|
|
self.change_handler(self)
|
|
return
|
|
|
|
def OnLeftUp(self, evt):
|
|
return
|
|
|
|
def set_state(self, state, force=False):
|
|
Button.set_state(self, state, force)
|
|
if state not in ('over', 'on_over'):
|
|
self.prev_state = self.state
|
|
self.parent.Refresh()
|
|
self.Refresh()
|
|
return
|
|
|
|
def get_state(self):
|
|
if self.name == 'link_status':
|
|
return self.state
|
|
return self.prev_state
|
|
|
|
def get_value(self):
|
|
if self.parent.render_me(self.name) == False:
|
|
self.Show(False)
|
|
else:
|
|
self.Show(True)
|
|
if self.prev_state == None:
|
|
return
|
|
else:
|
|
res = self.STATES.index(self.prev_state)
|
|
return res
|
|
|
|
def set_value(self, val):
|
|
try:
|
|
self.set_state(self.STATES[int(val)])
|
|
except:
|
|
print mytime.displayTime() + ' sp.ToggleButton ("%s").set_value(%s) failed!' % (self.name, val)
|
|
|
|
return
|
|
|
|
|
|
def get_op(function):
|
|
if function == '>':
|
|
return greater_than
|
|
if function == '<':
|
|
return smaller_than
|
|
if function == '>=' or function == '=>':
|
|
return greater_than_equal
|
|
if function == '<=' or function == '=<':
|
|
return smaller_than_equal
|
|
if function == '==' or function == '=':
|
|
return equal
|
|
if function == '!=' or function == '<>':
|
|
return not_equal
|
|
return
|
|
|
|
|
|
def greater_than(value1, value2):
|
|
try:
|
|
if float(value1) > float(value2):
|
|
return True
|
|
else:
|
|
return False
|
|
except:
|
|
return False
|
|
|
|
return
|
|
|
|
|
|
def smaller_than(value1, value2):
|
|
try:
|
|
if float(value1) < float(value2):
|
|
return True
|
|
else:
|
|
return False
|
|
except:
|
|
return False
|
|
|
|
return
|
|
|
|
|
|
def greater_than_equal(value1, value2):
|
|
try:
|
|
if float(value1) >= float(value2):
|
|
return True
|
|
else:
|
|
return False
|
|
except:
|
|
return False
|
|
|
|
return
|
|
|
|
|
|
def smaller_than_equal(value1, value2):
|
|
try:
|
|
if float(value1) <= float(value2):
|
|
return True
|
|
else:
|
|
return False
|
|
except:
|
|
return False
|
|
|
|
return
|
|
|
|
|
|
def equal(value1, value2):
|
|
try:
|
|
if float(value1) == float(value2):
|
|
return True
|
|
else:
|
|
return False
|
|
except:
|
|
return False
|
|
|
|
return
|
|
|
|
|
|
def not_equal(value1, value2):
|
|
try:
|
|
if float(value1) != float(value2):
|
|
return True
|
|
else:
|
|
return False
|
|
except:
|
|
return False
|
|
|
|
return
|
|
|
|
|
|
class Indicator(Button):
|
|
|
|
def __init__(self, name, condition, config, section, action=None, state='off'):
|
|
Button.__init__(self, name, action, state)
|
|
self.prev_state = state
|
|
self.condition = condition
|
|
self.keys = []
|
|
self.ops = []
|
|
self.values = {}
|
|
self.test_values = []
|
|
self.masks = []
|
|
self.name = name
|
|
var_names = []
|
|
functions = []
|
|
self.and_or = []
|
|
condition_parts = [_[1] for s in condition.split(' ')]
|
|
i = 0
|
|
while i < len(condition_parts):
|
|
if condition_parts[i][0] == '(':
|
|
pos = condition_parts[i].find('&')
|
|
var_name = condition_parts[i][1:pos]
|
|
mask = condition_parts[i][pos + 1:-1]
|
|
else:
|
|
var_name = condition_parts[i]
|
|
mask = None
|
|
var_names.append(var_name)
|
|
self.masks.append(mask)
|
|
i += 1
|
|
functions.append(condition_parts[i])
|
|
i += 1
|
|
self.test_values.append(condition_parts[i])
|
|
i += 1
|
|
try:
|
|
if condition_parts[i] == '&&':
|
|
self.and_or.append('&&')
|
|
i += 1
|
|
else:
|
|
self.and_or.append('||')
|
|
except:
|
|
self.and_or.append('||')
|
|
|
|
for var in var_names:
|
|
struct_id = config.getint(var, 'struct_id')
|
|
member_id = config.getint(var, 'member_id')
|
|
num = config.getint(var, 'num')
|
|
try:
|
|
channel = config.get(var, 'channel')
|
|
x_pos = channel.find('x') + 1
|
|
if x_pos > 0:
|
|
channel = int(channel, 16)
|
|
except:
|
|
channel = -1
|
|
|
|
channel = int(channel)
|
|
key = data_model.Key(struct_id, member_id, channel, num)
|
|
self.keys.append(key)
|
|
self.values[key] = None
|
|
|
|
for function in functions:
|
|
self.ops.append(get_op(function))
|
|
|
|
return
|
|
|
|
def OnLeftDown(self, evt):
|
|
print mytime.displayTime() + " Button '%s': svg_action is '%s'" % (self.name, self.svg_action)
|
|
try:
|
|
self.parent.ctrl_with_focus.on_lost_focus()
|
|
except:
|
|
pass
|
|
|
|
self.parent.ctrl_with_focus = self
|
|
wx.CallAfter(self.exec_svg)
|
|
return
|
|
|
|
def OnLeftUp(self, evt):
|
|
return
|
|
|
|
def on_mouse_leave(self):
|
|
return
|
|
|
|
def on_mouse_enter(self):
|
|
return
|
|
|
|
def OnLeftDClick(self, evt):
|
|
return
|
|
|
|
def get_values(self, changed_only=True):
|
|
return self.values
|
|
|
|
def set_values(self, values):
|
|
changed = False
|
|
for key in values:
|
|
val = values[key]
|
|
if self.values[key] != val:
|
|
self.values[key] = val
|
|
changed = True
|
|
|
|
if changed == True:
|
|
if self.and_or[0] == '||':
|
|
result = False
|
|
else:
|
|
result = True
|
|
for i in range(len(self.ops)):
|
|
op = self.ops[i]
|
|
value = self.values[self.keys[i]]
|
|
test_value = self.test_values[i]
|
|
mask = self.masks[i]
|
|
if mask != None:
|
|
try:
|
|
value = int(value)
|
|
mask = int(mask, 16)
|
|
value &= mask
|
|
except:
|
|
pass
|
|
|
|
if self.and_or[0] == '||':
|
|
if op(value, test_value) == True:
|
|
result = True
|
|
elif op(value, test_value) == False:
|
|
result = False
|
|
|
|
if result == False:
|
|
self.set_state('off')
|
|
else:
|
|
self.set_state('on')
|
|
return
|
|
|
|
def set_state(self, state, force=False):
|
|
Button.set_state(self, state, force)
|
|
self.parent.Refresh()
|
|
return
|
|
|
|
|
|
class TextValueCtrl(wx.TextCtrl, SVG_control):
|
|
VAL_ANY = 0
|
|
VAL_FREQ = 1
|
|
VAL_DB = 2
|
|
VAL_FLOAT = 3
|
|
VAL_DELAY = 4
|
|
VAL_COMP_MS = 5
|
|
|
|
def __init__(self, parent, id=-1, value='', change_handler=None, pos=(-1, -1), size=(-1, -1), style=wx.BORDER_NONE | wx.TE_PROCESS_ENTER | wx.TE_CENTRE, validator=wx.DefaultValidator, name='TextValueCtrl', value_type=0, visible_unit='', custom_colours=False, default_text_colour=(0, 0, 0), write_protect=False, pix=14, autoresize=True):
|
|
if name == 'check_password':
|
|
style |= wx.TE_PASSWORD
|
|
w = size[0]
|
|
h = size[1]
|
|
if w < 13:
|
|
w = 13
|
|
if h < 13:
|
|
h = 13
|
|
self.name = name
|
|
self.targetHeight = pix
|
|
self.bb = parent.svg_doc.get_bb(self.name)
|
|
self.makeBackground(parent)
|
|
size = (w, h)
|
|
wx.TextCtrl.__init__(self, parent, id, value, pos, size, style, validator, name)
|
|
self.font = self.GetFont()
|
|
if os.name in mac_names:
|
|
pix *= 0.8
|
|
self.font_size = pix
|
|
self.font.SetPixelSize((0, self.font_size))
|
|
self.SetFont(self.font)
|
|
SVG_control.__init__(self, name, change_handler)
|
|
self.parent = parent
|
|
self.value_type = value_type
|
|
self.autoresize = autoresize
|
|
try:
|
|
self.scaleValue = eval(self.parent.config.get(self.parent.name, self.name + '_scaleValue'))
|
|
except:
|
|
self.scaleValue = 1.0
|
|
|
|
self.lower_limit = None
|
|
self.max_current = 10000
|
|
self.higher_limit = None
|
|
self.load_impedance = 4.0
|
|
self.showMe = True
|
|
self.show_unit = True
|
|
self.linked_load_impedance_ctrl_name = None
|
|
if visible_unit[:5] == '_IMP_':
|
|
self.linked_load_impedance_ctrl_name = visible_unit[5:]
|
|
self.style = 'number'
|
|
self.value_type = self.VAL_FLOAT
|
|
self.value = value
|
|
self.default_text_colour = default_text_colour
|
|
if visible_unit[:1] == '_':
|
|
self.show_unit = False
|
|
visible_unit = visible_unit[1:]
|
|
self.unit = visible_unit
|
|
if self.unit.find('offset') >= 0:
|
|
self.offset = float(self.unit[self.unit.find('offset') + 6:])
|
|
if self.unit.find('offset') == 0:
|
|
self.unit = ''
|
|
else:
|
|
self.unit = self.unit[:self.unit.find('_offset')]
|
|
else:
|
|
self.offset = 0
|
|
self.disabled = False
|
|
self.off_value = None
|
|
self.off_text = 'Off'
|
|
self.losing_focus = False
|
|
self.key = None
|
|
self.max_value = None
|
|
self.max_text = 'Max'
|
|
self.write_protect = write_protect
|
|
self.custom_colours = custom_colours
|
|
self.name = name
|
|
self.float_value = None
|
|
self.Bind(wx.EVT_KILL_FOCUS, self.on_lost_focus_evt, self)
|
|
self.Bind(wx.EVT_TEXT_ENTER, self.on_lost_focus_evt, self)
|
|
self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown, self)
|
|
self.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown, self)
|
|
self.Bind(wx.EVT_MOUSEWHEEL, self.OnMouseWheel, self)
|
|
self.SetMaxLength(10)
|
|
self.style = 'number'
|
|
if self.unit == 'cm':
|
|
self.unit = ' m'
|
|
self.isDelayStackDelay = True
|
|
else:
|
|
self.isDelayStackDelay = False
|
|
if self.unit == 'string':
|
|
self.unit = ''
|
|
self.style = 'text'
|
|
if self.name.find('long_name') >= 0:
|
|
self.SetMaxLength(128)
|
|
else:
|
|
self.SetMaxLength(32)
|
|
if write_protect:
|
|
self.SetEditable(False)
|
|
if os.name in mac_names:
|
|
self.Enable(False)
|
|
self.Bind(wx.EVT_RIGHT_DOWN, self.OnRightDown, self)
|
|
self.Bind(wx.EVT_PAINT, self.OnPaint)
|
|
return
|
|
|
|
def OnPaint(self, evt):
|
|
if self.parent.full_screen_diagram == True:
|
|
dc = wx.PaintDC(self)
|
|
return
|
|
evt.Skip(True)
|
|
return
|
|
|
|
def OnPaintBg(self, evt):
|
|
if self.parent.full_screen_diagram == True:
|
|
dc = wx.PaintDC(self.bg)
|
|
return
|
|
evt.Skip(True)
|
|
return
|
|
|
|
def OnRightDown(self, e):
|
|
self.parent.parent.clickTime = mytime.clock()
|
|
point = self.parent.getEventCoordinates(e)
|
|
self.parent.currentPoint = (point[0] + self.GetPosition()[0], point[1] + self.GetPosition()[1])
|
|
self.parent.executeOnRightDown(self)
|
|
return
|
|
|
|
def makeBackground(self, parent):
|
|
try:
|
|
bb = self.bb
|
|
if bb is None:
|
|
return
|
|
x = bb.left * parent.svg_scale_x
|
|
h = (bb.bottom - bb.top) * parent.svg_scale_y
|
|
if os.name in mac_names:
|
|
y = (16 - h - bb.top) * parent.svg_scale_y
|
|
else:
|
|
y = bb.top * parent.svg_scale_y
|
|
w = (bb.right - bb.left) * parent.svg_scale_x
|
|
pos = wx.Point(x, y)
|
|
self.bg = wx.Panel(parent, -1, size=(w, h))
|
|
self.bg.SetPosition(pos)
|
|
self.bg.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
|
|
self.bg.Bind(wx.EVT_RIGHT_DOWN, self.OnRightDown)
|
|
self.bg.Bind(wx.EVT_KILL_FOCUS, self.on_lost_focus_evt)
|
|
self.bg.Bind(wx.EVT_TEXT_ENTER, self.on_lost_focus_evt)
|
|
self.bg.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown)
|
|
self.bg.Bind(wx.EVT_MOUSEWHEEL, self.OnMouseWheel)
|
|
self.bg.Bind(wx.EVT_PAINT, self.OnPaintBg)
|
|
except:
|
|
traceback.print_exc(file=sys.stdout)
|
|
|
|
return
|
|
|
|
def on_add(self, parent):
|
|
self.parent = parent
|
|
bb = self.bb
|
|
if bb is None:
|
|
self.Show(False)
|
|
self.disabled = True
|
|
return -1
|
|
else:
|
|
self.x = bb.left * parent.svg_scale_x
|
|
self.width = (bb.right - bb.left) * parent.svg_scale_x
|
|
if os.name in mac_names:
|
|
self.height = (bb.bottom - bb.top) * parent.svg_scale_y
|
|
self.y = (16 - self.height - bb.top) * parent.svg_scale_y
|
|
else:
|
|
self.y = bb.top * parent.svg_scale_y
|
|
self.height = (bb.bottom - bb.top) * parent.svg_scale_y
|
|
pos = wx.Point(self.x, self.y)
|
|
if self.x > self.parent.size[0] or self.y > self.parent.size[1] or self.x < 0 or self.y < 0:
|
|
self.Show(False)
|
|
self.showMe = False
|
|
return
|
|
self.bg.SetBackgroundColour((255, 255, 255))
|
|
self.bg.Show(True)
|
|
self.text_height = self.targetHeight
|
|
if self.height > self.text_height and self.autoresize == True:
|
|
height = self.text_height
|
|
diff = self.height - self.text_height
|
|
pos = wx.Point(self.x, self.y + diff / 2)
|
|
else:
|
|
height = self.height
|
|
size = wx.Size(self.width, height)
|
|
self.SetSize(size)
|
|
if self.custom_colours == True:
|
|
(brush, pen, txt_colour) = self.parent.svg_doc.colours[self.name]
|
|
self.SetBackgroundColour(brush)
|
|
self.bg.SetBackgroundColour(brush)
|
|
if txt_colour != None:
|
|
try:
|
|
self.SetForegroundColour(eval(txt_colour))
|
|
except:
|
|
pass
|
|
|
|
else:
|
|
try:
|
|
self.SetForegroundColour(self.default_text_colour)
|
|
except:
|
|
pass
|
|
|
|
rc = self.SetPosition(pos)
|
|
if self.linked_load_impedance_ctrl_name != None:
|
|
self.set_value(None)
|
|
if self.unit[:6] == 'Wrms@4':
|
|
self.load_impedance = 4.0
|
|
self.font = self.GetFont()
|
|
self.font.SetPixelSize((0, 13))
|
|
self.SetFont(self.font)
|
|
if self.unit[:6] == 'Wrms@8':
|
|
self.load_impedance = 8.0
|
|
self.font = self.GetFont()
|
|
self.font.SetPixelSize((0, 13))
|
|
self.SetFont(self.font)
|
|
doc = parent.svg_doc
|
|
for element in doc.tree.getiterator():
|
|
if element.get('id', None) != self.name:
|
|
continue
|
|
self.svg_action = element.get('onclick', None)
|
|
|
|
return 0
|
|
|
|
def OnMouseWheel(self, evt):
|
|
if self.write_protect == True:
|
|
return
|
|
if self.parent.ctrl_with_focus != self:
|
|
return
|
|
delta = int(evt.GetWheelRotation() / 120)
|
|
if delta > 0:
|
|
for i in range(delta):
|
|
self.add_one_notch()
|
|
|
|
if delta < 0:
|
|
delta = -delta
|
|
for i in range(delta):
|
|
self.sub_one_notch()
|
|
|
|
return
|
|
|
|
def add_one_notch(self):
|
|
if self.write_protect == True:
|
|
return
|
|
if self.style != 'number':
|
|
return
|
|
try:
|
|
self.float_value = self.float_value * 1.0
|
|
except:
|
|
print mytime.displayTime() + ' svg_panel.AON:', self.name, 'Float Error'
|
|
traceback.print_exc(file=sys.stdout)
|
|
self.float_value = 0.0
|
|
|
|
if self.value_type == self.VAL_FREQ:
|
|
step = self.float_value / 20
|
|
val = self.float_value + step
|
|
elif self.value_type == self.VAL_DB:
|
|
val = int(self.float_value * 4) / 4.0 + 0.25
|
|
elif self.value_type == self.VAL_DELAY:
|
|
if self.float_value > 0.1:
|
|
step = self.float_value / 10
|
|
else:
|
|
step = 0.01
|
|
val = self.float_value + step
|
|
else:
|
|
val = self.float_value + 0.1
|
|
my_lo = self.lower_limit
|
|
my_hi = self.higher_limit
|
|
if val < my_lo:
|
|
val = my_lo
|
|
elif val > my_hi:
|
|
val = my_hi
|
|
self.set_value(val)
|
|
if callable(self.change_handler):
|
|
self.change_handler(self)
|
|
return
|
|
|
|
def sub_one_notch(self):
|
|
if self.write_protect == True:
|
|
return
|
|
if self.style != 'number':
|
|
return
|
|
try:
|
|
self.float_value = self.float_value * 1.0
|
|
except:
|
|
print mytime.displayTime() + ' svg_panel.SON:', self.name, 'Float Error'
|
|
traceback.print_exc(file=sys.stdout)
|
|
self.float_value = 0.0
|
|
|
|
if self.value_type == self.VAL_FREQ:
|
|
step = self.float_value / 20
|
|
val = self.float_value - step
|
|
elif self.value_type == self.VAL_DB:
|
|
val = int(self.float_value * 4) / 4.0 - 0.25
|
|
elif self.value_type == self.VAL_DELAY:
|
|
if self.float_value > 0.1:
|
|
step = self.float_value / 10
|
|
else:
|
|
step = 0.01
|
|
val = self.float_value - step
|
|
else:
|
|
val = self.float_value - 0.1
|
|
my_lo = self.lower_limit
|
|
my_hi = self.higher_limit
|
|
if val < my_lo:
|
|
val = my_lo
|
|
elif val > my_hi:
|
|
val = my_hi
|
|
self.set_value(val)
|
|
if callable(self.change_handler):
|
|
self.change_handler(self)
|
|
return
|
|
|
|
def OnKeyDown(self, evt):
|
|
if self.write_protect == True:
|
|
return
|
|
else:
|
|
key = evt.GetRawKeyCode()
|
|
if os.name in mac_names:
|
|
kTAB = 48
|
|
kUP = 126
|
|
kDN = 125
|
|
else:
|
|
kTAB = 9
|
|
kUP = 38
|
|
kDN = 40
|
|
if key == kUP:
|
|
self.add_one_notch()
|
|
if key == kDN:
|
|
self.sub_one_notch()
|
|
if key == kTAB:
|
|
evt.StopPropagation()
|
|
self.losing_focus = True
|
|
self.on_lost_focus()
|
|
self.losing_focus = False
|
|
if self.key is not None:
|
|
if self.key.channel < 0:
|
|
if self.key.struct_id == protocol.STRUCT_ID_PEQ:
|
|
if self.key.member_id == protocol.MEMBER_ID_FREQ:
|
|
newKey = data_model.Key(self.key.struct_id, protocol.MEMBER_ID_Q, self.key.channel, self.key.num)
|
|
if self.key.num < 10:
|
|
if self.key.member_id == protocol.MEMBER_ID_Q:
|
|
newKey = data_model.Key(self.key.struct_id, protocol.MEMBER_ID_GAIN, self.key.channel, self.key.num)
|
|
if self.key.member_id == protocol.MEMBER_ID_GAIN:
|
|
newKey = data_model.Key(self.key.struct_id, protocol.MEMBER_ID_FREQ, self.key.channel, self.key.num + 1)
|
|
elif self.key.member_id == protocol.MEMBER_ID_Q:
|
|
newKey = data_model.Key(protocol.STRUCT_ID_COMPRESSOR, protocol.MEMBER_ID_THRESHOLD, self.key.channel, self.key.num - 14)
|
|
if newKey not in self.parent.ctrl_keys:
|
|
newKey = data_model.Key(protocol.STRUCT_ID_HPF, protocol.MEMBER_ID_FREQ, self.key.channel, 0)
|
|
elif self.key.struct_id == protocol.STRUCT_ID_HPF:
|
|
newKey = data_model.Key(protocol.STRUCT_ID_LPF, self.key.member_id, self.key.channel, self.key.num)
|
|
elif self.key.struct_id == protocol.STRUCT_ID_LPF:
|
|
newKey = data_model.Key(protocol.STRUCT_ID_GAIN, protocol.MEMBER_ID_GAIN, self.key.channel, 0)
|
|
elif self.key.struct_id == protocol.STRUCT_ID_GAIN:
|
|
newKey = data_model.Key(protocol.STRUCT_ID_DELAY, protocol.MEMBER_ID_DELAY, self.key.channel, 0)
|
|
elif self.key.struct_id == protocol.STRUCT_ID_DELAY:
|
|
newKey = data_model.Key(protocol.STRUCT_ID_LIMITER, protocol.MEMBER_ID_THRESHOLD, self.key.channel, 0)
|
|
elif self.key.struct_id in (protocol.STRUCT_ID_LIMITER, protocol.STRUCT_ID_COMPRESSOR):
|
|
if self.key.num == 0:
|
|
if self.key.member_id == protocol.MEMBER_ID_THRESHOLD:
|
|
newKey = data_model.Key(protocol.STRUCT_ID_COMPRESSOR, protocol.MEMBER_ID_ATTACK, self.key.channel, self.key.num)
|
|
elif self.key.member_id == protocol.MEMBER_ID_ATTACK:
|
|
newKey = data_model.Key(protocol.STRUCT_ID_LIMITER, protocol.MEMBER_ID_RELEASE, self.key.channel, self.key.num)
|
|
elif self.key.member_id == protocol.MEMBER_ID_RELEASE:
|
|
newKey = data_model.Key(protocol.STRUCT_ID_PEQ, protocol.MEMBER_ID_FREQ, self.key.channel, 0)
|
|
else:
|
|
if self.key.member_id == protocol.MEMBER_ID_THRESHOLD:
|
|
newKey = data_model.Key(protocol.STRUCT_ID_COMPRESSOR, protocol.MEMBER_ID_ATTACK, self.key.channel, self.key.num)
|
|
elif self.key.member_id == protocol.MEMBER_ID_ATTACK:
|
|
newKey = data_model.Key(protocol.STRUCT_ID_COMPRESSOR, protocol.MEMBER_ID_RELEASE, self.key.channel, self.key.num)
|
|
elif self.key.member_id == protocol.MEMBER_ID_RELEASE:
|
|
newKey = data_model.Key(protocol.STRUCT_ID_COMPRESSOR, protocol.MEMBER_ID_RATIO, self.key.channel, self.key.num)
|
|
elif self.key.member_id == protocol.MEMBER_ID_RATIO:
|
|
newKey = data_model.Key(protocol.STRUCT_ID_PEQ, protocol.MEMBER_ID_FREQ, self.key.channel, self.key.num + 15)
|
|
if newKey not in self.parent.ctrl_keys:
|
|
newKey = data_model.Key(protocol.STRUCT_ID_PEQ, protocol.MEMBER_ID_FREQ, self.key.channel, 15)
|
|
else:
|
|
newChannel = self.key.channel + 1
|
|
if newChannel not in self.parent.parent.unit_channels:
|
|
if newChannel < 128:
|
|
newChannel = 128
|
|
else:
|
|
newChannel = 0
|
|
newKey = data_model.Key(self.key.struct_id, self.key.member_id, newChannel, self.key.num)
|
|
try:
|
|
for ctrlName in self.parent.ctrl_keys[newKey]:
|
|
newCtrl = self.parent.controls[ctrlName][0]
|
|
if isinstance(newCtrl, type(self)):
|
|
newCtrl.receiveFocus()
|
|
return
|
|
|
|
except:
|
|
pass
|
|
|
|
return
|
|
evt.Skip()
|
|
return
|
|
|
|
def set_unit(self, unit):
|
|
print mytime.displayTime(), 'setting unit for', self.name, 'to', unit
|
|
self.unit = unit
|
|
self.set_value(self.value)
|
|
return
|
|
|
|
def set_off_value(self, val):
|
|
self.off_value = val
|
|
return
|
|
|
|
def set_off_text(self, val):
|
|
self.off_text = val
|
|
return
|
|
|
|
def set_max_value(self, val):
|
|
self.max_value = val
|
|
return
|
|
|
|
def set_max_text(self, val):
|
|
self.max_text = val
|
|
return
|
|
|
|
def OnLeftDown(self, evt):
|
|
print 'sp.oLD', self.name, self.svg_action
|
|
if self.svg_action:
|
|
locals = {'self': self, 'app': (wx.GetApp()), 'parent': (self.parent),
|
|
'frame': (self.parent.parent)}
|
|
exec self.svg_action in globals(), locals
|
|
self.receiveFocus()
|
|
return
|
|
|
|
def receiveFocus(self):
|
|
try:
|
|
self.parent.ctrl_with_focus.on_lost_focus()
|
|
except:
|
|
pass
|
|
|
|
if self.write_protect == True:
|
|
return
|
|
self.parent.ctrl_with_focus = self
|
|
self.SetModified(False)
|
|
self.SetFocus()
|
|
self.parent.ctrl_with_focus = self
|
|
self.SetSelection(0, 32)
|
|
return
|
|
|
|
def set_limits(self, lower, higher):
|
|
self.lower_limit = lower
|
|
self.higher_limit = higher
|
|
return
|
|
|
|
def set_impedance(self, val):
|
|
if self.linked_load_impedance_ctrl_name != None:
|
|
val = float(val)
|
|
if val < 1:
|
|
val = 1
|
|
(ctrl, key, dummy) = self.parent.controls[self.linked_load_impedance_ctrl_name]
|
|
ctrl.load_impedance = val
|
|
ctrl.set_value(ctrl.get_value())
|
|
self.set_value(val)
|
|
return
|
|
|
|
def on_lost_focus_evt(self, e):
|
|
if self.losing_focus:
|
|
e.StopPropagation()
|
|
return
|
|
self.losing_focus = True
|
|
self.on_lost_focus()
|
|
self.losing_focus = False
|
|
return
|
|
|
|
def on_lost_focus(self):
|
|
if self.write_protect == True:
|
|
return
|
|
else:
|
|
if not self.IsModified():
|
|
if self.name != 'check_password':
|
|
return
|
|
else:
|
|
print mytime.displayTime() + ' sp.tc not modified bij wx.TE_PASSWORD -> let op: dit ligt aan wxPython 3.0.3.0, is OK in windows op wxPython 2.8.10.1'
|
|
self.value = self.GetValue().strip()
|
|
self.change_handler(self)
|
|
return
|
|
if self.style == 'number':
|
|
val = None
|
|
myval = self.GetValue().replace(',', '.')
|
|
myNumericVal = ''
|
|
for c in myval:
|
|
try:
|
|
d = int(c)
|
|
myNumericVal += c
|
|
except:
|
|
if c == '.':
|
|
myNumericVal += c
|
|
elif c in ('k', 'K'):
|
|
myNumericVal += 'k'
|
|
|
|
myval = myNumericVal
|
|
if myval.find('k') > 0:
|
|
myval = myval.replace('k', '')
|
|
myval = float(myval)
|
|
myval = myval * 1000
|
|
try:
|
|
myval = float(myval) * self.scaleValue
|
|
except:
|
|
traceback.print_exc(file=sys.stdout)
|
|
else:
|
|
if self.max_value is not None:
|
|
if str.lower(str(myval).strip()) == str.lower(str(self.max_text).strip()):
|
|
val = self.max_value
|
|
myval = val
|
|
print mytime.displayTime() + ' set max'
|
|
if self.off_value is not None:
|
|
if str.lower(str(myval).strip()) == str.lower(str(self.off_text).strip()):
|
|
val = self.off_value
|
|
myval = val
|
|
elif self.lower_limit == 19:
|
|
if self.higher_limit == 20000 and (myval == 'off' or myval == 'Off' or myval == 'OFF' or myval == 'AUS' or myval == 'aus' or myval == 'Aus' or myval == '0'):
|
|
val = self.lower_limit
|
|
myval = val
|
|
elif self.higher_limit == 20001 and self.lower_limit in (20, 50):
|
|
if myval == 'off' or myval == 'Off' or myval == 'OFF' or myval == 'AUS' or myval == 'aus' or myval == 'Aus' or myval == '0':
|
|
val = 20001
|
|
myval = val
|
|
try:
|
|
dummyval = float(myval)
|
|
except:
|
|
self.SetModified(False)
|
|
self.set_value(self.get_value())
|
|
return
|
|
else:
|
|
if self.parent.parent.oluUnit != None and self.parent.current_channel >= 128 and self.name.find('threshold') >= 0:
|
|
print mytime.displayTime(), 'setting unit for', self.name, 'to', self.parent.parent.oluUnit, 'from oluUnit'
|
|
self.unit = self.parent.parent.oluUnit
|
|
if val == None:
|
|
try:
|
|
val = parse_value(self.GetValue())
|
|
try:
|
|
val = float(val) * self.scaleValue
|
|
except:
|
|
traceback.print_exc(file=sys.stdout)
|
|
|
|
if self.linked_load_impedance_ctrl_name != None:
|
|
val = float(val)
|
|
if val < 0.001:
|
|
val = 0.001
|
|
(ctrl, key, dummy) = self.parent.controls[self.linked_load_impedance_ctrl_name]
|
|
ctrl.load_impedance = val
|
|
ctrl.set_value(ctrl.get_value())
|
|
if self.isDelayStackDelay:
|
|
val = val * 100.0
|
|
print 'ja is delay stack delay s_p', self.name, self.lower_limit, self.higher_limit
|
|
elif self.unit == 'Vpk':
|
|
if val < 0.001:
|
|
val = 0.001
|
|
else:
|
|
val = math.log10(val / 1.414213562373095 / 0.775) * 20.0
|
|
elif self.unit == 'Wrms':
|
|
if val < 0.001:
|
|
val = 0.001
|
|
val *= self.load_impedance
|
|
val = math.sqrt(val)
|
|
val = math.log10(val / 0.775) * 20.0
|
|
elif self.unit == 'Wrms@4':
|
|
if val < 0.001:
|
|
val = 0.001
|
|
val *= 4.0
|
|
val = math.sqrt(val)
|
|
val = math.log10(val / 0.775) * 20.0
|
|
elif self.unit == 'Wrms@8':
|
|
if val < 0.001:
|
|
val = 0.001
|
|
val *= 8.0
|
|
val = math.sqrt(val)
|
|
val = math.log10(val / 0.775) * 20.0
|
|
elif self.unit == 'Vrms':
|
|
if val < 0.001:
|
|
val = 0.001
|
|
val = math.log10(val / 0.775) * 20.0
|
|
elif self.unit == 'dBV':
|
|
val += 2.22
|
|
if self.value_type == self.VAL_DELAY:
|
|
if self.parent.delay_unit == 'ms':
|
|
unit_val = val
|
|
elif self.parent.delay_unit == 's':
|
|
unit_val = val * 1000.0
|
|
elif self.parent.delay_unit == 'mm':
|
|
unit_val = val / 343.26
|
|
elif self.parent.delay_unit == 'm':
|
|
unit_val = val / 343.26 * 1000
|
|
elif self.parent.delay_unit == 'mil':
|
|
unit_val = val / 343.26 / 39.3700787
|
|
elif self.parent.delay_unit == 'inch':
|
|
unit_val = val / 343.26 / 39.3700787 * 1000.0
|
|
elif self.parent.delay_unit == 'feet':
|
|
unit_val = val / 343.26 / 0.0032808399
|
|
val = round(unit_val, 3)
|
|
print mytime.displayTime(), 'sp.delay 1', val, unit_val
|
|
except:
|
|
if self.float_value is not None:
|
|
val = self.float_value
|
|
else:
|
|
self.DiscardEdits()
|
|
return
|
|
|
|
try:
|
|
if self.offset != 0:
|
|
print mytime.displayTime(), 'Offsetting value from', val, 'to', val - self.offset, 'for', self.name
|
|
val -= self.offset
|
|
except:
|
|
traceback.print_exc(file=sys.stdout)
|
|
else:
|
|
if val < self.lower_limit and self.off_value != 4:
|
|
dlgMessage = 'The value ' + str(val) + ' is too low and will be clipped to ' + str(self.lower_limit) + '. Continue?'
|
|
dlgTitle = 'Out Of Bounds Value'
|
|
res = wx.MessageBox(dlgMessage, dlgTitle, wx.OK | wx.CANCEL)
|
|
if res == wx.OK:
|
|
val = self.lower_limit
|
|
else:
|
|
val = self.get_value()
|
|
elif val > self.higher_limit:
|
|
dlgMessage = 'The value ' + str(val) + ' is too high and will be clipped to ' + str(self.higher_limit) + '. Continue?'
|
|
dlgTitle = 'Out Of Bounds Value'
|
|
res = wx.MessageBox(dlgMessage, dlgTitle, wx.OK | wx.CANCEL)
|
|
if res == wx.OK:
|
|
val = self.higher_limit
|
|
else:
|
|
val = self.get_value()
|
|
else:
|
|
val = self.GetValue()
|
|
self.SetModified(False)
|
|
self.set_value(val)
|
|
self.parent.repaint_time = mytime.clock()
|
|
self.parent.OLU_Refresh()
|
|
if callable(self.change_handler):
|
|
self.change_handler(self)
|
|
return
|
|
|
|
def HitTest(self, x, y):
|
|
return SVG_control.HitTest(self, x, y)
|
|
|
|
def get_value(self):
|
|
if self.parent.render_me(self.name) == False or self.disabled == True:
|
|
self.Show(False)
|
|
self.bg.Show(False)
|
|
elif self.showMe:
|
|
self.Show(True)
|
|
self.bg.Show(True)
|
|
if self.style == 'text':
|
|
return self.value
|
|
else:
|
|
if isinstance(self.float_value, float):
|
|
return self.float_value
|
|
if self.value_type != TextValueCtrl.VAL_ANY:
|
|
val = parse_value(self.value)
|
|
return val
|
|
return
|
|
|
|
def format_delay_value(self, val):
|
|
if self.parent.delay_unit in ('ppm', 'voc'):
|
|
unit_val = val * 1000
|
|
return unit_val
|
|
else:
|
|
if self.parent.autoScaleDelay:
|
|
if self.parent.delay_unit == 'ms':
|
|
if val > 1000:
|
|
self.parent.delay_unit = 's'
|
|
elif self.parent.delay_unit == 's':
|
|
if val < 1000:
|
|
self.parent.delay_unit = 'ms'
|
|
elif self.parent.delay_unit == 'mm':
|
|
if val > 2.913:
|
|
self.parent.delay_unit = 'm'
|
|
elif self.parent.delay_unit == 'm':
|
|
if val < 2.913:
|
|
self.parent.delay_unit = 'mm'
|
|
elif self.parent.delay_unit == 'mil':
|
|
if val > 0.888:
|
|
self.parent.delay_unit = 'feet'
|
|
elif val > 0.074:
|
|
self.parent.delay_unit = 'inch'
|
|
elif self.parent.delay_unit == 'inch':
|
|
if val > 0.888:
|
|
self.parent.delay_unit = 'feet'
|
|
elif val < 0.074:
|
|
self.parent.delay_unit = 'mil'
|
|
elif self.parent.delay_unit == 'feet':
|
|
if val < 0.074:
|
|
self.parent.delay_unit = 'mil'
|
|
elif val < 0.888:
|
|
self.parent.delay_unit = 'inch'
|
|
try:
|
|
self.parent.controls['delay_unit'][0].set_value(self.parent.delay_unit)
|
|
except:
|
|
pass
|
|
|
|
if self.parent.delay_unit == 'ms':
|
|
unit_val = val
|
|
elif self.parent.delay_unit == 's':
|
|
unit_val = round(val / 1000.0, 3)
|
|
elif self.parent.delay_unit == 'mm':
|
|
unit_val = round(val * 343.26, 3)
|
|
elif self.parent.delay_unit == 'm':
|
|
unit_val = round(val * 343.26 / 1000, 3)
|
|
elif self.parent.delay_unit == 'mil':
|
|
unit_val = int(val * 343.26 * 39.3700787)
|
|
elif self.parent.delay_unit == 'inch':
|
|
unit_val = round(val * 343.26 * 39.3700787 / 1000.0, 3)
|
|
elif self.parent.delay_unit == 'feet':
|
|
unit_val = round(val * 343.26 * 0.0032808399, 3)
|
|
if unit_val < 10:
|
|
unit_val = round(unit_val, 3)
|
|
elif unit_val < 100:
|
|
unit_val = round(unit_val, 2)
|
|
elif unit_val < 1000:
|
|
unit_val = round(unit_val, 1)
|
|
else:
|
|
unit_val = int(round(unit_val, 0))
|
|
if self.parent.include_delay_unit:
|
|
return str(unit_val) + self.parent.delay_unit
|
|
return str(unit_val)
|
|
return
|
|
|
|
def set_value(self, val):
|
|
try:
|
|
if val.strip() == 'No Name':
|
|
if self.name.startswith('channel_name'):
|
|
channel = int(self.name[self.name.rfind('name_') + 5:self.name.rfind('_')]) + 1
|
|
if channel > 128:
|
|
channel -= 128
|
|
val = 'Out ' + str(channel)
|
|
else:
|
|
val = 'In ' + str(channel)
|
|
if self.name.startswith('unit_name'):
|
|
val = self.parent.parent.active_unit.name
|
|
if self.name.startswith('preset_name'):
|
|
val = 'Demo Preset'
|
|
except:
|
|
pass
|
|
|
|
if self.linked_load_impedance_ctrl_name != None:
|
|
(ctrl, key, dummy) = self.parent.controls[self.linked_load_impedance_ctrl_name]
|
|
val = ctrl.load_impedance
|
|
if self.style == 'number':
|
|
try:
|
|
self.float_value = float(val)
|
|
except:
|
|
self.style = 'text'
|
|
self.SetMaxLength(16)
|
|
else:
|
|
if self.IsModified():
|
|
return
|
|
if val == None:
|
|
return
|
|
if isinstance(val, types.StringTypes):
|
|
text = val
|
|
self.value = val
|
|
elif self.isDelayStackDelay:
|
|
val = round(val / 100.0, 2)
|
|
if int(val) == val:
|
|
val = int(val)
|
|
text = str(val)
|
|
self.value = val
|
|
elif self.value_type == self.VAL_FREQ:
|
|
lower_limit = self.lower_limit
|
|
if lower_limit == 19:
|
|
lower_limit = 20
|
|
if val < lower_limit or val > self.higher_limit:
|
|
text = 'Off'
|
|
self.value = 'Off'
|
|
else:
|
|
text = format_text_freq(val)
|
|
self.value = format_value_freq(val)
|
|
elif self.value_type == self.VAL_FLOAT:
|
|
text = str(round(val / self.scaleValue, 2))
|
|
if val >= 25 and self.unit == ':1':
|
|
text = 'inf'
|
|
self.value = val
|
|
elif self.value_type == self.VAL_DB:
|
|
if self.parent.current_channel >= 128:
|
|
print mytime.displayTime(), 'sp.olu', self.parent.parent.oluUnit, self.key, self.parent.current_channel, self.name
|
|
oluElements = {'dBu': 1104, 'dBV': 1105, 'Vpk': 1103, 'Vrms': 1106, 'Wrms@4': 1107, 'Wrms@8': 1108}
|
|
if self.parent.parent.oluUnit == None and self.unit in oluElements:
|
|
self.parent.parent.oluUnit = self.unit
|
|
try:
|
|
self.parent.parent.oluMenu.Check(oluElements[self.unit], True)
|
|
except:
|
|
pass
|
|
|
|
if self.parent.parent.oluUnit != None and self.parent.current_channel >= 128 and self.name.find('threshold') >= 0:
|
|
self.unit = self.parent.parent.oluUnit
|
|
if self.unit == 'Vpk':
|
|
text = format_text_vpk(val + self.offset - 2.22)
|
|
elif self.unit == 'Vrms':
|
|
text = format_text_vrms(val + self.offset - 2.22)
|
|
elif self.unit == 'Wrms':
|
|
(text, set_val, limitedCurrent) = format_text_wrms(val + self.offset, self.load_impedance, self.max_current)
|
|
elif self.unit == 'Wrms@4':
|
|
(text, set_val, limitedCurrent) = format_text_wrms(val + self.offset, 4.0, self.max_current)
|
|
elif self.unit == 'Wrms@8':
|
|
(text, set_val, limitedCurrent) = format_text_wrms(val + self.offset, 8.0, self.max_current)
|
|
elif self.unit == 'dBV':
|
|
text = format_text_db(val + self.offset - 2.22)
|
|
else:
|
|
text = format_text_db(val + self.offset)
|
|
self.value = format_value_db(val)
|
|
elif self.value_type == self.VAL_COMP_MS:
|
|
self.value = int(round(val, 0))
|
|
val = self.value
|
|
text = str(val)
|
|
elif self.unit in ('ppm', 'voc'):
|
|
text = str(int(val * 1000))
|
|
elif self.value_type == self.VAL_DELAY:
|
|
unit_val = self.format_delay_value(val / self.scaleValue)
|
|
text = str(unit_val)
|
|
if 'delay_unit' not in self.parent.controls:
|
|
text += self.parent.delay_unit
|
|
self.value = val
|
|
else:
|
|
print mytime.displayTime(), 'sp.du.2'
|
|
try:
|
|
text = str(int(round(val / self.scaleValue)))
|
|
self.value = val
|
|
except:
|
|
print mytime.displayTime() + ' svg_panel.TextValueCtrl.set_value: Failed to set value:', val
|
|
return
|
|
|
|
if self.show_unit == True:
|
|
text = text + self.unit[:4]
|
|
if val == self.off_value:
|
|
text = self.off_text
|
|
if val == self.max_value:
|
|
text = self.max_text
|
|
else:
|
|
try:
|
|
text = val
|
|
self.value = text
|
|
if self.name == 'check_password':
|
|
text = '********'
|
|
self.ChangeValue(text)
|
|
except:
|
|
self.style = 'number'
|
|
print mytime.displayTime(), self.name, 'set from string to number'
|
|
try:
|
|
wx.CallAfter(self.set_value, val)
|
|
print mytime.displayTime(), self.name, 'Repeat set_value'
|
|
except:
|
|
pass
|
|
|
|
return
|
|
|
|
if self.autoresize == True:
|
|
try:
|
|
dc = wx.ScreenDC()
|
|
dc.SetFont(self.font)
|
|
(w, h) = dc.GetTextExtent(text)
|
|
w += 2
|
|
ratio = 1.0
|
|
while w > self.width:
|
|
ratio *= 1.01
|
|
self.font.SetPixelSize((0, self.font_size / ratio))
|
|
dc.SetFont(self.font)
|
|
(w, h) = dc.GetTextExtent(text)
|
|
w += 2
|
|
|
|
except:
|
|
ratio = 1.0
|
|
else:
|
|
self.font.SetPixelSize((0, self.font_size / ratio))
|
|
self.SetFont(self.font)
|
|
self.ChangeValue(text)
|
|
self.SetSelection(0, 0)
|
|
try:
|
|
set_val -= self.offset
|
|
if round(set_val, 2) != round(val, 2):
|
|
future.Future(1, self.set_value, set_val)
|
|
if callable(self.change_handler):
|
|
future.Future(1, self.change_handler, self)
|
|
except:
|
|
pass
|
|
|
|
return
|
|
|
|
|
|
class Color_gauge(wx.Panel, SVG_control):
|
|
|
|
def __init__(self, parent, update_func, name='VU_meter', id=-1):
|
|
wx.Panel.__init__(self, parent, id, name=name)
|
|
SVG_control.__init__(self, name)
|
|
self.update_func = update_func
|
|
self.name = name
|
|
self.last_temp = None
|
|
self.update_interval = 50
|
|
self.lower_limit = 0
|
|
self.higher_limit = 100
|
|
self.parent = parent
|
|
self.remote_link = parent.remote_link
|
|
self.vu_demo = one_unit.app.enable_vu_demo
|
|
self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)
|
|
self.SetBackgroundColour('BLACK')
|
|
self.Bind(wx.EVT_PAINT, self.OnPaint)
|
|
self.value = -999
|
|
self.last_value = -999
|
|
self.range = 100
|
|
self.green_pen = wx.GREEN_PEN
|
|
self.green_brush = wx.GREEN_BRUSH
|
|
self.yellow_brush = wx.Brush('YELLOW')
|
|
self.yellow_pen = wx.Pen('YELLOW')
|
|
self.red_brush = wx.Brush('RED')
|
|
self.red_pen = wx.Pen('RED')
|
|
self.muted = False
|
|
self.style = 'leds'
|
|
self.led_shape = 'square'
|
|
self.colours = {}
|
|
self.led_size = 3
|
|
self.led_spacing = 5
|
|
self.show_temp_val = True
|
|
try:
|
|
self.show_temp_val = eval(self.parent.config.get(self.parent.name, 'show_temp_val'))
|
|
except:
|
|
pass
|
|
|
|
self.led_values = []
|
|
self.yellow = 0
|
|
self.red = 6
|
|
self.bg_colour = 'BLACK'
|
|
self.grey_on_mute = 'yes'
|
|
self.peak_value = -999
|
|
self.last_peak = mytime.clock()
|
|
self.painting = False
|
|
self.black_start = 0
|
|
self.black_size = 1
|
|
self.test_val = 0
|
|
self.memory_dc = None
|
|
self.last_release = 0
|
|
if self.name[:11] == 'temperature':
|
|
self.timer = wx.Timer(self)
|
|
self.Bind(wx.EVT_TIMER, self.OnTimer, self.timer)
|
|
self.timer.Start(5000)
|
|
if self.parent.parent.MAC.startswith('DEMO') == False:
|
|
self.vu_demo = False
|
|
if self.vu_demo == True:
|
|
print mytime.displayTime() + ' Setting ', self.name, 'to demo mode'
|
|
self.demotimer = wx.Timer(self)
|
|
self.Bind(wx.EVT_TIMER, self.DemoTimer, self.demotimer)
|
|
self.demotimer.Start(5000)
|
|
self.Bind(wx.EVT_RIGHT_DOWN, self.OnRightDown, self)
|
|
try:
|
|
kleur = eval(self.parent.config.get('DEFAULT', 'green_led_colour'))
|
|
self.defaultGreenPen = wx.Pen(kleur)
|
|
self.defaultGreenBrush = wx.Brush(kleur)
|
|
except:
|
|
self.defaultGreenPen = wx.Pen('GREEN')
|
|
self.defaultGreenBrush = wx.Brush('GREEN')
|
|
|
|
try:
|
|
kleur = eval(self.parent.config.get('DEFAULT', 'yellow_led_colour'))
|
|
self.defaultYellowPen = wx.Pen(kleur)
|
|
self.defaultYellowBrush = wx.Brush(kleur)
|
|
except:
|
|
self.defaultYellowPen = wx.Pen('YELLOW')
|
|
self.defaultYellowBrush = wx.Brush('YELLOW')
|
|
|
|
try:
|
|
kleur = eval(self.parent.config.get('DEFAULT', 'red_led_colour'))
|
|
self.defaultRedPen = wx.Pen(kleur)
|
|
self.defaultRedBrush = wx.Brush(kleur)
|
|
except:
|
|
self.defaultRedPen = wx.Pen('RED')
|
|
self.defaultRedBrush = wx.Brush('RED')
|
|
|
|
return
|
|
|
|
def OnRightDown(self, e):
|
|
self.parent.parent.clickTime = mytime.clock()
|
|
point = self.parent.getEventCoordinates(e)
|
|
self.parent.currentPoint = (point[0] + self.GetPosition()[0], point[1] + self.GetPosition()[1])
|
|
self.parent.executeOnRightDown(self)
|
|
return
|
|
|
|
def OnPaint(self, evt):
|
|
if self.painting or self.parent.full_screen_diagram == True:
|
|
dc = wx.PaintDC(self)
|
|
return
|
|
dc = wx.BufferedPaintDC(self)
|
|
self.paint(dc)
|
|
return
|
|
|
|
def paint(self, dc=None):
|
|
if self.painting or self.parent.full_screen_diagram == True:
|
|
return
|
|
else:
|
|
self.painting = True
|
|
if dc == None:
|
|
dc = wx.ClientDC(self)
|
|
(w, h) = self.GetSizeTuple()
|
|
val = self.value
|
|
if val < self.lower_limit and self.peak_value < self.lower_limit and self.higher_limit > self.lower_limit or val < self.higher_limit and self.peak_value < self.higher_limit and self.higher_limit < self.lower_limit:
|
|
self.draw_nothing(w, h, dc)
|
|
self.painting = False
|
|
return
|
|
if self.muted == False or self.grey_on_mute == 'no':
|
|
self.green_brush = self.defaultGreenBrush
|
|
self.green_pen = self.defaultGreenPen
|
|
self.yellow_brush = self.defaultYellowBrush
|
|
self.yellow_pen = self.defaultYellowPen
|
|
self.red_brush = self.defaultRedBrush
|
|
self.red_pen = self.defaultRedPen
|
|
if self.name[:11] == 'temperature':
|
|
self.green_pen = wx.Pen(wx.Colour(0, 128, 0))
|
|
self.green_brush = wx.Brush(wx.Colour(0, 128, 0))
|
|
else:
|
|
self.green_brush = wx.Brush((150, 150, 150))
|
|
self.green_pen = wx.Pen((150, 150, 150))
|
|
self.yellow_brush = wx.Brush((200, 200, 200))
|
|
self.yellow_pen = wx.Pen((200, 200, 200))
|
|
self.red_brush = wx.Brush((250, 250, 250))
|
|
self.red_pen = wx.Pen((250, 250, 250))
|
|
self.draw_leds(val, w, h, dc)
|
|
self.painting = False
|
|
return
|
|
|
|
def draw_nothing(self, w, h, dc):
|
|
dc.SetPen(wx.Pen(self.bg_colour))
|
|
dc.SetBrush(wx.Brush(self.bg_colour))
|
|
dc.DrawRectangle(0, 0, w, h)
|
|
return
|
|
|
|
def draw_leds(self, val, w, h, dc):
|
|
self.draw_nothing(w, h, dc)
|
|
step = 0
|
|
loopcounter = 1000
|
|
if h >= w:
|
|
start = self.led_size
|
|
while loopcounter > 0:
|
|
loopcounter -= 1
|
|
if step >= len(self.led_values) or step * int(self.led_spacing) > self.height:
|
|
break
|
|
if val <= self.led_values[step]:
|
|
break
|
|
if self.continuous_colour == False:
|
|
if self.led_values[step] >= self.red:
|
|
pen = self.red_pen
|
|
brush = self.red_brush
|
|
elif self.led_values[step] > self.yellow:
|
|
pen = self.yellow_pen
|
|
brush = self.yellow_brush
|
|
else:
|
|
pen = self.green_pen
|
|
brush = self.green_brush
|
|
else:
|
|
pen = wx.Pen(self.colours[step])
|
|
brush = wx.Brush(self.colours[step])
|
|
dc.SetPen(pen)
|
|
dc.SetBrush(brush)
|
|
if self.lower_limit < self.higher_limit:
|
|
dc.DrawRectangle(0, h - start, w, self.led_size)
|
|
else:
|
|
dc.DrawRectangle(0, start - self.led_size, w, self.led_size)
|
|
start += int(self.led_spacing)
|
|
step += 1
|
|
|
|
else:
|
|
start = 0
|
|
while loopcounter > 0:
|
|
loopcounter -= 1
|
|
if step >= len(self.led_values) or step * int(self.led_spacing) > self.width:
|
|
break
|
|
if val < self.led_values[step]:
|
|
break
|
|
if self.continuous_colour == False:
|
|
if self.led_values[step] >= self.red:
|
|
pen = self.red_pen
|
|
brush = self.red_brush
|
|
elif self.led_values[step] > self.yellow:
|
|
pen = self.yellow_pen
|
|
brush = self.yellow_brush
|
|
else:
|
|
pen = self.green_pen
|
|
brush = self.green_brush
|
|
else:
|
|
pen = wx.Pen(self.colours[step])
|
|
brush = wx.Brush(self.colours[step])
|
|
dc.SetPen(pen)
|
|
dc.SetBrush(brush)
|
|
if self.lower_limit < self.higher_limit:
|
|
dc.DrawRectangle(start, 0, self.led_size, h)
|
|
else:
|
|
dc.DrawRectangle(w - (start + self.led_size), 0, self.led_size, h)
|
|
start += int(self.led_spacing)
|
|
step += 1
|
|
|
|
if self.name[:11] == 'temperature' and self.show_temp_val == True:
|
|
if one_unit.app.init_finished and self.parent.parent.IsShown() and self.parent.parent.isVisible and val != self.last_temp:
|
|
self.last_temp = val
|
|
self.timer.Stop()
|
|
self.timer.Start(5000)
|
|
if os.name in mac_names:
|
|
if self.memory_dc == None:
|
|
windowDC = wx.BufferedDC(wx.ClientDC(self.parent), self.parent.display_buffer)
|
|
self.memory_bitmap = wx.EmptyBitmap(30, 11)
|
|
self.memory_dc = wx.MemoryDC(self.memory_bitmap)
|
|
self.memory_dc.Blit(0, 0, 30, 11, windowDC, self.x + self.text_location[0], self.y + self.text_location[1])
|
|
self.parent.tempDC = wx.MemoryDC(wx.EmptyBitmap(30, 11))
|
|
self.parent.tempDC.Blit(0, 0, 30, 11, self.memory_dc, 0, 0)
|
|
self.parent.tempPos = [self.x + self.text_location[0], self.y + self.text_location[1]]
|
|
brush = wx.Brush((255, 0, 255))
|
|
pen = wx.Pen((255, 0, 255))
|
|
self.parent.tempDC.SetTextForeground(self.default_text_colour)
|
|
self.parent.tempDC.SetFont(wx.Font(11, wx.SWISS, wx.NORMAL, wx.NORMAL))
|
|
self.parent.tempDC.DrawText(str(val) + u'\xb0C', 0, 0)
|
|
dcp = wx.BufferedDC(wx.ClientDC(self.parent), self.parent.display_buffer)
|
|
dcp.Blit(self.parent.tempPos[0], self.parent.tempPos[1], 30, 11, self.parent.tempDC, 0, 0)
|
|
else:
|
|
dc2 = wx.WindowDC(self.parent)
|
|
if self.memory_dc == None:
|
|
self.memory_bitmap = wx.EmptyBitmap(30, 11)
|
|
self.memory_dc = wx.MemoryDC(self.memory_bitmap)
|
|
self.memory_dc.Blit(0, 0, 30, 11, dc2, self.x + self.text_location[0], self.y + self.text_location[1])
|
|
else:
|
|
dc2.Blit(self.x + self.text_location[0], self.y + self.text_location[1], 30, 11, self.memory_dc, 0, 0)
|
|
dc2.SetTextForeground(self.default_text_colour)
|
|
dc2.SetFont(wx.Font(8, wx.SWISS, wx.NORMAL, wx.BOLD))
|
|
dc2.DrawText(str(val) + u'\xb0C', self.x + self.text_location[0], self.y + self.text_location[1])
|
|
return
|
|
if self.peak_value == val or self.vintage == True or self.led_spacing == 0:
|
|
return
|
|
start = h - (self.led_spacing * (len(self.led_values) - 1) + self.led_size)
|
|
step = len(self.led_values) - 1
|
|
loopcounter = 1000
|
|
while step >= 0 and loopcounter > 0:
|
|
loopcounter -= 1
|
|
if self.led_values[step] < self.peak_value:
|
|
if start < 0:
|
|
break
|
|
if self.led_values[step] >= self.red:
|
|
pen = self.red_pen
|
|
brush = self.red_brush
|
|
elif self.led_values[step] >= self.yellow:
|
|
pen = self.yellow_pen
|
|
brush = self.yellow_brush
|
|
else:
|
|
pen = self.green_pen
|
|
brush = self.green_brush
|
|
dc.SetPen(pen)
|
|
dc.SetBrush(brush)
|
|
if self.lower_limit < self.higher_limit:
|
|
dc.DrawRectangle(0, start, w, self.led_size)
|
|
else:
|
|
h = h - self.led_size
|
|
dc.DrawRectangle(0, h - start, w, self.led_size)
|
|
break
|
|
start += int(self.led_spacing)
|
|
step -= 1
|
|
|
|
return
|
|
|
|
def set_mute(self, val):
|
|
self.muted = val
|
|
return
|
|
|
|
def is_muted(self):
|
|
return self.muted
|
|
|
|
def set_style(self, style='leds', led_shape='square', led_size=3, led_spacing=5, led_values=None, yellow=0, red=6, grey_on_mute='yes', text_location=(10, 0), bg_colour='BLACK', default_text_colour=(128, 128, 128)):
|
|
self.style = style
|
|
self.default_text_colour = default_text_colour
|
|
self.led_shape = led_shape
|
|
self.bg_colour = bg_colour
|
|
self.SetBackgroundColour(bg_colour)
|
|
self.led_size = int(led_size)
|
|
self.led_spacing = int(led_spacing)
|
|
self.led_values = led_values
|
|
self.vintage = False
|
|
if yellow == 'continuous' or yellow == 'vintage':
|
|
self.continuous_colour = True
|
|
if yellow == 'vintage':
|
|
self.vintage = True
|
|
else:
|
|
self.continuous_colour = False
|
|
self.yellow = int(yellow)
|
|
self.red = int(red)
|
|
self.text_location = text_location
|
|
if self.name[:11] == 'temperature':
|
|
self.led_size = 1
|
|
self.led_spacing = 1
|
|
self.yellow = 60
|
|
self.red = 75
|
|
return
|
|
|
|
def on_add(self, parent):
|
|
try:
|
|
self.parent = parent
|
|
bb = parent.svg_doc.get_bb(self.name)
|
|
if bb is None:
|
|
self.Show(False)
|
|
dial = wx.MessageDialog(None, os.path.join('No location found for ', self.name), 'Error', wx.OK | wx.ICON_ERROR)
|
|
dial.ShowModal()
|
|
return -1
|
|
self.x = bb.left
|
|
if os.name in mac_names:
|
|
self.y = 15 - bb.bottom
|
|
else:
|
|
self.y = bb.top
|
|
self.width = bb.right - bb.left
|
|
self.height = bb.bottom - bb.top
|
|
if self.led_spacing != 0:
|
|
count = 0
|
|
if self.height >= self.width:
|
|
original_height = self.height
|
|
self.height -= int(self.led_size)
|
|
while self.height > 0:
|
|
self.height -= int(self.led_spacing)
|
|
count += 1
|
|
|
|
self.height = count * int(self.led_spacing) + int(self.led_size)
|
|
else:
|
|
original_width = self.width
|
|
self.width -= int(self.led_size)
|
|
while self.width > 0:
|
|
self.width -= int(self.led_spacing)
|
|
count += 1
|
|
|
|
self.width = count * int(self.led_spacing) + int(self.led_size)
|
|
self.led_count = count + 1
|
|
elif self.led_values == None:
|
|
self.led_count = 1
|
|
else:
|
|
self.led_count = len(self.led_values)
|
|
if self.led_count < 1:
|
|
self.led_count = 1
|
|
if self.style == 'leds' and self.led_values == None:
|
|
self.led_values = []
|
|
led_pos = 0
|
|
vu_step = (self.higher_limit - self.lower_limit) / (self.led_count * 1.0)
|
|
while led_pos < self.led_count:
|
|
self.led_values.append(round(self.lower_limit + led_pos * vu_step))
|
|
if led_pos > 2:
|
|
if self.led_values[led_pos] == self.led_values[led_pos - 1] and self.led_values[led_pos] == self.led_values[led_pos - 2]:
|
|
self.led_values[led_pos] += 1
|
|
led_pos += 1
|
|
|
|
self.led_values.sort()
|
|
if self.red > int(self.led_values[led_pos - 1]) and self.continuous_colour == False:
|
|
self.red = int(self.led_values[led_pos - 1])
|
|
pos = wx.Point(self.x, self.y)
|
|
size = wx.Size(self.width, self.height)
|
|
self.SetSize(size)
|
|
self.SetPosition(pos)
|
|
for val in self.led_values:
|
|
if self.higher_limit > self.lower_limit:
|
|
if val > self.higher_limit or val < self.lower_limit:
|
|
if val > self.higher_limit:
|
|
self.higher_limit = val
|
|
if val < self.lower_limit:
|
|
self.lower_limit = val
|
|
if self.higher_limit < self.lower_limit:
|
|
if val < self.higher_limit or val > self.lower_limit:
|
|
if val < self.higher_limit:
|
|
self.higher_limit = val
|
|
if val > self.lower_limit:
|
|
self.lower_limit = val
|
|
|
|
try:
|
|
self.parent.register_gauge(self, self.key)
|
|
except:
|
|
traceback.print_exc(file=sys.stdout)
|
|
|
|
self.set_value(-1000)
|
|
colours = []
|
|
if self.higher_limit > self.lower_limit:
|
|
try:
|
|
factor = float(self.parent.config.get(self.parent.name, 'vu_slope'))
|
|
except:
|
|
try:
|
|
factor = 255.0 / (0 - self.lower_limit)
|
|
except:
|
|
factor = 1
|
|
|
|
else:
|
|
try:
|
|
self.red = float(self.parent.config.get(self.parent.name, 'vu_red'))
|
|
except:
|
|
pass
|
|
else:
|
|
for i in range(len(self.led_values)):
|
|
green = 255
|
|
red = factor * (self.led_values[i] - self.lower_limit - self.red)
|
|
if red > 255:
|
|
green -= red - 255
|
|
red = 255
|
|
if red < 0:
|
|
red = 0
|
|
red = int(round(red, 0))
|
|
if green > 255:
|
|
green = 255
|
|
if green < 0:
|
|
green = 0
|
|
green = int(round(green, 0))
|
|
colours.append((red, green, 0))
|
|
|
|
else:
|
|
try:
|
|
factor = 255.0 / (0 - self.higher_limit)
|
|
except:
|
|
factor = 1
|
|
|
|
for i in range(len(self.led_values)):
|
|
red = factor * (self.led_values[i] - self.lower_limit)
|
|
if red > 255:
|
|
red = 255
|
|
if red < 0:
|
|
red = 0
|
|
red = int(round(red, 0))
|
|
green_min_val = 0
|
|
if self.lower_limit == 0:
|
|
green_min_val = self.higher_limit
|
|
green_factor = 255.0 / (self.lower_limit - green_min_val)
|
|
green = 255 - 2 * (green_factor * (self.led_values[i] - green_min_val))
|
|
if green > 255:
|
|
green = 255
|
|
if green < 0:
|
|
green = 0
|
|
green = int(round(green, 0))
|
|
colours.append((red, green, 0))
|
|
|
|
if self.vintage == True:
|
|
colours = []
|
|
for i in range(len(self.led_values)):
|
|
factor = i * (1.0 / len(self.led_values))
|
|
colours.append((209 - factor * 93, 245 - factor * 50, 241 - factor * 62))
|
|
|
|
self.colours = colours
|
|
return 0
|
|
except:
|
|
traceback.print_exc(file=sys.stdout)
|
|
|
|
return
|
|
|
|
def get_value(self):
|
|
return self.value
|
|
|
|
def set_value(self, value):
|
|
if value < self.peak_value:
|
|
if mytime.clock() - self.last_peak > 3 and mytime.clock() - self.last_release > 0.2:
|
|
peak_value = self.peak_value - 1
|
|
self.last_release = mytime.clock()
|
|
else:
|
|
peak_value = self.peak_value
|
|
else:
|
|
self.last_peak = mytime.clock()
|
|
peak_value = value
|
|
if self.value == value and self.peak_value == peak_value:
|
|
return
|
|
self.peak_value = peak_value
|
|
self.value = value
|
|
self.last_value = self.value
|
|
wx.CallAfter(self.paint)
|
|
return
|
|
|
|
def set_limits(self, lower, higher):
|
|
self.lower_limit = lower
|
|
self.higher_limit = higher
|
|
if self.lower_limit < self.higher_limit:
|
|
self.value = lower
|
|
else:
|
|
self.value = higher
|
|
if self.name[:11] == 'temperature':
|
|
self.lower_limit = 0
|
|
self.higher_limit = 100
|
|
return
|
|
|
|
def HitTest(self, x, y):
|
|
return SVG_control.HitTest(self, x, y)
|
|
|
|
def OnTimer(self, evt):
|
|
try:
|
|
new_val = self.update_func(self)
|
|
self.update(new_val)
|
|
except:
|
|
traceback.print_exc(file=sys.stdout)
|
|
|
|
return
|
|
|
|
def DemoTimer(self, e):
|
|
self.update(0)
|
|
self.demotimer.Stop()
|
|
self.demotimer.Start(50)
|
|
return
|
|
|
|
def demo_val(self):
|
|
if self.name[:11] == 'temperature':
|
|
try:
|
|
self.democounter += 1
|
|
except:
|
|
self.democounter = 1
|
|
|
|
if self.democounter > 100:
|
|
self.democounter = 0
|
|
return self.democounter
|
|
else:
|
|
import random
|
|
channel = int(self.key.channel) & 254
|
|
speed = 0.7
|
|
val = math.sin((mytime.clock() * 17 + self.x + self.y) * speed) * 9.0 + 9.0
|
|
val *= val
|
|
val /= 20
|
|
val -= 15
|
|
val2 = math.sin((mytime.clock() * 7 + self.x + self.y) * speed) * 9.0 + 9.0
|
|
val2 *= val2
|
|
val2 /= 50
|
|
val2 -= 3
|
|
val3 = math.cos((mytime.clock() * 6 + self.x + self.y) * speed) * 9.0 + 9.0
|
|
val3 *= val3
|
|
val3 /= 50
|
|
val3 -= 3
|
|
val4 = math.cos((mytime.clock() * 27 + self.x + self.y) * speed) * 9.0 + 9.0
|
|
val4 *= val4
|
|
val4 /= 50
|
|
val4 -= 3
|
|
val5 = math.sin(mytime.clock() / 10 * speed) * 9.0 + 9.0
|
|
val5 *= val5
|
|
val5 /= 30
|
|
val5 -= 7
|
|
return int(val + val2 + val3 + val4 + val5)
|
|
return
|
|
|
|
def verifyRender(self):
|
|
if self.parent.render_me(self.name) == False:
|
|
self.Show(False)
|
|
else:
|
|
self.Show(True)
|
|
return
|
|
|
|
def update(self, new_val, ignoreRender=1):
|
|
if self.parent != self.parent.parent.current_view:
|
|
self.painting = False
|
|
return
|
|
else:
|
|
if self.painting == True:
|
|
return
|
|
if ignoreRender == 0:
|
|
if self.parent.render_me(self.name) == False:
|
|
self.Show(False)
|
|
return
|
|
self.Show(True)
|
|
if self.vu_demo == True:
|
|
new_val = self.demo_val()
|
|
elif self.remote_link.ResetValues == True:
|
|
new_val = -1000
|
|
if new_val is None:
|
|
new_val = -1000
|
|
if self.name[:11] == 'temperature':
|
|
if new_val == -1000:
|
|
return
|
|
new_val = int(new_val)
|
|
new_val = new_val & 255
|
|
if new_val == self.value:
|
|
return
|
|
if self.higher_limit > self.lower_limit:
|
|
if new_val > self.higher_limit:
|
|
new_val = self.higher_limit
|
|
if new_val < self.lower_limit - 1:
|
|
new_val = self.lower_limit - 1
|
|
elif new_val > self.lower_limit:
|
|
new_val = self.lower_limit
|
|
if new_val < self.higher_limit - 1:
|
|
new_val = self.higher_limit - 1
|
|
self.set_value(int(new_val))
|
|
return
|
|
|
|
|
|
class Choice(wx.Panel, SVG_control):
|
|
|
|
def __init__(self, parent, choices, change_handler=None, name='choice', id=-1, sort_list=None, pix=14, style=wx.BORDER_NONE | wx.TE_PROCESS_ENTER | wx.TE_LEFT, visible_unit='', custom_colours=False, default_text_colour=(0, 0, 0)):
|
|
self.choices = choices
|
|
for choice in self.choices:
|
|
try:
|
|
self.choices[choice] = unicode(self.choices[choice])
|
|
except:
|
|
print mytime.displayTime() + ' s_p.C.i: choice: unicode error'
|
|
print mytime.displayTime(), self.choices[choice]
|
|
self.choices[choice] = 'Unicode Decode Error'
|
|
|
|
self.sort_list = sort_list
|
|
wx.Panel.__init__(self, parent, id)
|
|
SVG_control.__init__(self, name, change_handler)
|
|
self.label = wx.TextCtrl(self, -1, style=style)
|
|
self.text = 'Default'
|
|
self.name = name
|
|
self.menu_selected = False
|
|
self.MenuOpened = False
|
|
self.default_text_colour = default_text_colour
|
|
self.font = self.GetFont()
|
|
if os.name in mac_names:
|
|
self.label.SetEditable(False)
|
|
pix *= 0.8
|
|
self.font_size = pix
|
|
self.font.SetPixelSize((0, self.font_size))
|
|
self.SetFont(self.font)
|
|
self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown, self)
|
|
self.label.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown, self.label)
|
|
self.label.Bind(wx.EVT_RIGHT_DOWN, self.OnRightDown, self.label)
|
|
self.label.Bind(wx.EVT_KILL_FOCUS, self.on_lost_focus_evt, self.label)
|
|
self.label.Bind(wx.EVT_TEXT_ENTER, self.OnTextEnter, self.label)
|
|
self.label.Bind(wx.EVT_SET_FOCUS, self.OnGetFocus, self.label)
|
|
self.label.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown, self.label)
|
|
self.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown, self)
|
|
self.custom_colours = custom_colours
|
|
bitmapdir = os.path.normpath(one_unit.app.cwd + '/bitmaps/')
|
|
self.arrow = wx.Bitmap(os.path.join(bitmapdir, 'choice.png'))
|
|
self.selectionbmp = wx.Bitmap(os.path.join(bitmapdir, 'selection.png'))
|
|
self.set_choices(choices)
|
|
return
|
|
|
|
def OnRightDown(self, e):
|
|
self.parent.parent.clickTime = mytime.clock()
|
|
point = self.parent.getEventCoordinates(e)
|
|
self.parent.currentPoint = (point[0] + self.GetPosition()[0], point[1] + self.GetPosition()[1])
|
|
self.parent.executeOnRightDown(self)
|
|
return
|
|
|
|
def OnTextEnter(self, e):
|
|
self.label.ChangeValue(self.text)
|
|
return
|
|
|
|
def OnKeyDown(self, e):
|
|
print mytime.displayTime(), self.name, 'key down'
|
|
key = e.GetRawKeyCode()
|
|
if key == 9:
|
|
if e.ShiftDown():
|
|
self.Navigate(flags=wx.NavigationKeyEvent.IsBackward)
|
|
else:
|
|
self.Navigate(flags=wx.NavigationKeyEvent.IsForward)
|
|
else:
|
|
self.showPopupMenu()
|
|
e.Skip()
|
|
return
|
|
|
|
def OnGetFocus(self, e):
|
|
print mytime.displayTime() + ' get focus'
|
|
if self.parent.ctrl_with_focus == self:
|
|
print mytime.displayTime() + ' Already have focus, skipping'
|
|
return
|
|
if os.name in mac_names:
|
|
self.showPopupMenu()
|
|
return
|
|
|
|
def createMenu(self):
|
|
print mytime.clock(), self.name, 'creating menu'
|
|
self.MenuOpened = True
|
|
self.menu = wx.Menu()
|
|
self.menu_items = {}
|
|
i = 0
|
|
self.sorted_choices = []
|
|
for no in self.sort_list:
|
|
try:
|
|
choice = self.choices[no]
|
|
except:
|
|
continue
|
|
|
|
self.sorted_choices.append(choice)
|
|
self.menu_items[choice] = wx.MenuItem(self.menu, 1836 + i, choice.replace('&', '&&'))
|
|
if choice == self.text:
|
|
self.menu_items[choice].SetBitmap(self.selectionbmp)
|
|
self.menu.AppendItem(self.menu_items[choice])
|
|
self.Bind(wx.EVT_MENU, self.OnSelectMenu, id=1836 + i)
|
|
i += 1
|
|
|
|
self.menu.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown)
|
|
return
|
|
|
|
def OnSelectMenu(self, e):
|
|
print mytime.clock(), self.name, 'Select Menu'
|
|
i = e.GetId() - 1836
|
|
self.text = self.sorted_choices[i]
|
|
self.parent.ctrl_with_focus = self
|
|
self.menu_selected = True
|
|
self.on_lost_focus()
|
|
return
|
|
|
|
def showPopupMenu(self):
|
|
self.createMenu()
|
|
position = (0, 0)
|
|
self.PopupMenu(self.menu, position)
|
|
return
|
|
|
|
def on_lost_focus_evt(self, e):
|
|
self.on_lost_focus()
|
|
return
|
|
|
|
def on_lost_focus(self):
|
|
print mytime.clock(), self.name, 'lost focus', self.parent.ctrl_with_focus == self, self.MenuOpened
|
|
if self.parent.ctrl_with_focus != self or self.MenuOpened == False:
|
|
print mytime.clock(), self.name, 'Menu not open! -> skipping on_lost_focus'
|
|
return
|
|
else:
|
|
print mytime.clock(), self.name, 'lost focus', self.parent.ctrl_with_focus
|
|
self.MenuOpened = False
|
|
self.label.Show(True)
|
|
self.arrow_button.Show(True)
|
|
if os.name not in mac_names:
|
|
self.label.SelectAll()
|
|
try:
|
|
del self.menu
|
|
except:
|
|
pass
|
|
|
|
self.parent.ctrl_with_focus = None
|
|
self.parent.dummy_focus.SetFocus()
|
|
if self.menu_selected == False:
|
|
return
|
|
self.menu_selected = False
|
|
if callable(self.change_handler):
|
|
self.change_handler(self)
|
|
self.label.ChangeValue(self.text)
|
|
wx.CallAfter(self.label.ChangeValue, self.text)
|
|
return
|
|
|
|
def OnLeftDown(self, evt):
|
|
print mytime.clock(), self.name, 'OnLeftDown'
|
|
self.parent.ctrl_with_focus = None
|
|
self.parent.dummy_focus.SetFocus()
|
|
try:
|
|
self.parent.ctrl_with_focus.on_lost_focus()
|
|
except:
|
|
pass
|
|
|
|
self.label.SetFocus()
|
|
self.parent.ctrl_with_focus = self
|
|
self.showPopupMenu()
|
|
return
|
|
|
|
def on_choice(self, e):
|
|
self.on_lost_focus()
|
|
return
|
|
|
|
def on_add(self, parent):
|
|
self.parent = parent
|
|
bb = parent.svg_doc.get_bb(self.name)
|
|
if bb is None:
|
|
self.Show(False)
|
|
return -1
|
|
else:
|
|
self.x = bb.left * parent.svg_scale_x
|
|
self.width = (bb.right - bb.left) * parent.svg_scale_x
|
|
if os.name in mac_names:
|
|
self.y = 17 - bb.bottom * parent.svg_scale_y
|
|
else:
|
|
self.y = bb.top * parent.svg_scale_y
|
|
pos = wx.Point(self.x, self.y)
|
|
self.height = (bb.bottom - bb.top) * parent.svg_scale_y
|
|
self.old_peq_style = False
|
|
if self.x > self.parent.size[0] or self.y > self.parent.size[1]:
|
|
self.Show(False)
|
|
self.text_height = self.font_size
|
|
if self.height > self.text_height:
|
|
labelheight = self.text_height
|
|
if labelheight < 18:
|
|
labelheight = 18
|
|
if labelheight > self.height:
|
|
labelheight = self.height
|
|
diff = self.height - labelheight
|
|
labelpos = wx.Point(0, diff / 2.0 - 0.5)
|
|
else:
|
|
labelheight = self.height
|
|
labelpos = (0, 0)
|
|
size = wx.Size(self.width, self.height - 1)
|
|
self.SetSize(size)
|
|
if self.font_size > size[1]:
|
|
self.font_size = size[1]
|
|
self.font.SetPixelSize((0, self.font_size))
|
|
self.label.SetSize((self.width - self.arrow.GetSize()[0], labelheight))
|
|
self.label.SetPosition(labelpos)
|
|
self.label.SetFont(self.font)
|
|
if self.custom_colours == True and self.old_peq_style == False:
|
|
(brush, pen, txt_colour) = self.parent.svg_doc.colours[self.name]
|
|
self.SetBackgroundColour(brush)
|
|
self.label.SetBackgroundColour(brush)
|
|
if txt_colour != None:
|
|
try:
|
|
self.SetForegroundColour(eval(txt_colour))
|
|
self.label.SetForegroundColour(eval(txt_colour))
|
|
except:
|
|
pass
|
|
|
|
else:
|
|
try:
|
|
self.SetForegroundColour(self.default_text_colour)
|
|
self.label.SetForegroundColour(self.default_text_colour)
|
|
except:
|
|
pass
|
|
|
|
else:
|
|
self.SetBackgroundColour((255, 255, 255))
|
|
self.label.SetBackgroundColour((255, 255, 255))
|
|
self.label.SetForegroundColour((100, 100, 100))
|
|
self.SetPosition(pos)
|
|
bitmap_x = self.label.GetPosition()[0] + self.label.GetSize()[0]
|
|
bitmap_y = self.label.GetPosition()[1]
|
|
self.arrow_button = wx.StaticBitmap(self, -1, self.arrow)
|
|
self.arrow_button.SetPosition((bitmap_x, bitmap_y))
|
|
self.arrow_button.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown, self.arrow_button)
|
|
self.SetForegroundColour(self.GetBackgroundColour())
|
|
return 0
|
|
|
|
def HitTest(self, x, y):
|
|
return SVG_control.HitTest(self, x, y)
|
|
|
|
def set_choices(self, choices):
|
|
sel = self.text
|
|
self.choices = choices
|
|
for choice in self.choices:
|
|
try:
|
|
self.choices[choice] = unicode(self.choices[choice])
|
|
except:
|
|
self.choices[choice] = 'Unicode Decode Error'
|
|
|
|
if self.sort_list == None:
|
|
choices_keys = sorted(choices.keys())
|
|
self.sort_list = choices_keys
|
|
else:
|
|
choices_keys = self.sort_list
|
|
sorted_choices = {}
|
|
for choice in choices_keys:
|
|
if choice in choices:
|
|
sorted_choices[choice] = choices[choice]
|
|
|
|
self.choices = sorted_choices
|
|
self.text = sel
|
|
return
|
|
|
|
def get_choices(self):
|
|
return self.choices
|
|
|
|
def get_value(self):
|
|
if self.parent.render_me(self.name) == False:
|
|
self.Show(False)
|
|
else:
|
|
self.Show(True)
|
|
s = self.text
|
|
for (key, val) in self.choices.items():
|
|
if s == val:
|
|
return key
|
|
|
|
return
|
|
|
|
def set_value(self, value):
|
|
try:
|
|
s = self.choices[value]
|
|
except KeyError:
|
|
return
|
|
|
|
self.text = s
|
|
self.label.ChangeValue(self.text)
|
|
return
|
|
|
|
def on_value_change(self, evt):
|
|
if callable(self.change_handler):
|
|
self.change_handler(self)
|
|
return
|
|
|
|
|
|
def format_text_freq(val):
|
|
if val > 20000:
|
|
return 'Off'
|
|
if True:
|
|
return '%dHz' % int(val)
|
|
return
|
|
|
|
|
|
def format_text_db(val):
|
|
return '%.2f' % val
|
|
|
|
|
|
def format_text_vpk(val):
|
|
val = pow(10, (val + 3.0) / 20.0)
|
|
if val >= 100:
|
|
val = int(round(val, 0))
|
|
elif val >= 10:
|
|
val = round(val, 1)
|
|
else:
|
|
val = round(val, 2)
|
|
return str(val)
|
|
|
|
|
|
def format_text_vrms(val):
|
|
val = pow(10, val / 20.0)
|
|
if val >= 100:
|
|
val = int(round(val, 0))
|
|
elif val >= 10:
|
|
val = round(val, 1)
|
|
else:
|
|
val = round(val, 2)
|
|
return str(val)
|
|
|
|
|
|
def format_text_wrms(val, impedance, max_current):
|
|
set_val = val
|
|
val = pow(10, (val - 2.22) / 20.0)
|
|
limitedCurrent = False
|
|
current = val / impedance
|
|
if current > max_current:
|
|
val = max_current * impedance
|
|
print mytime.displayTime() + ' sp.ftw.Limited current to', max_current
|
|
set_val = 20.0 * math.log10(val) + 2.22
|
|
limitedCurrent = True
|
|
val = val * val / impedance
|
|
if val >= 100:
|
|
val = int(round(val, 0))
|
|
elif val >= 10:
|
|
val = round(val, 1)
|
|
else:
|
|
val = round(val, 2)
|
|
return (str(val), set_val, limitedCurrent)
|
|
|
|
|
|
def format_value_freq(val):
|
|
return '%dHz' % int(val)
|
|
|
|
|
|
def format_value_db(val):
|
|
return '%.2f' % val
|
|
|
|
|
|
def parse_value(value):
|
|
"""Parse the text representation of value that may have the units name
|
|
appended: dB, kHz, Hz.
|
|
"""
|
|
if isinstance(value, types.StringTypes):
|
|
value = value.replace(',', '.')
|
|
if value.count('.') > 1:
|
|
value = 0
|
|
if isinstance(value, types.StringTypes) and (value.endswith('ms') or value.endswith('dB') or value.endswith('db')):
|
|
return float(value[:-2])
|
|
else:
|
|
if isinstance(value, types.StringTypes) and value.endswith('K'):
|
|
return float(value[:-1]) * 1000
|
|
if isinstance(value, types.StringTypes) and value.endswith('kHz'):
|
|
return float(value[:-3]) * 1000
|
|
if isinstance(value, types.StringTypes) and value.endswith(' Q'):
|
|
return float(value[:-1])
|
|
if isinstance(value, types.StringTypes) and value.endswith(' Oc'):
|
|
return float(value[:-2])
|
|
if isinstance(value, types.StringTypes) and value.endswith('Hz'):
|
|
try:
|
|
res = float(value[:-2])
|
|
except:
|
|
res = None
|
|
|
|
return res
|
|
if isinstance(value, types.StringTypes) and value.endswith('k'):
|
|
return float(value[:-1]) * 1000
|
|
try:
|
|
res = float(value)
|
|
except:
|
|
res = None
|
|
|
|
return res
|
|
|
|
|
|
class itemGroupTypeOne(wx.Panel):
|
|
|
|
def __init__(self, parent, name, groupOrMac, index):
|
|
self.parent = parent
|
|
self.name = name
|
|
self.mac = groupOrMac
|
|
self.group = groupOrMac
|
|
self.textForegroundColour = (255, 255, 255)
|
|
self.textBackgroundColour = (255, 255, 255)
|
|
self.backgroundColour = (66, 66, 66)
|
|
self.textForegroundColour = self.parent.settings['textForegroundColour']
|
|
self.textBackgroundColour = self.parent.settings['textBackgroundColour']
|
|
self.backgroundColour = self.parent.settings['backgroundColour']
|
|
wx.Panel.__init__(self, parent, -1, style=wx.ST_NO_AUTORESIZE)
|
|
self.font = self.GetFont()
|
|
pix = self.parent.pix
|
|
if os.name in mac_names:
|
|
pix *= 0.8
|
|
self.font_size = pix
|
|
self.font.SetPixelSize((0, self.font_size))
|
|
try:
|
|
self.launch = self.parent.settings['launch']
|
|
except:
|
|
self.launch = None
|
|
|
|
namePos = self.parent.settings['namePos']
|
|
nameSize = self.parent.settings['nameSize']
|
|
self.nameLabel = wx.StaticText(self, -1, name.decode('utf-8'), pos=namePos, size=nameSize, style=wx.ST_NO_AUTORESIZE)
|
|
self.nameLabel.SetForegroundColour(self.textForegroundColour)
|
|
if str(self.name).strip() == str(self.parent.activeItemName).strip():
|
|
self.active = True
|
|
else:
|
|
self.active = False
|
|
self.nameLabel.SetFont(self.font)
|
|
if False:
|
|
self.SetBackgroundColour(self.activeBackgroundColour)
|
|
self.nameLabel.SetBackgroundColour(self.activeBackgroundColour)
|
|
else:
|
|
self.SetBackgroundColour(self.backgroundColour)
|
|
self.nameLabel.SetBackgroundColour(self.textBackgroundColour)
|
|
self.nameLabel.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
|
|
if self.launch != None:
|
|
self.launchImg = wx.StaticBitmap(self, -1, wx.Bitmap(self.launch[0] + '_default.png'), pos=self.launch[1])
|
|
self.launchImg.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
|
|
else:
|
|
self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
|
|
try:
|
|
self.showID = self.parent.settings['showID']
|
|
except:
|
|
self.showID = None
|
|
|
|
if self.showID != None:
|
|
try:
|
|
startNumber = int(self.showID[0])
|
|
myNumber = str(startNumber + index)
|
|
except:
|
|
myNumber = chr(ord(self.showID[0]) + index)
|
|
else:
|
|
self.idTag = wx.StaticText(self, -1, myNumber, pos=self.showID[3], size=self.showID[4], style=wx.ST_NO_AUTORESIZE | wx.ALIGN_CENTRE)
|
|
self.idTag.SetBackgroundColour(self.showID[1])
|
|
self.idTag.SetForegroundColour(self.showID[2])
|
|
pix = self.showID[6]
|
|
if os.name in mac_names:
|
|
pix *= 0.8
|
|
self.font.SetPixelSize((0, pix))
|
|
self.idTag.SetFont(self.font)
|
|
if self.active:
|
|
self.idTag.SetBackgroundColour(self.showID[5])
|
|
if self.launch == None:
|
|
self.idTag.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
|
|
self.SetSize(self.parent.childSize)
|
|
self.SetMinSize(self.parent.childSize)
|
|
print mytime.displayTime(), 'sp.igto.1', self.parent.childSize, self.GetSize()
|
|
return
|
|
|
|
def switchToMyGroup(self):
|
|
self.parent.parent.parent.group = self.group
|
|
mac = one_unit.getLeadingMAC(self.group)
|
|
customTitle = 'Group: ' + self.name + ', Reference: ' + self.parent.parent.parent.peers.units[mac].name.strip() + ' (' + mac + ')'
|
|
self.parent.parent.parent.customTitle = customTitle
|
|
self.parent.parent.switchActiveUnitTo(mac)
|
|
return
|
|
|
|
def switchToUnit(self):
|
|
print mytime.displayTime(), 'sp.window reference.', self.parent.parent.parent.windowReference
|
|
one_unit.executeLaunch(self.mac, keepOpen=self.parent.parent.parent.windowReference)
|
|
if self.parent.startedUnitFromMe != None:
|
|
try:
|
|
one_unit.app.main_frame.network_window.children[self.parent.startedUnitFromMe].close()
|
|
except:
|
|
traceback.print_exc(file=sys.stdout)
|
|
|
|
self.parent.startedUnitFromMe = self.mac
|
|
return
|
|
|
|
def OnLeftDown(self, e):
|
|
print mytime.displayTime(), 'sp.igto.OLD', self.name, self.group
|
|
if self.parent.switchGroup == True:
|
|
if self.showID != None:
|
|
self.idTag.SetBackgroundColour(self.showID[5])
|
|
wx.CallAfter(self.switchToMyGroup)
|
|
self.Refresh()
|
|
elif self.parent.switchToUnit == True and self.mac != None:
|
|
self.parent.setAllItemsDefault(skip=self)
|
|
one_unit.tryYield()
|
|
wx.CallAfter(self.switchToUnit)
|
|
if self.showID != None:
|
|
self.idTag.SetBackgroundColour(self.showID[1])
|
|
self.Refresh()
|
|
e.Skip()
|
|
return
|
|
|
|
|
|
class itemList(wx.lib.scrolledpanel.ScrolledPanel, SVG_control):
|
|
VAL_ANY = 0
|
|
VAL_FREQ = 1
|
|
VAL_DB = 2
|
|
VAL_FLOAT = 3
|
|
VAL_DELAY = 4
|
|
VAL_COMP_MS = 5
|
|
|
|
def __init__(self, parent, id=-1, value='', change_handler=None, pos=(-1, -1), size=(-1, -1), style=wx.BORDER_NONE | wx.TE_PROCESS_ENTER | wx.TE_CENTRE, validator=wx.DefaultValidator, name='memberList', value_type=0, visible_unit='', custom_colours=False, default_text_colour=(0, 0, 0), write_protect=False, pix=14, autoresize=True, itemList={}, settings=None):
|
|
if name == 'check_password':
|
|
style |= wx.TE_PASSWORD
|
|
w = size[0]
|
|
h = size[1]
|
|
try:
|
|
self.filter = settings['filter']
|
|
except:
|
|
self.filter = None
|
|
|
|
try:
|
|
self.border = settings['border']
|
|
except:
|
|
self.border = (0, 0)
|
|
|
|
try:
|
|
self.scroll = settings['scroll']
|
|
except:
|
|
self.scroll = True
|
|
|
|
if self.scroll:
|
|
wx.lib.scrolledpanel.ScrolledPanel.__init__(self, parent, id)
|
|
else:
|
|
wx.Panel.__init__(self, parent, id)
|
|
SVG_control.__init__(self, name, change_handler)
|
|
self.parent = parent
|
|
self.settings = settings
|
|
self.value = value
|
|
self.pix = pix
|
|
self.switchGroup = False
|
|
self.switchToUnit = False
|
|
self.startedUnitFromMe = None
|
|
self.itemList = itemList
|
|
self.name = name
|
|
self.Bind(wx.EVT_KILL_FOCUS, self.on_lost_focus_evt, self)
|
|
self.Bind(wx.EVT_TEXT_ENTER, self.on_lost_focus_evt, self)
|
|
self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown, self)
|
|
self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp, self)
|
|
self.activeItemName = None
|
|
self.itemPanels = {}
|
|
self.bSizer = wx.BoxSizer(wx.VERTICAL)
|
|
self.bSizer.Add(self.border)
|
|
self.hSizer = wx.BoxSizer(wx.HORIZONTAL)
|
|
self.hSizer.Add(self.border)
|
|
self.hSizer.Add(self.bSizer)
|
|
self.SetSizer(self.hSizer)
|
|
if self.scroll:
|
|
self.SetupScrolling()
|
|
if os.name in mac_names:
|
|
self.scrollBarWidth = 30
|
|
else:
|
|
self.scrollBarWidth = 30
|
|
else:
|
|
self.scrollBarWidth = 0
|
|
try:
|
|
self.childSize = settings['childSize']
|
|
except:
|
|
self.childSize = (25, 25)
|
|
|
|
self.Bind(wx.EVT_MOTION, self.parent.OnMotion)
|
|
return
|
|
|
|
def setAllItemsDefault(self, skip=None):
|
|
for itemPanel in self.itemPanels.values():
|
|
if itemPanel == skip:
|
|
continue
|
|
itemPanel.SetBackgroundColour(itemPanel.backgroundColour)
|
|
if itemPanel.showID != None:
|
|
itemPanel.idTag.SetBackgroundColour(itemPanel.showID[1])
|
|
itemPanel.idTag.SetForegroundColour(itemPanel.showID[2])
|
|
itemPanel.Refresh()
|
|
|
|
return
|
|
|
|
def on_add(self, parent):
|
|
self.parent = parent
|
|
bb = parent.svg_doc.get_bb(self.name)
|
|
if bb is None:
|
|
self.Show(False)
|
|
self.disabled = True
|
|
return -1
|
|
else:
|
|
self.x = bb.left * parent.svg_scale_x
|
|
self.width = (bb.right - bb.left) * parent.svg_scale_x
|
|
if os.name in mac_names:
|
|
self.y = 17 - bb.bottom * parent.svg_scale_y
|
|
self.height = (bb.bottom - bb.top) * parent.svg_scale_y
|
|
pos = wx.Point(self.x, self.y)
|
|
else:
|
|
self.y = bb.top * parent.svg_scale_y
|
|
pos = wx.Point(self.x + 1, self.y + 1)
|
|
self.height = (bb.bottom - bb.top) * parent.svg_scale_y
|
|
if self.x > self.parent.size[0] or self.y > self.parent.size[1]:
|
|
self.Show(False)
|
|
size = wx.Size(self.width, self.height)
|
|
self.SetSize(size)
|
|
self.SetPosition((bb.left, self.y))
|
|
(brush, pen, txt_colour) = self.parent.svg_doc.colours[self.name]
|
|
self.SetBackgroundColour(brush)
|
|
return 0
|
|
|
|
def OnKeyDown(self, evt):
|
|
evt.Skip()
|
|
return
|
|
|
|
def OnLeftDown(self, evt):
|
|
self.parent.mouse_down = True
|
|
point = self.parent.getEventCoordinates(evt)
|
|
self.parent.currentPoint = (point[0] + self.GetPosition()[0], point[1] + self.GetPosition()[1])
|
|
self.parent.parent.clickTime = mytime.clock()
|
|
try:
|
|
self.parent.ctrl_with_focus.on_lost_focus()
|
|
except:
|
|
pass
|
|
|
|
self.parent.ctrl_with_focus = None
|
|
self.parent.dummy_focus.SetFocus()
|
|
self.parent.getOrReleaseMouseCapture(True)
|
|
evt.Skip()
|
|
return
|
|
|
|
def OnLeftUp(self, evt):
|
|
self.parent.mouse_down = False
|
|
self.parent.getOrReleaseMouseCapture(False)
|
|
self.parent.svg_doc.dragging = False
|
|
evt.Skip()
|
|
return
|
|
|
|
def on_lost_focus_evt(self, e):
|
|
self.on_lost_focus()
|
|
return
|
|
|
|
def on_lost_focus(self):
|
|
return
|
|
|
|
def HitTest(self, x, y):
|
|
return SVG_control.HitTest(self, x, y)
|
|
|
|
def get_value(self):
|
|
if self.parent.render_me(self.name) == False:
|
|
self.Show(False)
|
|
else:
|
|
self.Show(True)
|
|
return self.itemList
|
|
|
|
def set_value(self, val):
|
|
try:
|
|
self.Freeze()
|
|
self.itemList = val
|
|
for p in self.itemPanels.values():
|
|
self.bSizer.Detach(p)
|
|
p.Destroy()
|
|
|
|
self.itemPanels = {}
|
|
height = 0
|
|
index = 0
|
|
for key in sorted(self.itemList.keys()):
|
|
height += self.childSize[1] + self.border[1]
|
|
if height > self.GetSize()[1] and self.scroll == False:
|
|
break
|
|
self.itemPanels[key] = itemGroupTypeOne(self, str(self.itemList[key]), key, index)
|
|
index += 1
|
|
self.bSizer.Add(self.itemPanels[key], 0, wx.BOTTOM, self.border[1])
|
|
|
|
if self.scroll:
|
|
self.SetupScrolling()
|
|
else:
|
|
self.hSizer.Layout()
|
|
self.Thaw()
|
|
print mytime.displayTime(), 'sp.fgh', self.GetSize()
|
|
for key in self.itemPanels:
|
|
print mytime.displayTime(), 'sp.ipk', self.itemPanels[key].GetSize()
|
|
|
|
except:
|
|
traceback.print_exc(file=sys.stdout)
|
|
|
|
return
|
|
|
|
|
|
|
|
# okay decompiling pycode/svg_panel.pyc
|