EventGhost/EventGhost

View on GitHub
eg/Classes/SmartSpinNumCtrl.py

Summary

Maintainability
A
2 hrs
Test Coverage
# -*- coding: utf-8 -*-
#
# This file is part of EventGhost.
# Copyright © 2005-2020 EventGhost Project <http://www.eventghost.net/>
#
# EventGhost is free software: you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free
# Software Foundation, either version 2 of the License, or (at your option)
# any later version.
#
# EventGhost is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
# more details.
#
# You should have received a copy of the GNU General Public License along
# with EventGhost. If not, see <http://www.gnu.org/licenses/>.

import wx

# Local imports
import eg

class SmartSpinNumCtrl(wx.Window):
    """
    A wx.Control that shows a fixed width floating point value and spin
    buttons to let the user easily input a floating point value.
    """
    ctrl = None

    def __init__(
        self,
        parent,
        id=-1,
        value=0.0,
        pos=wx.DefaultPosition,
        size=wx.DefaultSize,
        style=wx.TE_RIGHT,
        validator=wx.DefaultValidator,
        name="eg.SmartSpinNumCtrl",
        **kwargs
    ):
        self.initValue = value
        self.value = value
        self.parent = parent
        self.kwargs = kwargs
        self.name = name
        self.nW = size[0] if size[0] != -1 else 60
        self.tW = size[0] if size[0] != -1 else 120
        if 'numWidth' in self.kwargs:
            self.nW = self.kwargs['numWidth']
            del self.kwargs['numWidth']
        if 'textWidth' in self.kwargs:
            self.tW = self.kwargs['textWidth']
            del self.kwargs['textWidth']

        wx.Window.__init__(self, parent, id, pos, size, 0)
        self.SetThemeEnabled(True)
        self.sizer = wx.BoxSizer(wx.HORIZONTAL)
        self.SetSizer(self.sizer)
        self.ctrl = self.CreateCtrl(int(not isinstance(value, (int, float))))
        self.Bind(wx.EVT_SIZE, self.OnSize)

    def CreateCtrl(self, ctrlType, init = True):
        szr = self.sizer
        szr.Clear(True)
        if ctrlType == 0:
            ctrl = eg.SpinNumCtrl(
                self,
                -1,
                self.initValue,
                **self.kwargs
            )
            ctrl.numCtrl.Bind(wx.EVT_RIGHT_UP, self.OnRclick)
            ctrl.numCtrl.SetToolTipString(eg.text.General.smartSpinTooltip)
            if init:
                ctrl.SetValue(self.value)
        else:
            ctrl = wx.TextCtrl(
                self,
                -1,
                str(self.value),
            )
            ctrl.Bind(wx.EVT_RIGHT_UP, self.OnRclick)
            ctrl.SetToolTipString(eg.text.General.smartSpinTooltip)
            if not init:
                ctrl.SetValue(("", "{eg.result}", "{eg.event.payload}", "")[ctrlType])
        szr.Add(ctrl, 1, wx.ALIGN_CENTER_VERTICAL | wx.EXPAND)
        szr.Layout()
        self.UpdateWidth(ctrl)
        return ctrl

    def GetSize(self):
        return self.ctrl.GetSize()

    def GetValue(self):
        return self.ctrl.GetValue()

    def OnMenu(self, evt):
        self.ctrl = self.CreateCtrl(self.popups.index(evt.GetId()), False)

    def OnRclick(self, evt):
        if not hasattr(self, "popupId0"):
            self.popupId0 = wx.NewId()
            self.popupId1 = wx.NewId()
            self.popupId2 = wx.NewId()
            self.popupId3 = wx.NewId()
            self.popups = (
                self.popupId0,
                self.popupId1,
                self.popupId2,
                self.popupId3
            )
            self.Bind(wx.EVT_MENU, self.OnMenu, id=self.popupId0)
            self.Bind(wx.EVT_MENU, self.OnMenu, id=self.popupId1)
            self.Bind(wx.EVT_MENU, self.OnMenu, id=self.popupId2)
            self.Bind(wx.EVT_MENU, self.OnMenu, id=self.popupId3)
        menu = wx.Menu()
        for i in range(4):
            menu.Append(self.popups[i], eg.text.General.smartSpinMenu[i])
        self.PopupMenu(menu)
        menu.Destroy()

    def OnSize(self, dummyEvent):
        if self.GetAutoLayout():
            self.Layout()

    def SetSize(self, size):
        w = size[0]
        if w != -1:
            self.tW = w
            self.nW = w
        self.UpdateWidth(self.ctrl)

    def SetValue(self, value):
        if isinstance(self.ctrl, eg.Classes.SpinNumCtrl.SpinNumCtrl):
            if isinstance(value, (str, unicode)):
                value = float(value)
            minValue, maxValue = self.ctrl.numCtrl.GetBounds()
            if maxValue is not None and value > maxValue:
                value = maxValue
            if minValue is not None and value < minValue:
                value = minValue
        elif isinstance(value, (int, float)):
            value = str(value)
        res = self.ctrl.SetValue(value)
        wx.PostEvent(self, eg.ValueChangedEvent(self.GetId(), value = value))
        return res

    def UpdateWidth(self, ctrl):
        w = (self.tW, self.nW)[int(isinstance(ctrl, eg.Classes.SpinNumCtrl.SpinNumCtrl))]
        parentSizer = self.GetContainingSizer()
        if parentSizer:
            parentSizer.SetItemMinSize(self, w, -1)
            parentSizer.Layout()
        else:
            ctrl.SetMinSize((w, -1))
            ctrl.SetSize((w, -1))