This repository has been archived on 2024-06-13. You can view files and clone it, but cannot push or open issues or pull requests.
mcedit/albow/tab_panel.py
David Vierra 4680add658 Revert "Cleanup: Remove extra glFlush calls from a few places."
This reverts commit a8978445d3afde3a57b7c74ec7b829e19d1110bd.

Ought to fix issue #250
2013-01-16 14:32:51 -10:00

220 lines
7.0 KiB
Python

################################################################
#
# Albow - Tab Panel
#
################################################################
from OpenGL.GL import *
from OpenGL.GLU import *
from OpenGL.GLUT import *
from albow import *
from pygame import Rect, Surface, draw, image
from pygame.locals import SRCALPHA
from widget import Widget
from theme import ThemeProperty, FontProperty
from utils import brighten
from numpy import fromstring
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])
def content_size(self):
return self.width, self.height - self.tab_height
def content_rect(self):
return Rect((0, self.tab_height), self.content_size())
def page_height(self):
return self.height - self.tab_height
def add_page(self, title, page):
self._add_page(title, page)
if not self.current_page:
self.show_page(page)
def _add_page(self, title, page):
page.tab_title = title
page.anchor = 'ltrb'
self.pages.append(page)
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)
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()
def draw(self, surf):
self.draw_tab_area_bg(surf)
self.draw_tabs(surf)
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))
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)
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
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)
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
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:
self.show_page(self.pages[i])
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
def gl_draw_self(self, root, offset):
self.gl_draw(root, offset)
def gl_draw(self, root, offset):
pages = self.pages
if len(pages) > 1:
tlcorner = (offset[0] + self.bottomleft[0], offset[1] + self.bottomleft[1])
pageTabContents = []
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
width = self.width - 2 * m + s - b
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)