from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals

import wx
import wx.propgrid as wxpg


class CustomEditor(wxpg.PGEditor):
    """
    Custom Editor class for use with PropertyGrid
    Mostly Taken from Phoenix Demo.
    """
    def __init__(self):
        wxpg.PGEditor.__init__(self)

    def CreateControls(self, propgrid, property, pos, sz):
        """ Create the actual wxPython controls here for editing the
            property value.

            You must use propgrid.GetPanel() as parent for created controls.

            Return value is either single editor control or tuple of two
            editor controls, of which first is the primary one and second
            is usually a button.
        """
        try:
            x, y = pos
            w, h = sz

            # Make room for button
            s = property.GetDisplayedString()

            tc = wx.TextCtrl(propgrid.GetPanel(), wxpg.PG_SUBID1, s,
                             (x, y), (w, h),
                             wx.TE_PROCESS_ENTER)
            return wxpg.PGWindowList(tc)
        except Exception:
            import traceback
            print(traceback.print_exc())

    def UpdateControl(self, property, ctrl):
        ctrl.SetValue(property.GetDisplayedString())

    def DrawValue(self, dc, rect, property, text):
        if not property.IsValueUnspecified():
            dc.DrawText(property.GetDisplayedString(), rect.x + 5, rect.y)

    def OnEvent(self, propgrid, property, ctrl, event):
        """ Return True if modified editor value should be committed to
            the property. To just mark the property value modified, call
            propgrid.EditorsValueWasModified().
        """
        if not ctrl:
            return False

        evtType = event.GetEventType()

        if evtType == wx.wxEVT_COMMAND_TEXT_ENTER:
            if propgrid.IsEditorsValueModified():
                return True
        elif evtType == wx.wxEVT_COMMAND_TEXT_UPDATED:
            #
            # Pass this event outside wxPropertyGrid so that,
            # if necessary, program can tell when user is editing
            # a textctrl.
            event.Skip()
            event.SetId(propgrid.GetId())

            propgrid.EditorsValueWasModified()
            return False

        return False

    def GetValueFromControl(self, property, ctrl):
        """ Return tuple (wasSuccess, newValue), where wasSuccess is True if
            different value was acquired succesfully.
        """
        tc = ctrl
        textVal = tc.GetValue()

        if property.UsesAutoUnspecified() and not textVal:
            return (True, None)

        res, value = property.StringToValue(textVal,
                                            wxpg.PG_EDITABLE_VALUE)

        # Changing unspecified always causes event (returning
        # True here should be enough to trigger it).
        if not res and value is None:
            res = True

        return (res, value)

    def SetValueToUnspecified(self, property, ctrl):
        ctrl.Remove(0, len(ctrl.GetValue()))

    def SetControlStringValue(self, property, ctrl, text):
        ctrl.SetValue(text)

    def OnFocus(self, property, ctrl):
        ctrl.SetSelection(-1, -1)
        ctrl.SetFocus()


if __name__ == '__main__':

    class MyPropGrid(wx.Frame):
        def __init__(self, *args, **kwargs):
            """
            Initialize the property Grid
            :param args:
            :param kwargs:
            """
            wx.Frame.__init__(self, *args, **kwargs)

            sizer = wx.BoxSizer(wx.HORIZONTAL)

            pg = wxpg.PropertyGrid(self)

            pg.RegisterEditor(CustomEditor)
            prop = wxpg.StringProperty("Simple Property", name="mine",
                                       value="Change me!!")
            pg.Append(prop)
            prop.SetEditor("CustomEditor")
            sizer.Add(pg, 1, wx.EXPAND | wx.ALL, 5)
            self.SetSizer(sizer)
            self.Layout()

    app = wx.App()
    frame = MyPropGrid(None)
    frame.Show()

    app.MainLoop()
