git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@46675 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
545 lines
21 KiB
Python
545 lines
21 KiB
Python
#----------------------------------------------------------------------------
|
|
# Name: wxroses.py
|
|
# Purpose: wxPython GUI using clroses.py to display a classic graphics
|
|
# hack.
|
|
#
|
|
# Author: Ric Werme, Robin Dunn.
|
|
# WWW: http://WermeNH.com/roses
|
|
#
|
|
# Created: June 2007
|
|
# CVS-ID: $Id$
|
|
# Copyright: Public Domain, please give credit where credit is due.
|
|
# License: Sorry, no EULA.
|
|
#----------------------------------------------------------------------------
|
|
|
|
# This module is responsible for everything involving GUI usage
|
|
# as clroses knows nothing about wxpython, tkintr, etc.
|
|
|
|
# There are some notes about how the Roses algorithm works in clroses.py,
|
|
# but the best reference should be at http://WermeNH.com/roses/index.html .
|
|
|
|
# There are a number of enhancements that could be done to wxRoses, and
|
|
# contributions are welcome as long as you don't destory the general
|
|
# structure, flavor, and all that. The following list is in the order
|
|
# I'd like to see done. Some are easy, some aren't, some are easy if
|
|
# you have experience in the right parts of external code.
|
|
|
|
# Brighter crossing points.
|
|
# Where many vectors cross, the display becomes washed out as a solid shape
|
|
# of light. On (antique) refresh vector graphics systems, crossing points
|
|
# are brighter because the electron beam paints the pixels multiple times.
|
|
# This gives complex patterns a lacy feel to some, and a 3-D sense to
|
|
# fluted shapes where vectors lie tangent to some curve. It would be
|
|
# nice to do the same in a bitmap buffer, the code to draw a vector is
|
|
# pretty simple, adding something that adds brightness to it via math or
|
|
# a lookup table ought to be a simple addition.
|
|
|
|
# Monochrome is so 20th century.
|
|
# There are a number of things that could be done with color. The simplest
|
|
# is to step through colors in a color list, better things to do would be
|
|
# for clroses.py to determine the length of an interesting "generator pattern,"
|
|
# e.g. the square in the opening display. Then it could change colors either
|
|
# every four vectors or cycle through the first four colors in the list.
|
|
|
|
# Bookmark that Rose!
|
|
# As you play with wxRoses, you'll come across some patterns that are
|
|
# "keepers." A bookmark mechanism would be handy.
|
|
|
|
# Save that Rose!
|
|
# It would be nice to have a Menu-bar/File/Save-as dialog to save a pattern
|
|
# as a jpg/png/gif file.
|
|
|
|
# Themes
|
|
# A pulldown option to select various themes is worthwhile. E.g.:
|
|
# Start an interesting animation,
|
|
# Select complex, lacy Roses,
|
|
# Select the author's favorites,
|
|
# Return to the initial Rose.
|
|
# Actually, all that's necessary are some pre-loaded bookmarks.
|
|
|
|
# Help text
|
|
# Standard fare, or:
|
|
|
|
# Slide show
|
|
# At CMU I created an interactive slide show that walked people through
|
|
# all the options and made suggestions about how to choose Style and Petal.
|
|
# I forget exactly what I said and may not have listings for it. At any rate,
|
|
# making the help mechanism start one of several "lessons" where it could
|
|
# control the display (without blocking the user's control) would be pretty
|
|
# straightforward.
|
|
|
|
import wx
|
|
import clroses
|
|
import wx.lib.colourselect as cs
|
|
|
|
|
|
# Class SpinPanel creates a control that includes both a StaticText widget
|
|
# which holds the the name of a parameter and a SpinCtrl widget which
|
|
# displays the current value. Values are set at initialization and can
|
|
# change via the SpinCtrl widget or by the program. So that the program
|
|
# can easily access the SpinCtrl, the SpinPanel handles are saved in the
|
|
# spin_panels dictionary.
|
|
class SpinPanel(wx.Panel):
|
|
def __init__(self, parent, name, min_value, value, max_value, callback):
|
|
wx.Panel.__init__(self, parent, -1)
|
|
if "wxMac" in wx.PlatformInfo:
|
|
self.SetWindowVariant(wx.WINDOW_VARIANT_SMALL)
|
|
self.st = wx.StaticText(self, -1, name)
|
|
self.sc = wx.SpinCtrl(self, -1, "", size = (70, -1))
|
|
self.sc.SetRange(min_value, max_value)
|
|
self.sc.SetValue(value)
|
|
self.sc.Bind(wx.EVT_SPINCTRL, self.OnSpin)
|
|
self.callback = callback
|
|
|
|
sizer = wx.BoxSizer(wx.HORIZONTAL)
|
|
sizer.Add(self.st, 0, wx.ALIGN_CENTER_VERTICAL)
|
|
sizer.Add((1,1), 1)
|
|
sizer.Add(self.sc)
|
|
self.SetSizer(sizer)
|
|
|
|
global spin_panels
|
|
spin_panels[name] = self
|
|
|
|
# Called (generally through spin_panels{}) to set the SpinCtrl value.
|
|
def SetValue(self, value):
|
|
self.sc.SetValue(value)
|
|
|
|
# Called when user changes the SpinCtrl value.
|
|
def OnSpin(self, event):
|
|
name = self.st.GetLabel()
|
|
value = self.sc.GetValue()
|
|
if verbose:
|
|
print 'OnSpin', name, '=', value
|
|
self.callback(name, value) # Call MyFrame.OnSpinback to call clroses
|
|
|
|
|
|
# This class is used to display the current rose diagram. It keeps a
|
|
# buffer bitmap of the current display, which it uses to refresh the
|
|
# screen with when needed. When it is told to draw some lines it does
|
|
# so to the buffer in order for it to always be up to date.
|
|
class RosePanel(wx.Panel):
|
|
def __init__(self, *args, **kw):
|
|
wx.Panel.__init__(self, *args, **kw)
|
|
self.InitBuffer()
|
|
self.resizeNeeded = False
|
|
self.useGCDC = False
|
|
self.useBuffer = True
|
|
|
|
# set default colors
|
|
self.SetBackgroundColour((51, 51, 51)) # gray20
|
|
self.SetForegroundColour((164, 211, 238)) # lightskyblue2
|
|
|
|
# connect the size and paint events to handlers
|
|
self.Bind(wx.EVT_SIZE, self.OnSize)
|
|
self.Bind(wx.EVT_PAINT, self.OnPaint)
|
|
self.Bind(wx.EVT_IDLE, self.OnIdle)
|
|
|
|
|
|
def InitBuffer(self):
|
|
size = self.GetClientSize()
|
|
self.buffer = wx.EmptyBitmap(max(1, size.width),
|
|
max(1, size.height))
|
|
|
|
def Clear(self):
|
|
dc = self.useBuffer and wx.MemoryDC(self.buffer) or wx.ClientDC(self)
|
|
dc.SetBackground(wx.Brush(self.GetBackgroundColour()))
|
|
dc.Clear()
|
|
if self.useBuffer:
|
|
self.Refresh(False)
|
|
|
|
def DrawLines(self, lines):
|
|
if len(lines) <= 1:
|
|
return
|
|
dc = self.useBuffer and wx.MemoryDC(self.buffer) or wx.ClientDC(self)
|
|
if self.useGCDC:
|
|
dc = wx.GCDC(dc)
|
|
dc.SetPen(wx.Pen(self.GetForegroundColour(), 1))
|
|
dc.DrawLines(lines)
|
|
if self.useBuffer:
|
|
self.Refresh(False)
|
|
|
|
def TriggerResize(self):
|
|
self.GetParent().TriggerResize(self.buffer.GetSize())
|
|
|
|
def TriggerRedraw(self):
|
|
self.GetParent().TriggerRedraw()
|
|
|
|
def OnSize(self, evt):
|
|
self.resizeNeeded = True
|
|
|
|
def OnIdle(self, evt):
|
|
if self.resizeNeeded:
|
|
self.InitBuffer()
|
|
self.TriggerResize()
|
|
if self.useBuffer:
|
|
self.Refresh()
|
|
self.resizeNeeded = False
|
|
|
|
def OnPaint(self, evt):
|
|
dc = wx.PaintDC(self)
|
|
if self.useBuffer:
|
|
dc.DrawBitmap(self.buffer, 0,0)
|
|
else:
|
|
self.TriggerRedraw()
|
|
|
|
|
|
# A panel used to collect options on how the rose is drawn
|
|
class OptionsPanel(wx.Panel):
|
|
def __init__(self, parent, rose):
|
|
wx.Panel.__init__(self, parent)
|
|
self.rose = rose
|
|
sizer = wx.StaticBoxSizer(wx.StaticBox(self, label='Options'),
|
|
wx.VERTICAL)
|
|
self.useGCDC = wx.CheckBox(self, label="Use GCDC")
|
|
sizer.Add(self.useGCDC, 0, wx.BOTTOM|wx.LEFT, 2)
|
|
self.useBuffer = wx.CheckBox(self, label="Use buffering")
|
|
sizer.Add(self.useBuffer, 0, wx.BOTTOM|wx.LEFT, 2)
|
|
|
|
def makeCButton(label):
|
|
btn = cs.ColourSelect(self, size=(20,22))
|
|
lbl = wx.StaticText(self, -1, label)
|
|
sizer = wx.BoxSizer(wx.HORIZONTAL)
|
|
sizer.Add(btn)
|
|
sizer.Add((4,4))
|
|
sizer.Add(lbl, 0, wx.ALIGN_CENTER_VERTICAL)
|
|
return sizer, btn
|
|
|
|
s, self.fg = makeCButton('Foreground')
|
|
sizer.Add(s)
|
|
s, self.bg = makeCButton('Background')
|
|
sizer.Add(s)
|
|
self.SetSizer(sizer)
|
|
|
|
self.Bind(wx.EVT_CHECKBOX, self.OnUseGCDC, self.useGCDC)
|
|
self.Bind(wx.EVT_CHECKBOX, self.OnUseBuffer, self.useBuffer)
|
|
self.Bind(wx.EVT_IDLE, self.OnIdle)
|
|
self.Bind(cs.EVT_COLOURSELECT, self.OnSetFG, self.fg)
|
|
self.Bind(cs.EVT_COLOURSELECT, self.OnSetBG, self.bg)
|
|
|
|
def OnIdle(self, evt):
|
|
if self.useGCDC.GetValue() != self.rose.useGCDC:
|
|
self.useGCDC.SetValue(self.rose.useGCDC)
|
|
if self.useBuffer.GetValue() != self.rose.useBuffer:
|
|
self.useBuffer.SetValue(self.rose.useBuffer)
|
|
if self.fg.GetValue() != self.rose.GetForegroundColour():
|
|
self.fg.SetValue(self.rose.GetForegroundColour())
|
|
if self.bg.GetValue() != self.rose.GetBackgroundColour():
|
|
self.bg.SetValue(self.rose.GetBackgroundColour())
|
|
|
|
def OnUseGCDC(self, evt):
|
|
self.rose.useGCDC = evt.IsChecked()
|
|
self.rose.TriggerRedraw()
|
|
|
|
def OnUseBuffer(self, evt):
|
|
self.rose.useBuffer = evt.IsChecked()
|
|
self.rose.TriggerRedraw()
|
|
|
|
def OnSetFG(self, evt):
|
|
self.rose.SetForegroundColour(evt.GetValue())
|
|
self.rose.TriggerRedraw()
|
|
|
|
def OnSetBG(self, evt):
|
|
self.rose.SetBackgroundColour(evt.GetValue())
|
|
self.rose.TriggerRedraw()
|
|
|
|
|
|
# MyFrame is the traditional class name to create and populate the
|
|
# application's frame. The general GUI has control/status panels on
|
|
# the right side and a panel on the left side that draws the rose
|
|
#
|
|
# This class also derives from clroses.rose so it can implement the
|
|
# required interfaces to connect the GUI to the rose engine.
|
|
class MyFrame(wx.Frame, clroses.rose):
|
|
# Color matching dictionary, convert label name to color:
|
|
# Stop and Go ala traffic lights,
|
|
# Skip and Forward look ahead to the purple mountain majesties (really bluish),
|
|
# Reverse and Backward look morosely behind to maroon memories,
|
|
# Redraw looks at the brown earth right below your feet.
|
|
# Yeah, so it's lame. All I really wanted was to color Stop and Go.
|
|
labelColours = {
|
|
'Go': 'dark green', 'Stop': 'red',
|
|
'Redraw': 'brown', 'Skip': 'dark slate blue',
|
|
'Backward': 'maroon', 'Forward': 'dark slate blue', 'Reverse': 'maroon'
|
|
}
|
|
|
|
def __init__(self):
|
|
def makeSP(name, labels, statictexts = None):
|
|
panel = wx.Panel(self.side_panel, -1)
|
|
box = wx.StaticBox(panel, -1, name)
|
|
sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
|
|
for name, min_value, value, max_value in labels:
|
|
sp = SpinPanel(panel, name, min_value, value, max_value, self.OnSpinback)
|
|
sizer.Add(sp, 0, wx.EXPAND)
|
|
if statictexts:
|
|
for name, text in statictexts:
|
|
st = wx.StaticText(panel, -1, text)
|
|
spin_panels[name] = st # Supposed to be a SpinPanel....
|
|
sizer.Add(st, 0, wx.EXPAND)
|
|
panel.SetSizer(sizer)
|
|
return panel
|
|
|
|
wx.Frame.__init__(self, None, title="Roses in wxPython")
|
|
|
|
self.rose_panel = RosePanel(self)
|
|
self.side_panel = wx.Panel(self)
|
|
|
|
# The cmd panel is four buttons whose names and foreground colors
|
|
# change. Plop them in a StaticBox like the SpinPanels. Use
|
|
# a 2x2 grid, but StaticBoxSizer can't handle that. Therefore,
|
|
# create a sub panel, layout the buttons there, then give that to
|
|
# a higher panel that has the static box stuff.
|
|
self.cmd_panel = wx.Panel(self.side_panel, -1)
|
|
self.sub_panel = wx.Panel(self.cmd_panel, -1)
|
|
sizer = wx.GridSizer(rows = 2, cols = 2)
|
|
global ctrl_buttons
|
|
border = 'wxMac' in wx.PlatformInfo and 3 or 1
|
|
for name, handler in (
|
|
('Go', self.OnGoStop),
|
|
('Redraw', self.OnRedraw),
|
|
('Backward', self.OnBackward),
|
|
('Forward', self.OnForward)):
|
|
button = wx.Button(self.sub_panel, -1, name)
|
|
button.SetForegroundColour(self.labelColours[name])
|
|
ctrl_buttons[name] = button
|
|
button.Bind(wx.EVT_BUTTON, handler)
|
|
sizer.Add(button, 0, wx.EXPAND|wx.ALL, border)
|
|
self.sub_panel.SetSizer(sizer)
|
|
|
|
# Set up cmd_panel with StaticBox stuff
|
|
box = wx.StaticBox(self.cmd_panel, -1, 'Command')
|
|
sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
|
|
sizer.Add(self.sub_panel)
|
|
self.cmd_panel.SetSizer(sizer)
|
|
|
|
# Now make the rest of the control panels...
|
|
# The order of creation of SpinCtrls and Buttons is the order that
|
|
# the tab key will step through, so the order of panel creation is
|
|
# important.
|
|
# In the SpinPanel data (name, min, value, max), value will be
|
|
# overridden by clroses.py defaults.
|
|
self.coe_panel = makeSP('Coefficient',
|
|
(('Style', 0, 100, 3600),
|
|
('Sincr', -3600, -1, 3600),
|
|
('Petal', 0, 2, 3600),
|
|
('Pincr', -3600, 1, 3600)))
|
|
|
|
self.vec_panel = makeSP('Vector',
|
|
(('Vectors' , 1, 399, 3600),
|
|
('Minimum' , 1, 1, 3600),
|
|
('Maximum' , 1, 3600, 3600),
|
|
('Skip first', 0, 0, 3600),
|
|
('Draw only' , 1, 3600, 3600)),
|
|
(('Takes', 'Takes 0000 vectors'), ))
|
|
|
|
self.tim_panel = makeSP('Timing',
|
|
(('Vec/tick' , 1, 20, 3600),
|
|
('msec/tick', 1, 50, 1000),
|
|
('Delay' , 1, 2000, 9999)))
|
|
|
|
self.opt_panel = OptionsPanel(self.side_panel, self.rose_panel)
|
|
|
|
# put them all on in a sizer attached to the side_panel
|
|
panelSizer = wx.BoxSizer(wx.VERTICAL)
|
|
panelSizer.Add(self.cmd_panel, 0, wx.EXPAND|wx.TOP|wx.LEFT|wx.RIGHT, 5)
|
|
panelSizer.Add(self.coe_panel, 0, wx.EXPAND|wx.TOP|wx.LEFT|wx.RIGHT, 5)
|
|
panelSizer.Add(self.vec_panel, 0, wx.EXPAND|wx.TOP|wx.LEFT|wx.RIGHT, 5)
|
|
panelSizer.Add(self.tim_panel, 0, wx.EXPAND|wx.TOP|wx.LEFT|wx.RIGHT, 5)
|
|
panelSizer.Add(self.opt_panel, 0, wx.EXPAND|wx.TOP|wx.LEFT|wx.RIGHT, 5)
|
|
self.side_panel.SetSizer(panelSizer)
|
|
|
|
# and now arrange the two main panels in another sizer for the frame
|
|
mainSizer = wx.BoxSizer(wx.HORIZONTAL)
|
|
mainSizer.Add(self.rose_panel, 1, wx.EXPAND)
|
|
mainSizer.Add(self.side_panel, 0, wx.EXPAND)
|
|
self.SetSizer(mainSizer)
|
|
|
|
# bind event handlers
|
|
self.timer = wx.Timer(self)
|
|
self.Bind(wx.EVT_TIMER, self.OnTimer, self.timer)
|
|
|
|
# Determine appropriate image size.
|
|
# At this point, the rose_panel and side_panel will both report
|
|
# size (20, 20). After mainSizer.Fit(self) they will report the
|
|
# same, but the Frame size, self.GetSize(), will report the desired
|
|
# side panel dimensions plus an extra 20 on the width. That lets
|
|
# us determine the frame size that will display the side panel and
|
|
# a square space for the diagram. Only after Show() will the two
|
|
# panels report the accurate sizes.
|
|
mainSizer.Fit(self)
|
|
rw, rh = self.rose_panel.GetSize()
|
|
sw, sh = self.side_panel.GetSize()
|
|
fw, fh = self.GetSize()
|
|
h = max(600, fh) # Change 600 to desired minimum size
|
|
w = h + fw - rw
|
|
if verbose:
|
|
print 'rose panel size', (rw, rh)
|
|
print 'side panel size', (sw, sh)
|
|
print ' frame size', (fw, fh)
|
|
print 'Want size', (w,h)
|
|
self.SetSize((w, h))
|
|
self.SupplyControlValues() # Ask clroses to tell us all the defaults
|
|
self.Show()
|
|
|
|
# Command button event handlers. These are relabled when changing between auto
|
|
# and manual modes. They simply reflect the call to a method in the base class.
|
|
#
|
|
# Go/Stop button
|
|
def OnGoStop(self, event):
|
|
if verbose:
|
|
print 'OnGoStop'
|
|
self.cmd_go_stop()
|
|
|
|
# Redraw/Redraw
|
|
def OnRedraw(self, event):
|
|
if verbose:
|
|
print 'OnRedraw'
|
|
self.cmd_redraw()
|
|
|
|
# Backward/Reverse
|
|
def OnBackward(self, event):
|
|
if verbose:
|
|
print 'OnBackward'
|
|
self.cmd_backward()
|
|
|
|
# Forward/Skip
|
|
def OnForward(self, event):
|
|
if verbose:
|
|
print 'OnForward'
|
|
self.cmd_step()
|
|
|
|
|
|
# The clroses.roses class expects to have methods available that
|
|
# implement the missing parts of the functionality needed to do
|
|
# the actual work of getting the diagram to the screen and etc.
|
|
# Those are implemented here as the App* methods.
|
|
|
|
def AppClear(self):
|
|
if verbose:
|
|
print 'AppClear: clear screen'
|
|
self.rose_panel.Clear()
|
|
|
|
def AppCreateLine(self, line):
|
|
# print 'AppCreateLine, len', len(line), 'next', self.nextpt
|
|
self.rose_panel.DrawLines(line)
|
|
|
|
# Here when clroses has set a new style and/or petal value, update
|
|
# strings on display.
|
|
def AppSetParam(self, style, petals, vectors):
|
|
spin_panels['Style'].SetValue(style)
|
|
spin_panels['Petal'].SetValue(petals)
|
|
spin_panels['Vectors'].SetValue(vectors)
|
|
|
|
def AppSetIncrs(self, sincr, pincr):
|
|
spin_panels['Sincr'].SetValue(sincr)
|
|
spin_panels['Pincr'].SetValue(pincr)
|
|
|
|
def AppSetVectors(self, vectors, minvec, maxvec, skipvec, drawvec):
|
|
spin_panels['Vectors'].SetValue(vectors)
|
|
spin_panels['Minimum'].SetValue(minvec)
|
|
spin_panels['Maximum'].SetValue(maxvec)
|
|
spin_panels['Skip first'].SetValue(skipvec)
|
|
spin_panels['Draw only'].SetValue(drawvec)
|
|
|
|
def AppSetTakesVec(self, takes):
|
|
spin_panels['Takes'].SetLabel('Takes %d vectors' % takes)
|
|
|
|
# clroses doesn't change this data, so it's not telling us something
|
|
# we don't already know.
|
|
def AppSetTiming(self, vecPtick, msecPtick, delay):
|
|
spin_panels['Vec/tick'].SetValue(vecPtick)
|
|
spin_panels['msec/tick'].SetValue(msecPtick)
|
|
spin_panels['Delay'].SetValue(delay)
|
|
|
|
# Command buttons change their names based on the whether we're in auto
|
|
# or manual mode.
|
|
def AppCmdLabels(self, labels):
|
|
for name, label in map(None, ('Go', 'Redraw', 'Backward', 'Forward'), labels):
|
|
ctrl_buttons[name].SetLabel(label)
|
|
ctrl_buttons[name].SetForegroundColour(self.labelColours[label])
|
|
|
|
|
|
# Timer methods. The paranoia about checking up on the callers is
|
|
# primarily because it's easier to check here. We expect that calls to
|
|
# AppAfter and OnTimer alternate, but don't verify that AppCancelTimer()
|
|
# is canceling anything as callers of that may be uncertain about what's
|
|
# happening.
|
|
|
|
# Method to provide a single callback after some amount of time.
|
|
def AppAfter(self, msec, callback):
|
|
if self.timer_callback:
|
|
print 'AppAfter: timer_callback already set!',
|
|
# print 'AppAfter:', callback
|
|
self.timer_callback = callback
|
|
self.timer.Start(msec, True)
|
|
|
|
# Method to cancel something we might be waiting for but have lost
|
|
# interest in.
|
|
def AppCancelTimer(self):
|
|
self.timer.Stop()
|
|
# print 'AppCancelTimer'
|
|
self.timer_callback = None
|
|
|
|
# When the timer happens, we come here and jump off to clroses internal code.
|
|
def OnTimer(self, evt):
|
|
callback = self.timer_callback
|
|
self.timer_callback = None
|
|
# print 'OnTimer,', callback
|
|
if callback:
|
|
callback() # Often calls AppAfter() and sets the callback
|
|
else:
|
|
print 'OnTimer: no callback!'
|
|
|
|
|
|
resize_delay = 300
|
|
|
|
def TriggerResize(self, size):
|
|
self.resize(size, self.resize_delay)
|
|
self.resize_delay = 100
|
|
|
|
def TriggerRedraw(self):
|
|
self.repaint(10)
|
|
|
|
# Called when data in spin boxes changes.
|
|
def OnSpinback(self, name, value):
|
|
if verbose:
|
|
print 'OnSpinback', name, value
|
|
if name == 'Style':
|
|
self.SetStyle(value)
|
|
elif name == 'Sincr':
|
|
self.SetSincr(value)
|
|
elif name == 'Petal':
|
|
self.SetPetals(value)
|
|
elif name == 'Pincr':
|
|
self.SetPincr(value)
|
|
|
|
elif name == 'Vectors':
|
|
self.SetVectors(value)
|
|
elif name == 'Minimum':
|
|
self.SetMinVec(value)
|
|
elif name == 'Maximum':
|
|
self.SetMaxVec(value)
|
|
elif name == 'Skip first':
|
|
self.SetSkipFirst(value)
|
|
elif name == 'Draw only':
|
|
self.SetDrawOnly(value)
|
|
|
|
elif name == 'Vec/tick':
|
|
self.SetStep(value)
|
|
elif name == 'msec/tick':
|
|
self.SetDrawDelay(value)
|
|
elif name == 'Delay':
|
|
self.SetWaitDelay(value)
|
|
else:
|
|
print 'OnSpinback: Don\'t recognize', name
|
|
|
|
verbose = 0 # Need some command line options...
|
|
spin_panels = {} # Hooks to get from rose to panel labels
|
|
ctrl_buttons = {} # Button widgets for command (NE) panel
|
|
|
|
app = wx.App(False)
|
|
MyFrame()
|
|
if verbose:
|
|
print 'spin_panels', spin_panels.keys()
|
|
print 'ctrl_buttons', ctrl_buttons.keys()
|
|
app.MainLoop()
|