Best Python code snippet using pyatom_python
dialogrenderer.py
Source:dialogrenderer.py
1import random2import re3from typing import Tuple, Callable4import pygame5import pypeg26from pygame.surface import Surface7from pypeg2 import contiguous, attr, parse, word, maybe_some8from engine.graphics.fontmanager import FontManager9from engine.graphics.frame import Frame10from engine.graphics.textures import Textures11from engine.timer import Timer12from engine.tween.easing import Easing13from engine.tween.tween import Tween14from engine.tween.tweensubject import TweenSubject15class Text(pypeg2.List):16 pass17class BoldText(pypeg2.List):18 grammar = "<b>", attr("text", Text), "</b>"19class UnderlineText(pypeg2.List):20 grammar = "<u>", attr("text", Text), "</u>"21class ShakingText(pypeg2.List):22 grammar = "<shaking>", attr("text", Text), "</shaking>"23class StrikeText(pypeg2.List):24 grammar = "<strike>", attr("text", Text), "</strike>"25class ItalicText(pypeg2.List):26 grammar = "<i>", attr("text", Text), "</i>"27class WavingText(pypeg2.List):28 grammar = "<waving>", attr("text", Text), "</waving>"29class SmallText(pypeg2.List):30 grammar = "<small>", attr("text", Text), "</small>"31class BigText(pypeg2.List):32 grammar = "<big>", attr("text", Text), "</big>"33class SlowText(pypeg2.List):34 grammar = "<slow>", attr("text", Text), "</slow>"35class FastText(pypeg2.List):36 grammar = "<fast>", attr("text", Text), "</fast>"37class ColoredText(pypeg2.List):38 grammar = "<color ", pypeg2.Symbol, ">", attr("text", Text), "</color>"39# Ugh not this again40Text.grammar = attr("text", contiguous(maybe_some([SlowText, FastText, SmallText, BigText, ColoredText, WavingText, StrikeText, ShakingText, ItalicText, BoldText, UnderlineText,41 re.compile(r"[^<>]")])))42class CharacterChunk:43 def __init__(self):44 self.char = ""45 self.surface = None46 self.state = {}47 self.yOffset = 0 # used to compensate the big and small text size48 self.animationXOffset = TweenSubject(0) # used to animate letters49 self.animationYOffset = TweenSubject(0)50class DialogRenderer:51 # TODO Add choices here52 # TODO In order : more rich text rendering53 # TODO Add sound54 STATE_PARSING = 055 STATE_BUILDING = 156 STATE_READY = 257 LINE_HEIGHT = 4058 DEFAULT_TEXT_COLOR = (0, 0, 0, 0)59 FONT = "Dialog"60 Y_OFFSET = -461 CARET_TIMER_DURATION = 10062 SHAKING_TIMER_DURATION = 2063 WAVING_TIMER_DURATION = 60064 LETTER_DURATION = 20 # TODO Make this a user choice65 WAVING_X_AMPLITUDE = 366 WAVING_Y_AMPLITUDE = 867 WAVING_OFFSET = 15 # ms offset between each letter68 def __init__(self, window : Surface, frame : Frame, text : str, endCallback : Callable):69 self.__boundaries = frame.rect70 self.__text = text71 self.__endCb = endCallback72 self.__window = window73 self.__caretTexture = Textures.getTexture("gui.caret")74 self.__caretStep = 0 # the current step in the caret texture75 self.__caretTimer = Timer("caret", DialogRenderer.CARET_TIMER_DURATION, self.caretTimerCb)76 self.__shakingTimer = Timer("shaking", DialogRenderer.SHAKING_TIMER_DURATION, self.shakingTimerCb)77 self.__regularFont = FontManager.getFont(DialogRenderer.FONT + "Regular")78 self.__smallFont = FontManager.getFont(DialogRenderer.FONT + "Small")79 self.__bigFont = FontManager.getFont(DialogRenderer.FONT + "Big")80 self.__font = self.__regularFont81 self.__linesMax = int((self.__boundaries[3] - Frame.PADDING * 2) / (self.__font.size("H")[1]))82 self.__frame = frame83 self.__parserState = DialogRenderer.STATE_PARSING84 self.__states = {}85 self.__lines = [[]]86 self.__linesCharactersIndex = [0]87 self.__currentPageOffset = 088 self.__currentlyDrawingLine = 089 self.__alive = True90 self.__shakingChunks = []91 self.__wavingChunksTweens = []92 # Rich text parser variables93 self.__lastWhitespacePosOnTheLine = 094 self.__currentPosOnTheLine = 095 self.__xOffset = 096 def buildLines(self, tree):97 for text in tree.text:98 textType = type(text)99 if textType == str:100 if text == " ":101 self.__lastWhitespacePosOnTheLine = self.__currentPosOnTheLine102 self.setFontProperties(self.__states)103 chunk = CharacterChunk()104 chunk.char = text105 chunk.surface = self.__font.render(text, True, DialogRenderer.DEFAULT_TEXT_COLOR) # TODO Right color106 chunk.state = {**self.__states}107 if self.stateEnabled(chunk.state, "Small"):108 chunk.yOffset = 10109 elif self.stateEnabled(chunk.state, "Big"):110 chunk.yOffset = -5111 if text == "\n":112 self.__lines.append([])113 self.__linesCharactersIndex.append(0)114 elif text == "\t":115 for x in range(0, (self.__linesMax - len(self.__lines) % self.__linesMax) + 1):116 self.__lines.append([])117 self.__linesCharactersIndex.append(0)118 elif self.__xOffset + chunk.surface.get_width() >= self.__boundaries[2] - Frame.PADDING * 2:119 # Rewind until the previous whitespace to put the previous120 # word on the newly created line121 newLine = self.__lines[-1][self.__lastWhitespacePosOnTheLine+1:self.__currentPosOnTheLine+1]122 self.__lines[-1] = self.__lines[-1][:self.__lastWhitespacePosOnTheLine+1]123 # Ignore empty new lines (overflowing whitespace)124 if len(newLine) > 0:125 # If the first char of the line is a whitespace126 # remove its chunk127 firstChar = newLine[0].char128 if firstChar == " ":129 newLine = newLine[1:]130 # Append new line and reset131 self.__xOffset = sum(x.surface.get_width() for x in newLine)132 self.__lines.append(newLine)133 self.__linesCharactersIndex.append(0)134 self.__currentPosOnTheLine = len(newLine)135 if text != "\n" and text != "\t":136 self.__lines[-1].append(chunk)137 self.__xOffset += chunk.surface.get_width()138 if self.stateEnabled(chunk.state, "Shaking"):139 self.__shakingChunks.append(chunk)140 elif self.stateEnabled(chunk.state, "Waving"):141 chunk.animationXOffset.value = -DialogRenderer.WAVING_X_AMPLITUDE142 chunk.animationYOffset.value = -DialogRenderer.WAVING_Y_AMPLITUDE143 xtween = Tween(None, chunk.animationXOffset, DialogRenderer.WAVING_X_AMPLITUDE,144 DialogRenderer.WAVING_TIMER_DURATION, Easing.easingInOutSine, None)145 xtween.runningSince = xtween.duration / 2 # fast forward half the time to offset X and Y animations146 ytween = Tween(None, chunk.animationYOffset, DialogRenderer.WAVING_Y_AMPLITUDE,147 DialogRenderer.WAVING_TIMER_DURATION, Easing.easingInOutSine, None)148 xtween.runningSince += DialogRenderer.WAVING_OFFSET * self.__currentPosOnTheLine149 ytween.runningSince += DialogRenderer.WAVING_OFFSET * self.__currentPosOnTheLine150 self.__wavingChunksTweens.append(xtween)151 self.__wavingChunksTweens.append(ytween)152 self.__currentPosOnTheLine += 1153 else:154 typeStr = textType.__name__[:-4]155 self.__states[typeStr] = True156 self.buildLines(text.text)157 self.__states[typeStr] = False158 def shakingTimerCb(self, tag):159 for chunk in self.__shakingChunks:160 chunk.animationXOffset.value = random.randint(-1, 1)161 chunk.animationYOffset.value = random.randint(-1, 1)162 self.__shakingTimer.restart()163 def setFontProperties(self, state):164 if self.stateEnabled(state, "Big"):165 self.__font = self.__bigFont166 elif self.stateEnabled(state, "Small"):167 self.__font = self.__smallFont168 else:169 self.__font = self.__regularFont170 self.__font.set_italic(self.stateEnabled(state, "Italic"))171 self.__font.set_underline(self.stateEnabled(state, "Underline"))172 self.__font.set_bold(self.stateEnabled(state, "Bold"))173 def stateEnabled(self, state, name):174 return name in state and state[name]175 def caretTimerCb(self, tag):176 self.__caretStep = (self.__caretStep + 1) % 4177 self.__caretTimer.restart()178 def update(self, dt, events):179 if not self.__alive:180 return181 self.__caretTimer.update(dt)182 self.__shakingTimer.update(dt)183 for tween in self.__wavingChunksTweens:184 tween.update(dt)185 if not tween.alive:186 tween.reverse()187 # Keys188 if self.__parserState == DialogRenderer.STATE_PARSING:189 self.__tree = parse(self.__text, Text)190 self.__parserState = DialogRenderer.STATE_BUILDING191 elif self.__parserState == DialogRenderer.STATE_BUILDING:192 self.buildLines(self.__tree)193 self.__characterTimer = Timer(None, DialogRenderer.LETTER_DURATION, self.characterTimerCb)194 self.__parserState = DialogRenderer.STATE_READY195 elif self.__parserState == DialogRenderer.STATE_READY:196 self.__characterTimer.update(dt)197 for event in events:198 if event.type == pygame.KEYDOWN:199 if (event.key == pygame.K_RETURN):200 if self.hasReachedEndOfPage():201 self.__currentPageOffset += self.__linesMax202 self.__currentlyDrawingLine = self.__currentPageOffset203 if self.__currentPageOffset > len(self.__lines):204 self.__alive = False205 self.__endCb(0)206 else:207 # TODO Disallow this if we're drawing slow text208 for line in range(self.__currentlyDrawingLine, self.__currentPageOffset + self.__linesMax):209 if line >= len(self.__lines):210 break211 self.__linesCharactersIndex[line] = len(self.__lines[line])212 def hasReachedEndOfPage(self):213 return (self.__currentlyDrawingLine == self.__currentPageOffset + self.__linesMax) or (not self.__characterTimer.alive)214 def characterTimerCb(self, tag):215 if self.__currentlyDrawingLine == self.__currentPageOffset + self.__linesMax:216 # Wait for user to press action to continue drawing lines217 self.__characterTimer.restart()218 return219 if self.__linesCharactersIndex[self.__currentlyDrawingLine] + 1 > len(self.__lines[self.__currentlyDrawingLine]):220 self.__currentlyDrawingLine += 1221 try:222 self.__linesCharactersIndex[self.__currentlyDrawingLine] += 1223 except IndexError:224 # Reached the end of the text225 return226 self.__characterTimer.restart()227 def draw(self):228 if not self.__alive:229 return230 # Draw frame231 self.__frame.draw()232 if self.__parserState != DialogRenderer.STATE_READY:233 return234 # Draw text235 xOffset = 0236 yOffset = 0237 lastXOffset = 0238 lastYOffset = 0239 lineIndex = self.__currentPageOffset240 for line in self.__lines[self.__currentPageOffset:self.__currentPageOffset + self.__linesMax]:241 if len(line) == 0:242 continue243 for chunk in line[:self.__linesCharactersIndex[lineIndex]]:244 cx = self.__boundaries[0] + Frame.PADDING + xOffset + chunk.animationXOffset.value245 cy = self.__boundaries[1] + Frame.PADDING + yOffset + DialogRenderer.Y_OFFSET + chunk.yOffset + chunk.animationYOffset.value246 self.__window.blit(chunk.surface, (cx, cy))247 if self.stateEnabled(chunk.state, "Strike"):248 pygame.draw.rect(self.__window, DialogRenderer.DEFAULT_TEXT_COLOR, (cx - 4, cy + 2 + chunk.surface.get_height() / 2, chunk.surface.get_width() + 4, 2)) # TODO Put right text color here249 xOffset += chunk.surface.get_width()250 lastXOffset = xOffset if chunk.char != " " else lastXOffset251 lastYOffset = yOffset252 yOffset += DialogRenderer.LINE_HEIGHT253 xOffset = 0254 lineIndex += 1255 # Draw the caret256 if self.hasReachedEndOfPage():...
dialogrenderer_old.py
Source:dialogrenderer_old.py
1import random2import re3from typing import Tuple, Callable4import pygame5import pypeg26from pygame.surface import Surface7from pypeg2 import contiguous, attr, parse, word, maybe_some8from engine.graphics.fontmanager import FontManager9from engine.graphics.frame import Frame10from engine.graphics.textures import Textures11from engine.timer import Timer12from engine.tween.easing import Easing13from engine.tween.tween import Tween14from engine.tween.tweensubject import TweenSubject15class Text(pypeg2.List):16 pass17class BoldText(pypeg2.List):18 grammar = "<b>", attr("text", Text), "</b>"19class UnderlineText(pypeg2.List):20 grammar = "<u>", attr("text", Text), "</u>"21class ShakingText(pypeg2.List):22 grammar = "<shaking>", attr("text", Text), "</shaking>"23class StrikeText(pypeg2.List):24 grammar = "<strike>", attr("text", Text), "</strike>"25class ItalicText(pypeg2.List):26 grammar = "<i>", attr("text", Text), "</i>"27class WavingText(pypeg2.List):28 grammar = "<waving>", attr("text", Text), "</waving>"29class SmallText(pypeg2.List):30 grammar = "<small>", attr("text", Text), "</small>"31class BigText(pypeg2.List):32 grammar = "<big>", attr("text", Text), "</big>"33class SlowText(pypeg2.List):34 grammar = "<slow>", attr("text", Text), "</slow>"35class FastText(pypeg2.List):36 grammar = "<fast>", attr("text", Text), "</fast>"37class ColoredText(pypeg2.List):38 grammar = "<color ", pypeg2.Symbol, ">", attr("text", Text), "</color>"39# Ugh not this again40Text.grammar = attr("text", contiguous(maybe_some([SlowText, FastText, SmallText, BigText, ColoredText, WavingText, StrikeText, ShakingText, ItalicText, BoldText, UnderlineText,41 re.compile(r"[^<>]")])))42class TextChunk:43 def __init__(self):44 self.text = ""45 self.surface = None46 self.state = {}47 self.yOffset = 0 # used to compensate the big and small text size48 self.animationXOffset = TweenSubject(0) # used to animate letters49 self.animationYOffset = TweenSubject(0)50class DialogRenderer:51 # TODO Add choices here52 # TODO In order : more rich text rendering, "scrolling", letter by letter rendering53 # TODO Add sound54 STATE_PARSING = 055 STATE_CHUNKING = 156 STATE_WRAPPING = 257 STATE_READY = 358 LINE_HEIGHT = 4059 DEFAULT_TEXT_COLOR = (0, 0, 0, 0)60 FONT = "Dialog"61 Y_OFFSET = -462 CARET_TIMER_DURATION = 10063 SHAKING_TIMER_DURATION = 2064 WAVING_TIMER_DURATION = 60065 WAVING_X_AMPLITUDE = 366 WAVING_Y_AMPLITUDE = 867 WAVING_OFFSET = 15 # ms offset between each letter68 def __init__(self, window : Surface, frame : Frame, text : str, endCallback : Callable):69 self.__boundaries = frame.rect70 self.__text = text71 self.__endCb = endCallback72 self.__window = window73 self.__caretTexture = Textures.getTexture("gui.caret")74 self.__caretStep = 0 # the current step in the caret texture75 self.__caretTimer = Timer("caret", DialogRenderer.CARET_TIMER_DURATION, self.caretTimerCb)76 self.__shakingTimer = Timer("shaking", DialogRenderer.SHAKING_TIMER_DURATION, self.shakingTimerCb)77 self.__regularFont = FontManager.getFont(DialogRenderer.FONT + "Regular")78 self.__smallFont = FontManager.getFont(DialogRenderer.FONT + "Small")79 self.__bigFont = FontManager.getFont(DialogRenderer.FONT + "Big")80 self.__font = self.__regularFont81 self.__linesMax = int((self.__boundaries[3] - Frame.PADDING * 2) / (self.__font.size("H")[1]))82 self.__frame = frame83 self.__state = DialogRenderer.STATE_PARSING84 self.__states = {}85 self.__stateChanged = True86 self.__textChunks = [] # list of TextChunk instances87 self.__wrappedTextChunks = [[]]88 self.__currentLine = 089 self.__alive = True90 self.__shakingChunks = []91 self.__wavingChunksTweens = []92 def shakingTimerCb(self, tag):93 for chunk in self.__shakingChunks:94 chunk.animationXOffset.value = random.randint(-1, 1)95 chunk.animationYOffset.value = random.randint(-1, 1)96 self.__shakingTimer.restart()97 def setFontProperties(self, state):98 if self.stateEnabled(state, "Big"):99 self.__font = self.__bigFont100 elif self.stateEnabled(state, "Small"):101 self.__font = self.__smallFont102 else:103 self.__font = self.__regularFont104 self.__font.set_italic(self.stateEnabled(state, "Italic"))105 self.__font.set_underline(self.stateEnabled(state, "Underline"))106 self.__font.set_bold(self.stateEnabled(state, "Bold"))107 def createNewChunk(self, chunk, text):108 newChunk = TextChunk()109 newChunk.text = text110 newChunk.state = chunk.state111 newChunk.yOffset = chunk.yOffset112 newChunk.animationXOffset = TweenSubject(chunk.animationXOffset.value)113 newChunk.animationYOffset = TweenSubject(chunk.animationYOffset.value)114 newChunk.surface = self.__font.render(newChunk.text, True, DialogRenderer.DEFAULT_TEXT_COLOR)115 return newChunk116 def createNewChunks(self, chunk, text):117 if self.stateEnabled(chunk.state, "Shaking"):118 list = []119 for letter in text:120 newChunk = self.createNewChunk(chunk, letter)121 self.__shakingChunks.append(newChunk)122 list.append(newChunk)123 return list124 elif self.stateEnabled(chunk.state, "Waving"):125 list = []126 letterIndex = 0127 for letter in text:128 newChunk = self.createNewChunk(chunk, letter)129 newChunk.animationXOffset.value = -DialogRenderer.WAVING_X_AMPLITUDE130 newChunk.animationYOffset.value = -DialogRenderer.WAVING_Y_AMPLITUDE131 xtween = Tween(None, newChunk.animationXOffset, DialogRenderer.WAVING_X_AMPLITUDE, DialogRenderer.WAVING_TIMER_DURATION, Easing.easingInOutSine, None)132 xtween.runningSince = xtween.duration/2 # fast forward half the time to offset X and Y animations133 ytween = Tween(None, newChunk.animationYOffset, DialogRenderer.WAVING_Y_AMPLITUDE, DialogRenderer.WAVING_TIMER_DURATION, Easing.easingInOutSine, None)134 xtween.runningSince += DialogRenderer.WAVING_OFFSET * letterIndex135 ytween.runningSince += DialogRenderer.WAVING_OFFSET * letterIndex136 self.__wavingChunksTweens.append(xtween)137 self.__wavingChunksTweens.append(ytween)138 list.append(newChunk)139 letterIndex += 1140 return list141 else:142 return [self.createNewChunk(chunk, text)]143 def wordWrap(self):144 xOffset = 0145 for chunk in self.__textChunks:146 self.setFontProperties(chunk.state)147 text = ""148 words = chunk.text.split(" ")149 for word in words:150 word = word + " "151 wordLength = self.__font.size(word)[0]152 isCarriageReturn = word[0:1] == "\n"153 isPageBreak = word[0:1] == "\t"154 if (wordLength + xOffset <= self.__boundaries[2] - Frame.PADDING * 2) and not (isCarriageReturn or isPageBreak):155 text += word156 xOffset += wordLength157 else:158 if not (isCarriageReturn or isPageBreak):159 text = text[:-1]160 if text != "":161 newChunk = self.createNewChunks(chunk, text)162 self.__wrappedTextChunks[-1].extend(newChunk)163 if not isPageBreak:164 self.__wrappedTextChunks.append([])165 else:166 for x in range(0, (self.__linesMax - len(self.__wrappedTextChunks) % self.__linesMax) + 1):167 self.__wrappedTextChunks.append([])168 if not (isCarriageReturn or isPageBreak):169 text = word170 xOffset = wordLength171 else:172 text = ""173 xOffset = 0174 text = text[:-1]175 if text != "":176 newChunk = self.createNewChunks(chunk, text)177 self.__wrappedTextChunks[-1].extend(newChunk)178 def stateEnabled(self, state, name):179 return name in state and state[name]180 def buildChunks(self, thing):181 for text in thing.text:182 textType = type(text)183 if textType == str:184 if self.__stateChanged:185 chunk = TextChunk()186 chunk.state = {**self.__states}187 if self.stateEnabled(chunk.state, "Small"):188 chunk.yOffset = 10189 elif self.stateEnabled(chunk.state, "Big"):190 chunk.yOffset = -5191 self.__textChunks.append(chunk)192 self.__stateChanged = False193 self.__textChunks[-1].text += text194 else:195 typeStr = textType.__name__[:-4]196 self.__stateChanged = True197 self.__states[typeStr] = True198 self.buildChunks(text.text)199 self.__stateChanged = True200 self.__states[typeStr] = False201 def caretTimerCb(self, tag):202 self.__caretStep = (self.__caretStep + 1) % 4203 self.__caretTimer.restart()204 def update(self, dt, events):205 if not self.__alive:206 return207 self.__caretTimer.update(dt)208 self.__shakingTimer.update(dt)209 for tween in self.__wavingChunksTweens:210 tween.update(dt)211 if not tween.alive:212 tween.reverse()213 # Keys214 if self.__state == DialogRenderer.STATE_PARSING:215 self.__tree = parse(self.__text, Text)216 self.__state = DialogRenderer.STATE_CHUNKING217 elif self.__state == DialogRenderer.STATE_CHUNKING:218 self.buildChunks(self.__tree)219 self.__state = DialogRenderer.STATE_WRAPPING220 elif self.__state == DialogRenderer.STATE_WRAPPING:221 self.wordWrap()222 self.__state = DialogRenderer.STATE_READY223 elif self.__state == DialogRenderer.STATE_READY:224 for event in events:225 if event.type == pygame.KEYDOWN:226 if event.key == pygame.K_RETURN:227 self.__currentLine += self.__linesMax228 if self.__currentLine > len(self.__wrappedTextChunks):229 self.__alive = False230 self.__endCb(0)231 def draw(self):232 if not self.__alive:233 return234 # Draw frame235 self.__frame.draw()236 if self.__state != DialogRenderer.STATE_READY:237 return238 # Draw text239 yOffset = 0240 xOffset = 0241 lastYOffset = 0242 lastXOffset = 0243 for line in self.__wrappedTextChunks[self.__currentLine:self.__currentLine+self.__linesMax]:244 for chunk in line:245 cx = self.__boundaries[0] + Frame.PADDING + xOffset + chunk.animationXOffset.value246 cy = self.__boundaries[1] + Frame.PADDING + yOffset + DialogRenderer.Y_OFFSET + chunk.yOffset + chunk.animationYOffset.value247 self.__window.blit(chunk.surface, (cx, cy))248 if self.stateEnabled(chunk.state, "Strike"):249 pygame.draw.rect(self.__window, DialogRenderer.DEFAULT_TEXT_COLOR, (cx - 4, cy + 2 + chunk.surface.get_height()/2, chunk.surface.get_width() + 4, 2)) # TODO Put right text color here250 xOffset += chunk.surface.get_width()251 lastYOffset = yOffset252 lastXOffset = lastXOffset if xOffset == 0 else xOffset253 yOffset += DialogRenderer.LINE_HEIGHT254 xOffset = 0255 # Draw the caret...
widget.py
Source:widget.py
1import pygame2def btn_pos(offs, row, col, size):3 x = 15 + col * (size[0] + 12)4 y = offs + 5 + row * (size[1] + 5)5 return (x, y)6class Text (object):7 font = None8 def __init__(self, label):9 if self.font is None:10 # can only do this once pygame.font.init() has been called11 self.__class__.font = pygame.font.SysFont('notomono', 20)12 self.color = (0, 0, 0)13 self.label = label14 def _redraw(self):15 self.text = self.font.render(self.label, True, self.color)16 def set_color(self, color):17 self.color = color18 self._redraw()19 def set_text(self, label):20 self.label = label21 self._redraw()22class Label (Text):23 def __init__(self, label, pos, size=None):24 super().__init__(label)25 self.ena = True26 self.size = size27 self.set_text(label)28 self.rect = pygame.Rect(pos, self.size)29 def _redraw(self):30 text = self.font.render(self.label, True, self.color if self.ena else (100, 100, 100))31 if self.size is None:32 self.size = text.get_size()33 self.lbl = pygame.Surface(self.size)34 self.lbl.fill((200, 200, 200))35 dx = max(0, (self.lbl.get_width() - text.get_width()) // 2)36 dy = max(0, (self.lbl.get_height() - text.get_height()) // 2)37 self.lbl.blit(text, (dx, dy))38 def draw(self, surface):39 return surface.blit(self.lbl, self.rect)40 def press(self, pos):41 return False42 def depress(self, pos):43 return False44 def track(self, pos):45 return False46 def enable(self, ena=True):47 if self.ena != ena:48 self.ena = ena49 self._redraw()50class PushButton (Text):51 StateEnabled = 052 StateArmed = 153 StateDisabled = 254 def __init__(self, label, on_click, pos, size=None):55 super().__init__(label)56 self.on_click = on_click57 self.state = self.StateEnabled58 self.size = size59 self._redraw()60 self.rect = pygame.Rect(pos, self.size)61 def _redraw(self):62 color= [(0, 0, 0), (255, 255, 255), (100, 100, 100)][self.state]63 text = self.font.render(self.label, True, color)64 if self.size is None:65 self.size = text.get_size()66 self.size = (self.size[0] + 4, self.size[1] + 4)67 size = self.size68 self.btn = pygame.Surface(size)69 self.btn.fill((200, 200, 200))70 dx = (self.btn.get_width() - text.get_width()) // 271 dy = (self.btn.get_height() - text.get_height()) // 272 if self.state != self.StateDisabled:73 ghost = self.font.render(self.label, True, (255 - color[0], 255 - color[1], 255 - color[2]))74 self.btn.blit(ghost, (dx+1, dy+1))75 self.btn.blit(text, (dx-1, dy-1))76 else:77 self.btn.blit(text, (dx, dy))78 if self.state == self.StateEnabled:79 pygame.draw.lines(self.btn, (50, 50, 50), False, [(size[0]-1, 1), (size[0]-1, size[1]-1), (1, size[1] - 1)], 3)80 pygame.draw.lines(self.btn, (255, 255, 255), False, [(size[0]-1, 1), (1, 1), (1, size[1] - 1)], 3)81 if self.state == self.StateArmed:82 pygame.draw.lines(self.btn, (50, 50, 50), False, [(size[0]-1, 1), (1, 1), (1, size[1] - 1)], 3)83 pygame.draw.lines(self.btn, (255, 255, 255), False, [(size[0]-1, 1), (size[0]-1, size[1]-1), (1, size[1] - 1)], 3)84 def draw(self, surface):85 return surface.blit(self.btn, self.rect)86 def press(self, pos):87 if self.state == self.StateEnabled and self.rect.collidepoint(pos):88 self.state = self.StateArmed89 self._redraw()90 return True91 return False92 def depress(self, pos):93 if self.state == self.StateArmed:94 self.state = self.StateEnabled95 self._redraw()96 if self.on_click and self.rect.collidepoint(pos):97 self.on_click(self)98 return True99 return False100 def track(self, pos):101 return False102 def enable(self, ena=True):103 self.state = self.StateEnabled if ena else self.StateDisabled104 self._redraw()105class Combobox (Label):106 StateDefault = 0107 StateArmed = 1108 StateArmedPost = 2109 def __init__(self, current, values, on_update, pos, size):110 self.index = values.index(current)111 self.values = values112 self.armed_state = self.StateDefault113 self.on_update = on_update114 super().__init__(f">{current}<", pos, size)115 self.armed_rect = pygame.Rect(self.rect.topleft, (self.rect.width, self.font.get_linesize() * len(values)))116 def is_armed(self):117 return self.ena and self.armed_state == self.StateArmed118 def _redraw_armed(self):119 self.sel = pygame.Surface(self.armed_rect.size)120 self.sel.fill((200, 200, 200))121 h = self.font.get_linesize()122 w = self.armed_rect.width123 for i, v in enumerate(self.values):124 rect = pygame.Rect((0, i * h), (w, h))125 if i == self.armed_index:126 self.sel.fill((100, 100, 100), rect)127 text = self.font.render(f">{v}<", True, (255, 255, 255))128 else:129 text = self.font.render(v, True, (0, 0, 0))130 dx = max(0, (w - text.get_width()) // 2)131 dy = max(0, (h - text.get_height()) // 2)132 self.sel.blit(text, (dx, dy + i * h))133 def draw(self, surface):134 if self.is_armed():135 return surface.blit(self.sel, self.armed_rect)136 surface.blit(self.lbl, self.rect)137 if self.armed_state == self.StateArmedPost:138 self.armed_state = self.StateDefault139 return self.armed_rect140 return self.rect141 def armed_cancel(self):142 if self.armed_state == self.StateArmed:143 self.armed_state = self.StateArmedPost144 self.set_text(f">{self.values[self.index]}<")145 def press(self, pos):146 if self.ena and self.armed_state == self.StateDefault and self.rect.collidepoint(pos):147 self.armed_state = self.StateArmed148 self.armed_index = self.index149 self._redraw_armed()150 return True151 return False152 def depress(self, pos):153 if self.is_armed():154 if self.armed_rect.collidepoint(pos):155 self.index = self.armed_index156 if self.on_update:157 self.on_update(self)158 self.armed_cancel()159 return True160 return False161 def track(self, pos):162 if self.is_armed():163 if self.armed_rect.collidepoint(pos):164 self.armed_index = min(len(self.values) - 1, (pos[1] - self.armed_rect.top) // self.font.get_linesize())165 self._redraw_armed()166 else:167 self.armed_cancel()168 return True169 return False170class Setting (object):171 def __init__(self, label, on_update, current, settings, pos, btn_offs, btn_size):172 self.btns = []173 self.btns.append(PushButton(f"{label} +", lambda b: self.setting_next(), btn_pos(btn_offs, pos[0]+0, pos[1], btn_size), btn_size))174 self.btns.append(PushButton(f"{label} -", lambda b: self.setting_prev(), btn_pos(btn_offs, pos[0]+2, pos[1], btn_size), btn_size))175 self.lbl = Label(current, btn_pos(btn_offs, pos[0]+1, pos[1], btn_size), btn_size)176 self.settings = settings177 self.index = self.settings.index(current)178 self.idx = self.index179 self.on_update = on_update180 self.update(False)181 def update(self, notify=True):182 self.btns[0].enable(self.index < (len(self.settings) - 1))183 self.btns[1].enable(self.index > 0)184 self.lbl.set_text(self.settings[self.index])185 if notify and self.on_update:186 self.on_update(self)187 def setting_next(self):188 self.index = min(self.index + 1, len(self.settings) - 1)189 self.update()190 def setting_prev(self):191 self.index = max(self.index - 1, 0)192 self.update()193 def setting_reset(self):194 self.index = self.idx195 self.update()196 def draw(self, surface):197 for btn in self.btns:198 btn.draw(surface)199 self.lbl.draw(surface)200 return self.rect()201 def press(self, pos):202 u = False203 for btn in self.btns:204 u |= btn.press(pos)205 return u206 def depress(self, pos):207 u = False208 for btn in self.btns:209 u |= btn.depress(pos)210 return u211 def track(self, pos):212 u = False213 for btn in self.btns:214 u |= btn.track(pos)215 return u216 def enable(self, ena=True):217 for btn in self.btns:218 btn.enable(ena)219 self.lbl.enable(ena)220 def rect(self):...
Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!