"""
WxSlider Class: Extended wx.Slider supporting floating point values
                you should call Enable() after binding any event with this control
"""

__all__ = ['WxSlider']

import wx


class WxSlider(wx.Slider):
    def __init__(self, parent, id, value, minValue, maxValue,
                 pos=wx.DefaultPosition, size=wx.DefaultSize,
                 style=wx.SL_HORIZONTAL, validator=wx.DefaultValidator,
                 name="slider", textSize=(40, 20)):

        self.maxValue = maxValue
        self.minValue = minValue
        intVal = int(100.0 / (self.maxValue - self.minValue) * (value - self.minValue))

        intMin = 0
        intMax = 100
        self.textValue = None
        self.updateCB = None

        if style & wx.SL_HORIZONTAL:
            newStyle = wx.SL_HORIZONTAL
            if style & wx.SL_LABELS:
                wx.StaticText(parent, -1, "%.2f" % minValue, (pos[0], pos[1]))
                strMaxValue = "%.2f" % maxValue
                wx.StaticText(parent, -1, strMaxValue, (pos[0] + size[0] - len(strMaxValue) * 8, pos[1]))
                strValue = "%.2f" % value
                self.textValue = wx.TextCtrl(parent, -1, strValue,
                                             (pos[0] + size[0] / 2 - textSize[0] / 2, pos[1]),
                                             textSize, wx.TE_CENTER | wx.TE_PROCESS_ENTER)

                self.textValue.Disable()
                pos = (pos[0], pos[1] + 20)
        else:
            newStyle = wx.SL_VERTICAL
            pos = (pos[0], pos[1] + 40)

        if style & wx.SL_AUTOTICKS:
            newStyle |= wx.SL_AUTOTICKS

        wx.Slider.__init__(self, parent, id, intVal, intMin, intMax, pos, size, style=newStyle)
        self.Disable()

    def GetValue(self):
        # overriding wx.Slider.GetValue()
        if self.textValue is not None: # Horizontal with labels
            return float(self.textValue.GetValue()) # [gjeon] since the value from the slider is not as precise as the value entered by the user
        else:
            return (wx.Slider.GetValue(self) * (self.maxValue - self.minValue) / 100.0 + self.minValue)

    def SetValue(self, value):
        # overriding wx.Slider.SetValue()
        if self.textValue is not None:
            self.textValue.SetValue("%.2f" % value)
        intVal = 100.0 / (self.maxValue - self.minValue) * (value - self.minValue)
        wx.Slider.SetValue(self, intVal)

    def onChange(self, event):
        # update textValue from slider
        if self.textValue is not None:
            self.textValue.Clear()
            floatVal = wx.Slider.GetValue(self) * (self.maxValue - self.minValue) / 100.0 + self.minValue
            self.textValue.WriteText("%.2f" % floatVal)
        if self.updateCB: # callback function sould receive event as the argument
            self.updateCB(event)
        event.Skip()

    def onEnter(self, event):
        # update slider from textValue
        if self.textValue is None:
            return
        intVal = 100.0 / (self.maxValue - self.minValue) * (float(self.textValue.GetValue()) - self.minValue)
        wx.Slider.SetValue(self, intVal)
        if self.updateCB: # callback function should receive event as the argument
            self.updateCB(event)
        event.Skip()

    def bindFunc(self, updateCB):
        self.updateCB = updateCB

    def Disable(self):
        # overriding wx.Slider.Disable()
        wx.Slider.Disable(self)
        if self.textValue is not None:
            self.textValue.Disable()

    def Enable(self):
        # overriding wx.Slider.Enable()
        wx.Slider.Enable(self)
        self.Bind(wx.EVT_SLIDER, self.onChange)

        if self.textValue is not None:
            self.textValue.Enable()
            self.textValue.Bind(wx.EVT_TEXT_ENTER, self.onEnter)
