class TextInput: """Text input field""" def __init__(self, batch, groups, on_click, on_enter, on_motion, on_search): # create document self.document = FormattedDocument(' ') self.document.set_style( 0, 1, dict(font_name=FONT_NAME, font_size=FONT_SIZE, color=FONT_COLOR)) # calculate font height and margin font = self.document.get_font(0) self.font_height = font.ascent - font.descent self.margin = self.font_height * TEXT_INPUT_MARGIN # create text input self.input = IncrementalTextLayout(self.document, 100, self.font_height, batch=batch, group=groups[1]) self.input.x = 100 self.input.y = 100 # creating a caret and push it to window handlers self.caret = Caret(self.input, FONT_COLOR[:3], on_click, on_enter, on_motion, on_search) self.clear_text() # create background rectangle self.rect = Rectangle(0, 0, 100, self.font_height + 2 * self.margin, color=TEXT_INPUT_COLOR, batch=batch, group=groups[0]) def resize(self, x, y, w): """Resize the text input with given coordinates and width""" self.rect.x = x self.rect.y = y self.rect.width = w self.input.x = x + self.margin self.input.y = y + self.margin self.input.width = w - 2 * self.margin def get_text(self): """Return currently displayed text""" return self.document.text def set_text(self, text): """Set the text to display""" self.document.text = text def clear_text(self): """Clear displayed text""" self.document.text = ''
class Editor(Layer): def __init__(self): super(Editor, self).__init__() self.doc = FormattedDocument('<b>testing</b> testing testing') self.doc.set_style(0, 1000, {'font_name': 'ProggySquareTT'}) self.itlo = IncrementalTextLayout(self.doc, 1024, 750, multiline=True, batch=self.batch) self.itlo.x = 0 self.itlo.y = 750 caret = Caret(self.itlo) caret.visible = True caret.color = (100, 255, 0) director.window.push_handlers(caret) def draw(self): pyglet.gl.glClearColor(1, 1, 1, 1) self.batch.draw()
class UIText(UIBase): def __init__(self, caption: str, position: Vector2 = Vector2.zero, size: Vector2 = Vector2.one, document_style=None, font_name: str = 'DisposableDroid BB', font_size: int = 20, color: (int, int, int, int) = ColorHelper.WHITE, hover_color: (int, int, int, int) = ColorHelper.TRANSPARENT): super().__init__(position, size) document_style = {} if document_style is None else document_style document_style.update(dict(font_name=font_name, font_size=font_size)) self._caption = caption self._document = FormattedDocument(caption) self.update_document_style(document_style) self._text_layout = TextLayout(self._document, width=size.x, height=size.y, batch=self.batch, group=OrderedGroup(self.group.order + 1.1), wrap_lines=True, multiline=True) self._text_layout.content_valign = 'center' self.position = position self.color = color self._set_background_color(hover_color) self._set_background_color(self._background_color) def set_text(self, text: str): self.my_label.text = text self.size.y = self.my_label.content_height self.my_label.height = self.my_label.content_height @property def caption(self) -> str: return self._caption @caption.setter def caption(self, value: str): self._caption = value self._document.text = value @UIBase.batch.setter def batch(self, value: Batch): UIBase.batch.fset(self, value) self._text_layout.batch = value @UIBase.group.setter def group(self, value: OrderedGroup): UIBase.group.fset(self, value) self._update_text_layout_groups(value) @UIBase.position.setter def position(self, value: Vector2): UIBase.position.fset(self, value) self._text_layout.x = value.x self._text_layout.y = value.y @UIBase.size.setter def size(self, value: Vector2): UIBase.size.fset(self, value) self._text_layout.width = value.x self._text_layout.height = value.y @UIBase.color.setter def color(self, value: (int, int, int, int)): UIBase.color.fset(self, value[:3]) self._background_color = value self.opacity = value[3] def _set_background_color(self, color: (int, int, int, int)): UIBase.color.fset(self, color[:3]) self.opacity = color[3] def update_document_style(self, style: dict): if style is not None: self._document.set_style(0, len(self._caption), style) def _update_text_layout_groups(self, group: OrderedGroup): self._text_layout.begin_update() self._text_layout._init_groups(OrderedGroup(group.order + 1)) self._text_layout.end_update() def update_logic(self, **kwargs): super().update_logic()
class MessageQueue(Widget): MSG_DELETE_FREQ = 0.5 # in seconds def __init__(self, padding=0): super(MessageQueue, self).__init__() self.font = gui.config.get('control_panel', 'MSG_QUEUE_FONT') self.titleLabelText = gui.config.get('control_panel_strings', 'MSG_QUEUE_TITLE') bgColorStr = gui.config.get('control_panel', 'MSG_QUEUE_BG_COLOR') self.bgColor = list(map(int, tuple(bgColorStr.split(',')))) self.titleLabel = None self.textLayout = None self.dt = 0 self.halfSecs = 0 self.bgRect = None self.border = None self.padding = padding self.currentPos = 0 self.numMsgs = 0 self.doc = FormattedDocument() self.msgs = list() def reset(self): self.doc.text = "" self.msgs = list() def delete(self): if self.textLayout is not None: self.textLayout.delete() if self.titleLabel is not None: self.titleLabel.delete() self.titleLabel = None if self.bgRect is not None: self.bgRect.delete() self.bgRect = None if self.border is not None: self.border.delete() self.border = None def size(self, frame): super(MessageQueue, self).size(frame) self.width = frame.width or 200 self.height = 200 if self.textLayout is None: self.textLayout = TextLayout(self.doc, width=self.width, batch=self.parentFrame.batch, group=fgGroup, multiline=True) self.parentFrame.setNeedsLayout() else: self.textLayout.width = self.width if self.titleLabel is None: self.titleLabel = Label(self.titleLabelText, x=self.x + 10, y=self.y + 10, batch=self.parentFrame.batch, group=fgGroup, color=(0, 0, 0, 255), font_name=self.font, font_size=14) else: self.titleLabel.x = self.x + 10 self.titleLabel.y = self.y + 10 def layout(self, x, y): super(MessageQueue, self).layout(x, y) self.textLayout.x = self.x + self.padding self.textLayout.y = self.y - self.padding self.textLayout.width = self.width self.textLayout.height = self.height self.titleLabel.x = self.x + 10 self.titleLabel.y = self.y + 10 self.createBackground() def createBackground(self): if self.bgRect is not None: self.bgRect.delete() self.bgRect = None if self.border is not None: self.border.delete() self.border = None self.bgRect = createRect(self.x, self.y, self.width, self.height, self.bgColor, self.parentFrame.batch, mgGroup) self.border = createRect(self.x, self.y + self.height, self.width, 2, (0, 0, 0, 255), self.parentFrame.batch, highlightGroup) def deleteMsg(self, item): self.msgs.remove(item) self.doc.delete_text(item.index, item.index + len(item)) for msg in self.msgs: if msg.num > item.num: msg.num -= 1 msg.index -= len(item) def addMessage(self, message): if len(self.msgs) and message == self.msgs[0].string: return message += '\n' item = Message(message, self.halfSecs) self.doc.set_style(0, len(self.doc.text), { 'font_name': self.font, 'bold': False }) for msg in self.msgs: msg.num += 1 msg.index += len(item) self.msgs.insert(0, item) self.doc.insert_text(0, message, { 'font_name': self.font, 'bold': True }) if self.textLayout is not None: while (self.textLayout.content_height >= self.height - self.titleLabel.content_height + 14): item = self.msgs[len(self.msgs) - 1] self.deleteMsg(item) def update(self, dt): self.dt += dt if self.dt >= self.MSG_DELETE_FREQ: # expired messages are collected on 0.5 sec freq self.halfSecs += 1 self.dt %= self.MSG_DELETE_FREQ toRemove = [] for item in self.msgs: if item.isExpired(self.halfSecs): toRemove.append(item) if len(toRemove): for item in toRemove: self.deleteMsg(item)
class Hud(object): """docstring for Hud""" def __init__(self, batch, window): super(Hud, self).__init__() self.text_ = 'This is the warmup phase' self.hp_t = '-1' self.armor_t = '-1' self.text_active = 5 self.killmsg_active = False self.chat_active = False self.batch = batch self.scale = vec2(window.width / 1280., window.height / 720.) self.hp = Label(self.hp_t, font_name=font, font_size=36, bold=True, x=80, y=10, anchor_x='center', anchor_y='bottom', batch=self.batch) self.armor = Label(self.armor_t, font_name=font, font_size=36, x=240, y=10, anchor_x='center', anchor_y='bottom', bold=True, batch=self.batch) self.text = Label(self.text_, font_name=font, font_size=36, x=640, y=360, anchor_x='center', anchor_y='center', batch=self.batch) self.weapon = Label('melee', font_name=font, font_size=32, x=1160, y=80, anchor_x='center', anchor_y='bottom', color=(0, 255, 255, 255), batch=self.batch) self.ammo = Label('1', font_name=font, font_size=36, x=1160, y=10, anchor_x='center', anchor_y='bottom', bold=True, batch=self.batch) self.time = Label('0:00', font_name=font, font_size=36, x=640, y=680, anchor_x='center', anchor_y='center', bold=True, batch=self.batch) self.chatdoc = FormattedDocument('\n' * 11) #self.chatlog = document .FormattedDocument('\n') self.chat = ScrollableTextLayout(self.chatdoc, width=500, height=208, multiline=True, batch=self.batch) self.chat.x = 130 self.chat.y = 130 self.chat.content_valign = 'bottom' self.killdoc = FormattedDocument('\n') self.killmsg = ScrollableTextLayout(self.killdoc, width=300, height=104, multiline=True, batch=self.batch) self.killmsg.x = 20 self.killmsg.y = 600 self.scoredoc = FormattedDocument('0 : 0') self.score = ScrollableTextLayout(self.scoredoc, width=150, height=104, multiline=True, batch=self.batch) self.score.x = 1270 self.score.y = 650 self.score.anchor_x = 'right' self.score.anchor_y = 'center' self.normal_hpcol = (255, 255, 255, 255) self.low_hpcol = (255, 128, 0, 255) self.high_hpcol = (0, 204, 255, 255) self.bname = '_' self.aname = '_' self.gametime = 70 self.weaponcolors = {proto.melee: (0, 255, 255, 255), proto.explBlaster: (255, 255, 0, 255)} self.killmsg_count = 0 self.scoreboard = None self.weaponbar = WeaponBar(self.batch, self.scale) self.do_scale() def do_scale(self): for item in (self.armor, self.hp, self.text, self.chat, self.killmsg, self.time, self.ammo, self.weapon, self.score): item.x *= self.scale.x item.y *= self.scale.y def init_player(self, players): if len(players) == 0: self.set_score(0, 0) else: self.bname = players.values()[0].name self.set_score(0, 0) self.init_pers_hud() def init_pers_hud(self): if self.hp._vertex_lists: self.weaponbar.batch = self.batch self.weapon.batch = self.batch self.ammo.batch = self.batch self.hp.batch = self.batch self.armor.begin_update() self.armor.batch = self.batch self.armor.end_update() def init_spec(self): self.weaponbar.remove() self.weapon.delete() self.ammo.delete() self.hp.delete() self.armor.delete() def draw(self): self.active_batch.draw() def update(self, dt): if self.text_active: self.text_active -= dt if self.text_active <= 0: self.text_active = False self.text.delete() if self.killmsg_active: self.killmsg_active -= dt if self.killmsg_active <= 0: self.killmsg_count -= 1 start = self.killdoc.get_paragraph_start(1) end = self.killdoc.get_paragraph_end(1) self.killdoc.delete_text(start, end) if self.killmsg_count > 0: self.killmsg_active = 4 else: self.killmsg_active = False self.killmsg.delete() if self.chat_active: self.chat_active -= dt if self.chat_active <= 0: self.chat_active = False self.chat.delete() self.time.text = self.calc_time(self.gametime) def update_prop(self, armor=False, hp=False, text=False, weapon=False, ammo=False, time=False, name=False, msg=False, chat=None): if armor: if armor != self.armor.text: self.armor.text = armor if int(armor) <= 20: self.armor.color = self.low_hpcol elif int(armor) > 100: self.armor.color = self.high_hpcol else: self.armor.color = self.normal_hpcol if hp: if hp != self.hp.text: self.hp.text = hp if int(hp) <= 20: self.hp.color = self.low_hpcol elif int(hp) > 100: self.hp.color = self.high_hpcol else: self.hp.color = self.normal_hpcol if text: if not self.text_active: self.text.begin_update() self.text.text = text self.text_active = 3 self.text.batch = self.batch self.text.end_update() else: self.text.text = text self.text_active = 3 if weapon: if weapon != self.weapon.text: self.weapon.text = weapon wkey = [key for key, val in allstrings.iteritems() if val == weapon][0] self.weapon.color = weaponcolors[wkey] + [255] if ammo: ammo, weapons = ammo if ammo != self.ammo.text: self.ammo.text = ammo self.weaponbar.update(weapons) if isinstance(time, float): self.gametime = time if name: a, name = name if a: self.aname = name else: self.bname = name #self.score.text = '0:0 ' + self.bname if chat: name, color, msg = chat self.chat.begin_update() #self.chat.text = chat self.chatdoc.insert_text(len(self.chatdoc.text), name, dict(color=list(color) + [255], bold=True)) self.chatdoc.insert_text(len(self.chatdoc.text), '\t' + msg + '\n', dict(color=[255] * 4, bold=False)) start = self.chatdoc.get_paragraph_start(0) end = self.chatdoc.get_paragraph_end(0) self.chatdoc.delete_text(start, end) """self.chatlog.insert_text(len(self.chatlog.text), name, dict(color=list(color) + [255], bold=True)) self.chatlog.insert_text(len(self.chatlog.text), '\t' + msg + '\n', dict(color=[255] * 4, bold=False))""" self.chat.batch = self.batch self.chat.view_y = -self.chat.content_height self.chat.end_update() self.chat_active = 4 def set_score(self, a, b, msg=False, scoreboard=False): self.score.begin_update() self.scoredoc.delete_text(0, len(self.scoredoc.text)) self.scoredoc.insert_text(0, ''.join((str(a), ' ', self.aname, '\n', str(b), ' ', self.bname)), dict(color=[255] * 4)) apos = self.scoredoc.get_paragraph_start(1) bpos = self.scoredoc.get_paragraph_start(len(self.scoredoc.text) - 1) self.scoredoc.set_style(apos, apos+len(str(a)), dict(font_size=24, baseline=-6)) self.scoredoc.set_style(bpos, bpos+len(str(b)), dict(font_size=24, baseline=-6)) self.score.end_update() self.score.width = self.score.content_width + 40 if msg: w, killer, killed = msg if w == 11: w = 4 if w == 12: w = 5 wcol = weaponcolors['w' + str(w-1)] self.killmsg.begin_update() self.killdoc.insert_text(len(self.killdoc.text), killer, dict(color=[255] * 4)) self.killdoc.insert_text(len(self.killdoc.text), ' fragged', dict(color=wcol + [255])) self.killdoc.insert_text(len(self.killdoc.text), ' '.join(('', killed, '\n')), dict(color=[255] * 4)) self.killmsg.batch = self.batch if not self.killmsg_active: self.killmsg_active = 4 self.killmsg_count += 1 self.killmsg.end_update() if scoreboard: if not self.scoreboard: self.scoreboard = ScoreBoard((a, self.aname), (b, self.bname), self.batch, self.scale) else: if not self.scoreboard is None: self.scoreboard.delete() self.scoreboard = None def calc_time(self, gametime): mins = '{:01.0f}'.format(gametime // 60) secs = '{:02.0f}'.format(gametime % 60) return ''.join((mins, ':', secs))
class WeaponBar(object): """docstring for WeaponBar""" def __init__(self, batch, scale): super(WeaponBar, self).__init__() self.batch = batch self.weapons = {} self.ammos = [] self.tris = [] self.scale = scale def __len__(self): return len(self.weapons) def init_bar(self, weapons): try: if self.ammolayout._document: self.ammolayout.delete() for tri in self.tris: tri.remove() except AttributeError: pass ammotext = '\t'.join(str(w.ammo) for key, w in weapons.iteritems() if key != 'w0') self.ammos = ammotext.split('\t') self.ammodoc = FormattedDocument(ammotext) self.ammodoc.set_style(0, len(ammotext), dict(color=[255]*4, tab_stops=[120*(i+1) for i in range(6)], font_size=24, align='center', wrap=False)) self.ammolayout = IncrementalTextLayout(self.ammodoc, width=600, height=50, batch=self.batch, multiline=True) self.ammolayout.x = (1280 / 2) * self.scale.x self.ammolayout.y = 20 * self.scale.y self.ammolayout.anchor_x = 'center' self.ammolayout.anchor_y = 'bottom' w = self.ammolayout.content_width colorlist = [weaponcolors[key] for key in weapons if key != 'w0'] self.tris = [Triangle(640*self.scale.x-w/2-52+120*i, 35*self.scale.y, 50, 50, col, self.batch, 0, 0) for i, col in enumerate(colorlist)] def update(self, weapons): if len(weapons) != len(self.weapons): self.init_bar(weapons) self.weapons = weapons.copy() else: ammotext = '\t'.join(str(w.ammo) for key, w in weapons.iteritems() if key != 'w0') ammos = ammotext.split('\t') self.ammolayout.begin_update() for i, a in enumerate(ammos): if a != self.ammos[i]: ln = sum(len(self.ammos[j]) for j in range(i)) + i self.ammodoc.delete_text(ln, ln + len(self.ammos[i])) self.ammodoc.insert_text(ln, a) self.ammolayout.end_update() self.ammos = ammos def remove(self): try: self.weapons = {} self.ammolayout.delete() for tri in self.tris: tri.remove() except AttributeError: pass
class ScoreBoard(object): """docstring for ScoreBoard""" def __init__(self, a, b, batch, scale): super(ScoreBoard, self).__init__() self.ascore, self.aname = a self.bscore, self.bname = b self.adoc = FormattedDocument('\t'.join((self.aname, str(self.ascore)))) self.bdoc = FormattedDocument('\t'.join((str(self.bscore), self.bname))) scsize = 100 nmsize = 32 self.scale = scale self.alayout = ScrollableTextLayout(self.adoc, width=400, height=300, batch=batch, multiline=True) w = 400 - len(str(self.ascore)) * scsize * 72 / 96 self.adoc.set_style(0, len(self.adoc.text), dict(wrap=False, color=[255]*4, align='left', tab_stops=[w])) self.adoc.set_style(0, len(self.aname), dict(font_size=nmsize)) a = len(self.aname)+1 self.adoc.set_style(a, a + len(str(self.ascore)), dict(font_size=scsize, baseline=-scsize / 4)) self.alayout.x = (1280 / 2) * self.scale.x self.alayout.y = (720 / 2) * self.scale.y + 50 self.alayout.anchor_x = 'right' self.alayout.anchor_y = 'center' self.blayout = ScrollableTextLayout(self.bdoc, width=400, height=300, batch=batch, multiline=True) w = 400 - len(str(self.bname)) * nmsize * 72 / 96 self.bdoc.set_style(0, len(self.bdoc.text), dict(wrap=False, color=[255]*4, align='right', tab_stops=[w])) self.bdoc.set_style(0, len(str(self.bscore)), dict(font_size=scsize, baseline=-scsize / 4)) a = len(str(self.bscore))+1 self.bdoc.set_style(a, a + len(self.bname), dict(font_size=nmsize)) self.blayout.x = 1280 / 2 self.blayout.y = 720 / 2 + 50 self.blayout.anchor_x = 'left' self.blayout.anchor_y = 'center' def delete(self): self.alayout.delete() self.blayout.delete()
class TextBox(Focusable, Caret, Hoverable): underline: Rectangle = None _on_enter: Callable = None ignore_enter: bool = False style: dict = {} def __init__(self, width: int, height: int = 0, multiline: bool = False, dpi: object = None, batch: Batch = None, group: Group = None, wrap_lines: bool = True, x: int = 0, y: int = 0, underlined: bool = True, caret_color: tuple = (0, 0, 0), numbers_only: bool = False, font_name=None, font_size=None, font_color=(255, 255, 255, 2555), max_chars=0) -> None: self.document = FormattedDocument() self.layout = IncrementalTextLayout(self.document, width, height, multiline, dpi, batch, group, wrap_lines) self.numbers_only = numbers_only self.style['color'] = font_color self.max_chars = max_chars if font_name: self.style['font_name'] = font_name if font_size: self.style['font_size'] = font_size self.reset_style() if not height: # If the dev didn't specify a height, make the height equal to the height of the font font = pyglet.font.load( font_name or self.document.get_style('font'), font_size or self.document.get_style('font_size')) self.height = font.ascent - font.descent self._hover_cursor = self.get_window().CURSOR_TEXT super().__init__(self.layout, color=caret_color) # TODO: Allow the dev to specify how x and y are treated self.x = x - self.width // 2 self.y = y - self.height // 2 if underlined: self.underline = Rectangle( x=self.x, y=self.y, width=self.width, height=1, ) def reset_style(self): self.document.set_style(0, len(self.document.text), self.style) @property def x(self): return self.layout.x @x.setter def x(self, value): if self.underline: self.underline.x = value self.layout.x = value @property def y(self): return self.layout.y @y.setter def y(self, value): print(value) if self.underline: self.underline.y = value self.layout.y = value @property def width(self): return self.layout.width @width.setter def width(self, value): if self.underline: self.underline.width = value self.layout.width = value @property def height(self): return self.layout.height @height.setter def height(self, value): print(value) self.layout.height = value def draw(self): if self.focused: self.on_activate() else: self.on_deactivate() self.layout.draw() if self.underline: self.underline.draw() def on_text(self, text: str): # Only type inside when the user is focused on the textbox # print(text) if not self.focused: return if ord(text) == 13: if self.ignore_enter: # Enter self.ignore_enter = False return else: return self.on_enter() # if self.max_chars and len(self.value) >= self.max_chars: # return # if self.numbers_only and not text.isnumeric(): # return res = super().on_text(text) print('res', res, 'text', text) self.reset_style() return res def _on_enter_base(self) -> None: """ The event handler that will be called by default if none are defined """ pass @property def value(self): return self.document.text @value.setter def value(self, val): self.document.text = val self.reset_style() @property def on_enter(self): if self._on_enter: return self._on_enter return self._on_enter_base @on_enter.setter def on_enter(self, func): def new_on_enter(): if self.focused: func() self._on_enter = new_on_enter
class MessageQueue(Widget): MSG_DELETE_FREQ = 0.5 # in seconds def __init__(self, padding=0): super(MessageQueue, self).__init__() self.font = gui.config.get('control_panel', 'MSG_QUEUE_FONT') self.titleLabelText = gui.config.get('control_panel_strings', 'MSG_QUEUE_TITLE') bgColorStr = gui.config.get('control_panel', 'MSG_QUEUE_BG_COLOR') self.bgColor = list(map(int, tuple(bgColorStr.split(',')))) self.titleLabel = None self.textLayout = None self.dt = 0 self.halfSecs = 0 self.bgRect = None self.border = None self.padding = padding self.currentPos = 0 self.numMsgs = 0 self.doc = FormattedDocument() self.msgs = list() def reset(self): self.doc.text = "" self.msgs = list() def delete(self): if self.textLayout is not None: self.textLayout.delete() if self.titleLabel is not None: self.titleLabel.delete() self.titleLabel = None if self.bgRect is not None: self.bgRect.delete() self.bgRect = None if self.border is not None: self.border.delete() self.border = None def size(self, frame): super(MessageQueue, self).size(frame) self.width = frame.width or 200 self.height = 200 if self.textLayout is None: self.textLayout = TextLayout(self.doc, width=self.width, batch=self.parentFrame.batch, group=fgGroup, multiline=True) self.parentFrame.setNeedsLayout() else: self.textLayout.width = self.width if self.titleLabel is None: self.titleLabel = Label(self.titleLabelText, x=self.x + 10, y=self.y + 10, batch=self.parentFrame.batch, group=fgGroup, color=(0, 0, 0, 255), font_name=self.font, font_size=14) else: self.titleLabel.x = self.x + 10 self.titleLabel.y = self.y + 10 def layout(self, x, y): super(MessageQueue, self).layout(x, y) self.textLayout.x = self.x + self.padding self.textLayout.y = self.y - self.padding self.textLayout.width = self.width self.textLayout.height = self.height self.titleLabel.x = self.x + 10 self.titleLabel.y = self.y + 10 self.createBackground() def createBackground(self): if self.bgRect is not None: self.bgRect.delete() self.bgRect = None if self.border is not None: self.border.delete() self.border = None self.bgRect = createRect(self.x, self.y, self.width, self.height, self.bgColor, self.parentFrame.batch, mgGroup) self.border = createRect(self.x, self.y + self.height, self.width, 2, (0, 0, 0, 255), self.parentFrame.batch, highlightGroup) def deleteMsg(self, item): self.msgs.remove(item) self.doc.delete_text(item.index, item.index + len(item)) for msg in self.msgs: if msg.num > item.num: msg.num -= 1 msg.index -= len(item) def addMessage(self, message): if len(self.msgs) and message == self.msgs[0].string: return message += '\n' item = Message(message, self.halfSecs) self.doc.set_style(0, len(self.doc.text), {'font_name': self.font, 'bold': False}) for msg in self.msgs: msg.num += 1 msg.index += len(item) self.msgs.insert(0, item) self.doc.insert_text(0, message, {'font_name': self.font, 'bold': True}) if self.textLayout is not None: while (self.textLayout.content_height >= self.height - self.titleLabel.content_height + 14): item = self.msgs[len(self.msgs) - 1] self.deleteMsg(item) def update(self, dt): self.dt += dt if self.dt >= self.MSG_DELETE_FREQ: # expired messages are collected on 0.5 sec freq self.halfSecs += 1 self.dt %= self.MSG_DELETE_FREQ toRemove = [] for item in self.msgs: if item.isExpired(self.halfSecs): toRemove.append(item) if len(toRemove): for item in toRemove: self.deleteMsg(item)
class LicensePageV2(UIObject, ABC): def __init__(self, logger, parent_viewport): super().__init__(logger, parent_viewport) self.license_text = '' self.document = None self.license_layout = None @final def on_activate(self): super().on_activate() if not self.document: self.document = FormattedDocument(text=self.license_text) self.document.set_style( 0, len(self.document.text), { 'font_name': 'Arial', 'font_size': get_bottom_bar_height(self.screen_resolution) // 5, 'bold': False, 'italic': False, 'color': (*WHITE_RGB, self.opacity), 'align': 'center' }) if not self.license_layout: self.license_layout = IncrementalTextLayout( document=self.document, width=self.viewport.x2 - self.viewport.x1, height=self.viewport.y2 - self.viewport.y1, multiline=True, batch=BATCHES['ui_batch'], group=GROUPS['button_text']) self.license_layout.x, self.license_layout.y = self.viewport.x1, self.viewport.y1 @final @window_size_has_changed def on_window_resize(self, width, height): super().on_window_resize(width, height) self.viewport.x1, self.viewport.x2 = self.parent_viewport.x1, self.parent_viewport.x2 self.viewport.y1 = self.parent_viewport.y1 + get_bottom_bar_height( self.screen_resolution) self.viewport.y2 = self.parent_viewport.y2 if self.is_activated: self.license_layout.x, self.license_layout.y = self.viewport.x1, self.viewport.y1 self.license_layout.width = self.viewport.x2 - self.viewport.x1 self.license_layout.height = self.viewport.y2 - self.viewport.y1 self.document.set_style(0, len(self.document.text), { 'font_size': get_bottom_bar_height(self.screen_resolution) // 5 }) @final @is_active @cursor_is_inside_the_text_box def on_mouse_scroll(self, x, y, scroll_x, scroll_y): self.license_layout.view_y += scroll_y * self.document.get_style( 'font_size') @final def on_update_opacity(self, new_opacity): super().on_update_opacity(new_opacity) if self.opacity <= 0: self.license_layout.delete() self.license_layout = None elif self.document: self.document.set_style(0, len(self.document.text), {'color': (*WHITE_RGB, self.opacity)})