import wx


class EditGridHead(wx.Panel):
    def __init__(self,parent):
        wx.Panel.__init__(self,parent)
        self.parent = parent
        self.dx = 0
        sizer = wx.BoxSizer(wx.HORIZONTAL)
        for i in range(15):
            sizer.Add(wx.StaticText(self,-1,label='col '+str(i),size=(100,30)))
        self.SetSizer(sizer)
        self.Fit()
        self.SetVirtualSize(100*15,30)

    def scrollX(self):
        x,y = self.parent.CalcUnscrolledPosition(0,0)
        self.ScrollWindow(self.dx-x,0)
        self.dx = x


class EditGridBody(wx.Panel):
    def __init__(self,parent,head):
        wx.Panel.__init__(self,parent)
        self.parent = parent
        self.head = head
        sizer = wx.FlexGridSizer(30,15,0,0)
        for i in range(30):
            for j in range(15):
                sizer.Add(wx.TextCtrl(self,-1,value=str(i)+','+str(j),size=(100,30)))
        self.SetSizer(sizer)
        self.Fit()
        self.SetVirtualSize(100*15,30*30)


class EditGridEvtHandler(wx.EvtHandler):
    def __init__(self,scrollHelper):
        wx.EvtHandler.__init__(self)
        self.scrollHelper = scrollHelper
        self.sized = False

    def ProcessEvent(self,evt):
        self.evtType = evt.GetEventType()
        processed = self.GetNextHandler().ProcessEvent(evt)
        if self.evtType==wx.EVT_SIZE.typeId:
            return True
        if self.evtType==wx.EVT_SCROLLWIN_TOP.typeId:
            self.scrollHelper.head.scrollX()
            return True
        if self.evtType==wx.EVT_SCROLLWIN_BOTTOM.typeId:
            self.scrollHelper.head.scrollX()
            return True
        if self.evtType==wx.EVT_SCROLLWIN_LINEUP.typeId:
            self.scrollHelper.head.scrollX()
            return True
        if self.evtType==wx.EVT_SCROLLWIN_LINEDOWN.typeId:
            self.scrollHelper.head.scrollX()
            return True
        if self.evtType==wx.EVT_SCROLLWIN_PAGEUP.typeId:
            self.scrollHelper.head.scrollX()
            return True
        if self.evtType==wx.EVT_SCROLLWIN_PAGEDOWN.typeId:
            self.scrollHelper.head.scrollX()
            return True
        if self.evtType==wx.EVT_SCROLLWIN_THUMBTRACK.typeId:
            self.scrollHelper.head.scrollX()
            return True
        if self.evtType==wx.EVT_SCROLLWIN_THUMBRELEASE.typeId:
            self.scrollHelper.head.scrollX()
            return True
        if hasattr(self.scrollHelper,'head'):
            self.scrollHelper.head.scrollX()
        return processed


class EditGrid(wx.ScrolledWindow):
    def __init__(self,parent):
        wx.ScrolledWindow.__init__(self,parent)
        self.evtHandler = EditGridEvtHandler(self)
        self.PushEventHandler(self.evtHandler)
        # head and body
        self.head = EditGridHead(self)
        self.body = EditGridBody(self,self.head)
        self.SetTargetWindow(self.body)
        self._scrollRate = 5
        self.SetScrollRate(self._scrollRate,self._scrollRate)
        self.Bind(wx.EVT_SIZE,self.OnSize)
        self.Bind(wx.EVT_WINDOW_DESTROY,self.OnWinDestroy)

    def OnWinDestroy(self,evt):
        self.RemoveEventHandler(self.evtHandler)
        evt.Skip()

    def GetSizeAvailableForScrollTarget(self,size):
        ssize = size
        ssize.y -= 30
        return ssize

    def OnSize(self,evt):
        w,h = self.GetClientSize()
        h = h-30 if h-30>0 else 0
        self.head.SetSize(0,0,w,30)
        self.body.SetSize(0,30,w,h)
        evt.Skip()


class MainFrame(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self,None,title='gridEditor',size=(700,600))
        panel = wx.Panel(self)
        self.grd = EditGrid(panel)
        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(self.grd,1,wx.EXPAND)
        # button = wx.Button(panel,label='点击')
        # self.Bind(wx.EVT_BUTTON,self.OnClick,button)
        # sizer.Add(button)
        panel.SetSizer(sizer)
        panel.Fit()

    # def OnClick(self,evt):
    #     x,y = self.grd.CalcUnscrolledPosition(0,0)
    #     self.grd.head.ScrollWindow(-x,0)
    #     self.grd.body.ScrollWindow(-x,-y)


class App(wx.App):
    def OnInit(self):
        self.frame = MainFrame()
        self.frame.Show()
        self.frame.Refresh()
        return True


if __name__ == '__main__':
    app = App()
    app.MainLoop()