|
Programmer's Notebook |
All computer source code presented on this page, unless it includes attribution to another author, is provided by Ed Halley under the Artistic License. Use such code freely and without any expectation of support. I would like to know if you make anything cool with the code, or need questions answered.
python/ bindings.py boards.py buzz.py cache.py cards.py constraints.py english.py getopts.py gizmos.py goals.py improv.py interpolations.py namespaces.py nihongo.py nodes.py octalplus.py patterns.py persist.py physics.py pieces.py quizzes.py recipes.py relays.py romaji.py ropen.py sheets.py strokes.py subscriptions.py svgbuild.py testing.py things.py timing.py ucsv.py useful.py uuid.py vectors.py weighted.py java/ GlobFilenameFilter.java RegexFilenameFilter.java StringBufferOutputStream.java ThreadSet.java TracingThread.java Utf8ConsoleTest.java perl/ CVQM.pm Kana.pm Typo.pm cxx/ CCache.h equalish.cpp |
# gizmos - a very minimal gui widget set for the things/pygame libraries ''' A very minimal set of GUI widgets for the "things" framework and pygame. ABSTRACT Some games want to have a very customized look for their dialog boxes or other onscreen controls. Some applications using pygame cannot also use a more traditional widget toolkit such as GTK or Tk or Qt. This module is intended to fill these needs in a lightweight way. A "gizmo" is similar to a widget or control or field on a dialog box. Many gizmos are given direct access to simple variables by reference and apply their value changes immediately. No need to copy and access the values in and out of most gizmo types. A "slate" is akin to a dialog box or other frame window. Typically, one or more gizmos are set to follow a slate, then the slate is set to be a hyperspace (a space drawn atop another) for the current application space. When the interaction on the slate has been done, it segues to nothing, which makes it disappear. Slates and gizmos cooperate to figure out the space required, similar to the way most widget toolkits allow for layout and packing. AUTHOR Ed Halley (ed@halley.cc) 6 November 2007 ''' import goals ; from goals import * import things ; from things import * import pygame ; from pygame.locals import * #---------------------------------------------------------------------------- class Gizmo (Thing): def __init__(self): super(Gizmo, self).__init__() self.id = None self.caption = '' self.variable = None self.minsize = [20, 10] self.maxsize = [800, 480] def set_id(self, id): self.id = id def set_caption(self, text): self.caption = str(text) def set_variable(self, variable): self.variable = variable def visit(self, context): # alter my followers' positions to avoid conflict # get my unionrect # add my margins pass class TextGizmo (Gizmo): def __init__(self, text=''): super(TextGizmo, self).__init__() self.color = (0x00, 0x00, 0x00) self.dirty = True self.set_text(text) def set_text(self, text): self.text = str(text) self.dirty = True def append_text(self, text): self.text += str(text) self.dirty = True def visit(self, context): if not self.dirty: return self.layout(context) def layout(self, context): space = self.space() if not space: return font = getattr(space, 'font', None) if not font: return strings = self.text.split('\n') self.images = [ self.font.render(string, 1, self.color) for string in strings ] self.rects = [ image.get_rect() for image in self.images ] self.minsize = [0,0] for i in range(len(self.images)): height = self.rects[i].height self.rects[i].top = self.minsize[1] self.minsize[0] = max(self.minsize[0], self.rects[i].width) self.minsize[1] += height self.dirty = False def paint(self, surface): for i in range(len(self.images)): surface.blit(self.images[i], self.rects[i].topleft) class PressGizmo (Gizmo): def __init__(self, todo=None): super(PressGizmo, self).__init__() self.todo = todo def trigger(self): if callable(self.todo): todo = self.todo todo(self) class CheckGizmo (PressGizmo): def __init__(self, states=None): super(CheckGizmo, self).__init__() if states is None: states = [ 'off', 'on' ] self.states = states self.state = 0 def set_state(self, state): self.state = state % len(self.states) return self.states[self.state] def get_state(self): return self.states[self.state] class RadioGizmo (PressGizmo): def __init__(self): super(RadioGizmo, self).__init__() def get_peers(self): if not self.frame: return [ self ] cls = RadioGizmo id = self.id f = self.frame.followers() # should get gizmos in tab order peers = [ p for p in f if isinstance(f, cls) and f.id == id ] return peers class ArrayGizmo (Gizmo): def __init__(self, rows=1, cols=1): super(ArrayGizmo, self).__init__() self.kids = {} self.just = {} self.reset(rows, cols) def add(self, gizmo, where=None): if where is None: if self.rows > 1 and self.cols == 1: where = (self.rows+1,1) self.reset(*where) elif self.rows == 1 and self.cols > 1: where = (1,self.cols+1) self.reset(*where) else: raise ValueError, 'must supply row/column of new gizmo' def resize(self, rows=1, cols=1): self.rows = rows self.cols = cols self.heights = [0,] * self.rows self.widths = [0,] * self.cols self.packed = False def pack(self): self.reset() # visit every child to determine heights and widths self.packed = True def visit(self, context): if not self.packed: self.pack() # visit every child collecting their final positions #---------------------------------------------------------------------------- class Slate (Space): def __init__(self): super(Slate, self).__init__(VectorContext()) self.font = App.resource('FreeSans.ttf', 16) self.timeout = V(0.) self.add_goal(TimeGoal(self.timeout, V(1.), dt=5.0)) def event(self, event): super(Slate, self).event(event) def segue(self): if self.timeout[0] >= 1.: return None return super(Slate, self).segue() def background(self, surface): '''A slate has no background, as such.''' pass def visit(self, surface): super(Slate, self).visit(surface) def paint(self, surface): super(Slate, self).visit(surface) #---------------------------------------------------------------------------- class _TestSlate (Slate): def __init__(self): super(_TestSlate, self).__init__() self.color = (0xFF,0xFF,0x80) self.quit = False def modal(self): return True def segue(self): if self.quit: return None return self def paint(self, surface): super(_TestSlate, self).paint(surface) pygame.draw.circle(surface, self.color, (200,200), 50) def event(self, event): super(_TestSlate, self).event(event) if event.type == KEYDOWN: if event.key == K_SPACE: print 'switch color' self.color = (self.color[1], self.color[2], self.color[0]) if event.key == K_ESCAPE: self.quit = True class _TestSpace (Space): def __init__(self, *args): super(_TestSpace, self).__init__(*args) self.text = [ "Press Space to see a slate.", "Press Esc to quit." ] self.font = App.resource("FreeSans.ttf", 25) def show_slate(self): print "show_slate" t = _TestSlate() self.hyper = t pass def event(self, event): super(_TestSpace, self).event(event) if self.hyper and self.hyper.modal(): return if event.type == KEYDOWN: if event.key == K_SPACE: self.show_slate() def paint(self, surface): super(_TestSpace, self).paint(surface) y = 25 for line in self.text: text = self.font.render( line, 1, (0xFF,0xCC,0x66) ) surface.blit( text, (15, y) ) y += text.get_rect().height if __name__ == '__main__': app = App('Slates', (720, 420)) app.space = _TestSpace() app.run() |
|
Contact Ed Halley by email at
ed@halley.cc. Text, code, layout and artwork are Copyright © 1996-2008 Ed Halley. Copying in whole or in part, with author attribution, is expressly allowed. Any references to trademarks are illustrative and are controlled by their respective owners. |
|