def __init__(self, width=800, height=600, url='http://localhost/'): self.VERSION = '0.6' self.USER_AGENT = 'SimpleWebBrowser/{version}'.format(version=self.VERSION) self.VSPACES = {'h1': 10, 'h2': 8, 'h3': 6, 'h4': 4, 'h5': 4, 'h6': 4, 'p': 8, 'pre': 8, 'ul': 8, 'ol': 8, 'table': 8, 'li': 0, 'tr': 0} self.IGNORE_TAGS = ['title', 'style', 'script'] pygame.init() pygame.key.set_repeat(100, 1000 // 25) self.top = 20 self.left = 0 self.width = width self.height = height self.g = Graphics() self.g.surface = pygame.display.set_mode((self.width, self.height), pygame.RESIZABLE) self.do_redraw = True self.address_bar = TextField(0, 0, self.width, 20, on_action_handler=self) self.text_box = TextBox (0, 20, self.width, self.height - 20) self.active_widget = self self.fonts = Fonts() self.g.font = self.fonts.normal self.ATTR = {'default': AttributeWidget(font=self.fonts.normal,fg=(0, 0, 0, 255),bg=(255, 255, 255, 255)), 'h1': AttributeWidget(font=self.fonts.h1), 'h2': AttributeWidget(font=self.fonts.h2), 'h3': AttributeWidget(font=self.fonts.h3), 'h4': AttributeWidget(font=self.fonts.h4), 'h5': AttributeWidget(font=self.fonts.h5), 'h6': AttributeWidget(font=self.fonts.h6), 'pre' : AttributeWidget(font=self.fonts.monospace), 'code': AttributeWidget(font=self.fonts.monospace) } self.attr_stack = [] self.attr_current = self.ATTR['default'] self.links = [] self.link_current = None self.link_active = '' pygame.display.set_caption('SimpleWebBrowser V{version}'.format(version=self.VERSION)) self.load(url)
class SimpleWebbrowser: def __init__(self, width=800, height=600, url='http://localhost/'): self.VERSION = '0.6' self.USER_AGENT = 'SimpleWebBrowser/{version}'.format(version=self.VERSION) self.VSPACES = {'h1': 10, 'h2': 8, 'h3': 6, 'h4': 4, 'h5': 4, 'h6': 4, 'p': 8, 'pre': 8, 'ul': 8, 'ol': 8, 'table': 8, 'li': 0, 'tr': 0} self.IGNORE_TAGS = ['title', 'style', 'script'] pygame.init() pygame.key.set_repeat(100, 1000 // 25) self.top = 20 self.left = 0 self.width = width self.height = height self.g = Graphics() self.g.surface = pygame.display.set_mode((self.width, self.height), pygame.RESIZABLE) self.do_redraw = True self.address_bar = TextField(0, 0, self.width, 20, on_action_handler=self) self.text_box = TextBox (0, 20, self.width, self.height - 20) self.active_widget = self self.fonts = Fonts() self.g.font = self.fonts.normal self.ATTR = {'default': AttributeWidget(font=self.fonts.normal,fg=(0, 0, 0, 255),bg=(255, 255, 255, 255)), 'h1': AttributeWidget(font=self.fonts.h1), 'h2': AttributeWidget(font=self.fonts.h2), 'h3': AttributeWidget(font=self.fonts.h3), 'h4': AttributeWidget(font=self.fonts.h4), 'h5': AttributeWidget(font=self.fonts.h5), 'h6': AttributeWidget(font=self.fonts.h6), 'pre' : AttributeWidget(font=self.fonts.monospace), 'code': AttributeWidget(font=self.fonts.monospace) } self.attr_stack = [] self.attr_current = self.ATTR['default'] self.links = [] self.link_current = None self.link_active = '' pygame.display.set_caption('SimpleWebBrowser V{version}'.format(version=self.VERSION)) self.load(url) def load(self, uri): """ Load new web page.""" self.link_active = urljoin(self.link_active, uri) self.address_bar.set_text(self.link_active) self.address_bar.draw(self.g) r = requests.get(self.link_active, headers={'user-agent': self.USER_AGENT}) self.html_sourcecode = r.text self.attr_stack = [] self.attr_current = self.ATTR['default'] self.links = [] self.text_box.scroll_left = 0 self.text_box.scroll_top = 0 self.text_box.widgets = [] html_parser = etree.HTMLParser(remove_blank_text=True) html_tree = etree.fromstring(self.html_sourcecode, html_parser) self.parse_html(html_tree) self.text_box.layout(self.g) def parse_html(self, element): if element.tag in self.IGNORE_TAGS: return if element.tag in self.VSPACES: self.text_box.widgets.append(VSpaceWidget(self.VSPACES[element.tag])) if element.tag in self.ATTR: self.attr_stack.append(self.attr_current) self.attr_current = self.ATTR[element.tag] self.text_box.widgets.append(self.attr_current) if element.tag == 'a': self.link_current = Link(href=element.get('href')) self.links.append(self.link_current) self.attr_stack.append(self.attr_current) self.attr_current = AttributeWidget(fg=(0,0,255,255), bg=(255,255,255,255)) self.text_box.widgets.append(self.attr_current) if element.tag in ['ul', 'ol']: self.text_box.widgets.append(IndentWidget(32)) if element.text != None: for word in element.text.split(): text_widget = TextWidget(word) self.text_box.widgets.append(text_widget) if self.link_current != None: self.link_current.widgets.append(text_widget) for child in element: self.parse_html(child) if element.tag in self.ATTR: self.attr_current = self.attr_stack.pop() self.text_box.widgets.append(self.attr_current) if element.tag == 'a': self.link_current = None self.attr_current = self.attr_stack.pop() self.text_box.widgets.append(self.attr_current) if element.tag in ['ul', 'ol']: self.text_box.widgets.append(IndentWidget(-32)) if element.tail != None: for word in element.tail.split(): text_widget = TextWidget(word) self.text_box.widgets.append(text_widget) if self.link_current != None: self.link_current.widgets.append(text_widget) def set_size(self, size): self.width = size[0] self.height = size[1] self.g.surface = pygame.display.set_mode(size, pygame.RESIZABLE) self.address_bar.set_size(self.width, 20) self.address_bar.layout(self.g) self.text_box.set_size(self.width, self.height - 20) self.text_box.layout(self.g) self.draw(self.g) def draw(self, g): g.fg = ( 0, 0, 0, 255) g.bg = (255, 255, 255, 255) g.font = self.fonts.normal self.g.surface.set_clip(None) g.surface.fill(g.bg) self.address_bar.draw(g) self.text_box.draw(g) def on_action(self, widget): self.load(self.address_bar.text) self.draw(self.g) pygame.display.flip() def on_focus(self): pass def on_blur(self): pass def on_mouse_down(self, event): pass def on_mouse_up(self, event): for link in self.links: if link.is_point_in(event.pos[0] - self.text_box.left + self.text_box.scroll_left, event.pos[1] - self.text_box.top + self.text_box.scroll_top): self.load(link.href) break def on_key_down(self, event): if event.key == pygame.K_UP : self.text_box.scroll( 0, -5) elif event.key == pygame.K_DOWN : self.text_box.scroll( 0, 5) elif event.key == pygame.K_LEFT : self.text_box.scroll(-20, 0) elif event.key == pygame.K_RIGHT: self.text_box.scroll( 20, 0) elif event.key == pygame.K_PAGEUP : self.text_box.scroll_page_up() elif event.key == pygame.K_PAGEDOWN: self.text_box.scroll_page_down() elif event.key == pygame.K_HOME: if event.mod & pygame.KMOD_SHIFT: self.text_box.scroll_x_home() else: self.text_box.scroll_y_home() elif event.key == pygame.K_END: if event.mod & pygame.KMOD_SHIFT: self.text_box.scroll_x_end() else: self.text_box.scroll_y_end() def run(self): while True: if self.active_widget.do_redraw: self.active_widget.draw(self.g) pygame.display.flip() if self.active_widget == self: self.do_redraw = True else: self.do_redraw = False event = pygame.event.wait() if event.type == pygame.QUIT: break if event.type == pygame.VIDEORESIZE: self.set_size(event.size) if event.type == pygame.MOUSEMOTION: self.do_redraw = False if event.type == pygame.MOUSEBUTTONDOWN: if self.address_bar.is_point_in(event.pos[0], event.pos[1]): new_active_widget = self.address_bar else: new_active_widget = self if new_active_widget != self.active_widget: self.active_widget.on_blur() self.active_widget.draw(self.g) self.active_widget = new_active_widget self.active_widget.on_focus() self.active_widget.draw(self.g) pygame.display.flip() self.active_widget.on_mouse_down(event) if event.type == pygame.MOUSEBUTTONUP: self.active_widget.on_mouse_up(event) if event.type == pygame.KEYDOWN: if event.key == pygame.K_ESCAPE: break self.active_widget.on_key_down(event) def quit(self): pygame.quit()