class LightPanel(wx.Panel): """A panel of controls for a single light source.""" def __init__(self, parent, lightToggle, lightPower=None, lightFilters=[]): super().__init__(parent, style=wx.BORDER_RAISED) self.light = lightToggle self.Sizer = wx.BoxSizer(wx.VERTICAL) self.button = EnableButton(self, self.light) self.button.setState(self.light.state) expCtrl = safeControls.SafeSpinCtrlDouble(self, inc=5) expCtrl.Bind(safeControls.EVT_SAFE_CONTROL_COMMIT, lambda evt: self.light.setExposureTime(evt.Value)) lightToggle.addWatch('exposureTime', expCtrl.SetValue) expCtrl.SetValue(lightToggle.exposureTime) self.Sizer.Add(self.button, flag=wx.EXPAND) self.Sizer.AddSpacer(2) line_height = int(self.GetFont().GetFractionalPointSize() / 2.0) line = wx.Control(self, size=(-1, line_height)) line.SetBackgroundColour(wavelengthToColor(self.light.wavelength)) self.Sizer.Add(line, flag=wx.EXPAND) self.Sizer.Add(wx.StaticText(self, label='Exposure / ms'), flag=wx.ALIGN_CENTER_HORIZONTAL) self.Sizer.Add(expCtrl, flag=wx.EXPAND) if lightPower is not None: self.Sizer.AddSpacer(4) self.Sizer.Add(wx.StaticText(self, label='Power (%)'), flag=wx.ALIGN_CENTER_HORIZONTAL) powCtrl = safeControls.SpinGauge( self, minValue=0.0, maxValue=100.0, fetch_current=lambda: lightPower.getPower() * 100.0) powCtrl.SetValue(lightPower.powerSetPoint * 100.0) lightPower.addWatch('powerSetPoint', lambda p: powCtrl.SetValue(p * 100.0)) powCtrl.Bind(safeControls.EVT_SAFE_CONTROL_COMMIT, lambda evt: lightPower.setPower(evt.Value / 100.0)) self.Sizer.Add(powCtrl) if lightFilters: self.Sizer.AddSpacer(4) self.Sizer.Add(wx.StaticText(self, label="Filters"), flag=wx.ALIGN_CENTER_HORIZONTAL) for f in lightFilters: self.Sizer.Add(f.makeSelector(self), flag=wx.EXPAND) def SetFocus(self): # Sets focus to the main button to avoid accidental data entry # in power or exposure controls. self.button.SetFocus() def onStatus(self, evt): light, state = evt.EventData if light != self.light: return self.button.setState(state)
class CameraPanel(wx.Panel): """A panel of controls for a single camera.""" def __init__(self, parent, camera): super().__init__(parent, style=wx.BORDER_RAISED) self.camera = camera self.Sizer = wx.BoxSizer(wx.VERTICAL) self.button = EnableButton(self, self.camera) self.button.setState(self.camera.state) self.Sizer.Add(self.button, flag=wx.EXPAND) self.Sizer.AddSpacer(2) line_height = int(self.GetFont().GetFractionalPointSize() / 2.0) self.line = wx.Control(self, size=(-1, line_height)) self.line.SetBackgroundColour(wavelengthToColor(self.camera.wavelength or 0)) self.Sizer.Add(self.line, flag=wx.EXPAND) # If there are problems here, it's because the inline function below is # being called outside of the main thread and needs taking out and # wrapping with wx.CallAfter. camera.addWatch('wavelength', self.onWavelengthChange) self.Sizer.AddSpacer(2) if hasattr(camera, 'modes'): modebutton = wx.Button(parent, label='Mode') self.Sizer.Add(modebutton) if camera.callbacks.get('makeUI', None): self.Sizer.Add(camera.callbacks['makeUI'](self)) self.Sizer.AddSpacer(2) def onWavelengthChange(self, wl): """Change the colour of our wavelength indicator.""" self.line.SetBackgroundColour(wavelengthToColor(wl or 0)) # Explicit refresh required under MSW. wx.CallAfter(self.line.Refresh) def SetFocus(self): # Sets focus to the main button to avoid accidental data entry # in power or exposure controls. self.button.SetFocus() def onStatus(self, evt): camera, state = evt.EventData if camera != self.camera: return self.button.setState(state)