def _load_scrollbar(self, height): if self._content.content_height > height: if self._scrollbar is None: self._scrollbar = VScrollbar(self.max_height) self._scrollbar.set_manager(self._manager) self._scrollbar.parent = self self._scrollbar.load() self._scrollbar.set_knob_size(self.height, self._content.content_height) # if smaller, we unload it if it is loaded elif self._scrollbar is not None: self._scrollbar.unload() self._scrollbar = None
def _load_scrollbars(self, width, height): # if content size bigger than our size, # we load a scrollbar if self.content.width > width: if self._hscrollbar is None: self._hscrollbar = HScrollbar(width) self._hscrollbar.set_manager(self._manager) self._hscrollbar.parent = self self._hscrollbar.load() # if smaller, we unload it if it is loaded elif self._hscrollbar is not None: self._hscrollbar.delete() self._hscrollbar = None if self.content.height > height: if self._vscrollbar is None: self._vscrollbar = VScrollbar(height) self._vscrollbar.set_manager(self._manager) self._vscrollbar.parent = self self._vscrollbar.load() elif self._vscrollbar is not None: self._vscrollbar.delete() self._vscrollbar = None self._manager.set_wheel_target(None)
class Document(Controller, Viewer): """ Allows you to embed a document within the GUI, which includes a vertical scrollbar. """ def __init__(self, document, width=0, height=0, is_fixed_size=False): Viewer.__init__(self, width, height) Controller.__init__(self) self.max_height = height if isinstance(document, str): self._document = pyglet.text.document.UnformattedDocument(document) else: self._document = document self._content = None self.content_width = width self._scrollbar = None self.set_document_style = False self.is_fixed_size = is_fixed_size def hit_test(self, x, y): if self._content is not None: return Rectangle(self._content.x, self._content.y, self._content.width, self._content.height).is_inside(x, y) else: return False def _load_scrollbar(self, height): if self._content.content_height > height: if self._scrollbar is None: self._scrollbar = VScrollbar(self.max_height) self._scrollbar.set_manager(self._manager) self._scrollbar.parent = self self._scrollbar.load() self._scrollbar.set_knob_size(self.height, self._content.content_height) # if smaller, we unload it if it is loaded elif self._scrollbar is not None: self._scrollbar.unload() self._scrollbar = None def load_graphics(self): if not self.set_document_style: self.do_set_document_style(self._manager) self._content = pyglet.text.layout.IncrementalTextLayout(self._document, self.content_width, self.max_height, multiline=True, **self.get_batch('background')) def unload_graphics(self): self._content.delete() if self._scrollbar is not None: self._scrollbar.unload() self._scrollbar = None def do_set_document_style(self, dialog): self.set_document_style = True # Check the style runs to make sure we don't stamp on anything # set by the user self._do_set_document_style('color', dialog.theme['text_color']) self._do_set_document_style('font_name', dialog.theme['font']) self._do_set_document_style('font_size', dialog.theme['font_size']) def _do_set_document_style(self, attr, value): length = len(self._document.text) runs = [(start, end, doc_value) for start, end, doc_value in self._document.get_style_runs(attr).ranges(0, length) if doc_value is not None] if not runs: terminator = len(self._document.text) else: terminator = runs[0][0] self._document.set_style(0, terminator, {attr: value}) def get_text(self): return self._document.text def layout(self): if self._scrollbar is not None: self._scrollbar.set_position(self.x + self._content.content_width, self.y) pos = self._scrollbar.get_knob_pos() if pos != -self._content.view_y: self._content.view_y = -pos self._content.begin_update() self._content.x = self.x self._content.y = self.y self._content.end_update() if self._scrollbar is not None: self._scrollbar.set_position(self.x + self.content_width, self.y) def on_gain_highlight(self): if self._scrollbar is not None: self._manager.set_wheel_target(self._scrollbar) def on_lose_highlight(self): self._manager.set_wheel_target(None) def compute_size(self): if self.is_fixed_size or (self.max_height and self._content.content_height > self.max_height): height = self.max_height else: height = self._content.content_height self._content.height = height self._load_scrollbar(height) if self._scrollbar is not None: self._scrollbar.set_knob_size(height, self._content.content_height) self._scrollbar.compute_size() width = self.content_width + self._scrollbar.width else: width = self.content_width return width, height def set_text(self, text): self._document.text = text self.layout() def delete(self): Controller.delete(self) Viewer.delete(self)
class Scrollable(Wrapper, Controller, ControllerManager): def __init__(self, content=None, width=None, height=None, is_fixed_size=False): if is_fixed_size: assert width is not None and height is not None Wrapper.__init__(self, content) ControllerManager.__init__(self) self.max_width = width self.max_height = height self.is_fixed_size = is_fixed_size self._hscrollbar = None self._vscrollbar = None self._content_width = 0 self._content_height = 0 self._content_x = 0 self._content_y = 0 # We emulate some aspects of Manager here. self._theme = None self.batch = None self.root_group = None self.group = {'panel': None, 'background': None, 'foreground': None, 'highlight': None} @Managed.theme.getter def theme(self): return self._theme def set_manager(self, manager): Controller.set_manager(self, manager) self._theme = manager.theme self.batch = manager.batch self.root_group = ScrollableGroup(0, 0, self.width, self.height, parent=manager.group['foreground']) self.group['panel'] = pyglet.graphics.OrderedGroup(0, self.root_group) self.group['background'] = pyglet.graphics.OrderedGroup(10, self.root_group) self.group['foreground'] = pyglet.graphics.OrderedGroup(20, self.root_group) self.group['highlight'] = pyglet.graphics.OrderedGroup(30, self.root_group) self.content.set_manager(self) self.content.parent = self def unload_graphics(self): Wrapper.unload_graphics(self) if self._hscrollbar is not None: self._hscrollbar.unload() self._hscrollbar = None if self._vscrollbar is not None: self._vscrollbar.unload() self._vscrollbar = None def expand(self, width, height): if self.content.is_expandable(): if self._vscrollbar is not None: self._content_width = width else: self._content_width = width if self._hscrollbar is not None: self._content_height = height else: self._content_height = height self.content.expand(max(self._content_width, self.content.width), max(self._content_height, self.content.height)) self.width, self.height = width, height def hit_test(self, x, y): # We only intercept events for the content region, not for # the scrollbars. They can handle themselves. return y >= self._content_y < self._content_y + self._content_height and \ self._content_x <= x < self._content_x + self._content_width def is_expandable(self): return True def _load_scrollbars(self, width, height): # if content size bigger than our size, # we load a scrollbar if self.content.width > width: if self._hscrollbar is None: self._hscrollbar = HScrollbar(width) self._hscrollbar.set_manager(self._manager) self._hscrollbar.parent = self self._hscrollbar.load() # if smaller, we unload it if it is loaded elif self._hscrollbar is not None: self._hscrollbar.delete() self._hscrollbar = None if self.content.height > height: if self._vscrollbar is None: self._vscrollbar = VScrollbar(height) self._vscrollbar.set_manager(self._manager) self._vscrollbar.parent = self self._vscrollbar.load() elif self._vscrollbar is not None: self._vscrollbar.delete() self._vscrollbar = None self._manager.set_wheel_target(None) def layout(self): Wrapper.layout(self) # Work out the adjusted content width and height y = self.y if self._hscrollbar is not None: self._hscrollbar.set_position(self.x, self.y) y += self._hscrollbar.height if self._vscrollbar is not None: self._vscrollbar.set_position(self.x + self._content_width, y) # Set the scissor group self.root_group.x, self.root_group.y = self.x - 1, y - 1 self.root_group.width = self._content_width + 1 self.root_group.height = self._content_height + 1 # Work out the content layout self._content_x, self._content_y = self.x, y left = self.x top = y + self._content_height - self.content.height if self._hscrollbar: left -= self._hscrollbar.get_knob_pos() if self._vscrollbar: top += self._vscrollbar.get_knob_pos() self.content.set_position(left, top) def on_gain_highlight(self): if self._hscrollbar is not None: self._manager.set_wheel_hint(self._hscrollbar) if self._vscrollbar is not None: self._manager.set_wheel_target(self._vscrollbar) def on_lose_highlight(self): self._manager.set_wheel_target(None) self._manager.set_wheel_hint(None) def compute_size(self): content_width, content_height = self.content.compute_size() width = min(self.max_width or content_width, content_width) height = min(self.max_height or content_height, content_height) self._content_width = width self._content_height = height # we have to load the scrolls here because they require knowing content size self._load_scrollbars(width, height) if self._hscrollbar is not None: self._hscrollbar.set_knob_size(self._content_width, content_height) _, scroll_height = self._hscrollbar.compute_size() height += scroll_height if self._vscrollbar is not None: self._vscrollbar.set_knob_size(self._content_height, content_height) scroll_width, _ = self._vscrollbar.compute_size() width += scroll_width return width, height def reset_size(self, reset_parent=True): super(Scrollable, self).reset_size(reset_parent) if self._hscrollbar is not None: self._hscrollbar.reset_size(reset_parent=False) if self._vscrollbar is not None: self._vscrollbar.reset_size(reset_parent=False) def delete(self): Wrapper.delete(self) ControllerManager.delete(self)
class Document(Controller, Viewer): """ Allows you to embed a document within the GUI, which includes a vertical scrollbar. """ def __init__(self, document, width=0, height=0, is_fixed_size=False, background=False, font_size=13, font_name='Segoe UI', font_color=None, chat=False): Viewer.__init__(self, width, height) Controller.__init__(self) self.max_height = height if isinstance(document, str): self._document = pyglet.text.document.UnformattedDocument(document) else: self._document = document self.h1 = height self.w1 = width self.chat = chat self.fontSize = font_size self.fontName = font_name self.fontColor = font_color self._bgcolor = background self._bg = None self._content = None self.content_width = width self._scrollbar = None self.set_document_style = False self.firstTimeLoad = True self.is_fixed_size = is_fixed_size def hit_test(self, x, y): if self._content is not None: return Rectangle(self._content.x, self._content.y, self._content.width, self._content.height).is_inside(x, y) else: return False def _load_scrollbar(self, height): if self._content.content_height > height: if self._scrollbar is None: self._scrollbar = VScrollbar(self.max_height) self._scrollbar.set_manager(self._manager) self._scrollbar.parent = self self._scrollbar.load() self._scrollbar.set_knob_size(self.height, self._content.content_height) # if smaller, we unload it if it is loaded elif self._scrollbar is not None: self._scrollbar.unload() self._scrollbar = None def load_graphics(self): if self._bgcolor is True: self._bg = self.theme[['document']]['image'].generate( self.theme[['document']]['gui_color'], **self.get_batch("background")) if not self.set_document_style and not self.chat: self.do_set_document_style(self._manager) self._content = pyglet.text.layout.IncrementalTextLayout( self._document, self.content_width, self.max_height, multiline=True, **self.get_batch('foreground')) def unload_graphics(self): if self._bg is not None: self._bg.unload() self._content.delete() if self._scrollbar is not None: self._scrollbar.unload() self._scrollbar = None def do_set_document_style(self, dialog): self.set_document_style = True # Check the style runs to make sure we don't stamp on anything # set by the user self._do_set_document_style('color', dialog.theme['text_color']) self._do_set_document_style('font_name', dialog.theme['font']) self._do_set_document_style('font_size', dialog.theme['font_size']) def _do_set_document_style(self, attr, value): length = len(self._document.text) runs = [(start, end, doc_value) for start, end, doc_value in self._document.get_style_runs(attr).ranges(0, length) if doc_value is not None] if not runs: terminator = len(self._document.text) else: terminator = runs[0][0] self._document.set_style(0, terminator, {attr: value}) def get_text(self): return self._document.text def layout(self): if self._bgcolor is True: self._bg.update(self.x, self.y, self.w1 + 2, self.h1) if self._scrollbar is not None: self._scrollbar.set_position( self.x + self._content.content_width + 2, self.y) pos = self._scrollbar.get_knob_pos() if pos != -self._content.view_y: self._content.view_y = -pos self._content.begin_update() self._content.x = self.x + 2 self._content.y = self.y self._content.end_update() if self._scrollbar is not None: self._scrollbar.set_position(self.x + self.content_width + 2, self.y) def on_gain_highlight(self): if self._scrollbar is not None: self._manager.set_wheel_target(self._scrollbar) def on_lose_highlight(self): self._manager.set_wheel_target(None) def compute_size(self): if self.is_fixed_size or ( self.max_height and self._content.content_height > self.max_height): height = self.max_height else: height = self._content.content_height self._content.height = height self._load_scrollbar(height) if self._scrollbar is not None: self._scrollbar.set_knob_size(height, self._content.content_height) if self.firstTimeLoad: self._scrollbar.set_knob_pos(0) self.firstTimeLoad = False else: self._scrollbar.set_knob_pos(1) self._scrollbar.compute_size() width = self.content_width + self._scrollbar.width #print self._scrollbar.get_knob_pos() else: width = self.content_width return width, height def set_text(self, text): self._document.text = text self.compute_size() self.layout() def update_text(self, text): realtext = '{font_size ' + str( self.fontSize ) + '}{font_name "' + self.fontName + '"}{wrap "char"}' + text t1 = time.time() * 1000 #self._document = pyglet.text.decode_attributed(realtext) #self._document.insert_text(0,text) #print len(self._document._text) #print self._document.__dict__ t2 = time.time() * 1000 #self._content.begin_update() #self._content._set_document(self._document) t3 = time.time() * 1000 #self._content.end_update() #self.compute_size() t4 = time.time() * 1000 #self.layout() t5 = time.time() * 1000 print "Total: " + str(int(t5 - t1)) + " ms. t2-t1: " + str( int(t2 - t1)) + " and t3-t2: " + str( int(t3 - t2)) + " and t4-t3: " + str( int(t4 - t3)) + " and t5-t4: " + str(int(t5 - t4)) def delete(self): Controller.delete(self) Viewer.delete(self)
class Scrollable(Wrapper, Controller, ControllerManager): def __init__(self, content=None, width=None, height=None, is_fixed_size=False): if is_fixed_size: assert width is not None and height is not None Wrapper.__init__(self, content) ControllerManager.__init__(self) self.max_width = width self.max_height = height self.is_fixed_size = is_fixed_size self._hscrollbar = None self._vscrollbar = None self._content_width = 0 self._content_height = 0 self._content_x = 0 self._content_y = 0 # We emulate some aspects of Manager here. self._theme = None self.batch = None self.root_group = None self.group = { 'panel': None, 'background': None, 'foreground': None, 'highlight': None } @Managed.theme.getter def theme(self): return self._theme def set_manager(self, manager): Controller.set_manager(self, manager) self._theme = manager.theme self.batch = manager.batch self.root_group = ScrollableGroup(0, 0, self.width, self.height, parent=manager.group['foreground']) self.group['panel'] = pyglet.graphics.OrderedGroup(0, self.root_group) self.group['background'] = pyglet.graphics.OrderedGroup( 10, self.root_group) self.group['foreground'] = pyglet.graphics.OrderedGroup( 20, self.root_group) self.group['highlight'] = pyglet.graphics.OrderedGroup( 30, self.root_group) self.content.set_manager(self) self.content.parent = self def unload_graphics(self): Wrapper.unload_graphics(self) if self._hscrollbar is not None: self._hscrollbar.unload() self._hscrollbar = None if self._vscrollbar is not None: self._vscrollbar.unload() self._vscrollbar = None def expand(self, width, height): if self.content.is_expandable(): if self._vscrollbar is not None: self._content_width = width else: self._content_width = width if self._hscrollbar is not None: self._content_height = height else: self._content_height = height self.content.expand(max(self._content_width, self.content.width), max(self._content_height, self.content.height)) self.width, self.height = width, height def hit_test(self, x, y): # We only intercept events for the content region, not for # the scrollbars. They can handle themselves. return y >= self._content_y < self._content_y + self._content_height and \ self._content_x <= x < self._content_x + self._content_width def is_expandable(self): return True def _load_scrollbars(self, width, height): # if content size bigger than our size, # we load a scrollbar if self.content.width > width: if self._hscrollbar is None: self._hscrollbar = HScrollbar(width) self._hscrollbar.set_manager(self._manager) self._hscrollbar.parent = self self._hscrollbar.load() # if smaller, we unload it if it is loaded elif self._hscrollbar is not None: self._hscrollbar.delete() self._hscrollbar = None if self.content.height > height: if self._vscrollbar is None: self._vscrollbar = VScrollbar(height) self._vscrollbar.set_manager(self._manager) self._vscrollbar.parent = self self._vscrollbar.load() elif self._vscrollbar is not None: self._vscrollbar.delete() self._vscrollbar = None self._manager.set_wheel_target(None) def layout(self): Wrapper.layout(self) # Work out the adjusted content width and height y = self.y if self._hscrollbar is not None: self._hscrollbar.set_position(self.x, self.y) y += self._hscrollbar.height if self._vscrollbar is not None: self._vscrollbar.set_position(self.x + self._content_width, y) # Set the scissor group self.root_group.x, self.root_group.y = self.x - 1, y - 1 self.root_group.width = self._content_width + 1 self.root_group.height = self._content_height + 1 # Work out the content layout self._content_x, self._content_y = self.x, y left = self.x top = y + self._content_height - self.content.height if self._hscrollbar: left -= self._hscrollbar.get_knob_pos() if self._vscrollbar: top += self._vscrollbar.get_knob_pos() self.content.set_position(left, top) def on_gain_highlight(self): if self._hscrollbar is not None: self._manager.set_wheel_hint(self._hscrollbar) if self._vscrollbar is not None: self._manager.set_wheel_target(self._vscrollbar) def on_lose_highlight(self): self._manager.set_wheel_target(None) self._manager.set_wheel_hint(None) def compute_size(self): content_width, content_height = self.content.compute_size() width = min(self.max_width or content_width, content_width) height = min(self.max_height or content_height, content_height) self._content_width = width self._content_height = height # we have to load the scrolls here because they require knowing content size self._load_scrollbars(width, height) if self._hscrollbar is not None: self._hscrollbar.set_knob_size(self._content_width, content_height) _, scroll_height = self._hscrollbar.compute_size() height += scroll_height if self._vscrollbar is not None: self._vscrollbar.set_knob_size(self._content_height, content_height) scroll_width, _ = self._vscrollbar.compute_size() width += scroll_width return width, height def reset_size(self, reset_parent=True): super(Scrollable, self).reset_size(reset_parent) if self._hscrollbar is not None: self._hscrollbar.reset_size(reset_parent=False) if self._vscrollbar is not None: self._vscrollbar.reset_size(reset_parent=False) def delete(self): Wrapper.delete(self) ControllerManager.delete(self)
class Document(Controller, Viewer): """ Allows you to embed a document within the GUI, which includes a vertical scrollbar. """ def __init__(self, document, width=0, height=0, is_fixed_size=False): Viewer.__init__(self, width, height) Controller.__init__(self) self.max_height = height if isinstance(document, str): self._document = pyglet.text.document.UnformattedDocument(document) else: self._document = document self._content = None self.content_width = width self._scrollbar = None self.set_document_style = False self.is_fixed_size = is_fixed_size def hit_test(self, x, y): if self._content is not None: return Rectangle(self._content.x, self._content.y, self._content.width, self._content.height).is_inside(x, y) else: return False def _load_scrollbar(self, height): if self._content.content_height > height: if self._scrollbar is None: self._scrollbar = VScrollbar(self.max_height) self._scrollbar.set_manager(self._manager) self._scrollbar.parent = self self._scrollbar.load() self._scrollbar.set_knob_size(self.height, self._content.content_height) # if smaller, we unload it if it is loaded elif self._scrollbar is not None: self._scrollbar.unload() self._scrollbar = None def load_graphics(self): if not self.set_document_style: self.do_set_document_style(self._manager) self._content = pyglet.text.layout.IncrementalTextLayout(self._document, self.content_width, self.max_height, multiline=True, **self.get_batch('background')) def unload_graphics(self): self._content.delete() if self._scrollbar is not None: self._scrollbar.unload() self._scrollbar = None def do_set_document_style(self, dialog): self.set_document_style = True # Check the style runs to make sure we don't stamp on anything # set by the user self._do_set_document_style('color', dialog.theme['text_color']) self._do_set_document_style('font_name', dialog.theme['font']) self._do_set_document_style('font_size', dialog.theme['font_size']) def _do_set_document_style(self, attr, value): length = len(self._document.text) runs = [(start, end, doc_value) for start, end, doc_value in self._document.get_style_runs(attr).ranges(0, length) if doc_value is not None] if not runs: terminator = len(self._document.text) else: terminator = runs[0][0] self._document.set_style(0, terminator, {attr: value}) def get_text(self): return self._document.text def layout(self): if self._scrollbar is not None: self._scrollbar.set_position(self.x + self._content.content_width, self.y) pos = self._scrollbar.get_knob_pos() if pos != -self._content.view_y: self._content.view_y = -pos self._content.begin_update() self._content.x = self.x self._content.y = self.y self._content.end_update() if self._scrollbar is not None: self._scrollbar.set_position(self.x + self.content_width, self.y) def on_gain_highlight(self): if self._scrollbar is not None: self._manager.set_wheel_target(self._scrollbar) def on_lose_highlight(self): self._manager.set_wheel_target(None) def compute_size(self): if self.is_fixed_size or (self.max_height and self._content.content_height > self.max_height): height = self.max_height else: height = self._content.content_height self._content.height = height self._load_scrollbar(height) if self._scrollbar is not None: self._scrollbar.set_knob_size(height, self._content.content_height) self._scrollbar.compute_size() width = self.content_width + self._scrollbar.width else: width = self.content_width return width, height def set_text(self, text): self._document.text = text self.compute_size() self.layout() def delete(self): Controller.delete(self) Viewer.delete(self)