# ###############################################################
#
# Albow - Tab Panel
#
################################################################
#-# Modified by D.C.-G. for translation purpose
from OpenGL.GL import *
from OpenGL.GLU import *
from OpenGL.GLUT import *
from albow import *
from pygame import Rect, Surface, image
from pygame.locals import SRCALPHA
from widget import Widget
from theme import ThemeProperty, FontProperty
from utils import brighten
from numpy import fromstring
from translate import _ # useless?
[docs]class TabPanel(Widget):
# pages [Widget]
# current_page Widget
tab_font = FontProperty('tab_font')
tab_height = ThemeProperty('tab_height')
tab_border_width = ThemeProperty('tab_border_width')
tab_spacing = ThemeProperty('tab_spacing')
tab_margin = ThemeProperty('tab_margin')
tab_fg_color = ThemeProperty('tab_fg_color')
default_tab_bg_color = ThemeProperty('default_tab_bg_color')
tab_area_bg_color = ThemeProperty('tab_area_bg_color')
tab_dimming = ThemeProperty('tab_dimming')
tab_titles = None
#use_page_bg_color_for_tabs = ThemeProperty('use_page_bg_color_for_tabs')
def __init__(self, pages=None, **kwds):
Widget.__init__(self, **kwds)
self.pages = []
self.current_page = None
if pages:
w = h = 0
for title, page in pages:
w = max(w, page.width)
h = max(h, page.height)
self._add_page(title, page)
self.size = (w, h)
self.show_page(pages[0][1])
[docs] def content_size(self):
return self.width, self.height - self.tab_height
[docs] def content_rect(self):
return Rect((0, self.tab_height), self.content_size())
[docs] def page_height(self):
return self.height - self.tab_height
[docs] def add_page(self, title, page, idx=None):
self._add_page(title, page, idx)
if not self.current_page:
self.show_page(page)
def _add_page(self, title, page, idx=None):
page.tab_title = _(title)
page.anchor = 'ltrb'
if idx is not None:
self.pages.insert(idx, page)
else:
self.pages.append(page)
[docs] def remove_page(self, page):
try:
i = self.pages.index(page)
del self.pages[i]
except IndexError:
pass
if page is self.current_page:
self.show_page(None)
[docs] def show_page(self, page):
if self.current_page:
self.remove(self.current_page)
self.current_page = page
if page:
th = self.tab_height
page.rect = Rect(0, th, self.width, self.height - th)
self.add(page)
page.focus()
[docs] def draw(self, surf):
self.draw_tab_area_bg(surf)
self.draw_tabs(surf)
[docs] def draw_tab_area_bg(self, surf):
bg = self.tab_area_bg_color
if bg:
surf.fill(bg, (0, 0, self.width, self.tab_height))
[docs] def draw_tabs(self, surf):
font = self.tab_font
fg = self.tab_fg_color
b = self.tab_border_width
if b:
surf.fill(fg, (0, self.tab_height - b, self.width, b))
for i, title, page, selected, rect in self.iter_tabs():
x0 = rect.left
w = rect.width
h = rect.height
r = rect
if not selected:
r = Rect(r)
r.bottom -= b
self.draw_tab_bg(surf, page, selected, r)
if b:
surf.fill(fg, (x0, 0, b, h))
surf.fill(fg, (x0 + b, 0, w - 2 * b, b))
surf.fill(fg, (x0 + w - b, 0, b, h))
buf = font.render(title, True, page.fg_color or fg)
r = buf.get_rect()
r.center = (x0 + w // 2, h // 2)
surf.blit(buf, r)
[docs] def iter_tabs(self):
pages = self.pages
current_page = self.current_page
n = len(pages)
b = self.tab_border_width
s = self.tab_spacing
h = self.tab_height
m = self.tab_margin
width = self.width - 2 * m + s - b
x0 = m
for i, page in enumerate(pages):
x1 = m + (i + 1) * width // n # self.tab_boundary(i + 1)
selected = page is current_page
yield i, page.tab_title, page, selected, Rect(x0, 0, x1 - x0 - s + b, h)
x0 = x1
[docs] def draw_tab_bg(self, surf, page, selected, rect):
bg = self.tab_bg_color_for_page(page)
if not selected:
bg = brighten(bg, self.tab_dimming)
surf.fill(bg, rect)
[docs] def tab_bg_color_for_page(self, page):
return getattr(page, 'tab_bg_color', None) \
or page.bg_color \
or self.default_tab_bg_color
[docs] def mouse_down(self, e):
x, y = e.local
if y < self.tab_height:
i = self.tab_number_containing_x(x)
if i is not None:
if self.current_page:
self.current_page.dispatch_attention_loss()
self.show_page(self.pages[i])
[docs] def tab_number_containing_x(self, x):
n = len(self.pages)
m = self.tab_margin
width = self.width - 2 * m + self.tab_spacing - self.tab_border_width
i = (x - m) * n // width
if 0 <= i < n:
return i
[docs] def gl_draw_self(self, root, offset):
self.gl_draw(root, offset)
[docs] def gl_draw(self, root, offset):
pages = self.pages
if len(pages) > 1:
tlcorner = (offset[0] + self.bottomleft[0], offset[1] + self.bottomleft[1])
current_page = self.current_page
n = len(pages)
b = self.tab_border_width
s = self.tab_spacing
h = self.tab_height
m = self.tab_margin
tabWidth = (self.size[0] - (s * n) - (2 * m)) / n
x0 = m + tlcorner[0]
font = self.tab_font
fg = self.tab_fg_color
surface = Surface(self.size, SRCALPHA)
glEnable(GL_BLEND)
for i, page in enumerate(pages):
x1 = x0 + tabWidth
selected = page is current_page
if selected:
glColor(1.0, 1.0, 1.0, 0.5)
else:
glColor(0.5, 0.5, 0.5, 0.5)
glRectf(x0, tlcorner[1] - (m + b), x1, tlcorner[1] - h)
buf = font.render(self.pages[i].tab_title, True, self.fg_color or fg)
r = buf.get_rect()
offs = ((tabWidth - r.size[0]) / 2) + m + ((s + tabWidth) * i)
surface.blit(buf, (offs, m))
x0 = x1 + s
data = image.tostring(surface, 'RGBA', 1)
rect = self.rect.move(offset)
w, h = root.size
glViewport(0, 0, w, h)
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
gluOrtho2D(0, w, 0, h)
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
glRasterPos2i(rect.left, h - rect.bottom)
glPushAttrib(GL_COLOR_BUFFER_BIT)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
glDrawPixels(self.width, self.height,
GL_RGBA, GL_UNSIGNED_BYTE, fromstring(data, dtype='uint8'))
glPopAttrib()
glFlush()
glDisable(GL_BLEND)