Layout and other tweaks/fixes from Ric

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/branches/WX_2_8_BRANCH@46586 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Robin Dunn
2007-06-21 15:19:49 +00:00
parent 18be86b20b
commit 6c474d6a46
2 changed files with 132 additions and 56 deletions

View File

@@ -103,7 +103,7 @@ class rose:
line = [] line = []
stop = self.nextpt + self.step stop = self.nextpt + self.step
keep_running = True keep_running = True
if stop > self.endpt: if stop >= self.endpt:
stop = self.endpt stop = self.endpt
keep_running = False keep_running = False
for i in range (self.nextpt, stop + 1): for i in range (self.nextpt, stop + 1):
@@ -122,10 +122,13 @@ class rose:
self.sin_table = [sin(2.0 * pi * i / vectors) for i in range(vectors)] self.sin_table = [sin(2.0 * pi * i / vectors) for i in range(vectors)]
self.cos_table = [cos(2.0 * pi * i / vectors) for i in range(vectors)] self.cos_table = [cos(2.0 * pi * i / vectors) for i in range(vectors)]
# Rescale (x,y) data to match our window. # Rescale (x,y) data to match our window. Note the negative scaling in the
# Y direction, this compensates for Y moving down the screen, but up on
# graph paper.
def rescale(self, line, offset, scale): def rescale(self, line, offset, scale):
for i in range(len(line)): for i in range(len(line)):
line[i] = (line[i][0] * scale + offset[0], line[i][1] * scale + offset[1]) line[i] = (line[i][0] * scale + offset[0],
line[i][1] * (-scale) + offset[1])
return line return line
# Euler's Method for computing the greatest common divisor. Knuth's # Euler's Method for computing the greatest common divisor. Knuth's
@@ -213,40 +216,34 @@ class rose:
self.next() self.next()
return self.restart() return self.restart()
# Stop/Redraw button. # Go/Stop button.
def cmd_stop(self): def cmd_go_stop(self):
if self.cmd_state == self.CMD_STOP:
self.restart() # Redraw current pattern
elif self.cmd_state == self.CMD_GO:
self.cmd_state = self.CMD_STOP
self.update_labels()
# Skip/Forward button. CMD_STOP & CMD_GO both just call resume.
def cmd_step(self):
# print 'cmd_step, cmd_state', self.cmd_state
self.resume() # Draw next pattern
# Go/Redraw button
def cmd_go(self):
if self.cmd_state == self.CMD_STOP: if self.cmd_state == self.CMD_STOP:
self.cmd_state = self.CMD_GO self.cmd_state = self.CMD_GO
self.update_labels()
self.resume() # Draw next pattern self.resume() # Draw next pattern
elif self.cmd_state == self.CMD_GO: elif self.cmd_state == self.CMD_GO:
self.restart() # Redraw current pattern self.cmd_state = self.CMD_STOP
self.update_labels()
# Centralize button naming to share with initialization. # Centralize button naming to share with initialization.
# Leave colors to the application (assuming it cares), we can't guess
# what's available.
def update_labels(self): def update_labels(self):
if self.cmd_state == self.CMD_STOP: if self.cmd_state == self.CMD_STOP:
self.AppCmdLabels(('Redraw', 'Forward', 'Go', 'Back')) self.AppCmdLabels(('Go', 'Redraw', 'Backward', 'Forward'))
else: # Must be in state CMD_GO else: # Must be in state CMD_GO
self.AppCmdLabels(('Stop', 'Skip', 'Redraw', 'Reverse')) self.AppCmdLabels(('Stop', 'Redraw', 'Reverse', 'Skip'))
# Reverse button. Useful for when you see an interesting pattern and want # Redraw/Redraw button
def cmd_redraw(self):
self.restart() # Redraw current pattern
# Backward/Reverse button
# Useful for when you see an interesting pattern and want
# to go back to it. If running, just change direction. If stopped, back # to go back to it. If running, just change direction. If stopped, back
# up one step. The resume code handles the step, then we change the # up one step. The resume code handles the step, then we change the
# incrementers back to what they were. (Unless resume changed them too.) # incrementers back to what they were. (Unless resume changed them too.)
def cmd_reverse(self): def cmd_backward(self):
self.sincr = -self.sincr self.sincr = -self.sincr
self.pincr = -self.pincr self.pincr = -self.pincr
if self.cmd_state == self.CMD_STOP: if self.cmd_state == self.CMD_STOP:
@@ -256,6 +253,10 @@ class rose:
else: else:
self.AppSetIncrs(self.sincr, self.pincr) self.AppSetIncrs(self.sincr, self.pincr)
# Forward/Skip button. CMD_STOP & CMD_GO both just call resume.
def cmd_step(self):
self.resume() # Draw next pattern
# Handler called on each timer event. This handles the metered drawing # Handler called on each timer event. This handles the metered drawing
# of a rose and the delays between them. It also registers for the next # of a rose and the delays between them. It also registers for the next
# timer event unless we're idle (rose is done and the delay between # timer event unless we're idle (rose is done and the delay between

