-"""
-"""
-import os
-
-import pguglobals
-from const import *
-import surface
-import container, table
-import group
-import basic, button, slider
-from pygame.font import Font
-
-class SlideBox(container.Container):
- """A scrollable area with no scrollbars.
-
- <pre>SlideBox(widget,width,height)</pre>
-
- <dl>
- <dt>widget<dd>widget to be able to scroll around
- <dt>width, height<dd>size of scrollable area
- </dl>
-
- <strong>Example</strong>
- <code>
- c = SlideBox(w,100,100)
- c.offset = (10,10)
- c.repaint()
- </code>
-
- """
-
- def __init__(self, widget, width, height, **params):
- params.setdefault('width', width)
- params.setdefault('height', height)
- container.Container.__init__(self, **params)
- self.offset = [0, 0]
- self.widget = widget
-
- def __setattr__(self,k,v):
- if k == 'widget':
- if hasattr(self,'widget'):
- self.remove(self.widget)
- self.add(v,0,0)
- self.__dict__[k] = v
-
-
- def paint(self, s):
- #if not hasattr(self,'surface'):
- self.surface = pygame.Surface((self.max_rect.w,self.max_rect.h),0,s)
- #self.surface.fill((0,0,0,0))
- pguglobals.app.theme.render(self.surface,self.style.background,pygame.Rect(0,0,self.max_rect.w,self.max_rect.h))
- self.bkgr = pygame.Surface((s.get_width(),s.get_height()),0,s)
- self.bkgr.blit(s,(0,0))
- container.Container.paint(self,self.surface)
- s.blit(self.surface,(-self.offset[0],-self.offset[1]))
- self._offset = self.offset[:]
- return
-
- def paint_for_when_pygame_supports_other_tricks(self,s):
- #this would be ideal if pygame had support for it!
- #and if pgu also had a paint(self,s,rect) method to paint small parts
- sr = (self.offset[0],self.offset[1],self.max_rect.w,self.max_rect.h)
- cr = (-self.offset[0],-self.offset[1],s.get_width(),s.get_height())
- s2 = s.subsurface(sr)
- s2.set_clip(cr)
- container.Container.paint(self,s2)
-
- def proxy_paint(self, s):
- container.Container.paint(self, surface.ProxySurface(parent=None,
- rect=self.max_rect,
- real_surface=s,
- offset=self.offset))
- def update(self, s):
- rects = container.Container.update(self,self.surface)
-
- rets = []
- s_rect = pygame.Rect(0,0,s.get_width(),s.get_height())
-
- if self.offset == self._offset:
- for r in rects:
- r2 = r.move((-self.offset[0],-self.offset[1]))
- if r2.colliderect(s_rect):
- s.blit(self.surface.subsurface(r),r2)
- rets.append(r2)
- else:
- s.blit(self.bkgr,(0,0))
- sub = pygame.Rect(self.offset[0],self.offset[1],min(s.get_width(),self.max_rect.w-self.offset[0]),min(s.get_height(),self.max_rect.h-self.offset[1]))
-# print sub
-# print self.surface.get_width(),self.surface.get_height()
-# print s.get_width(),s.get_height()
-# print self.offset
-# print self.style.width,self.style.height
- s.blit(self.surface.subsurface(sub),(0,0))
- rets.append(s_rect)
- self._offset = self.offset[:]
- return rets
-
- def proxy_update(self, s):
- rects = container.Container.update(self, surface.ProxySurface(parent=None,
- rect=self.max_rect,
- real_surface=s,
- offset=self.offset))
- result = []
- for r in rects: result.append(pygame.Rect(r).move(self.offset))
- return result
-
- def resize(self, width=None, height=None):
- container.Container.resize(self)
- self.max_rect = pygame.Rect(self.widget.rect)
- #self.max_rect.w = max(self.max_rect.w,self.style.width)
- #self.max_rect.h = max(self.max_rect.h,self.style.height)
- return self.style.width,self.style.height
- #self.rect = pygame.Rect(self.rect[0], self.rect[1], self.style.width, self.style.height)
-
- def event(self, e):
- if e.type in [MOUSEBUTTONDOWN, MOUSEBUTTONUP, MOUSEMOTION]:
- pos = (e.pos[0] + self.offset[0], e.pos[1] + self.offset[1])
- if self.max_rect.collidepoint(pos):
- e_params = {'pos': pos }
- if e.type == MOUSEMOTION:
- e_params['buttons'] = e.buttons
- e_params['rel'] = e.rel
- else:
- e_params['button'] = e.button
- e = pygame.event.Event(e.type, e_params)
- container.Container.event(self, e)
-
-#class SlideBox(Area):
-# def __init__(self,*args,**params):
-# print 'gui.SlideBox','Scheduled to be renamed to Area.'
-# Area.__init__(self,*args,**params)
-
-class ScrollArea(table.Table):
- """A scrollable area with scrollbars.
-
- <pre>ScrollArea(widget,width,height,hscrollbar=True)</pre>
-
- <dl>
- <dt>widget<dd>widget to be able to scroll around
- <dt>width, height<dd>size of scrollable area. Set either to 0 to default to size of widget.
- <dt>hscrollbar<dd>set to False if you do not wish to have a horizontal scrollbar
- <dt>vscrollbar<dd>set to False if you do not wish to have a vertical scrollbar
- <dt>step<dd>set to how far clicks on the icons will step
- </dl>
- """
- def __init__(self, widget, width=0, height=0, hscrollbar=True, vscrollbar=True,step=24, **params):
- w= widget
- params.setdefault('cls', 'scrollarea')
- table.Table.__init__(self, width=width,height=height,**params)
-
- self.sbox = SlideBox(w, width=width, height=height, cls=self.cls+".content")
- self.widget = w
- self.vscrollbar = vscrollbar
- self.hscrollbar = hscrollbar
-
- self.step = step
-
- def __setattr__(self,k,v):
- if k == 'widget':
- self.sbox.widget = v
- self.__dict__[k] = v
-
- def resize(self,width=None,height=None):
- widget = self.widget
- box = self.sbox
-
- #self.clear()
- table.Table.clear(self)
- #print 'resize',self,self._rows
-
- self.tr()
- self.td(box)
-
- widget.rect.w, widget.rect.h = widget.resize()
- my_width,my_height = self.style.width,self.style.height
- if not my_width:
- my_width = widget.rect.w
- self.hscrollbar = False
- if not my_height:
- my_height = widget.rect.h
- self.vscrollbar = False
-
- box.style.width,box.style.height = my_width,my_height #self.style.width,self.style.height
-
- box.rect.w,box.rect.h = box.resize()
-
- #print widget.rect
- #print box.rect
- #r = table.Table.resize(self,width,height)
- #print r
- #return r
-
- #print box.offset
-
-# #this old code automatically adds in a scrollbar if needed
-# #but it doesn't always work
-# self.vscrollbar = None
-# if widget.rect.h > box.rect.h:
-# self.vscrollbar = slider.VScrollBar(box.offset[1],0, 65535, 0,step=self.step)
-# self.td(self.vscrollbar)
-# self.vscrollbar.connect(CHANGE, self._vscrollbar_changed, None)
-#
-# vs = self.vscrollbar
-# vs.rect.w,vs.rect.h = vs.resize()
-# box.style.width = self.style.width - vs.rect.w
-#
-#
-# self.hscrollbar = None
-# if widget.rect.w > box.rect.w:
-# self.hscrollbar = slider.HScrollBar(box.offset[0], 0,65535, 0,step=self.step)
-# self.hscrollbar.connect(CHANGE, self._hscrollbar_changed, None)
-# self.tr()
-# self.td(self.hscrollbar)
-#
-# hs = self.hscrollbar
-# hs.rect.w,hs.rect.h = hs.resize()
-# box.style.height = self.style.height - hs.rect.h
-
- xt,xr,xb,xl = pguglobals.app.theme.getspacing(box)
-
-
- if self.vscrollbar:
- self.vscrollbar = slider.VScrollBar(box.offset[1],0, 65535, 0,step=self.step)
- self.td(self.vscrollbar)
- self.vscrollbar.connect(CHANGE, self._vscrollbar_changed, None)
-
- vs = self.vscrollbar
- vs.rect.w,vs.rect.h = vs.resize()
- if self.style.width:
- box.style.width = self.style.width - (vs.rect.w + xl+xr)
-
- if self.hscrollbar:
- self.hscrollbar = slider.HScrollBar(box.offset[0], 0,65535, 0,step=self.step)
- self.hscrollbar.connect(CHANGE, self._hscrollbar_changed, None)
- self.tr()
- self.td(self.hscrollbar)
-
- hs = self.hscrollbar
- hs.rect.w,hs.rect.h = hs.resize()
- if self.style.height:
- box.style.height = self.style.height - (hs.rect.h + xt + xb)
-
- if self.hscrollbar:
- hs = self.hscrollbar
- hs.min = 0
- hs.max = widget.rect.w - box.style.width
- hs.style.width = box.style.width
- hs.size = hs.style.width * box.style.width / max(1,widget.rect.w)
- else:
- box.offset[0] = 0
-
- if self.vscrollbar:
- vs = self.vscrollbar
- vs.min = 0
- vs.max = widget.rect.h - box.style.height
- vs.style.height = box.style.height
- vs.size = vs.style.height * box.style.height / max(1,widget.rect.h)
- else:
- box.offset[1] = 0
-
- #print self.style.width,box.style.width, hs.style.width
-
- r = table.Table.resize(self,width,height)
- return r
-
- def x_resize(self, width=None, height=None):
- w,h = table.Table.resize(self, width, height)
- if self.hscrollbar:
- if self.widget.rect.w <= self.sbox.rect.w:
- self.hscrollbar.size = self.hscrollbar.style.width
- else:
- self.hscrollbar.size = max(20,self.hscrollbar.style.width * self.sbox.rect.w / self.widget.rect.w)
- self._hscrollbar_changed(None)
- if self.widget.rect.h <= self.sbox.rect.h:
- self.vscrollbar.size = self.vscrollbar.style.height
- else:
- self.vscrollbar.size = max(20,self.vscrollbar.style.height * self.sbox.rect.h / self.widget.rect.h)
- self._vscrollbar_changed(None)
- return w,h
-
- def _vscrollbar_changed(self, xxx):
- #y = (self.widget.rect.h - self.sbox.rect.h) * self.vscrollbar.value / 1000
- #if y >= 0: self.sbox.offset[1] = -y
- self.sbox.offset[1] = self.vscrollbar.value
- self.sbox.reupdate()
-
- def _hscrollbar_changed(self, xxx):
- #x = (self.widget.rect.w - self.sbox.rect.w) * self.hscrollbar.value / 1000
- #if x >= 0: self.sbox.offset[0] = -x
- self.sbox.offset[0] = self.hscrollbar.value
- self.sbox.reupdate()
-
-
- def set_vertical_scroll(self, percents):
- #if not self.vscrollbar: return
- if not hasattr(self.vscrollbar,'value'): return
- self.vscrollbar.value = percents #min(max(percents*10, 0), 1000)
- self._vscrollbar_changed(None)
-
- def set_horizontal_scroll(self, percents):
- #if not self.hscrollbar: return
- if not hasattr(self.hscrollbar,'value'): return
- self.hscrollbar.value = percents #min(max(percents*10, 0), 1000)
- self._hscrollbar_changed(None)
-
- def event(self, e):
- #checking for event recipient
- if (table.Table.event(self, e)):
- return True
-
- #mouse wheel scrolling
- if self.vscrollbar:
- if not hasattr(self.vscrollbar,'value'):
- return False
-
- if e.type == pygame.locals.MOUSEBUTTONDOWN:
- if e.button == 4: #wheel up
- self.vscrollbar._click(-1)
- return True
- elif e.button == 5: #wheel down
- self.vscrollbar._click(1)
- return True
- return False
-
-
-
-
-class _List_Item(button._button):
- def __init__(self,label=None,image=None,value=None,**params): #TODO label= could conflict with the module label
- #param image: an imagez.Image object (optional)
- #param text: a string object
- params.setdefault('cls','list.item')
- button._button.__init__(self,**params)
- self.group = None
- self.value = value #(self, value)
- self.widget = None
-
- if type(label) == str:
- label = basic.Label(label, cls=self.cls+".label")
-
- if image and label:
- self.widget = container.Container()
- self.widget.add(image, 0, 0)
- #HACK: improper use of .resize()
- image.rect.w,image.rect.h = image.resize()
- self.widget.add(label, image.rect.w, 0)
- elif image: self.widget = image
- elif label: self.widget = label
-
- self.pcls = ""
-
- def resize(self,width=None,height=None):
- self.widget.rect.w,self.widget.rect.h = self.widget.resize()
- return self.widget.rect.w,self.widget.rect.h
-# self.widget._resize()
-# self.rect.w,self.rect.h = self.widget.rect_margin.w,self.widget.rect_margin.h
-
- def event(self,e):
- button._button.event(self,e)
- if self.group.value == self.value: self.pcls = "down"
-
- def paint(self,s):
- if self.group.value == self.value: self.pcls = "down"
- self.widget.paint(surface.subsurface(s,self.widget.rect))
-
- def click(self):
- self.group.value = self.value
- for w in self.group.widgets:
- if w != self: w.pcls = ""
-
-
-
-class List(ScrollArea):
- """A list of items in an area.
-
- <p>This widget can be a form element, it has a value set to whatever item is selected.</p>
-
- <pre>List(width,height)</pre>
- """
- def _change(self, value):
- self.value = self.group.value
- self.send(CHANGE)
-
- def __init__(self, width, height, **params):
- params.setdefault('cls', 'list')
- self.table = table.Table(width=width)
- ScrollArea.__init__(self, self.table, width, height,hscrollbar=False ,**params)
-
- self.items = []
-
- g = group.Group()
- self.group = g
- g.connect(CHANGE,self._change,None)
- self.value = self.group.value = None
-
- self.add = self._add
- self.remove = self._remove
-
- def clear(self):
- """Clear the list.
-
- <pre>List.clear()</pre>
- """
- self.items = []
- self.group = group.Group()
- self.group.connect(CHANGE,self._change,None)
- self.table.clear()
- self.set_vertical_scroll(0)
- self.blur(self.myfocus)
-
- def _docs(self): #HACK: nasty hack to get the docs in "my way"
- def add(self, label, image=None, value=None):
- """Add an item to the list.
-
- <pre>List.add(label,image=None,value=None)</pre>
-
- <dl>
- <dt>label<dd>a label for the item
- <dt>image<dd>an image for the item
- <dt>value<dd>a value for the item
- </dl>
- """
-
- def remove(self,value):
- """Remove an item from the list.
-
- <pre>List.remove(value)</pre>
-
- <dl>
- <dt>value<dd>a value of an item to remove from the list
- </dl>
- """
-
- def _add(self, label, image = None, value=None):
- item = _List_Item(label,image=image,value=value)
- self.table.tr()
- self.table.add(item)
- self.items.append(item)
- item.group = self.group
- item.group.add(item)
-
- def _remove(self, item):
- for i in self.items:
- if i.value == item: item = i
- if item not in self.items: return
- item.blur()
- self.items.remove(item)
- self.group.widgets.remove(item)
- self.table.remove_row(item.style.row)
-
-#class List(ListArea):
-# def __init__(self,*args,**params):
-# print 'gui.List','Scheduled to be renamed to ListArea. API may also be changed in the future.'
-# ListArea.__init__(self,*args,**params)