X-Git-Url: https://scm.cri.minesparis.psl.eu/git/minwii.git/blobdiff_plain/346a9b8e1fcfe30629f0d1ee4675e9e8f89890cf..4c4732c6ed8cb0aaa70fb2d4c6e5a958868c5349:/src/pgu/html.py?ds=sidebyside diff --git a/src/pgu/html.py b/src/pgu/html.py deleted file mode 100644 index 817c000..0000000 --- a/src/pgu/html.py +++ /dev/null @@ -1,571 +0,0 @@ -"""a html renderer -""" - -import sys -import htmllib -import re -import pygame -from pygame.locals import * - -from pgu import gui - -_amap = {'left':-1,'right':1,'center':0,None:None,'':None,} -_vamap = {'top':-1,'bottom':1,'center':0,'middle':0,None:None,'':None,} - -# Used by the HTML parser to load external resources (like images). This -# class loads content from the local file system. But you can pass your own -# resource loader to the HTML parser to find images by other means. -class ResourceLoader(object): - # Loads an image and returns it as a pygame image - def load_image(this, path): - return pygame.image.load(path) - -class _dummy: - pass - -class _flush: - def __init__(self): - self.style = _dummy() - self.style.font = None - self.style.color = None - self.cls = None - def add(self,w): pass - def space(self,v): pass - -class _hr(gui.Color): - def __init__(self,**params): - gui.Color.__init__(self,(0,0,0),**params) - def resize(self,width=None,height=None): - w,h = self.style.width,self.style.height - #if width != None: self.rect.w = width - #else: self.rect.w = 1 - - #xt,xr,xb,xl = self.getspacing() - - if width != None: w = max(w,width) - if height != None: h = max(h,height) - w = max(w,1) - h = max(h,1) - - return w,h #self.container.rect.w,h - - #self.rect.w = max(1,width,self.container.rect.w-(xl+xr)) - - #print self.rect - #self.rect.w = 1 - -class _html(htmllib.HTMLParser): - def init(self,doc,font,color,_globals,_locals,loader=None): - self.mystack = [] - self.document = doc - if (loader): - self.loader = loader - else: - # Use the default resource loader - self.loader = ResourceLoader() - self.myopen('document',self.document) - - self.myfont = self.font = font - self.mycolor = self.color = color - - self.form = None - - self._globals = _globals - self._locals = _locals - - def myopen(self,type_,w): - - self.mystack.append((type_,w)) - self.type,self.item = type_,w - - self.font = self.item.style.font - self.color = self.item.style.color - - if not self.font: self.font = self.myfont - if not self.color: self.color = self.mycolor - - def myclose(self,type_): - t = None - self.mydone() - while t != type_: - #if len(self.mystack)==0: return - t,w = self.mystack.pop() - t,w = self.mystack.pop() - self.myopen(t,w) - - def myback(self,type_): - if type(type_) == str: type_ = [type_,] - self.mydone() - #print 'myback',type_ - t = None - while t not in type_: - #if len(self.mystack)==0: return - t,w = self.mystack.pop() - self.myopen(t,w) - - def mydone(self): - #clearing out the last
- if not hasattr(self.item,'layout'): return - if len(self.item.layout._widgets) == 0: return - w = self.item.layout._widgets[-1] - if type(w) == tuple: - del self.item.layout._widgets[-1] - - - def start_b(self,attrs): self.font.set_bold(1) - def end_b(self): self.font.set_bold(0) - def start_i(self,attrs): self.font.set_italic(1) - def end_i(self): self.font.set_italic(0) - def start_u(self,attrs): self.font.set_underline(1) - def end_u(self): self.font.set_underline(0) - def start_br(self,attrs): self.do_br(attrs) - def do_br(self,attrs): self.item.br(self.font.size(" ")[1]) - def attrs_to_map(self,attrs): - k = None - r = {} - for k,v in attrs: r[k] = v - return r - - def map_to_params(self,r): - anum = re.compile("\D") - - params = {'style':{}} - style = params['style'] - - if 'bgcolor' in r: - style['background'] = gui.parse_color(r['bgcolor']) - if 'background' in r: - style['background'] = self.loader.load_image(r['background']) - if 'border' in r: style['border'] = int(r['border']) - - for k in ['width','height','colspan','rowspan','size','min','max']: - if k in r: params[k] = int(anum.sub("",r[k])) - - for k in ['name','value']: - if k in r: params[k] = r[k] - - if 'class' in r: params['cls'] = r['class'] - - if 'align' in r: - params['align'] = _amap[r['align']] - if 'valign' in r: - params['valign'] = _vamap[r['valign']] - - if 'style' in r: - for st in r['style'].split(";"): - #print st - if ":" in st: - #print st.split(":") - k,v = st.split(":") - k = k.replace("-","_") - k = k.replace(" ","") - v = v.replace(" ","") - if k == 'color' or k == 'border_color' or k == 'background': - v = gui.parse_color(v) - else: - v = int(anum.sub("",v)) - style[k] = v - return params - - def map_to_connects(self,e,r): - for k,evt in [('onclick',gui.CLICK),('onchange',gui.CHANGE)]: #blah blah blah - - if k in r: - #print k,r[k] - e.connect(evt,self.myexec,(e,r[k])) - - def start_p(self,attrs): - r = self.attrs_to_map(attrs) - align = r.get("align","left") - - self.check_p() - self.item.block(_amap[align]) - - def check_p(self): - if len(self.item.layout._widgets) == 0: return - if type(self.item.layout._widgets[-1]) == tuple: - w,h = self.item.layout._widgets[-1] - if w == 0: return - self.do_br(None) - - def end_p(self): - #print 'end p' - self.check_p() - - - def start_block(self,t,attrs,align=-1): - r = self.attrs_to_map(attrs) - params = self.map_to_params(r) - if 'cls' in params: params['cls'] = t+"."+params['cls'] - else: params['cls'] = t - b = gui.Document(**params) - b.style.font = self.item.style.font - if 'align' in params: - align = params['align'] - self.item.block(align) - self.item.add(b) - self.myopen(t,b) - - - - def end_block(self,t): - self.myclose(t) - self.item.block(-1) - - def start_div(self,attrs): self.start_block('div',attrs) - def end_div(self): self.end_block('div') - def start_center(self,attrs): self.start_block('div',attrs,0) - def end_center(self): self.end_block('div') - - def start_h1(self,attrs): self.start_block('h1',attrs) - def end_h1(self): self.end_block('h1') - def start_h2(self,attrs): self.start_block('h2',attrs) - def end_h2(self): self.end_block('h2') - def start_h3(self,attrs): self.start_block('h3',attrs) - def end_h3(self): self.end_block('h3') - def start_h4(self,attrs): self.start_block('h4',attrs) - def end_h4(self): self.end_block('h4') - def start_h5(self,attrs): self.start_block('h5',attrs) - def end_h5(self): self.end_block('h5') - def start_h6(self,attrs): self.start_block('h6',attrs) - def end_h6(self): self.end_block('h6') - - def start_ul(self,attrs): self.start_block('ul',attrs) - def end_ul(self): self.end_block('ul') - def start_ol(self,attrs): - self.start_block('ol',attrs) - self.item.counter = 0 - def end_ol(self): self.end_block('ol') - def start_li(self,attrs): - self.myback(['ul','ol']) - cur = self.item - self.start_block('li',attrs) - if hasattr(cur,'counter'): - cur.counter += 1 - self.handle_data("%d. "%cur.counter) - else: - self.handle_data("- ") - #def end_li(self): self.end_block('li') #this isn't needed because of how the parser works - - def start_pre(self,attrs): self.start_block('pre',attrs) - def end_pre(self): self.end_block('pre') - def start_code(self,attrs): self.start_block('code',attrs) - def end_code(self): self.end_block('code') - - def start_table(self,attrs): - r = self.attrs_to_map(attrs) - params = self.map_to_params(r) - - align = r.get("align","left") - self.item.block(_amap[align]) - - t = gui.Table(**params) - self.item.add(t) - - self.myopen('table',t) - - def start_tr(self,attrs): - self.myback('table') - self.item.tr() - - def _start_td(self,t,attrs): - r = self.attrs_to_map(attrs) - params = self.map_to_params(r) - if 'cls' in params: params['cls'] = t+"."+params['cls'] - else: params['cls'] = t - b = gui.Document(cls=t) - - self.myback('table') - self.item.td(b,**params) - self.myopen(t,b) - - self.font = self.item.style.font - self.color = self.item.style.color - - def start_td(self,attrs): - self._start_td('td',attrs) - - def start_th(self,attrs): - self._start_td('th',attrs) - - def end_table(self): - self.myclose('table') - self.item.block(-1) - - def start_form(self,attrs): - r = self.attrs_to_map(attrs) - e = self.form = gui.Form() - e.groups = {} - - self._locals[r.get('id',None)] = e - - def start_input(self,attrs): - r = self.attrs_to_map(attrs) - params = self.map_to_params(r) #why bother - #params = {} - - type_,name,value = r.get('type','text'),r.get('name',None),r.get('value',None) - f = self.form - if type_ == 'text': - e = gui.Input(**params) - self.map_to_connects(e,r) - self.item.add(e) - elif type_ == 'radio': - if name not in f.groups: - f.groups[name] = gui.Group(name=name) - g = f.groups[name] - del params['name'] - e = gui.Radio(group=g,**params) - self.map_to_connects(e,r) - self.item.add(e) - if 'checked' in r: g.value = value - elif type_ == 'checkbox': - if name not in f.groups: - f.groups[name] = gui.Group(name=name) - g = f.groups[name] - del params['name'] - e = gui.Checkbox(group=g,**params) - self.map_to_connects(e,r) - self.item.add(e) - if 'checked' in r: g.value = value - - elif type_ == 'button': - e = gui.Button(**params) - self.map_to_connects(e,r) - self.item.add(e) - elif type_ == 'submit': - e = gui.Button(**params) - self.map_to_connects(e,r) - self.item.add(e) - elif type_ == 'file': - e = gui.Input(**params) - self.map_to_connects(e,r) - self.item.add(e) - b = gui.Button(value='Browse...') - self.item.add(b) - def _browse(value): - d = gui.FileDialog(); - d.connect(gui.CHANGE,gui.action_setvalue,(d,e)) - d.open(); - b.connect(gui.CLICK,_browse,None) - - self._locals[r.get('id',None)] = e - - def start_object(self,attrs): - r = self.attrs_to_map(attrs) - params = self.map_to_params(r) - code = "e = %s(**params)"%r['type'] - #print code - #print params - exec(code) - #print e - #print e.style.width,e.style.height - self.map_to_connects(e,r) - self.item.add(e) - - self._locals[r.get('id',None)] = e - - def start_select(self,attrs): - r = self.attrs_to_map(attrs) - params = {} - - name,value = r.get('name',None),r.get('value',None) - e = gui.Select(name=name,value=value,**params) - self.map_to_connects(e,r) - self.item.add(e) - self.myopen('select',e) - - def start_option(self,attrs): - r = self.attrs_to_map(attrs) - params = {} #style = self.map_to_style(r) - - self.myback('select') - e = gui.Document(**params) - self.item.add(e,value=r.get('value',None)) - self.myopen('option',e) - - - def end_select(self): - self.myclose('select') - - def start_hr(self,attrs): - self.do_hr(attrs) - def do_hr(self,attrs): - h = self.font.size(" ")[1]/2 - - r = self.attrs_to_map(attrs) - params = self.map_to_params(r) - params['style']['padding'] = h - print params - - self.item.block(0) - self.item.add(_hr(**params)) - self.item.block(-1) - - def anchor_begin(self,href,name,type_): - pass - - def anchor_end(self): - pass - - def start_title(self,attrs): self.myopen('title',_flush()) - def end_title(self): self.myclose('title') - - def myexec(self,value): - w,code = value - g = self._globals - l = self._locals - l['self'] = w - exec(code,g,l) - - def handle_image(self,src,alt,ismap,align,width,height): - try: - w = gui.Image(self.loader.load_image(src)) - if align != '': - self.item.add(w,_amap[align]) - else: - self.item.add(w) - except: - print 'handle_image: missing %s'%src - - def handle_data(self,txt): - if self.type == 'table': return - elif self.type in ('pre','code'): - txt = txt.replace("\t"," ") - ss = txt.split("\n") - if ss[-1] == "": del ss[-1] - for sentence in ss: - img = self.font.render(sentence,1,self.color) - w = gui.Image(img) - self.item.add(w) - self.item.block(-1) - return - - txt = re.compile("^[\t\r\n]+").sub("",txt) - txt = re.compile("[\t\r\n]+$").sub("",txt) - - tst = re.compile("[\t\r\n]+").sub("",txt) - if tst == "": return - - txt = re.compile("\s+").sub(" ",txt) - if txt == "": return - - if txt == " ": - self.item.space(self.font.size(" ")) - return - - for word in txt.split(" "): - word = word.replace(chr(160)," ") # - #print self.item.cls - w = gui.Image(self.font.render(word,1,self.color)) - self.item.add(w) - self.item.space(self.font.size(" ")) - - -class HTML(gui.Document): - """a gui HTML object - -HTML(data,globals=None,locals=None)- -
you may access html elements that have an id via widget[id]
- """ - def __init__(self,data,globals=None,locals=None,loader=None,**params): - gui.Document.__init__(self,**params) - # This ensures that the whole HTML document is left-aligned within - # the rendered surface. - self.style.align = -1 - - _globals,_locals = globals,locals - - if _globals == None: _globals = {} - if _locals == None: _locals = {} - self._globals = _globals - self._locals = _locals - - #font = gui.theme.get("label","","font") - p = _html(htmllib.AS_IS,0) - p.init(self,self.style.font,self.style.color,_globals,_locals, - loader=loader) - p.feed(data) - p.close() - p.mydone() - - - def __getitem__(self,k): - return self._locals[k] - - # Returns a box (pygame rectangle) surrounding all widgets in this document - def get_bounding_box(this): - minx = miny = sys.maxint - maxx = maxy = -sys.maxint - for e in this.layout.widgets: - minx = min(minx, e.rect.left) - miny = min(miny, e.rect.top) - maxx = max(maxx, e.rect.right+1) - maxy = max(maxy, e.rect.bottom+1) - return pygame.Rect(minx, miny, maxx-minx, maxy-miny) - - -def render_ext(font, rect, text, aa, color, bgcolor=(0,0,0,0), **params): - """Renders some html and returns the rendered surface, plus the - HTML instance that produced it. - """ - - htm = HTML(text, font=font, color=color, **params) - - if (rect == -1): - # Make the surface large enough to fit the rendered text - htm.resize(width=sys.maxint) - (width, height) = htm.get_bounding_box().size - # Now set the proper document width (computed from the bounding box) - htm.resize(width=width) - elif (type(rect) == int): - # Fix the width of the document, while the height is variable - width = rect - height = htm.resize(width=width)[1] - else: - # Otherwise the width and height of the document is fixed - (width, height) = rect.size - htm.resize(width=width) - - # Now construct a surface and paint to it - surf = pygame.Surface((width, height)).convert_alpha() - surf.fill(bgcolor) - htm.paint(surf) - return (surf, htm) - -def render(font, rect, text, aa, color, bgcolor=(0,0,0,0), **params): - """Renders some html - -render(font,rect,text,aa,color,bgcolor=(0,0,0,0))- """ - return render_ext(font, rect, text, aa, color, bgcolor, **params)[0] - -def rendertrim(font,rect,text,aa,color,bgcolor=(0,0,0,0),**params): - """render html, and make sure to trim the size - - rendertrim(font,rect,text,aa,color,bgcolor=(0,0,0,0)) - """ - # Render the HTML - (surf, htm) = render_ext(font, rect, text, aa, color, bgcolor, **params) - return surf.subsurface(htm.get_bounding_box()) - - -def write(s,font,rect,text,aa=0,color=(0,0,0), **params): - """write html to a surface - - write(s,font,rect,text,aa=0,color=(0,0,0)) - """ - htm = HTML(text, font=font, color=color, **params) - htm.resize(width=rect.w) - s = s.subsurface(rect) - htm.paint(s) - -# vim: set filetype=python sts=4 sw=4 noet si :