Richard Jones' Log

Mon, 25 Jun 2007
pyglet Vista tester requested

pyglet is rapidly approaching alpha release. The only thing left before release is to test the library on Vista - but neither Alex nor I have access to Vista.

Is there a Vista user out there who's willing to give the pyglet tests a run on their machine for us please?

It's remarkably hard to find anyone I know who has or even knows someone who has Vista installed.

Tue, 19 Jun 2007
GUI naming issue

There's a certain situation in GUIs where an element (e.g. a popup menu) wants to know when the user has clicked on something else other than the menu -- causing the menu to close.

Currently the mechanism in my framework has the menu element calling gui.registerParanoid(self) (gui being the top-level event handler) and if the condition is met then the gui invokes element.itsNotInYourHead().

Hrm :)

Update: Toby's pointed me in the direction of thinking about focus as a solution to the problem. That is, the menu is focused and when it loses focus it closes. That works for most other items too. There's a problem to solve (the menu has to stay alive when its children are focused) but it's not impossible.

category: Python | permanent link
Sun, 17 Jun 2007
Yes, Pong

Some have noticed the mention of my having added Pong to the gui designer I'm working on.

Currently the ball just bounces around the screen and off of any gui elements laid out. You can drag the toolbar (or any gui element) around as a paddle.

Once I've implemented Undo I'll have the ball destroy any gui elements it bounces off of - thus I'll need to change the name to Breakout.

I'll give the designers / players extra incentive by scoring how quickly they can demolish their design :)

The whole GUI framework and designer are coming along nicely. Stuff like sorting out a small bug in the interaction between the pyglet clock and my animations which resulted in a little jitter (Python 101: don't modify lists as you're iterating over them). I'm really looking forward to the first pyglet alpha release, and hope to move the gui framework into the pyglet svn around the same time.

Fri, 15 Jun 2007
A Bouncy bugfix and joystick release

I've just released a new version of my PyWeek entry Bouncy the Hungry Rabbit which has some bug fixes for the latest PyOpenGL.

Thanks, Paul Holt, for the patches! Enjoy!

category: Python | permanent link
Wed, 13 Jun 2007
Some updates

I'm still loving the new job. As part of it I've been developing a GUI framework which integrates with and uses some of the design patterns from pyglet. GUIs may be defined wholly in Python code or in a combination of Python and XML files. There's the beginnings of a GUI designer tool to create the XML files. A simple, dumb example:

<frame is_transparent="true">
 <frame is_transparent="true" id="left-frame" width="50%" height="100%">
  <vertical align="top" halign="center" padding="20">
   <frame scrollable="true" width="256" height="256" class="draggable">
    <image file="kitten.jpg" id="kitten" />
   </frame>
   <frame scrollable="true" width="128" height="128" class="draggable">
    <xhtml>
&lt;h1&gt;Synopsis&lt;/h1&gt;
&lt;p style="font-size:12px"&gt;Lorem ipsum dolor sit amet consectetuer
adipiscing elit. Suspendisse vel tellus. Nam sem massa, accumsan id,
sollicitudin at, feugiat non, felis. Etiam nunc. Nam augue mauris,
semper in, hendrerit vitae, congue viverra, massa. Suspendisse at lacus.
Proin mollis dui ut sem. Donec auctor, pede nec hendrerit tincidunt,
lacus diam laoreet diam, ut varius odio felis eget enim. Curabitur dui
sem, rutrum sed, mattis eu, rhoncus ultrices, erat. Maecenas eu tellus.
Vivamus bibendum facilisis orci. Aliquam risus. Aliquam erat. Aenean
dignissim fringilla diam. Quisque dapibus, nulla non consectetuer iaculis,
velit urna ornare orci, quis sodales neque sapien id turpis. Etiam urna
lacus, vulputate congue, vulputate in, aliquet vitae, tellus. Maecenas
sem. Ut sed massa. Etiam non ipsum eget nibh cursus placerat.
Vivamus at mauris.
&lt;/p&gt;
    </xhtml>
   </frame>
   <button class="draggable" text="Drag me, press me!" id="press-me" />
   <textinput value="Enter text" width="128" />
   <movie file="/Users/richard/Desktop/movies/Sunshine SD.mov" />
  </vertical>
 </frame>
 <frame class="droppable" width="50%" height="75%" x="512" y="128">
  <label>Drop here!</label>
 </frame>
</frame>

So this splits the window into two halves. On the left half we have a picture of a kitten (larger than the containing frame and scrollable), some XHMTL (again scrollable), a button to click, a text input field and a movie. Take note of the classes and ids, they're used...

And then some Python code to make this GUI do fun things:

from pyglet.window import *
from pyglet import clock
from pyglet.gl import *
from pyglet import media

import gui
from gui import event, dialog, dragndrop, anim

window = Window(width=1024, height=768, vsync=False)

gui = gui.GUI.fromXML(window, 'test_gui.xml')
window.push_handlers(gui)

@gui.select('frame')
def on_mouse_press(widget, x, y, buttons, modifiers):
    if not buttons & mouse.MOUSE_RIGHT_BUTTON: return event.EVENT_UNHANDLED
    def _f(*args):
        print 'Dialog returned', args
    dialog.FileDialog(gui, 'Select file to open', _f).run()
    return event.EVENT_HANDLED
  
gui.push_handlers(dragndrop.DragHandler('.draggable'))
 
@gui.select('button')
def on_click(widget, x, y, button, modifiers):
    print 'BUTTON PRESS', widget
    return event.EVENT_UNHANDLED

@gui.select('button#press-me', 'on_click')
def on_press_me(widget, x, y, button, modifiers):
    fr = widget.getGUI().getByID('left-frame')
    if fr.scale == 1.:
        anim.TranslateProperty(fr, 'scale', .5, duration=.5)
    else:
        anim.TranslateProperty(fr, 'scale', 1., duration=.5)
    return event.EVENT_UNHANDLED

@gui.select('.droppable')
def on_drop(widget, x, y, button, modifiers, element):
    element.reparent(widget)
    widget.bgcolor = (1, 1, 1, 1)
    return event.EVENT_HANDLED

@gui.select('.droppable')
def on_drag_enter(widget, x, y, element):
    widget.bgcolor = (.8, 1, .8, 1)
    return event.EVENT_HANDLED

@gui.select('.droppable')
def on_drag_leave(widget, x, y, element):
    widget.bgcolor = (1, 1, 1, 1)
    return event.EVENT_HANDLED

while not window.has_exit:
    clock.tick()
    window.dispatch_events()
    media.dispatch_events()

    glClearColor(.2, .2, .2, 1)
    glClear(GL_COLOR_BUFFER_BIT)
    gui.draw()

    window.flip()

So the fun bits of this code is where we assign behaviors to gui elements based on the CSS-style selectors. All items that are of class "draggable" are draggable, and the right-hand frame is designated a drop area. The kitten, XHTML and button are draggable into that frame. The frame highlights as you hold a dragged item over it. A right-mouse click will open a file dialog. A click on the "press me" button is fun - it scales the left-hand frame (smoothly animated and still fully interactive even during the animation).

I have permission to release this code, which I will eventually do once I have some spare tuits here at work. The designers here have just handed me some more storyboards to implement :)

Speaking of whom -- when they heard about the addition of "wet floor" to the OS X dock, the reaction was quite fun. They can be quite bitchy about designers over-using the latest cool effect (see also spiral logos suddenly abounding when Illustrator got the spiral tool). "Do Apple designers have a big red 'wet floor' button on their computer or something?"

Wet floor, anyone?