############################################################################# ## This file is part of TunnelHack II. ## ##-------------------------------------------------------------------------## ## Copyright 2007-2008 Bryce Schroeder ## ## bryce.schroeder@gmail.com ## ## http://www.ferazelhosting.net/~bryce/ ## ##-------------------------------------------------------------------------## ## This program is free software: you can redistribute it and/or modify ## ## it under the terms of the GNU General Public License as published by ## ## the Free Software Foundation, either version 3 of the License, or ## ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## ## along with this program. If not, see . ## ############################################################################# from .interface import IObj from .g import g class IWindow(IObj): """ An IWindow is a basic window class. You can move it about, put widgets in it, and so forth. """ def render_self(self, theme, target, px, py): if self.window_focused: self.draw_rect((3, 2), target, px, py, self.p.w, self.p.h) else: self.draw_rect((0, 2), target, px, py, self.p.w, self.p.h) if self.p.movable: self.archon.theme.blit((0 if not self.window_focused else 1,0),target, (self.p.w-1)*16,16*(self.p.h/2)) return True def render_overlay(self, theme, target, px, py): if not self.window_manager: return mf = self.window_manager.has_modal_focus() if mf and not mf is self: self.draw_rect((6, 2), target, px, py, self.p.w, self.p.h) def release_focus(self): return not bool(self.mouse_follow) #def accept_click(self, x, y): # return self.rect.collidepoint(x,y) #def handle_click(self, lx, ly): # #def accept_unclick(self, x, y): # return True # THIS DOESN'T WORK - see comment on archon's getting events. #def handle_unclick(self, lx, ly): # if self.p.get('movable', False): # if self.mouse_follow: # self.mouse_follow = None # else: # self.mouse_follow = lx,ly class ITabbedWindow(IWindow): """ A window with tabs. takes a parameter tabs=['firstone', 'gnu'] or whatever. The first tab is the default and leftmost. Clicking the tab switches to it. The tabbedwindow should contain only frame/container objects representing the tab contents. Only one will be active at a time. """ class ITabbedWindowTab(IObj): def init(self): self.p.sticky = True self.link = self.p.link self.linkmsg = self.p.linkmsg font = g.resources.get('Font', self.p.get('font', 'Junicode')).pygame_font( self.p.get('size', 12)) self.radio_group = self.p.radio_group self.text_surf = font.render(self.p.text, 1, self.p.color) self.p.w = self.text_surf.get_width()/16 + 2 self.base_my = (self.p.h * 16 - font.get_height() - 1) / 2 self.compute_rect() def handle_click(self, lx, ly): pass#self.set_state(self.CLICKED) def handle_click(self, lx, ly): for button in self.radio_group: if not button is self: button.set_state(self.NORMAL) else: button.set_state(self.CLICKED) self.link.get_message(self.linkmsg) def render_self(self, theme, target, px, py): theme.blit(0x55-(5 if self.state in [self.CLICKED,self.TOGGLED] else 0), target, px, py) for x in xrange(1, self.p.w-1): theme.blit(0x65-(5 if self.state in [self.CLICKED,self.TOGGLED] else 0), target, px+16*x, py) theme.blit(0x75-(5 if self.state in [self.CLICKED,self.TOGGLED] else 0), target, px+16*(self.p.w-1), py) target.blit(self.text_surf, (px + (self.p.w*16 - self.text_surf.get_width())/2, py + self.base_my)) def init(self): self.tabs = [] font = g.resources.get('Font', self.p.get('font', 'Junicode')) self.font = font.pygame_font(self.p.get('size', 12)) self.tabtext = [] for tab in self.p.get('tabs', []): self.tabtext.append(self.font.render(tab, 1, self.p.color)) def load(self): prev = None self.tabbuttons = [] for tab in self.p.get('tabs',[]): xpos = prev.p.w + xpos if prev else 0 prev = self.ITabbedWindowTab(self, link=self, linkmsg=tab, text=tab, y=0, x=xpos, auto=True, radio_group = self.tabbuttons, color = self.p.get('tab_color', (100,100,100))) self.tabbuttons.append(prev) self.tabs_width = xpos def add(self, child): """ Add a tab or button. """ if isinstance(child, self.ITabbedWindowTab): self.contents.append(child) else: self.tabs.append(child) def switch_tab(self, index): self.contents[-1] = self.tabs[index] self.dirty_all() def get_message(self, msg): self.switch_tab(self.p.tabs.index(msg)) def finish(self): self.contents.append(self.tabs[0]) self.tabbuttons[0].state = self.CLICKED def render_self(self, theme, target, px, py): theme_blit = theme.blit x = 0 #for tab self.p.tabs: # x += self.render_tab(x) # ^^ tabs are now buttons. self.draw_rect((9,2), target, px, py+16, self.p.w, self.p.h-1, False) for x in xrange(self.tabs_width, self.p.w): theme_blit(0x80, target, x*16 + px, py) return True class IFrame(IObj): """ An IWindow is a frame meant to be put inside in a window, useful for spatial organization of stuff. If the parameter visible=False is passed, it will be invisible. This is useful for frames used in tabbed windows. """ def render_self(self, theme, target, px, py): if not self.p.get('visible', True): return True theme_blit = theme.blit # THIS COULD BE LESS UGLY perhaps self.draw_rect((6,2), target, px, py, self.p.w, self.p.h, False) return True