#=============================================================================== # Copyright (C) 2010 Diego Duclos # # This file is part of pyfa. # # pyfa 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 3 of the License, or # (at your option) any later version. # # pyfa 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 pyfa. If not, see . #=============================================================================== import wx class PFListPane(wx.ScrolledWindow): def __init__(self, parent): wx.ScrolledWindow.__init__ (self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition, size=wx.Size(1, 1), style=wx.TAB_TRAVERSAL) self._wList = [] self._wCount = 0 self.itemsHeight = 1 self.SetBackgroundColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOW)) self.SetVirtualSize((1, 1)) self.SetScrollRate(0, 1) self.Bind(wx.EVT_SCROLLWIN_LINEUP, self.MScrollUp) self.Bind(wx.EVT_SCROLLWIN_LINEDOWN, self.MScrollDown) # self.Bind(wx.EVT_CHILD_FOCUS, self.OnChildFocus) # self.Bind(wx.EVT_LEFT_DOWN, self.ForceFocus) self.SetFocus() # self.Bind(wx.EVT_MOUSE_CAPTURE_CHANGED, self.ForceFocus) self.Bind(wx.EVT_SCROLLWIN_THUMBRELEASE, self.ForceFocus) def ForceFocus(self,event): if self.FindFocus() and self.FindFocus().Parent != self: self.SetFocus() event.Skip() def OnChildFocus(self, event): event.Skip() child = event.GetWindow() self.ScrollChildIntoView(child) def MScrollUp(self, event): posy = self.GetScrollPos(wx.VERTICAL) posy -= self.itemsHeight self.Scroll(0, posy) event.Skip() def MScrollDown(self, event): posy = self.GetScrollPos(wx.VERTICAL) posy += self.itemsHeight self.Scroll(0, posy) event.Skip() def ScrollChildIntoView(self, child): """ Scrolls the panel such that the specified child window is in view. """ sppu_x, sppu_y = self.GetScrollPixelsPerUnit() vs_x, vs_y = self.GetViewStart() cr = child.GetRect() clntsz = self.GetSize() new_vs_x, new_vs_y = -1, -1 # is it before the left edge? if cr.x < 0 and sppu_x > 0: new_vs_x = vs_x + (cr.x / sppu_x) # is it above the top? if cr.y < 0 and sppu_y > 0: new_vs_y = vs_y + (cr.y / sppu_y) # For the right and bottom edges, scroll enough to show the # whole control if possible, but if not just scroll such that # the top/left edges are still visible # is it past the right edge ? if cr.right > clntsz.width and sppu_x > 0: diff = (cr.right - clntsz.width + 1) / sppu_x if cr.x - diff * sppu_x > 0: new_vs_x = vs_x + diff else: new_vs_x = vs_x + (cr.x / sppu_x) # is it below the bottom ? if cr.bottom > clntsz.height and sppu_y > 0: diff = (cr.bottom - clntsz.height + 1) / sppu_y if cr.y - diff * sppu_y > 0: new_vs_y = vs_y + diff else: new_vs_y = vs_y + (cr.y / sppu_y) # if we need to adjust if new_vs_x != -1 or new_vs_y != -1: self.Scroll(new_vs_x, new_vs_y) def AddWidget(self, widget): widget.Reparent(self) self._wList.append(widget) self._wCount += 1 def GetWidgetList(self): return self._wList # Override this method if needed ( return False by default if we do not want to scroll to selected widget) def IsWidgetSelectedByContext(self, widget): return False def RefreshList(self, doRefresh = False, doFocus = False): ypos = 0 maxy = 0 scrollTo = 0 selected = None for i in xrange( len(self._wList) ): iwidth, iheight = self._wList[i].GetSize() xa, ya = self.CalcScrolledPosition((0, maxy)) self._wList[i].SetPosition((xa, ya)) if self.IsWidgetSelectedByContext(i): selected = self._wList[i] maxy += iheight self.SetVirtualSize((1, maxy)) cwidth, cheight = self.GetVirtualSize() if selected: self.ScrollChildIntoView(selected) #selected.SetFocus() elif doFocus: self.SetFocus() clientW,clientH = self.GetSize() for i in xrange( len(self._wList) ): iwidth, iheight = self._wList[i].GetSize() itemX,itemY = self._wList[i].GetPosition() self._wList[i].SetSize((cwidth, iheight)) if doRefresh == True: self._wList[i].Refresh() self.itemsHeight = max(self.itemsHeight, iheight - 1) def RemoveWidget(self, child): child.Destroy() self._wList.remove(child) def RemoveAllChildren(self): for widget in self._wList: widget.Destroy() self._wList = []