View File

@@ -15,6 +15,59 @@
# This module is responsible for everything involving GUI usage # This module is responsible for everything involving GUI usage
# as clroses knows nothing about wxpython, tkintr, etc. # 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 wx
import clroses import clroses
import wx.lib.colourselect as cs import wx.lib.colourselect as cs
@@ -73,7 +126,7 @@ class RosePanel(wx.Panel):
self.useBuffer = True self.useBuffer = True
# set default colors # set default colors
self.SetBackgroundColour((51,51,51)) # gray20 self.SetBackgroundColour((51, 51, 51)) # gray20
self.SetForegroundColour((164, 211, 238)) # lightskyblue2 self.SetForegroundColour((164, 211, 238)) # lightskyblue2
# connect the size and paint events to handlers # connect the size and paint events to handlers
@@ -151,9 +204,9 @@ class OptionsPanel(wx.Panel):
sizer.Add(lbl, 0, wx.ALIGN_CENTER_VERTICAL) sizer.Add(lbl, 0, wx.ALIGN_CENTER_VERTICAL)
return sizer, btn return sizer, btn
s, self.fg = makeCButton('foreground') s, self.fg = makeCButton('Foreground')
sizer.Add(s) sizer.Add(s)
s, self.bg = makeCButton('background') s, self.bg = makeCButton('Background')
sizer.Add(s) sizer.Add(s)
self.SetSizer(sizer) self.SetSizer(sizer)
@@ -197,6 +250,18 @@ class OptionsPanel(wx.Panel):
# This class also derives from clroses.rose so it can implement the # This class also derives from clroses.rose so it can implement the
# required interfaces to connect the GUI to the rose engine. # required interfaces to connect the GUI to the rose engine.
class MyFrame(wx.Frame, clroses.rose): 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 __init__(self):
def makeSP(name, labels, statictexts = None): def makeSP(name, labels, statictexts = None):
panel = wx.Panel(self.side_panel, -1) panel = wx.Panel(self.side_panel, -1)
@@ -219,22 +284,31 @@ class MyFrame(wx.Frame, clroses.rose):
self.side_panel = wx.Panel(self) self.side_panel = wx.Panel(self)
# The cmd panel is four buttons whose names and foreground colors # The cmd panel is four buttons whose names and foreground colors
# change. Plop them in a StaticBox like the SpinPanels. # 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.cmd_panel = wx.Panel(self.side_panel, -1)
box = wx.StaticBox(self.cmd_panel, -1, 'Command') self.sub_panel = wx.Panel(self.cmd_panel, -1)
sizer = wx.StaticBoxSizer(box, wx.VERTICAL) sizer = wx.GridSizer(rows = 2, cols = 2)
global ctrl_buttons global ctrl_buttons
border = 'wxMac' in wx.PlatformInfo and 3 or 0 border = 'wxMac' in wx.PlatformInfo and 3 or 1
for name, color, handler in ( for name, handler in (
('Redraw', 'red', self.OnRedraw), ('Go', self.OnGoStop),
('Forward', 'magenta', self.OnForward), ('Redraw', self.OnRedraw),
('Go', 'dark green', self.OnGo), ('Backward', self.OnBackward),
('Back', 'blue', self.OnBack)): ('Forward', self.OnForward)):
button = wx.Button(self.cmd_panel, -1, name) button = wx.Button(self.sub_panel, -1, name)
button.SetForegroundColour(color) button.SetForegroundColour(self.labelColours[name])
ctrl_buttons[name] = button ctrl_buttons[name] = button
button.Bind(wx.EVT_BUTTON, handler) button.Bind(wx.EVT_BUTTON, handler)
sizer.Add(button, 0, wx.EXPAND|wx.TOP|wx.BOTTOM, border) 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) self.cmd_panel.SetSizer(sizer)
# Now make the rest of the control panels... # Now make the rest of the control panels...
@@ -243,7 +317,7 @@ class MyFrame(wx.Frame, clroses.rose):
# important. # important.
# In the SpinPanel data (name, min, value, max), value will be # In the SpinPanel data (name, min, value, max), value will be
# overridden by clroses.py defaults. # overridden by clroses.py defaults.
self.coe_panel = makeSP('Coefficients', self.coe_panel = makeSP('Coefficient',
(('Style', 0, 100, 3600), (('Style', 0, 100, 3600),
('Sincr', -3600, -1, 3600), ('Sincr', -3600, -1, 3600),
('Petal', 0, 2, 3600), ('Petal', 0, 2, 3600),
@@ -309,30 +383,30 @@ class MyFrame(wx.Frame, clroses.rose):
# Command button event handlers. These are relabled when changing between auto # 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. # and manual modes. They simply reflect the call to a method in the base class.
# #
# Stop/Redraw button # Go/Stop button
def OnGoStop(self, event):
if verbose:
print 'OnGoStop'
self.cmd_go_stop()
# Redraw/Redraw
def OnRedraw(self, event): def OnRedraw(self, event):
if verbose: if verbose:
print 'OnRedraw' print 'OnRedraw'
self.cmd_stop() self.cmd_redraw()
# Skip/Forward # Backward/Reverse
def OnBackward(self, event):
if verbose:
print 'OnBackward'
self.cmd_backward()
# Forward/Skip
def OnForward(self, event): def OnForward(self, event):
if verbose: if verbose:
print 'OnForward' print 'OnForward'
self.cmd_step() self.cmd_step()
# Redraw/Go
def OnGo(self, event):
if verbose:
print 'OnGo'
self.cmd_go()
# Reverse/Back
def OnBack(self, event):
if verbose:
print 'OnBack'
self.cmd_reverse()
# The clroses.roses class expects to have methods available that # The clroses.roses class expects to have methods available that
# implement the missing parts of the functionality needed to do # implement the missing parts of the functionality needed to do
@@ -379,8 +453,9 @@ class MyFrame(wx.Frame, clroses.rose):
# Command buttons change their names based on the whether we're in auto # Command buttons change their names based on the whether we're in auto
# or manual mode. # or manual mode.
def AppCmdLabels(self, labels): def AppCmdLabels(self, labels):
for name, label in map(None, ('Redraw', 'Forward', 'Go', 'Back'), labels): for name, label in map(None, ('Go', 'Redraw', 'Backward', 'Forward'), labels):
ctrl_buttons[name].SetLabel(label) ctrl_buttons[name].SetLabel(label)
ctrl_buttons[name].SetForegroundColour(self.labelColours[label])
# Timer methods. The paranoia about checking up on the callers is # Timer methods. The paranoia about checking up on the callers is