class Control(object): highlighted = overridable_property('highlighted') enabled = overridable_property('enabled') value = overridable_property('value') enable = None ref = None _highlighted = False _enabled = True _value = None def get_value(self): ref = self.ref if ref: return ref.get() else: return self._value def set_value(self, x): ref = self.ref if ref: ref.set(x) else: self._value = x
class Control(object): highlighted = overridable_property('highlighted') enabled = overridable_property('enabled') value = overridable_property('value') enable = None ref = None _highlighted = False _enabled = True _value = None def get_value(self): ref = self.ref if ref: return ref.get() else: return self._value def set_value(self, x): ref = self.ref if ref: ref.set(x) else: self._value = x def get_highlighted(self): return self._highlighted def get_enabled(self): enable = self.enable if enable: return enable() else: return self._enabled def set_enabled(self, x): self._enabled = x if __builtins__.get("mcenf_tab_to_next"): def key_down(self, event): """Handles key press. Captured events are ENTER and SPACE key press. :param event: object: The event being processed.""" key = event.key if key in (K_RETURN, K_KP_ENTER, K_SPACE): self.call_handler("action") else: Widget.key_down(self, event)
class Image(Widget): # image Image to display highlight_color = ThemeProperty('highlight_color') image = overridable_property('image') highlighted = False def __init__(self, image=None, rect=None, **kwds): Widget.__init__(self, rect, **kwds) if image: if isinstance(image, basestring): image = resource.get_image(image) w, h = image.get_size() d = 2 * self.margin self.size = w + d, h + d self._image = image def get_image(self): return self._image def set_image(self, x): self._image = x def draw(self, surf): frame = surf.get_rect() if self.highlighted: surf.fill(self.highlight_color) image = self.image r = image.get_rect() r.center = frame.center surf.blit(image, r)
class MenuBar(Widget): menus = overridable_property('menus', "List of Menu instances") def __init__(self, menus = None, width = 0, **kwds): font = self.predict_font(kwds) height = font.get_linesize() Widget.__init__(self, Rect(0, 0, width, height), **kwds) self.menus = menus or [] self._hilited_menu = None def get_menus(self): return self._menus def set_menus(self, x): self._menus = x def draw(self, surf): fg = self.fg_color bg = self.bg_color font = self.font hilited = self._hilited_menu x = 0 for menu in self._menus: text = " %s " % menu.title if menu is hilited: buf = font.render(text, True, bg, fg) else: buf = font.render(text, True, fg, bg) surf.blit(buf, (x, 0)) x += surf.get_width() def mouse_down(self, e): mx = e.local[0] font = self.font x = 0 for menu in self._menus: text = " %s " % menu.title w = font.size(text)[0] if x <= mx < x + w: self.show_menu(menu, x) def show_menu(self, menu, x): self._hilited_menu = menu try: i = menu.present(self, (x, self.height)) finally: self._hilited_menu = None menu.invoke_item(i) def handle_command_key(self, e): menus = self.menus for m in xrange(len(menus)-1, -1, -1): menu = menus[m] i = menu.find_item_for_key(e) if i >= 0: menu.invoke_item(i) return True return False
class Label(Widget): text = overridable_property('text') align = overridable_property('align') hover_color = ThemeProperty('hover_color') highlight_color = ThemeProperty('highlight_color') disabled_color = ThemeProperty('disabled_color') highlight_bg_color = ThemeProperty('highlight_bg_color') hover_bg_color = ThemeProperty('hover_bg_color') enabled_bg_color = ThemeProperty('enabled_bg_color') disabled_bg_color = ThemeProperty('disabled_bg_color') enabled = True highlighted = False _align = 'l' def __init__(self, text, width=None, **kwds): Widget.__init__(self, **kwds) font = self.font text = _(text, doNotTranslate=kwds.get('doNotTranslate', False)) lines = text.split("\n") tw, th = 0, 0 for line in lines: w, h = font.size(line) tw = max(tw, w) th += h if width is not None: tw = width else: tw = max(1, tw) d = 2 * self.margin self.size = (tw + d, th + d) self._text = text def __repr__(self): return "Label {0}, child of {1}".format(self.text, self.parent) def get_text(self): return self._text def set_text(self, x): self._text = _(x) def get_align(self): return self._align def set_align(self, x): self._align = x def draw(self, surface): if not self.enabled: fg = self.disabled_color bg = self.disabled_bg_color else: fg = self.fg_color bg = self.enabled_bg_color if self.is_default: fg = self.default_choice_color or fg bg = self.default_choice_bg_color or bg if self.is_hover: fg = self.hover_color or fg bg = self.hover_bg_color or bg if self.highlighted: fg = self.highlight_color or fg bg = self.highlight_bg_color or bg self.draw_with(surface, fg, bg) is_default = False def draw_with(self, surface, fg, bg=None): if bg: r = surface.get_rect() b = self.border_width if b: e = -2 * b r.inflate_ip(e, e) surface.fill(bg, r) m = self.margin align = self.align width = surface.get_width() y = m lines = self.text.split("\n") font = self.font dy = font.get_linesize() for line in lines: if len(line): size = font.size(line) if size[0] == 0: continue image = font.render(line, True, fg) r = image.get_rect() r.top = y if align == 'l': r.left = m elif align == 'r': r.right = width - m else: r.centerx = width // 2 surface.blit(image, r) y += dy
class Label(Widget): text = overridable_property('text') align = overridable_property('align') hover_color = ThemeProperty('hover_color') highlight_color = ThemeProperty('highlight_color') disabled_color = ThemeProperty('disabled_color') highlight_bg_color = ThemeProperty('highlight_bg_color') hover_bg_color = ThemeProperty('hover_bg_color') enabled_bg_color = ThemeProperty('enabled_bg_color') disabled_bg_color = ThemeProperty('disabled_bg_color') enabled = True highlighted = False _align = 'l' def __init__(self, text, width=None, base_text=None, **kwds): #-# Translation live update preparation # base_text: to be used each time a widget takes a formated string # defaults to 'text'. Widget.__init__(self, **kwds) #-# Translation live update preparation self.fixed_width = width self.base_text = base_text or text self.previous_translation = _(text, doNotTranslate=kwds.get( 'doNotTranslate', False)) #-# self._text = _(text, doNotTranslate=kwds.get('doNotTranslate', False)) #-# self.calc_size() #-# #-# Translation live update preparation def calc_size(self): lines = self._text.split("\n") tw, th = 0, 0 for i in range(len(lines)): line = lines[i] if i == len(lines) - 1: w, h = self.font.size(line) else: w, h = self.font.size(line)[0], self.font.get_linesize() tw = max(tw, w) th += h if self.fixed_width is not None: tw = self.fixed_width else: tw = max(1, tw) d = 2 * self.margin self.size = (tw + d, th + d) def get_update_translation(self): return Widget.update_translation(self) def set_update_ui(self, v): self.text = self.base_text self.set_text(self.base_text) self.calc_size() Widget.set_update_ui(self, v) #-# def __repr__(self): return "Label {0}, child of {1}".format(self.text, self.parent) def get_text(self): return self._text def set_text(self, x, doNotTranslate=False): self._text = _(x, doNotTranslate=doNotTranslate or self.doNotTranslate) self.calc_size() def get_align(self): return self._align def set_align(self, x): self._align = x def draw(self, surface): if not self.enabled: fg = self.disabled_color bg = self.disabled_bg_color else: fg = self.fg_color bg = self.enabled_bg_color if self.is_default: fg = self.default_choice_color or fg bg = self.default_choice_bg_color or bg if self.is_hover: fg = self.hover_color or fg bg = self.hover_bg_color or bg if self.highlighted: fg = self.highlight_color or fg bg = self.highlight_bg_color or bg self.draw_with(surface, fg, bg) is_default = False def draw_with(self, surface, fg, bg=None): if bg: r = surface.get_rect() b = self.border_width if b: e = -2 * b r.inflate_ip(e, e) surface.fill(bg, r) m = self.margin align = self.align width = surface.get_width() y = m lines = self.text.split("\n") font = self.font dy = font.get_linesize() for line in lines: if len(line): size = font.size(line) if size[0] == 0: continue image = font.render(line, True, fg) r = image.get_rect() r.top = y if align == 'l': r.left = m elif align == 'r': r.right = width - m else: r.centerx = width // 2 surface.blit(image, r) y += dy
class TextEditor(Widget): upper = False tab_stop = True _text = "" def __init__(self, width, upper=None, **kwds): Widget.__init__(self, **kwds) self.set_size_for_text(width) if upper is not None: self.upper = upper self.insertion_point = None def get_text(self): return self._text def set_text(self, text): self._text = text text = overridable_property('text') def draw(self, surface): frame = self.get_margin_rect() fg = self.fg_color font = self.font focused = self.has_focus() text, i = self.get_text_and_insertion_point() if focused and i is None: surface.fill(self.sel_color, frame) image = font.render(text, True, fg) surface.blit(image, frame) if focused and i is not None: x, h = font.size(text[:i]) x += frame.left y = frame.top draw.line(surface, fg, (x, y), (x, y + h - 1)) def key_down(self, event): if not (event.cmd or event.alt): k = event.key if k == K_LEFT: self.move_insertion_point(-1) return if k == K_RIGHT: self.move_insertion_point(1) return if k == K_TAB: self.attention_lost() self.tab_to_next() return try: c = event.unicode except ValueError: c = "" if self.insert_char(c) <> 'pass': return if event.cmd and event.unicode: self.attention_lost() self.call_parent_handler('key_down', event) def get_text_and_insertion_point(self): text = self.get_text() i = self.insertion_point if i is not None: i = max(0, min(i, len(text))) return text, i def move_insertion_point(self, d): text, i = self.get_text_and_insertion_point() if i is None: if d > 0: i = len(text) else: i = 0 else: i = max(0, min(i + d, len(text))) self.insertion_point = i def insert_char(self, c): if self.upper: c = c.upper() if c <= "\x7f": if c == "\x08" or c == "\x7f": text, i = self.get_text_and_insertion_point() if i is None: text = "" i = 0 else: text = text[:i - 1] + text[i:] i -= 1 self.change_text(text) self.insertion_point = i return elif c == "\r" or c == "\x03": return self.call_handler('enter_action') elif c == "\x1b": return self.call_handler('escape_action') elif c >= "\x20": if self.allow_char(c): text, i = self.get_text_and_insertion_point() if i is None: text = c i = 1 else: text = text[:i] + c + text[i:] i += 1 self.change_text(text) self.insertion_point = i return return 'pass' def allow_char(self, c): return True def mouse_down(self, e): self.focus() x, y = e.local text = self.get_text() font = self.font n = len(text) def width(i): return font.size(text[:i])[0] i1 = 0 i2 = len(text) x1 = 0 x2 = width(i2) while i2 - i1 > 1: i3 = (i1 + i2) // 2 x3 = width(i3) if x > x3: i1, x1 = i3, x3 else: i2, x2 = i3, x3 if x - x1 > (x2 - x1) // 2: i = i2 else: i = i1 self.insertion_point = i def change_text(self, text): self.set_text(text) self.call_handler('change_action')
class TextEditorWrapped(Widget): upper = False tab_stop = True _text = u"" def __init__(self, width, lines, upper=None, **kwds): Widget.__init__(self, **kwds) self.set_size_for_text(width, lines) if upper is not None: self.upper = upper self.insertion_point = None self.insertion_step = None self.insertion_line = None self.selection_start = None self.selection_end = None self.topLine = 0 self.dispLines = lines self.textChanged = True def get_text(self): return self._text def set_text(self, text): self._text = _(text) self.textChanged = True text = overridable_property('text') #Text line list and text line EoL index reference textL = [] textRefList = [] def draw(self, surface): frame = self.get_margin_rect() fg = self.fg_color font = self.font focused = self.has_focus() text, i, il = self.get_text_and_insertion_data() ip = self.insertion_point self.doFix = True self.updateTextWrap() #Scroll the text up or down if necessary if self.insertion_line > self.topLine + self.dispLines - 1: self.scroll_down() elif self.insertion_line < self.topLine: self.scroll_up() #Draw Border draw.rect( surface, self.sel_color, pygame.Rect(frame.left, frame.top, frame.size[0], frame.size[1]), 1) #Draw Selection Highlighting if Applicable if focused and ip is None: if self.selection_start is None or self.selection_end is None: surface.fill(self.sel_color, frame) else: startLine, startStep = self.get_char_position( self.selection_start) endLine, endStep = self.get_char_position(self.selection_end) rects = [] if startLine == endLine: if startStep > endStep: x1, h = font.size(self.textL[startLine][0:endStep]) x2, h = font.size(self.textL[startLine][0:startStep]) x1 += frame.left x2 += frame.left lineOffset = startLine - self.topLine y = frame.top + lineOffset * h if lineOffset >= 0: selRect = pygame.Rect(x1, y, (x2 - x1), h) else: x1, h = font.size(self.textL[startLine][0:startStep]) x2, h = font.size(self.textL[startLine][0:endStep]) x1 += frame.left x2 += frame.left lineOffset = startLine - self.topLine y = frame.top + lineOffset * h if lineOffset >= 0: selRect = pygame.Rect(x1, y, (x2 - x1), h) draw.rect(surface, self.sel_color, selRect) elif startLine < endLine: x1, h = font.size(self.textL[startLine][0:startStep]) x2, h = font.size(self.textL[endLine][0:endStep]) x1 += frame.left x2 += frame.left lineOffsetS = startLine - self.topLine lineOffsetE = endLine - self.topLine lDiff = lineOffsetE - lineOffsetS while lDiff > 1 and 0 <= lDiff + lineOffsetS + lDiff < self.dispLines: y = frame.top + lineOffsetS * h + (lDiff - 1) * h rects.append( pygame.Rect(frame.left, y, frame.right - frame.left, h)) lDiff += -1 y = frame.top + lineOffsetS * h if lineOffsetS >= 0: rects.append(pygame.Rect(x1, y, frame.right - x1, h)) y = frame.top + lineOffsetE * h if lineOffsetE < self.dispLines: rects.append( pygame.Rect(frame.left, y, x2 - frame.left, h)) for selRect in rects: draw.rect(surface, self.sel_color, selRect) elif startLine > endLine: x2, h = font.size(self.textL[startLine][0:startStep]) x1, h = font.size(self.textL[endLine][0:endStep]) x1 += frame.left x2 += frame.left lineOffsetE = startLine - self.topLine lineOffsetS = endLine - self.topLine lDiff = lineOffsetE - lineOffsetS while lDiff > 1 and 0 <= lDiff + lineOffsetS + lDiff < self.dispLines: y = frame.top + lineOffsetS * h + (lDiff - 1) * h rects.append( pygame.Rect(frame.left, y, frame.right - frame.left, h)) lDiff += -1 y = frame.top + lineOffsetS * h if lineOffsetS >= 0: rects.append(pygame.Rect(x1, y, frame.right - x1, h)) y = frame.top + lineOffsetE * h if lineOffsetE < self.dispLines: rects.append( pygame.Rect(frame.left, y, x2 - frame.left, h)) for selRect in rects: draw.rect(surface, self.sel_color, selRect) # Draw Lines of Text h = 0 for textLine in self.textL[self.topLine:self.topLine + self.dispLines]: image = font.render(textLine, True, fg) surface.blit(image, frame.move(0, h)) h += font.size(textLine)[1] # Draw Cursor if Applicable if focused and ip is not None and i is not None and il is not None: if self.textL: x, h = font.size(self.textL[il][:i]) else: x, h = (0, font.size("X")[1]) if ip != i: if self.doFix: self.move_insertion_point(-1) self.doFix = False x += font.size(self.textL[il][i])[0] if not self.doFix: self.move_insertion_point(1) x += frame.left y = frame.top + h * (il - self.topLine) draw.line(surface, fg, (x, y), (x, y + h - 1)) def key_down(self, event): self.get_root().notMove = True if not event.cmd or (event.alt and event.unicode): k = event.key if k == K_LEFT: if not (key.get_mods() & KMOD_SHIFT): self.move_insertion_point(-1) else: if self.selection_end is None and self.selection_start is None and self.insertion_point is None: return if self.selection_end is None and self.insertion_point != 0: self.selection_start = self.insertion_point self.selection_end = self.insertion_point - 1 self.insertion_point = None elif self.selection_end is not None and self.selection_end != 0: self.selection_end -= 1 if self.selection_end == self.selection_start: self.insertion_point = self.selection_end self.selection_end = None self.selection_start = None return if k == K_RIGHT: if not (key.get_mods() & KMOD_SHIFT): self.move_insertion_point(1) else: if self.selection_end is None and self.selection_start is None and self.insertion_point is None: return if self.selection_start is None and self.insertion_point < len( self.text): self.selection_start = self.insertion_point self.selection_end = self.insertion_point + 1 self.insertion_point = None elif self.selection_start is not None and self.selection_end < len( self.text): self.selection_end += 1 if self.selection_end == self.selection_start: self.insertion_point = self.selection_end self.selection_end = None self.selection_start = None return if k == K_TAB: self.attention_lost() self.tab_to_next() return if k == K_DOWN: self.move_insertion_line(1) return if k == K_UP: self.move_insertion_line(-1) return if k == K_HOME: if not (key.get_mods() & KMOD_SHIFT): self.selection_start = None self.selection_end = None self.insertion_point = 0 self.sync_line_and_step() elif self.insertion_point != 0: if self.insertion_point is not None: self.selection_start = self.insertion_point self.insertion_point = None self.selection_end = 0 if self.selection_end == self.selection_start: self.insertion_point = self.selection_end self.selection_end = None self.selection_start = None self.sync_line_and_step() return if k == K_END: if not (key.get_mods() & KMOD_SHIFT): self.selection_start = None self.selection_end = None self.insertion_point = len(self.text) self.sync_line_and_step() elif self.insertion_point != len(self.text): if self.insertion_point is not None: self.selection_start = self.insertion_point self.insertion_point = None self.selection_end = len(self.text) if self.selection_end == self.selection_start: self.insertion_point = self.selection_end self.selection_end = None self.selection_start = None self.sync_line_and_step() return try: c = event.unicode except ValueError: print 'value error' c = "" if self.insert_char(c, k) != 'pass': return if event.cmd and event.unicode: if event.key == K_c or event.key == K_x: try: #pygame.scrap.put(SCRAP_TEXT, self.text) text, i = self.get_text_and_insertion_point() if i is None and (self.selection_start is None or self.selection_end is None): text = self.text elif i is None and self.selection_start is not None and self.selection_end is not None: text = text[( min(self.selection_start, self.selection_end) ):max(self.selection_start, self.selection_end)] else: return pyperclip.copy(text) except: print "scrap not available" finally: if event.key == K_x and i is None: self.insert_char(event.unicode, K_BACKSPACE) elif event.key == K_v: try: #t = pygame.scrap.get(SCRAP_TEXT).replace('\0', '') t = pyperclip.paste().replace("\n", " ") if t is not None: if self.insertion_point is not None: self.text = self.text[:self. insertion_point] + t + self.text[ self.insertion_point:] self.insertion_point += len(t) elif self.insertion_point is None and ( self.selection_start is None or self.selection_end is None): self.text = t self.insertion_point = len(t) elif self.insertion_point is None and self.selection_start is not None and self.selection_end is not None: self.selection_point = min( self.selection_start, self.selection_end) + len(t) self.text = self.text[:( min(self.selection_start, self.selection_end) )] + t + self.text[(max(self.selection_start, self. selection_end)):] self.selection_start = None self.selection_end = None else: return self.change_text(self.text) self.sync_line_and_step() except: print "scrap not available" #print repr(t) else: self.attention_lost() def key_up(self, event): pass def get_text_and_insertion_point(self): text = self.get_text() i = self.insertion_point if i is not None: i = max(0, min(i, len(text))) return text, i def get_text_and_insertion_data(self): text = self.get_text() i = self.insertion_step il = self.insertion_line if il is not None: il = max(0, min(il, (len(self.textL) - 1))) if i is not None and il is not None and len(self.textL) > 0: i = max(0, min(i, len(self.textL[il]) - 1)) return text, i, il def move_insertion_point(self, d): self.selection_end = None self.selection_start = None text, i = self.get_text_and_insertion_point() if i is None: if d > 0: i = len(text) else: i = 0 else: i = max(0, min(i + d, len(text))) self.insertion_point = i self.sync_line_and_step() def sync_line_and_step(self): self.updateTextWrap() self.sync_insertion_line() self.sync_insertion_step() def sync_insertion_line(self): ip = self.insertion_point i = 0 for refVal in self.textRefList: if ip > refVal: i += 1 elif ip <= refVal: break self.insertion_line = i def sync_insertion_step(self): ip = self.insertion_point il = self.insertion_line if ip is None: self.move_insertion_point(0) ip = self.insertion_point if il is None: self.move_insertion_line(0) il = self.insertion_line if il > 0: refPoint = self.textRefList[il - 1] else: refPoint = 0 self.insertion_step = ip - refPoint def get_char_position(self, i): j = 0 for refVal in self.textRefList: if i > refVal: j += 1 elif i <= refVal: break line = j if line > 0: refPoint = self.textRefList[line - 1] else: refPoint = 0 step = i - refPoint return line, step def move_insertion_line(self, d): text, i, il = self.get_text_and_insertion_data() if self.selection_end is not None: endLine, endStep = self.get_char_position(self.selection_end) il = endLine i = endStep self.insertion_step = i self.selection_end = None self.selection_start = None if il is None: if d > 0: if len(self.textL) > 1: self.insertion_line = d else: self.insertion_line = 0 else: self.insertion_line = 0 if i is None: self.insertion_step = 0 elif 0 <= d + il + d < len(self.textL): self.insertion_line = il + d if self.insertion_line > 0: self.insertion_point = self.textRefList[self.insertion_line - 1] + self.insertion_step if self.insertion_point > len(self.text): self.insertion_point = len(self.text) else: if self.insertion_step is not None: self.insertion_point = self.insertion_step else: self.insertion_point = 0 self.insertion_step = 0 def insert_char(self, c, k=None): if self.upper: c = c.upper() if k == K_BACKSPACE or k == K_DELETE: text, i = self.get_text_and_insertion_point() if i is None and (self.selection_start is None or self.selection_end is None): text = "" i = 0 self.insertion_line = i self.insertion_step = i elif i is None and self.selection_start is not None and self.selection_end is not None: i = min(self.selection_start, self.selection_end) text = text[:( min(self.selection_start, self.selection_end))] + text[ (max(self.selection_start, self.selection_end)):] self.selection_start = None self.selection_end = None elif i > 0: if k == K_BACKSPACE: text = text[:i - 1] + text[i:] i -= 1 else: text = text[:i] + text[i + 1:] self.change_text(text) self.insertion_point = i self.sync_line_and_step() return elif c == "\r" or c == "\x03": return self.call_handler('enter_action') elif c == "\x1b": return self.call_handler('escape_action') elif c >= "\x20": if self.allow_char(c): text, i = self.get_text_and_insertion_point() if i is None and (self.selection_start is None or self.selection_end is None): text = c i = 1 elif i is None and self.selection_start is not None and self.selection_end is not None: i = min(self.selection_start, self.selection_end) + 1 text = text[:(min(self.selection_start, self.selection_end) )] + c + text[(max(self.selection_start, self .selection_end)):] self.selection_start = None self.selection_end = None else: text = text[:i] + c + text[i:] i += 1 self.change_text(text) self.insertion_point = i self.sync_line_and_step() return return 'pass' @staticmethod def allow_char(c): return True def mouse_down(self, e): self.get_root().notMove = True self.focus() if e.button == 1: if e.num_clicks == 2: self.insertion_point = None self.selection_start = None self.selection_end = None return x, y = e.local i = self.pos_to_index(x, y) self.insertion_point = i self.selection_start = None self.selection_end = None self.sync_line_and_step() if e.button == 5: # self.scroll_down() self.move_insertion_line(1) if e.button == 4: # self.scroll_up() self.move_insertion_line(-1) def mouse_drag(self, e): x, y = e.local i = self.pos_to_index(x, y) if self.insertion_point is not None: if i != self.insertion_point: if self.selection_start is None: self.selection_start = self.insertion_point self.selection_end = i self.insertion_point = None else: if self.selection_start is None: self.selection_start = i else: if self.selection_start == i: self.selection_start = None self.selection_end = None self.insertion_point = i else: self.selection_end = i def pos_to_index(self, x, y): textL = self.textL textRef = self.textRefList topLine = self.topLine dispLines = self.dispLines font = self.font if textL: h = font.size("X")[1] line = y // h if line >= dispLines: line = dispLines - 1 line += topLine if line >= len(textL): line = len(textL) - 1 if line < 0: line = 0 def width(i): return font.size(textL[line][:i])[0] i1 = 0 i2 = len(textL[line]) x1 = 0 x2 = width(i2) while i2 - i1 > 1: i3 = (i1 + i2) // 2 x3 = width(i3) if x > x3: i1, x1 = i3, x3 else: i2, x2 = i3, x3 if x - x1 > (x2 - x1) // 2: i = i2 else: i = i1 if line > 0: i = i + textRef[line - 1] else: i = 0 return i def change_text(self, text): self.set_text(_(text)) self.textChanged = True self.updateTextWrap() self.call_handler('change_action') def scroll_up(self): if self.topLine - 1 >= 0: self.topLine += -1 def scroll_down(self): if self.topLine + 1 < len(self.textL) - self.dispLines + 1: self.topLine += 1 def updateTextWrap(self): # Update text wrapping for box font = self.font frame = self.get_margin_rect() frameW, frameH = frame.size if self.textChanged: ix = 0 iz = 0 textLi = 0 text = self.text textL = [] textR = [] while ix < len(text): ix += 1 if ix == '\r' or ix == '\x03' or ix == '\n': print("RETURN FOUND") if len(textL) > textLi: textL[textLi] = text[iz:ix] textR[textLi] = ix else: textL.append(text[iz:ix]) textR.append(ix) iz = ix + 1 textLi += 1 segW = font.size(text[iz:ix])[0] if segW > frameW: if len(textL) > textLi: textL[textLi] = text[iz:ix - 1] textR[textLi] = ix - 1 else: textL.append(text[iz:ix - 1]) textR.append(ix - 1) iz = ix - 1 textLi += 1 if iz < ix: if len(textL) > textLi: textL[textLi] = text[iz:ix] textR[textLi] = ix else: textL.append(text[iz:ix]) textR.append(ix) iz = ix textLi += 1 textL = textL[:textLi] textR = textR[:textLi] self.textL = textL self.textRefList = textR self.textChanged = False i = 0
class TextEditor(Widget): upper = False tab_stop = True _text = u"" def __init__(self, width, upper=None, **kwds): Widget.__init__(self, **kwds) self.set_size_for_text(width) if upper is not None: self.upper = upper self.insertion_point = None self.root = self.get_root() def get_text(self): return self._text def set_text(self, text): self._text = _(text) text = overridable_property('text') def draw(self, surface): frame = self.get_margin_rect() fg = self.fg_color font = self.font focused = self.has_focus() text, i = self.get_text_and_insertion_point() if focused and i is None: surface.fill(self.sel_color, frame) image = font.render(text, True, fg) surface.blit(image, frame) if focused and i is not None: x, h = font.size(text[:i]) x += frame.left y = frame.top draw.line(surface, fg, (x, y), (x, y + h - 1)) def key_down(self, event): self.root.notMove = True if not event.cmd or (event.alt and event.unicode): k = event.key if k == K_LEFT: self.move_insertion_point(-1) return if k == K_RIGHT: self.move_insertion_point(1) return if k == K_TAB: self.attention_lost() self.tab_to_next() return try: c = event.unicode except ValueError: c = "" if k != K_DOWN and k != K_UP: if self.insert_char(c, k) != 'pass': return if event.cmd and event.unicode: if event.key == K_c: try: #pygame.scrap.put(SCRAP_TEXT, self.text) pyperclip.copy(self.text) except: print "scrap not available" elif event.key == K_v: try: #t = pygame.scrap.get(SCRAP_TEXT).replace('\0', '') t = pyperclip.paste() DEF_ENC = locale.getdefaultlocale()[1] if DEF_ENC is None: DEF_ENC = "UTF-8" if type(t) == unicode and DEF_ENC != "UTF-8": t = t.encode(DEF_ENC) allow = True for char in t: if not self.allow_char(char): allow = False if allow: self.text = t except: print "scrap not available" else: self.attention_lost() def key_up(self, event): pass def get_text_and_insertion_point(self): text = self.get_text() i = self.insertion_point if i is not None: i = max(0, min(i, len(text))) return text, i def move_insertion_point(self, d): text, i = self.get_text_and_insertion_point() if i is None: if d > 0: i = len(text) else: i = 0 else: i = max(0, min(i + d, len(text))) self.insertion_point = i def insert_char(self, c, k=None): if self.upper: c = c.upper() if k == K_BACKSPACE or k == K_DELETE: text, i = self.get_text_and_insertion_point() if i is None: text = "" i = 0 else: if k == K_BACKSPACE: text = text[:i - 1] + text[i:] i -= 1 else: text = text[:i] + text[i + 1:] self.change_text(text) self.insertion_point = i return elif c == "\r" or c == "\x03": return self.call_handler('enter_action') elif c == "\x1b": return self.call_handler('escape_action') elif c >= "\x20": if self.allow_char(c): text, i = self.get_text_and_insertion_point() if i is None: text = c i = 1 else: text = text[:i] + c + text[i:] i += 1 self.change_text(text) self.insertion_point = i return return 'pass' def allow_char(self, c): return True def mouse_down(self, e): self.root.notMove = True self.focus() if e.num_clicks == 2: self.insertion_point = None return x, y = e.local i = self.pos_to_index(x) self.insertion_point = i def pos_to_index(self, x): text = self.get_text() font = self.font def width(i): return font.size(text[:i])[0] i1 = 0 i2 = len(text) x1 = 0 x2 = width(i2) while i2 - i1 > 1: i3 = (i1 + i2) // 2 x3 = width(i3) if x > x3: i1, x1 = i3, x3 else: i2, x2 = i3, x3 if x - x1 > (x2 - x1) // 2: i = i2 else: i = i1 return i def change_text(self, text): self.set_text(text) self.call_handler('change_action')
class Label(Widget): text = overridable_property('text') align = overridable_property('align') highlight_color = ThemeProperty('highlight_color') disabled_color = ThemeProperty('disabled_color') highlight_bg_color = ThemeProperty('highlight_bg_color') enabled_bg_color = ThemeProperty('enabled_bg_color') disabled_bg_color = ThemeProperty('disabled_bg_color') enabled = True highlighted = False _align = 'l' def __init__(self, text, width = None, **kwds): Widget.__init__(self, **kwds) font = self.font lines = text.split("\n") tw, th = 0, 0 for line in lines: w, h = font.size(line) tw = max(tw, w) th += h if width is not None: tw = width else: tw = max(1, tw) d = 2 * self.margin self.size = (tw + d, th + d) self._text = text def get_text(self): return self._text def set_text(self, x): self._text = x def get_align(self): return self._align def set_align(self, x): self._align = x def draw(self, surface): if not self.enabled: fg = self.disabled_color bg = self.disabled_bg_color elif self.highlighted: fg = self.highlight_color bg = self.highlight_bg_color else: fg = self.fg_color bg = self.enabled_bg_color self.draw_with(surface, fg, bg) def draw_with(self, surface, fg, bg = None): if bg: r = surface.get_rect() b = self.border_width if b: e = - 2 * b r.inflate_ip(e, e) surface.fill(bg, r) m = self.margin align = self.align width = surface.get_width() y = m lines = self.text.split("\n") font = self.font dy = font.get_linesize() for line in lines: image = font.render(line, True, fg) r = image.get_rect() r.top = y if align == 'l': r.left = m elif align == 'r': r.right = width - m else: r.centerx = width // 2 surface.blit(image, r) y += dy
class Label(Widget): text = overridable_property('text') align = overridable_property('align') highlight_color = ThemeProperty('highlight_color') disabled_color = ThemeProperty('disabled_color') highlight_bg_color = ThemeProperty('highlight_bg_color') enabled_bg_color = ThemeProperty('enabled_bg_color') disabled_bg_color = ThemeProperty('disabled_bg_color') enabled = True highlighted = False _align = 'l' def __init__(self, text, width = None, **kwds): Widget.__init__(self, **kwds) font = self.font self.set_text(text) return lines = text.split("\n") tw, th = 0, 0 for line in lines: w, h = font.size(line) tw = max(tw, w) th += h if width is not None: tw = width else: tw = max(1, tw) d = 2 * self.margin self.size = (tw + d, th + d) self._text = text def get_text(self): return self._text def _render_image(self): ''' Render image to be blited on draw ''' line_height = self.font.get_linesize() lines = self._text.split("\n") fg = self.fg_color bg = self.bg_color line_images = [] line_width = 0 for line in lines: print bg img = self.font.render(line, True, fg) line_width = max(line_width, img.get_width()) line_images.append(img) space = self.border_width + self.margin self.width = 2*space + line_width self.height = 2*space + len(line_images)*line_height self._image = pygame.Surface(self.size) if bg: self._image.fill() dest = pygame.Rect((0,0),(self.width,line_height)) for img in line_images: dest.width = img.get_width() if self.align=='c': dest.centerx = self.width/2 elif self.align=='r': dest.right = self.width # else: # dest.left = 0 # blit it self._image.blit(img, dest) dest.top += dest.height def set_text(self, text): self._text = text self._render_image() def get_align(self): return self._align def set_align(self, x): self._align = x self._render_image() def draw(self, surface): surface.blit(self._image, self.rect) def draw_with(self, surface, fg, bg = None): if bg: r = surface.get_rect() b = self.border_width if b: e = - 2 * b r.inflate_ip(e, e) surface.fill(bg, r) m = self.margin align = self.align width = surface.get_width() y = m lines = self.text.split("\n") font = self.font dy = font.get_linesize() for line in lines: image = font.render(line, True, fg) r = image.get_rect() r.top = y if align == 'l': r.left = m elif align == 'r': r.right = width - m else: r.centerx = width // 2 surface.blit(image, r) y += dy