I use the same Python classes in all my projects. I don’t post them every time. If you don’t already have them, copy them from here. Use find function of your browser to navigate.
If you didn’t find what you looking for, chat me, I send you.
NewListBox, NewListBoxItem
class NewListBox(Window): def __init__(self): Window.__init__(self) self.items = [] self.selected = None self.basePos = 0 self.itemWidth = 100 self.itemStep = 4 self.totalItemHeight = 0 self.scrollbar = None self.scrollBarPos = 0.0 self.manualMode = False self.selectEvent = None def __del__(self): Window.__del__(self) self.items = [] self.selected = None self.basePos = 0 self.itemWidth = 100 self.itemStep = 4 self.totalItemHeight = 0 self.scrollbar = None self.scrollBarPos = 0.0 self.manualMode = False self.selectEvent = None def SetSize(self, w, h): Window.SetSize(self, w, h + self.itemStep) # self.SetItemWidth(w) self.UpdateList() def SetScrollBar(self, scrollbar): self.scrollbar = scrollbar self.scrollbar.SetScrollEvent(__mem_func__(self.__OnScroll)) self.scrollbar.SetScrollStep(0.07) self.UpdateList() def CalcTotalItemHeight(self): return self.totalItemHeight def ConfigureScrollBar(self): if self.scrollbar: itemheight = self.CalcTotalItemHeight() myheight = self.GetHeight() - 2 * self.itemStep dif = 0.97 if itemheight > myheight and itemheight != 0: dif = 1.0 * myheight / itemheight self.scrollbar.SetScrollStep(0.12 * dif) self.scrollbar.SetMiddleBarSize(dif) def __OnScroll(self, position=None): pos = self.scrollbar.GetPos() if position == None else position self.scrollBarPos = pos toscr = self.CalcTotalItemHeight() - self.GetHeight() + 2 * self.itemStep self.basePos = toscr * pos self.UpdateList() def GetScrollBarPosition(self): return self.scrollBarPos def OnScroll(self, pos): self.__OnScroll(pos) def SelectItem(self, item): self.selected = item if self.selectEvent: self.selectEvent(item) def AppendItem(self, item): item.SetParent(self) # item.SetWidth(self.itemWidth) item.Show() self.items.append(item) if not self.manualMode: self.UpdateList() def RemoveItem(self, item): item.Hide() self.items.remove(item) self.UpdateList() def ClearItems(self): map(lambda wnd: wnd.Hide(), self.items) del self.items[:] self.basePos = 0 if self.scrollbar: self.scrollbar.SetPos(0) self.UpdateList() def UpdateList(self): self.ConfigureScrollBar() self.RecalcItemPositions() def IsEmpty(self): return len(self.items) == 0 def SetItemWidth(self, w): self.itemWidth = w for item in self.items: item.SetWidth(w) def RecalcItemPositions(self): curbp = self.basePos itemheight = self.CalcTotalItemHeight() myheight = self.GetHeight() - 2 * self.itemStep if itemheight < myheight: curbp = 0 fromPos = curbp curPos = 0 curX = 0 toPos = curbp + self.GetHeight() for item in self.items: hw = item.GetHeight() if curPos + hw < fromPos: item.Hide() elif curPos < fromPos < curPos + hw: item.SetRenderMin(fromPos - curPos) item.Show() elif curPos < toPos < curPos + hw: item.SetRenderMax(toPos - curPos) item.Show() elif curPos > toPos: item.Hide() else: item.SetRenderMin(0) item.Show() item.SetPosition(curX, curPos - fromPos) curX += item.GetWidth() if curX >= self.GetWidth(): curX = 0 curPos += hw + self.itemStep elif self.items.index(item) == len(self.items) - 1: curPos += item.GetHeight() # if len(self.items): # curPos += self.items[-1].GetHeight() self.totalItemHeight = curPos class NewListBoxItem(Window): def __init__(self): Window.__init__(self) self.width = 0 self.height = 0 self.minh = 0 self.maxh = 0 self.components = [] def __del__(self): Window.__del__(self) def SetColor(self, color=0xff0099ff): self.color = color def SetParent(self, parent): Window.SetParent(self, parent) def SetHeight(self, h): self.SetSize(self.width, h) def SetWidth(self, w): self.SetSize(w, self.height) def SetSize(self, w, h): self.width = w self.height = h self.maxh = h Window.SetSize(self, w, h) def SetRenderMin(self, minh): self.minh = minh self.maxh = self.height self.RecalculateRenderedComponents() def SetRenderMax(self, maxh): self.maxh = maxh self.minh = 0 self.RecalculateRenderedComponents() def RegisterComponent(self, component): mtype = type(component).__name__ if mtype == "Bar": (x, y, w, h) = component.GetRect() (x, y) = component.GetLocalPosition() component.__list_data = [x, y, w, h] if component not in self.components: self.components.append(component) component.Show() def UnregisterComponent(self, component): if component in self.components: self.components.remove(component) component.Hide() def RecalculateRenderedComponents(self): for component in self.components: (xl, yl) = component.GetLocalPosition() (x, y, w, h) = component.GetRect() mtype = type(component).__name__ if mtype == "TextLine": (w, h) = component.GetTextSize() if yl + h < self.minh: component.Hide() elif yl > self.maxh: component.Hide() else: if mtype == "ExpandedImageBox" or mtype == "ExpandedButton": miny = 0 if self.minh > 0 and yl < self.minh: miny = -float(self.minh - yl) / float(h) maxy = 0 if h != 0: maxy = float(self.maxh - yl - h) / float(h) maxy = min(0, max(-1, maxy)) component.SetRenderingRect(0.0, miny, 0.0, maxy) component.Show() elif mtype == "Bar": component.SetSize(w, min(self.maxh + self.minh, h)) component.Show() else: if yl < self.minh or yl + h > self.maxh: component.Hide() else: component.Show() def OnRender(self): x, y = self.GetGlobalPosition() grp.SetColor(self.color) grp.RenderBar(x, y + self.minh, self.GetWidth(), self.maxh - self.minh)
ExpandedButton
class ExpandedButton(ExpandedImageBox): def __init__(self): ExpandedImageBox.__init__(self) self.images = {"UP": "", "OVER": "", "DOWN": ""} self.state = "NORMAL" self.xScale = 1.0 self.yScale = 1.0 self.rect = {} self.isDown = False self.ButtonText = None self.eventDict = {} self.argsDict = {} def __del__(self): ExpandedImageBox.__del__(self) self.eventDict = {} self.argsDict = {} def SetScale(self, xScale, yScale): self.xScale = float(xScale) self.yScale = float(yScale) ExpandedImageBox.SetScale(self, xScale, yScale) def SetRenderingRect(self, left, top, right, bottom): ExpandedImageBox.SetRenderingRect(self, left, top, right, bottom) self.rect = (left, top, right, bottom) def LoadImage(self, imgPath): ExpandedImageBox.LoadImage(self, imgPath) if self.xScale and self.yScale: ExpandedImageBox.SetScale(self, self.xScale, self.yScale) if self.rect: self.SetRenderingRect(*self.rect) def SetUpVisual(self, filename): self.images["UP"] = filename if self.state == "NORMAL": self.LoadImage(filename) def SetOverVisual(self, filename): self.images["OVER"] = filename if self.state == "OVER": self.LoadImage(filename) def SetDownVisual(self, filename): self.images["DOWN"] = filename if self.state == "DOWN": self.LoadImage(filename) def GetUpVisualFileName(self): return self.images["UP"] def GetOverVisualFileName(self): return self.images["OVER"] def GetDownVisualFileName(self): return self.images["DOWN"] def SetTextColor(self, color): if not self.ButtonText: return self.ButtonText.SetPackedFontColor(color) def SetRGBTextColor(self, r, g, b): if not self.ButtonText: return self.ButtonText.SetFontColor(r, g, b) def SetTextPosition(self, x, y): if self.ButtonText: self.ButtonText.SetHorizontalAlignLeft() self.ButtonText.SetPosition(x, y) def SetText(self, text, height=4): if not self.ButtonText: textLine = TextLine() textLine.SetParent(self) textLine.SetPosition(self.GetWidth() / 2, self.GetHeight() / 2) textLine.SetVerticalAlignCenter() textLine.SetHorizontalAlignCenter() textLine.Show() self.ButtonText = textLine self.ButtonText.SetText(text) def GetText(self): if self.ButtonText: return self.ButtonText.GetText() def IsDown(self): return self.isDown def Enable(self): try: apply(self.eventDict["ENABLE"], self.argsDict["ENABLE"]) except KeyError: pass self.SetUp() def SetEnableEvent(self, func, *args): self.eventDict["ENABLE"] = __mem_func__(func) self.argsDict["ENABLE"] = args def Disable(self): try: apply(self.eventDict["DISABLE"], self.argsDict["DISABLE"]) except KeyError: pass self.Down() def SetDisableEvent(self, func, *args): self.eventDict["DISABLE"] = __mem_func__(func) self.argsDict["DISABLE"] = args def SetUp(self): self.isDown = False self.LoadImage(self.images["UP"]) def Down(self): self.isDown = True self.LoadImage(self.images["DOWN"]) def OnMouseLeftButtonUp(self): if self.isDown: return self.state = "NORMAL" if self.IsIn(): self.LoadImage(self.images["OVER"]) snd.PlaySound("sound/ui/click.wav") try: apply(self.eventDict["MOUSE_CLICK"], self.argsDict["MOUSE_CLICK"]) except KeyError: pass else: self.LoadImage(self.images["UP"]) def SAFE_SetEvent(self, func, *args): self.eventDict["MOUSE_CLICK"] = __mem_func__(func) self.argsDict["MOUSE_CLICK"] = args def SetEvent(self, func, *args): self.eventDict["MOUSE_CLICK"] = func self.argsDict["MOUSE_CLICK"] = args def SetMouseLeftButtonDownEvent(self, func, *args): self.eventDict["MOUSE_DOWN"] = func self.argsDict["MOUSE_DOWN"] = args def GetEvent(self): return self.eventFunc, self.eventArgs def OnMouseOverIn(self): if self.isDown: return self.LoadImage(self.images["OVER"]) def OnMouseOverOut(self): if self.isDown: return self.LoadImage(self.images["UP"]) def OnMouseLeftButtonDown(self): if self.isDown: return self.state = "DOWN" self.LoadImage(self.images["DOWN"]) try: apply(self.eventDict["MOUSE_DOWN"], self.argsDict["MOUSE_DOWN"]) except KeyError: pass def SetMouseDoubleClickEvent(self, func, *args): if self.isDown: return self.eventDict["MOUSE_DOUBLE_CLICK"] = __mem_func__(func) self.argsDict["MOUSE_DOUBLE_CLICK"] = args def OnMouseLeftButtonDoubleClick(self): if self.isDown: return try: apply(self.eventDict["MOUSE_DOUBLE_CLICK"], self.argsDict["MOUSE_DOUBLE_CLICK"]) except KeyError: pass