These directories renamed: tkinter -> lib-tk, stdwin -> lib-stdwin.

This commit is contained in:
Guido van Rossum 1997-09-09 03:39:21 +00:00
parent 045e688f6f
commit d7500fcbb4
46 changed files with 0 additions and 6876 deletions

View file

@ -1,63 +0,0 @@
# Abstract classes for parents and children.
#
# Do not use as base class -- this is for documentation only.
#
# Note that the tree must be built top down (create the parent,
# then add the children).
#
# Also note that the creation methods are not standardized --
# these have extra parameters dependent on the widget type.
# For historical reasons, button creation methods are called
# define() while split creation methods are called create().
class AbstractParent:
#
# Upcalls from child to parent
#
def addchild(self, child): unimpl()
def delchild(self, child): unimpl()
#
def need_mouse(self, child): unimpl()
def no_mouse(self, child): unimpl()
#
def need_timer(self, child): unimpl()
def no_timer(self, child): unimpl()
#
# XXX need_kbd, no_kbd; focus???
#
def begindrawing(self): return unimpl()
def beginmeasuring(self): return unimpl()
def getwindow(self): return unimpl() # Only for very special cases
#
def change(self, area): unimpl()
def scroll(self, area, (dh, dv)): unimpl()
def settimer(self, itimer): unimpl()
class AbstractChild:
#
# Downcalls from parent to child
#
def destroy(self): unimpl()
#
def realize(self): return unimpl()
def getminsize(self, m, (width, height)): return unimpl()
def getbounds(self): return unimpl()
def setbounds(self, bounds): unimpl()
def draw(self, d, area): unimpl()
#
# Downcalls only made after certain upcalls
#
def mouse_down(self, detail): unimpl()
def mouse_move(self, detail): unimpl()
def mouse_up(self, detail): unimpl()
#
def timer(self): unimpl()
# A "Split" is a child that manages one or more children.
# (This terminology is due to DEC SRC, except for CSplits.)
# A child of a split may be another split, a button, a slider, etc.
# Certain upcalls and downcalls can be handled transparently, but
# for others (e.g., all geometry related calls) this is not possible.
class AbstractSplit(AbstractChild, AbstractParent):
pass

View file

@ -1,40 +0,0 @@
from TransParent import TransParent
class BoxParent(TransParent):
#
def create(self, parent, (dh, dv)):
self = TransParent.create(self, parent)
self.dh = dh
self.dv = dv
return self
#
def getminsize(self, m, (width, height)):
width = max(0, width - 2*self.dh)
height = max(0, height - 2*self.dv)
width, height = self.child.getminsize(m, (width, height))
return width + 2*self.dh, height + 2*self.dv
#
def setbounds(self, bounds):
(left, top), (right, bottom) = bounds
self.bounds = bounds
left = min(right, left + self.dh)
top = min(bottom, top + self.dv)
right = max(left, right - self.dh)
bottom = max(top, bottom - self.dv)
self.innerbounds = (left, top), (right, bottom)
self.child.setbounds(self.innerbounds)
#
def getbounds(self):
return self.bounds
#
def draw(self, d, area):
(left, top), (right, bottom) = self.bounds
left = left + 1
top = top + 1
right = right - 1
bottom = bottom - 1
d.box((left, top), (right, bottom))
TransParent.draw(self, d, area) # XXX clip to innerbounds?
#
# XXX should scroll clip to innerbounds???
# XXX currently the only user restricts itself to child's bounds

View file

@ -1,411 +0,0 @@
# Module 'Buttons'
# Import module 'rect' renamed as '_rect' to avoid exporting it on
# 'from Buttons import *'
#
import rect
_rect = rect
del rect
# Field indices in mouse event detail
#
_HV = 0
_CLICKS = 1
_BUTTON = 2
_MASK = 3
# LabelAppearance provides defaults for all appearance methods.
# selected state not visible
# disabled --> crossed out
# hilited --> inverted
#
class LabelAppearance:
#
# Initialization
#
def init_appearance(self):
self.bounds = _rect.empty
self.enabled = 1
self.hilited = 0
self.selected = 0
self.text = ''
#
# Size enquiry
#
def getminsize(self, m, (width, height)):
width = max(width, m.textwidth(self.text) + 6)
height = max(height, m.lineheight() + 6)
return width, height
#
def getbounds(self):
return self.bounds
#
# Changing the parameters
#
def settext(self, text):
self.text = text
if self.bounds <> _rect.empty:
self.recalctextpos()
self.redraw()
#
def setbounds(self, bounds):
self.bounds = bounds
if self.bounds <> _rect.empty:
self.recalc()
#
def realize(self):
pass
#
# Changing the state bits
#
def enable(self, flag):
if flag <> self.enabled:
self.enabled = flag
if self.bounds <> _rect.empty:
self.flipenable(self.parent.begindrawing())
#
def hilite(self, flag):
if flag <> self.hilited:
self.hilited = flag
if self.bounds <> _rect.empty:
self.fliphilite(self.parent.begindrawing())
#
def select(self, flag):
if flag <> self.selected:
self.selected = flag
if self.bounds <> _rect.empty:
self.redraw()
#
# Recalculate the box bounds and text position.
# This can be overridden by buttons that draw different boxes
# or want their text in a different position.
#
def recalc(self):
if self.bounds <> _rect.empty:
self.recalcbounds()
self.recalctextpos()
#
def recalcbounds(self):
self.hilitebounds = _rect.inset(self.bounds, (3, 3))
self.crossbounds = self.bounds
#
def recalctextpos(self):
(left, top), (right, bottom) = self.bounds
m = self.parent.beginmeasuring()
h = (left + right - m.textwidth(self.text)) / 2
v = (top + bottom - m.lineheight()) / 2
self.textpos = h, v
#
# Generic drawing interface.
# Do not override redraw() or draw() methods; override drawit() c.s.
#
def redraw(self):
if self.bounds <> _rect.empty:
d = self.parent.begindrawing()
d.erase(self.bounds)
self.draw(d, self.bounds)
#
def draw(self, d, area):
area = _rect.intersect([area, self.bounds])
if area == _rect.empty:
return
d.cliprect(area)
self.drawit(d)
d.noclip()
#
# The drawit() method is fairly generic but may be overridden.
#
def drawit(self, d):
self.drawpict(d)
if self.text:
d.text(self.textpos, self.text)
if not self.enabled:
self.flipenable(d)
if self.hilited:
self.fliphilite(d)
#
# Default drawing detail functions.
# Overriding these is normally sufficient to get different
# appearances.
#
def drawpict(self, d):
pass
#
def flipenable(self, d):
_xorcross(d, self.crossbounds)
#
def fliphilite(self, d):
d.invert(self.hilitebounds)
# A Strut is a label with no width of its own.
class StrutAppearance(LabelAppearance):
#
def getminsize(self, m, (width, height)):
height = max(height, m.lineheight() + 6)
return width, height
#
# ButtonAppearance displays a centered string in a box.
# selected --> bold border
# disabled --> crossed out
# hilited --> inverted
#
class ButtonAppearance(LabelAppearance):
#
def drawpict(self, d):
d.box(_rect.inset(self.bounds, (1, 1)))
if self.selected:
# Make a thicker box
d.box(self.bounds)
d.box(_rect.inset(self.bounds, (2, 2)))
d.box(_rect.inset(self.bounds, (3, 3)))
#
# CheckAppearance displays a small square box and a left-justified string.
# selected --> a cross appears in the box
# disabled --> whole button crossed out
# hilited --> box is inverted
#
class CheckAppearance(LabelAppearance):
#
def getminsize(self, m, (width, height)):
minwidth = m.textwidth(self.text) + 6
minheight = m.lineheight() + 6
width = max(width, minwidth + minheight + m.textwidth(' '))
height = max(height, minheight)
return width, height
#
def drawpict(self, d):
d.box(self.boxbounds)
if self.selected: _xorcross(d, self.boxbounds)
#
def recalcbounds(self):
LabelAppearance.recalcbounds(self)
(left, top), (right, bottom) = self.bounds
self.size = bottom - top - 4
self.boxbounds = (left+2, top+2), (left+2+self.size, bottom-2)
self.hilitebounds = self.boxbounds
#
def recalctextpos(self):
m = self.parent.beginmeasuring()
(left, top), (right, bottom) = self.boxbounds
h = right + m.textwidth(' ')
v = top + (self.size - m.lineheight()) / 2
self.textpos = h, v
#
# RadioAppearance displays a round indicator and a left-justified string.
# selected --> a dot appears in the indicator
# disabled --> whole button crossed out
# hilited --> indicator is inverted
#
class RadioAppearance(CheckAppearance):
#
def drawpict(self, d):
(left, top), (right, bottom) = self.boxbounds
radius = self.size / 2
center = left + radius, top + radius
d.circle(center, radius)
if self.selected:
d.fillcircle(center, radius*3/5)
#
# NoReactivity ignores mouse events.
#
class NoReactivity:
def init_reactivity(self): pass
# BaseReactivity defines hooks and asks for mouse events,
# but provides only dummy mouse event handlers.
# The trigger methods call the corresponding hooks set by the user.
# Hooks (and triggers) mean the following:
# down_hook called on some mouse-down events
# move_hook called on some mouse-move events
# up_hook called on mouse-up events
# on_hook called for buttons with on/off state, when it goes on
# hook called when a button 'fires' or a radiobutton goes on
# There are usually extra conditions, e.g., hooks are only called
# when the button is enabled, or active, or selected (on).
#
class BaseReactivity:
#
def init_reactivity(self):
self.down_hook = self.move_hook = self.up_hook = \
self.on_hook = self.off_hook = \
self.hook = self.active = 0
self.parent.need_mouse(self)
#
def mousetest(self, hv):
return _rect.pointinrect(hv, self.bounds)
#
def mouse_down(self, detail):
pass
#
def mouse_move(self, detail):
pass
#
def mouse_up(self, detail):
pass
#
def down_trigger(self):
if self.down_hook: self.down_hook(self)
#
def move_trigger(self):
if self.move_hook: self.move_hook(self)
#
def up_trigger(self):
if self.up_hook: self.up_hook(self)
#
def on_trigger(self):
if self.on_hook: self.on_hook(self)
#
def off_trigger(self):
if self.off_hook: self.off_hook(self)
#
def trigger(self):
if self.hook: self.hook(self)
# ToggleReactivity acts like a simple pushbutton.
# It toggles its hilite state on mouse down events.
#
class ToggleReactivity(BaseReactivity):
#
def mouse_down(self, detail):
if self.enabled and self.mousetest(detail[_HV]):
self.active = 1
self.hilite(not self.hilited)
self.down_trigger()
#
def mouse_move(self, detail):
if self.active:
self.move_trigger()
#
def mouse_up(self, detail):
if self.active:
self.up_trigger()
self.active = 0
#
def down_trigger(self):
if self.hilited:
self.on_trigger()
else:
self.off_trigger()
self.trigger()
#
# TriggerReactivity acts like a fancy pushbutton.
# It hilites itself while the mouse is down within its bounds.
#
class TriggerReactivity(BaseReactivity):
#
def mouse_down(self, detail):
if self.enabled and self.mousetest(detail[_HV]):
self.active = 1
self.hilite(1)
self.down_trigger()
#
def mouse_move(self, detail):
if self.active:
self.hilite(self.mousetest(detail[_HV]))
if self.hilited:
self.move_trigger()
#
def mouse_up(self, detail):
if self.active:
self.hilite(self.mousetest(detail[_HV]))
if self.hilited:
self.up_trigger()
self.trigger()
self.active = 0
self.hilite(0)
#
# CheckReactivity handles mouse events like TriggerReactivity,
# It overrides the up_trigger method to flip its selected state.
#
class CheckReactivity(TriggerReactivity):
#
def up_trigger(self):
self.select(not self.selected)
if self.selected:
self.on_trigger()
else:
self.off_trigger()
self.trigger()
# RadioReactivity turns itself on and the other buttons in its group
# off when its up_trigger method is called.
#
class RadioReactivity(TriggerReactivity):
#
def init_reactivity(self):
TriggerReactivity.init_reactivity(self)
self.group = []
#
def up_trigger(self):
for b in self.group:
if b <> self:
if b.selected:
b.select(0)
b.off_trigger()
self.select(1)
self.on_trigger()
self.trigger()
# Auxiliary class for 'define' method.
# Call the initializers in the right order.
#
class Define:
#
def define(self, parent):
self.parent = parent
parent.addchild(self)
self.init_appearance()
self.init_reactivity()
return self
#
def destroy(self):
self.parent = 0
#
def definetext(self, parent, text):
self = self.define(parent)
self.settext(text)
return self
# Subroutine to cross out a rectangle.
#
def _xorcross(d, bounds):
((left, top), (right, bottom)) = bounds
# This is s bit funny to make it look better
left = left + 2
right = right - 2
top = top + 2
bottom = bottom - 3
d.xorline(((left, top), (right, bottom)))
d.xorline((left, bottom), (right, top))
# Ready-made button classes.
#
class Label(NoReactivity, LabelAppearance, Define): pass
class Strut(NoReactivity, StrutAppearance, Define): pass
class PushButton(TriggerReactivity, ButtonAppearance, Define): pass
class CheckButton(CheckReactivity, CheckAppearance, Define): pass
class RadioButton(RadioReactivity, RadioAppearance, Define): pass
class ToggleButton(ToggleReactivity, ButtonAppearance, Define): pass

View file

@ -1,69 +0,0 @@
# A CSplit is a Clock-shaped split: the children are grouped in a circle.
# The numbering is a little different from a real clock: the 12 o'clock
# position is called 0, not 12. This is a little easier since Python
# usually counts from zero. (BTW, there needn't be exactly 12 children.)
from math import pi, sin, cos
from Split import Split
class CSplit(Split):
#
def getminsize(self, m, (width, height)):
# Since things look best if the children are spaced evenly
# along the circle (and often all children have the same
# size anyway) we compute the max child size and assume
# this is each child's size.
for child in self.children:
wi, he = child.getminsize(m, (0, 0))
width = max(width, wi)
height = max(height, he)
# In approximation, the diameter of the circle we need is
# (diameter of box) * (#children) / pi.
# We approximate pi by 3 (so we slightly overestimate
# our minimal size requirements -- not so bad).
# Because the boxes stick out of the circle we add the
# box size to each dimension.
# Because we really deal with ellipses, do everything
# separate in each dimension.
n = len(self.children)
return width + (width*n + 2)/3, height + (height*n + 2)/3
#
def getbounds(self):
return self.bounds
#
def setbounds(self, bounds):
self.bounds = bounds
# Place the children. This involves some math.
# Compute center positions for children as if they were
# ellipses with a diameter about 1/N times the
# circumference of the big ellipse.
# (There is some rounding involved to make it look
# reasonable for small and large N alike.)
# XXX One day Python will have automatic conversions...
n = len(self.children)
fn = float(n)
if n == 0: return
(left, top), (right, bottom) = bounds
width, height = right-left, bottom-top
child_width, child_height = width*3/(n+4), height*3/(n+4)
half_width, half_height = \
float(width-child_width)/2.0, \
float(height-child_height)/2.0
center_h, center_v = center = (left+right)/2, (top+bottom)/2
fch, fcv = float(center_h), float(center_v)
alpha = 2.0 * pi / fn
for i in range(n):
child = self.children[i]
fi = float(i)
fh, fv = \
fch + half_width*sin(fi*alpha), \
fcv - half_height*cos(fi*alpha)
left, top = \
int(fh) - child_width/2, \
int(fv) - child_height/2
right, bottom = \
left + child_width, \
top + child_height
child.setbounds(((left, top), (right, bottom)))
#

View file

@ -1,58 +0,0 @@
# DirList -- Directory Listing widget
# XXX Displays messy paths when following '..'
import os
import stdwin, rect
from stdwinevents import *
from Buttons import PushButton
from WindowParent import WindowParent
from HVSplit import HSplit, VSplit
class DirList(VSplit):
#
def create(self, parent, dirname):
self = VSplit.create(self, parent)
names = os.listdir(dirname)
for name in names:
if os.path.isdir(os.path.join(dirname, name)):
fullname = os.path.join(dirname, name)
btn = SubdirButton().definetext(self, fullname)
elif name[-3:] == '.py':
btn = ModuleButton().definetext(self, name)
else:
btn = FileButton().definetext(self, name)
return self
#
class DirListWindow(WindowParent):
#
def create(self, dirname):
self = WindowParent.create(self, dirname, (0, 0))
child = DirList().create(self, dirname)
self.realize()
return self
#
class SubdirButton(PushButton):
#
def drawpict(self, d):
PushButton.drawpict(self, d)
d.box(rect.inset(self.bounds, (3, 1)))
#
def up_trigger(self):
window = DirListWindow().create(self.text)
#
class FileButton(PushButton):
#
def up_trigger(self):
stdwin.fleep()
#
class ModuleButton(FileButton):
#
def drawpict(self, d):
PushButton.drawpict(self, d)
d.box(rect.inset(self.bounds, (1, 3)))
#

View file

@ -1,58 +0,0 @@
# A FormSplit lets you place its children exactly where you want them
# (including silly places!).
# It does no explicit geometry management except moving its children
# when it is moved.
# The interface to place children is as follows.
# Before you add a child, you may specify its (left, top) position
# relative to the FormSplit. If you don't specify a position for
# a child, it goes right below the previous child; the first child
# goes to (0, 0) by default.
# NB: This places data attributes named form_* on its children.
# XXX Yes, I know, there should be options to do all sorts of relative
# placement, but for now this will do.
from Split import Split
class FormSplit(Split):
#
def create(self, parent):
self.next_left = self.next_top = 0
self.last_child = None
return Split.create(self, parent)
#
def getminsize(self, m, sugg_size):
max_width, max_height = 0, 0
for c in self.children:
c.form_width, c.form_height = c.getminsize(m, (0, 0))
max_width = max(max_width, c.form_width + c.form_left)
max_height = max(max_height, \
c.form_height + c.form_top)
return max_width, max_height
#
def getbounds(self):
return self.bounds
#
def setbounds(self, bounds):
self.bounds = bounds
fleft, ftop = bounds[0]
for c in self.children:
left, top = c.form_left + fleft, c.form_top + ftop
right, bottom = left + c.form_width, top + c.form_height
c.setbounds(((left, top), (right, bottom)))
#
def placenext(self, left, top):
self.next_left = left
self.next_top = top
self.last_child = None
#
def addchild(self, child):
if self.last_child:
width, height = \
self.last_child.getminsize(self.beginmeasuring(), \
(0, 0))
self.next_top = self.next_top + height
child.form_left = self.next_left
child.form_top = self.next_top
Split.addchild(self, child)
self.last_child = child
#

View file

@ -1,62 +0,0 @@
# HVSplit contains generic code for HSplit and VSplit.
# HSplit and VSplit are specializations to either dimension.
# XXX This does not yet stretch/shrink children if there is too much
# XXX or too little space in the split dimension.
# XXX (NB There is no interface to ask children for stretch preferences.)
from Split import Split
class HVSplit(Split):
#
def create(self, parent, hv):
# hv is 0 for HSplit, 1 for VSplit
self = Split.create(self, parent)
self.hv = hv
return self
#
def getminsize(self, m, sugg_size):
hv, vh = self.hv, 1 - self.hv
size = [0, 0]
sugg_size = [sugg_size[0], sugg_size[1]]
sugg_size[hv] = 0
sugg_size = sugg_size[0], sugg_size[1] # Make a tuple
for c in self.children:
csize = c.getminsize(m, sugg_size)
if csize[vh] > size[vh]: size[vh] = csize[vh]
size[hv] = size[hv] + csize[hv]
return size[0], size[1]
#
def getbounds(self):
return self.bounds
#
def setbounds(self, bounds):
self.bounds = bounds
hv, vh = self.hv, 1 - self.hv
mf = self.parent.beginmeasuring
begin, end = bounds
sugg_size = end[0] - begin[0], end[1] - begin[1]
size = self.getminsize(mf(), sugg_size)
origin = [begin[0], begin[1]]
sugg_size = [sugg_size[0], sugg_size[1]] # Make a list
sugg_size[hv] = 0
sugg_size = sugg_size[0], sugg_size[1] # Make a tuple
for c in self.children:
size = c.getminsize(mf(), sugg_size)
corner = [0, 0]
corner[vh] = end[vh]
corner[hv] = origin[hv] + size[hv]
c.setbounds(((origin[0], origin[1]), \
(corner[0], corner[1])))
origin[hv] = corner[hv]
# XXX stretch
# XXX too-small
#
class HSplit(HVSplit):
def create(self, parent):
return HVSplit.create(self, parent, 0)
class VSplit(HVSplit):
def create(self, parent):
return HVSplit.create(self, parent, 1)

View file

@ -1,36 +0,0 @@
# Module 'Histogram'
from Buttons import *
# A Histogram displays a histogram of numeric data.
#
class HistogramAppearance(LabelAppearance, Define):
#
def define(self, parent):
Define.define(self, (parent, ''))
self.ydata = []
self.scale = (0, 100)
return self
#
def setdata(self, ydata, scale):
self.ydata = ydata
self.scale = scale # (min, max)
self.parent.change(self.bounds)
#
def drawpict(self, d):
(left, top), (right, bottom) = self.bounds
min, max = self.scale
size = max-min
width, height = right-left, bottom-top
ydata = self.ydata
npoints = len(ydata)
v1 = top + height # constant
h1 = left # changed in loop
for i in range(npoints):
h0 = h1
v0 = top + height - (ydata[i]-min)*height/size
h1 = left + (i+1) * width/npoints
d.paint((h0, v0), (h1, v1))
#
class Histogram(NoReactivity, HistogramAppearance): pass

View file

@ -1,174 +0,0 @@
# Module 'Sliders'
import stdwin
from stdwinevents import *
import rect
from Buttons import *
from HVSplit import HSplit
# Field indices in event detail
#
_HV = 0
_CLICKS = 1
_BUTTON = 2
_MASK = 3
# DragSlider is the simplest possible slider.
# It looks like a button but dragging the mouse left or right
# changes the controlled value.
# It does not support any of the triggers or hooks defined by Buttons,
# but defines its own setval_trigger and setval_hook.
#
class DragSliderReactivity(BaseReactivity):
#
def mouse_down(self, detail):
h, v = hv = detail[_HV]
if self.enabled and self.mousetest(hv):
self.anchor = h
self.oldval = self.val
self.active = 1
#
def mouse_move(self, detail):
if self.active:
h, v = detail[_HV]
self.setval(self.oldval + (h - self.anchor))
#
def mouse_up(self, detail):
if self.active:
h, v = detail[_HV]
self.setval(self.oldval + (h - self.anchor))
self.active = 0
#
class DragSliderAppearance(ButtonAppearance):
#
# INVARIANTS maintained by the setval method:
#
# self.min <= self.val <= self.max
# self.text = self.pretext + `self.val` + self.postext
#
# (Notice that unlike Python ranges, the end point belongs
# to the range.)
#
def init_appearance(self):
ButtonAppearance.init_appearance(self)
self.min = 0
self.val = 0
self.max = 100
self.hook = 0
self.pretext = self.postext = ''
self.recalctext()
#
# The 'get*' and 'set*' methods belong to the generic slider interface
#
def getval(self): return self.val
#
def sethook(self, hook):
self.hook = hook
#
def setminvalmax(self, min, val, max):
self.min = min
self.max = max
self.setval(val)
#
def settexts(self, pretext, postext):
self.pretext = pretext
self.postext = postext
self.recalctext()
#
def setval(self, val):
val = min(self.max, max(self.min, val))
if val <> self.val:
self.val = val
self.recalctext()
self.trigger()
#
def trigger(self):
if self.hook:
self.hook(self)
#
def recalctext(self):
self.settext(self.pretext + `self.val` + self.postext)
#
class DragSlider(DragSliderReactivity, DragSliderAppearance, Define):
def definetext(self, parent, text):
raise RuntimeError, 'DragSlider.definetext() not supported'
# Auxiliary class for PushButton incorporated in ComplexSlider
#
class _StepButton(PushButton):
def define(self, parent):
self = PushButton.define(self, parent)
self.step = 0
return self
def setstep(self, step):
self.step = step
def definetextstep(self, parent, text, step):
self = self.definetext(parent, text)
self.setstep(step)
return self
def init_reactivity(self):
PushButton.init_reactivity(self)
self.parent.need_timer(self)
def step_trigger(self):
self.parent.setval(self.parent.getval() + self.step)
def down_trigger(self):
self.step_trigger()
self.parent.settimer(5)
def timer(self):
if self.hilited:
self.step_trigger()
if self.active:
self.parent.settimer(1)
# A complex slider is an HSplit initialized to three buttons:
# one to step down, a dragslider, and one to step up.
#
class ComplexSlider(HSplit):
#
# Override Slider define() method
#
def define(self, parent):
self = self.create(parent) # HSplit
#
self.downbutton = _StepButton().definetextstep(self, '-', -1)
self.dragbutton = DragSlider().define(self)
self.upbutton = _StepButton().definetextstep(self, '+', 1)
#
return self
#
# Override HSplit methods
#
def getminsize(self, m, (width, height)):
w1, h1 = self.downbutton.getminsize(m, (0, height))
w3, h3 = self.upbutton.getminsize(m, (0, height))
w1 = max(w1, h1)
w3 = max(w3, h3)
w2, h2 = self.dragbutton.getminsize(m, (width-w1-w3, height))
return w1+w2+w3, max(h1, h2, h3)
#
def setbounds(self, bounds):
(left, top), (right, bottom) = self.bounds = bounds
size = bottom - top
self.downbutton.setbounds(((left, top), (left+size, bottom)))
self.dragbutton.setbounds(((left+size, top), \
(right-size, bottom)))
self.upbutton.setbounds(((right-size, top), (right, bottom)))
#
# Pass other Slider methods on to dragbutton
#
def getval(self): return self.dragbutton.getval()
def sethook(self, hook): self.dragbutton.sethook(hook)
def setminvalmax(self, args): self.dragbutton.setminvalmax(args)
def settexts(self, args): self.dragbutton.settexts(args)
def setval(self, val): self.dragbutton.setval(val)
def enable(self, flag):
self.downbutton.enable(flag)
self.dragbutton.enable(flag)
self.upbutton.enable(flag)

View file

@ -1,36 +0,0 @@
# Module 'Soundogram'
import audio
from Histogram import Histogram
class Soundogram(Histogram):
#
def define(self, win, chunk):
width, height = corner = win.getwinsize()
bounds = (0, 0), corner
self.chunk = chunk
self.step = (len(chunk)-1)/(width/2+1) + 1
ydata = _make_ydata(chunk, self.step)
return Histogram.define(self, (win, bounds, ydata, (0, 128)))
#
def setchunk(self, chunk):
self.chunk = chunk
self.recompute()
#
def recompute(self):
(left, top), (right, bottom) = self.bounds
width = right - left
self.step = (len(chunk)-1)/width + 1
ydata = _make_ydata(chunk, self.step)
self.setdata(ydata, (0, 128))
#
def _make_ydata(chunk, step):
ydata = []
for i in range(0, len(chunk), step):
piece = audio.chr2num(chunk[i:i+step])
mi, ma = min(piece), max(piece)
y = max(abs(mi), abs(ma))
ydata.append(y)
return ydata

View file

@ -1,211 +0,0 @@
# Generic Split implementation.
# Use as a base class for other splits.
# Derived classes should at least implement the methods that call
# unimpl() below: getminsize(), getbounds() and setbounds().
Error = 'Split.Error' # Exception
import rect
from stdwinevents import *
class Split:
#
# Calls from creator
# NB derived classes may add parameters to create()
#
def create(self, parent):
parent.addchild(self)
self.parent = parent
self.children = []
self.mouse_interest = []
self.keybd_interest = []
self.timer_interest = []
self.altdraw_interest = []
self.mouse_focus = None
self.keybd_focus = None
return self
#
# Downcalls from parent to child
#
def destroy(self):
self.parent = None
for child in self.children:
child.destroy()
del self.children[:]
del self.mouse_interest[:]
del self.keybd_interest[:]
del self.timer_interest[:]
del self.altdraw_interest[:]
self.mouse_focus = None
self.keybd_focus = None
#
def getminsize(self, m, (width, height)):
return unimpl() # Should ask children
def getbounds(self):
return unimpl()
def setbounds(self, bounds):
unimpl() # Should tell children
#
def realize(self):
for child in self.children:
child.realize()
#
def draw(self, d, detail):
# (Could avoid calls to children outside the area)
for child in self.children:
child.draw(d, detail)
#
def altdraw(self, detail):
for child in self.altdraw_interest:
child.altdraw(detail)
#
# Keyboard focus handling (used internally)
# XXX This is not enough if two levels of splits
# XXX surround text fields!
#
def set_keybd_focus(self, child):
if self.keybd_focus <> child:
if self.keybd_focus:
self.keybd_focus.deactivate()
self.keybd_focus = None
if child:
child.activate()
self.keybd_focus = child
def next_keybd_focus(self):
if not self.keybd_interest:
self.set_keybd_focus(None)
return
if self.keybd_focus in self.keybd_interest:
i = self.keybd_interest.index(self.keybd_focus)
i = (i+1) % len(self.keybd_interest)
else:
i = 0
self.set_keybd_focus(self.keybd_interest[i])
#
# Downcalls only made after certain upcalls
#
def mouse_down(self, detail):
if self.mouse_focus:
self.mouse_focus.mouse_down(detail)
return
p = detail[0]
for child in self.mouse_interest:
if rect.pointinrect(p, child.getbounds()):
self.mouse_focus = child
if child in self.keybd_interest:
self.set_keybd_focus(child)
child.mouse_down(detail)
def mouse_move(self, detail):
if self.mouse_focus:
self.mouse_focus.mouse_move(detail)
def mouse_up(self, detail):
if self.mouse_focus:
self.mouse_focus.mouse_up(detail)
self.mouse_focus = None
#
def activate(self):
if self.keybd_focus:
self.keybd_focus.activate()
else:
self.next_keybd_focus()
def deactivate(self):
if self.keybd_focus:
self.keybd_focus.deactivate()
#
def keybd(self, type, detail):
if not self.keybd_focus:
self.set_keybd_focus(self.keybd_interest[0])
if type == WE_COMMAND and detail == WC_TAB and \
len(self.keybd_interest) > 1:
self.next_keybd_focus()
return
self.keybd_focus.keybd(type, detail)
#
def timer(self):
for child in self.timer_interest:
child.timer()
#
# Upcalls from child to parent
#
def addchild(self, child):
if child in self.children:
raise Error, 'addchild: child already inlist'
self.children.append(child)
def delchild(self, child):
if child not in self.children:
raise Error, 'delchild: child not in list'
self.children.remove(child)
if child in self.mouse_interest:
self.mouse_interest.remove(child)
if child in self.keybd_interest:
self.keybd_interest.remove(child)
if child in self.timer_interest:
self.timer_interest.remove(child)
if child in self.altdraw_interest:
self.altdraw_interest.remove(child)
if child == self.mouse_focus:
self.mouse_focus = None
if child == self.keybd_focus:
self.keybd_focus = None
#
def need_mouse(self, child):
if child not in self.mouse_interest:
self.mouse_interest.append(child)
self.parent.need_mouse(self)
def no_mouse(self, child):
if child == self.mouse_focus:
self.mouse_focus = None
if child in self.mouse_interest:
self.mouse_interest.remove(child)
if not self.mouse_interest:
self.parent.no_mouse(self)
#
def need_keybd(self, child):
if child not in self.keybd_interest:
self.keybd_interest.append(child)
self.parent.need_keybd(self)
if not self.keybd_focus:
self.set_keybd_focus(child)
def no_keybd(self, child):
if child == self.keybd_focus:
self.keybd_focus = None # Don't call child.deactivate()
if child in self.keybd_interest:
self.keybd_interest.remove(child)
if not self.keybd_interest:
self.parent.no_keybd(self)
#
def need_timer(self, child):
if child not in self.timer_interest:
self.timer_interest.append(child)
self.parent.need_timer(self)
def no_timer(self, child):
if child in self.timer_interest:
self.timer_interest.remove(child)
if not self.timer_interest:
self.parent.no_timer(self)
#
def need_altdraw(self, child):
if child not in self.altdraw_interest:
self.altdraw_interest.append(child)
self.parent.need_altdraw(self)
def no_altdraw(self, child):
if child in self.altdraw_interest:
self.altdraw_interest.remove(child)
if not self.altdraw_interest:
self.parent.no_altdraw(self)
#
# The rest are transparent:
#
def begindrawing(self):
return self.parent.begindrawing()
def beginmeasuring(self):
return self.parent.beginmeasuring()
def getwindow(self):
return self.parent.getwindow()
#
def change(self, area):
self.parent.change(area)
def scroll(self, area, vector):
self.parent.scroll(area, vector)
def settimer(self, itimer):
self.parent.settimer(itimer)

View file

@ -1,70 +0,0 @@
# Module 'StripChart'
import rect
from Buttons import LabelAppearance, NoReactivity
# A StripChart doesn't really look like a label but it needs a base class.
# LabelAppearance allows it to be disabled and hilited.
class StripChart(LabelAppearance, NoReactivity):
#
def define(self, parent, scale):
self.parent = parent
parent.addchild(self)
self.init_appearance()
self.init_reactivity()
self.ydata = []
self.scale = scale
self.resetbounds()
return self
#
def destroy(self):
self.parent = 0
#
def setbounds(self, bounds):
LabelAppearance.setbounds(self, bounds)
self.resetbounds()
#
def resetbounds(self):
(left, top), (right, bottom) = self.bounds
self.width = right-left
self.height = bottom-top
excess = len(self.ydata) - self.width
if excess > 0:
del self.ydata[:excess]
elif excess < 0:
while len(self.ydata) < self.width:
self.ydata.insert(0, 0)
#
def append(self, y):
self.ydata.append(y)
excess = len(self.ydata) - self.width
if excess > 0:
del self.ydata[:excess]
if self.bounds <> rect.empty:
self.parent.scroll(self.bounds, (-excess, 0))
if self.bounds <> rect.empty:
(left, top), (right, bottom) = self.bounds
i = len(self.ydata)
area = (left+i-1, top), (left+i, bottom)
self.draw(self.parent.begindrawing(), area)
#
def draw(self, d, area):
area = rect.intersect([area, self.bounds])
if area == rect.empty:
return
d.cliprect(area)
d.erase(self.bounds)
(a_left, a_top), (a_right, a_bottom) = area
(left, top), (right, bottom) = self.bounds
height = bottom - top
i1 = a_left - left
i2 = a_right - left
for i in range(max(0, i1), min(len(self.ydata), i2)):
split = bottom-self.ydata[i]*height/self.scale
d.paint((left+i, split), (left+i+1, bottom))
if not self.enabled:
self.flipenable(d)
if self.hilited:
self.fliphilite(d)
d.noclip()

View file

@ -1,126 +0,0 @@
# Text editing widget
# NB: this always assumes fixed bounds.
# For auto-growing TextEdit windows, different code would be needed.
from stdwinevents import *
class TextEdit:
#
def create(self, parent, (cols, rows)):
parent.addchild(self)
self.parent = parent
self.cols = cols
self.rows = rows
self.text = ''
# Creation of the editor is done in realize()
self.editor = None
self.dh = self.dv = 0
return self
#
def createboxed(self, parent, (cols, rows), (dh, dv)):
self = self.create(parent, (cols, rows))
self.dh = max(0, dh)
self.dv = max(0, dv)
return self
#
def settext(self, text):
self.editor.settext(text)
#
def gettext(self):
return self.editor.gettext(text)
#
# Downcalls from parent to child
#
def destroy(self):
del self.parent
del self.editor
del self.window
#
def getminsize(self, m, (width, height)):
width = max(0, width - 2*self.dh)
height = max(0, height - 2*self.dv)
if width > 0 and self.editor:
(left, top), (right, bottom) = self.editor.getrect()
act_width, act_height = right - left, bottom - top
if width >= act_width:
width = width + 2*self.dh
height = max(height, act_height) + 2*self.dv
return width, height
width = max(width, self.cols*m.textwidth('in')/2) + 2*self.dh
height = max(height, self.rows*m.lineheight()) + 2*self.dv
return width, height
#
def setbounds(self, bounds):
self.bounds = bounds
if self.editor:
(left, top), (right, bottom) = bounds
left = left + self.dh
top = top + self.dv
right = right - self.dh
bottom = bottom - self.dv
self.editor.move((left, top), (right, bottom))
if self.dh and self.dv:
(left, top), (right, bottom) = bounds
left = left + 1
top = top + 1
right = right - 1
bottom = bottom - 1
bounds = (left, top), (right, bottom)
self.editor.setview(bounds)
#
def getbounds(self):
return self.bounds
#
def realize(self):
self.window = self.parent.getwindow()
(left, top), (right, bottom) = self.bounds
left = left + self.dh
top = top + self.dv
right = right - self.dh
bottom = bottom - self.dv
self.editor = \
self.window.textcreate((left, top), (right, bottom))
self.editor.setactive(0)
bounds = self.bounds
if self.dh and self.dv:
(left, top), (right, bottom) = bounds
left = left + 1
top = top + 1
right = right - 1
bottom = bottom - 1
bounds = (left, top), (right, bottom)
self.editor.setview(bounds)
self.editor.settext(self.text)
self.parent.need_mouse(self)
self.parent.need_keybd(self)
self.parent.need_altdraw(self)
#
def draw(self, d, area):
if self.dh and self.dv:
d.box(self.bounds)
#
def altdraw(self, area):
self.editor.draw(area)
#
# Event downcalls
#
def mouse_down(self, detail):
x = self.editor.event(WE_MOUSE_DOWN, self.window, detail)
#
def mouse_move(self, detail):
x = self.editor.event(WE_MOUSE_MOVE, self.window, detail)
#
def mouse_up(self, detail):
x = self.editor.event(WE_MOUSE_UP, self.window, detail)
#
def keybd(self, type, detail):
x = self.editor.event(type, self.window, detail)
#
def activate(self):
self.editor.setfocus(0, 30000)
self.editor.setactive(1)
#
def deactivate(self):
self.editor.setactive(0)
#

View file

@ -1,123 +0,0 @@
# A class that sits transparently between a parent and one child.
# First create the parent, then this thing, then the child.
# Use this as a base class for objects that are almost transparent.
# Don't use as a base class for parents with multiple children.
Error = 'TransParent.Error' # Exception
class ManageOneChild:
#
# Upcalls shared with other single-child parents
#
def addchild(self, child):
if self.child:
raise Error, 'addchild: one child only'
if not child:
raise Error, 'addchild: bad child'
self.child = child
#
def delchild(self, child):
if not self.child:
raise Error, 'delchild: no child'
if child <> self.child:
raise Error, 'delchild: not my child'
self.child = 0
class TransParent(ManageOneChild):
#
# Calls from creator
# NB derived classes may add parameters to create()
#
def create(self, parent):
parent.addchild(self)
self.parent = parent
self.child = None # No child yet
return self
#
# Downcalls from parent to child
#
def destroy(self):
del self.parent
if self.child: self.child.destroy()
del self.child
#
def getminsize(self, args):
if not self.child:
m, size = args
return size
else:
return self.child.getminsize(args)
def getbounds(self, bounds):
if not self.child:
raise Error, 'getbounds w/o child'
else:
return self.child.getbounds()
def setbounds(self, bounds):
if not self.child:
raise Error, 'setbounds w/o child'
else:
self.child.setbounds(bounds)
def realize(self):
if self.child:
self.child.realize()
def draw(self, d, area):
if self.child:
self.child.draw(d, area)
def altdraw(self, area):
if self.child:
self.child.altdraw(area)
#
# Downcalls only made after certain upcalls
#
def mouse_down(self, detail):
if self.child: self.child.mouse_down(detail)
def mouse_move(self, detail):
if self.child: self.child.mouse_move(detail)
def mouse_up(self, detail):
if self.child: self.child.mouse_up(detail)
#
def keybd(self, type_detail):
self.child.keybd(type_detail)
def activate(self):
self.child.activate()
def deactivate(self):
self.child.deactivate()
#
def timer(self):
if self.child: self.child.timer()
#
# Upcalls from child to parent
#
def need_mouse(self, child):
self.parent.need_mouse(self)
def no_mouse(self, child):
self.parent.no_mouse(self)
#
def need_timer(self, child):
self.parent.need_timer(self)
def no_timer(self, child):
self.parent.no_timer(self)
#
def need_altdraw(self, child):
self.parent.need_altdraw(self)
def no_altdraw(self, child):
self.parent.no_altdraw(self)
#
def need_keybd(self, child):
self.parent.need_keybd(self)
def no_keybd(self, child):
self.parent.no_keybd(self)
#
def begindrawing(self):
return self.parent.begindrawing()
def beginmeasuring(self):
return self.parent.beginmeasuring()
def getwindow(self):
return self.parent.getwindow()
#
def change(self, area):
self.parent.change(area)
def scroll(self, area, vector):
self.parent.scroll(area, vector)
def settimer(self, itimer):
self.parent.settimer(itimer)

View file

@ -1,47 +0,0 @@
# Module 'VUMeter'
import audio
from StripChart import StripChart
K = 1024
Rates = [0, 32*K, 16*K, 8*K]
class VUMeter(StripChart):
#
# Override define() and timer() methods
#
def define(self, parent):
self = StripChart.define(self, (parent, 128))
self.parent.need_timer(self)
self.sampling = 0
self.rate = 3
self.enable(0)
return self
#
def timer(self):
if self.sampling:
chunk = audio.wait_recording()
self.sampling = 0
nums = audio.chr2num(chunk)
ampl = max(abs(min(nums)), abs(max(nums)))
self.append(ampl)
if self.enabled and not self.sampling:
audio.setrate(self.rate)
size = Rates[self.rate]/10
size = size/48*48
audio.start_recording(size)
self.sampling = 1
if self.sampling:
self.parent.settimer(1)
#
# New methods: start() and stop()
#
def stop(self):
if self.sampling:
chunk = audio.stop_recording()
self.sampling = 0
self.enable(0)
#
def start(self):
self.enable(1)
self.timer()

View file

@ -1,189 +0,0 @@
# A 'WindowParent' is the only module that uses real stdwin functionality.
# It is the root of the tree.
# It should have exactly one child when realized.
#
# There is also an alternative interface to "mainloop" here.
import stdwin
from stdwinevents import *
import mainloop
from TransParent import ManageOneChild
Error = 'WindowParent.Error' # Exception
class WindowParent(ManageOneChild):
#
def create(self, title, size):
self.title = title
self.size = size # (width, height)
self._reset()
self.close_hook = WindowParent.delayed_destroy
return self
#
def _reset(self):
self.child = None
self.win = None
self.itimer = 0
self.do_mouse = 0
self.do_keybd = 0
self.do_timer = 0
self.do_altdraw = 0
self.pending_destroy = 0
self.close_hook = None
self.menu_hook = None
#
def destroy(self):
mainloop.unregister(self.win)
if self.child: self.child.destroy()
self._reset()
#
def delayed_destroy(self):
# This interface to be used by 'Close' buttons etc.;
# destroying a window from within a button hook
# is not a good idea...
self.pending_destroy = 1
#
def close_trigger(self):
if self.close_hook: self.close_hook(self)
#
def menu_trigger(self, menu, item):
if self.menu_hook:
self.menu_hook(self, menu, item)
#
def need_mouse(self, child): self.do_mouse = 1
def no_mouse(self, child): self.do_mouse = 0
#
def need_keybd(self, child):
self.do_keybd = 1
self.child.activate()
def no_keybd(self, child):
self.do_keybd = 0
self.child.deactivate()
#
def need_timer(self, child): self.do_timer = 1
def no_timer(self, child): self.do_timer = 0
#
def need_altdraw(self, child): self.do_altdraw = 1
def no_altdraw(self, child): self.do_altdraw = 0
#
def realize(self):
if self.win:
raise Error, 'realize(): called twice'
if not self.child:
raise Error, 'realize(): no child'
# Compute suggested size
self.size = self.child.getminsize(self.beginmeasuring(), \
self.size)
save_defsize = stdwin.getdefwinsize()
scrwidth, scrheight = stdwin.getscrsize()
width, height = self.size
if width > scrwidth:
width = scrwidth * 2/3
if height > scrheight:
height = scrheight * 2/3
stdwin.setdefwinsize(width, height)
self.hbar, self.vbar = stdwin.getdefscrollbars()
self.win = stdwin.open(self.title)
stdwin.setdefwinsize(save_defsize)
self.win.setdocsize(self.size)
if self.itimer:
self.win.settimer(self.itimer)
width, height = self.win.getwinsize()
if self.hbar:
width = self.size[0]
if self.vbar:
height = self.size[1]
self.child.setbounds(((0, 0), (width, height)))
self.child.realize()
self.win.dispatch = self.dispatch
mainloop.register(self.win)
#
def fixup(self):
# XXX This could share code with realize() above
self.size = self.child.getminsize(self.beginmeasuring(), \
self.win.getwinsize())
self.win.setdocsize(self.size)
width, height = self.win.getwinsize()
if self.hbar:
width = self.size[0]
if self.vbar:
height = self.size[1]
self.child.setbounds(((0, 0), (width, height)))
# Force a redraw of the entire window:
self.win.change((0, 0), self.size)
#
def beginmeasuring(self):
# Return something with which a child can measure text
if self.win:
return self.win.begindrawing()
else:
return stdwin
#
def begindrawing(self):
if self.win:
return self.win.begindrawing()
else:
raise Error, 'begindrawing(): not realized yet'
#
def getwindow(self):
if self.win:
return self.win
else:
raise Error, 'getwindow(): not realized yet'
#
def change(self, area):
if self.win:
self.win.change(area)
#
def scroll(self, area, vector):
if self.win:
self.win.scroll(area, vector)
#
def settimer(self, itimer):
if self.win:
self.win.settimer(itimer)
else:
self.itimer = itimer
#
# Only call dispatch once we are realized
#
def dispatch(self, (type, win, detail)):
if type == WE_DRAW:
d = self.win.begindrawing()
self.child.draw(d, detail)
del d
if self.do_altdraw: self.child.altdraw(detail)
elif type == WE_MOUSE_DOWN:
if self.do_mouse: self.child.mouse_down(detail)
elif type == WE_MOUSE_MOVE:
if self.do_mouse: self.child.mouse_move(detail)
elif type == WE_MOUSE_UP:
if self.do_mouse: self.child.mouse_up(detail)
elif type in (WE_CHAR, WE_COMMAND):
if self.do_keybd: self.child.keybd(type, detail)
elif type == WE_TIMER:
if self.do_timer: self.child.timer()
elif type == WE_SIZE:
self.fixup()
elif type == WE_CLOSE:
self.close_trigger()
elif type == WE_MENU:
self.menu_trigger(detail)
if self.pending_destroy:
self.destroy()
#
def MainLoop():
mainloop.mainloop()
def Dispatch(event):
mainloop.dispatch(event)
# Interface used by WindowSched:
def CountWindows():
return mainloop.countwindows()
def AnyWindow():
return mainloop.anywindow()

View file

@ -1,62 +0,0 @@
# Combine a real-time scheduling queue and stdwin event handling.
# Keeps times in milliseconds.
import stdwin, stdwinq
from stdwinevents import WE_TIMER
import mainloop
import sched
import time
# Delay function called by the scheduler when it has nothing to do.
# Return immediately when something is done, or when the delay is up.
#
def delayfunc(msecs):
msecs = int(msecs)
#
# Check for immediate stdwin event
#
event = stdwinq.pollevent()
if event:
mainloop.dispatch(event)
return
#
# Use sleep for very short delays or if there are no windows
#
if msecs < 100 or mainloop.countwindows() == 0:
if msecs > 0:
time.sleep(msecs * 0.001)
return
#
# Post a timer event on an arbitrary window and wait for it
#
window = mainloop.anywindow()
window.settimer(msecs/100)
event = stdwinq.getevent()
window.settimer(0)
if event[0] <> WE_TIMER:
mainloop.dispatch(event)
def millitimer():
return time.time() * 1000
q = sched.scheduler(millitimer, delayfunc)
# Export functions enter, enterabs and cancel just like a scheduler
#
enter = q.enter
enterabs = q.enterabs
cancel = q.cancel
# Emptiness check must check both queues
#
def empty():
return q.empty() and mainloop.countwindows() == 0
# Run until there is nothing left to do
#
def run():
while not empty():
if q.empty():
mainloop.dispatch(stdwinq.getevent())
else:
q.run()

View file

@ -1,14 +0,0 @@
# Module 'anywin'
# Open a file or directory in a window
import dirwin
import filewin
import os
def open(name):
print 'opening', name, '...'
if os.path.isdir(name):
w = dirwin.open(name)
else:
w = filewin.open(name)
return w

View file

@ -1,64 +0,0 @@
# basewin.py
import stdwin
import mainloop
from stdwinevents import *
class BaseWindow:
def __init__(self, title):
self.win = stdwin.open(title)
self.win.dispatch = self.dispatch
mainloop.register(self.win)
# def reopen(self):
# title = self.win.gettitle()
# winpos = self.win.getwinpos()
# winsize = self.win.getwinsize()
# origin = self.win.getorigin()
# docsize = self.win.getdocsize()
# mainloop.unregister(self.win)
# del self.win.dispatch
# self.win.close()
# stdwin.setdefwinpos(winpos)
# stdwin.setdefwinsize(winsize)
# self.win = stdwin.open(title)
# stdwin.setdefwinpos(0, 0)
# stdwin.setdefwinsize(0, 0)
# self.win.setdocsize(docsize)
# self.win.setorigin(origin)
# self.win.dispatch = self.dispatch
# mainloop.register(self.win)
def popup(self):
if self.win is not stdwin.getactive():
self.win.setactive()
def close(self):
mainloop.unregister(self.win)
del self.win.dispatch
self.win.close()
def dispatch(self, event):
type, win, detail = event
if type == WE_CHAR:
self.char(detail)
elif type == WE_COMMAND:
self.command(detail)
elif type == WE_MOUSE_DOWN:
self.mouse_down(detail)
elif type == WE_MOUSE_MOVE:
self.mouse_move(detail)
elif type == WE_MOUSE_UP:
self.mouse_up(detail)
elif type == WE_DRAW:
self.draw(detail)
elif type == WE_CLOSE:
self.close()
def no_op(self, detail):
pass
char = command = mouse_down = mouse_move = mouse_up = draw = no_op
def refreshall(self):
self.win.change((-10, 0), (10000, 30000))

View file

@ -1,29 +0,0 @@
# Module 'dirwin'
# Directory windows, a subclass of listwin
import os
import gwin
import listwin
import anywin
import dircache
def action(w, string, i, detail):
(h, v), clicks, button, mask = detail
if clicks == 2:
name = os.path.join(w.name, string)
try:
w2 = anywin.open(name)
w2.parent = w
except os.error, why:
stdwin.message('Can\'t open ' + name + ': ' + why[1])
def open(name):
name = os.path.join(name, '')
list = dircache.opendir(name)[:]
list.sort()
dircache.annotate(name, list)
w = listwin.open(name, list)
w.name = name
w.action = action
return w

View file

@ -1,20 +0,0 @@
# Module 'filewin'
# File windows, a subclass of textwin (which is a subclass of gwin)
import textwin
import __builtin__
# FILE WINDOW
def open_readonly(fn): # Open a file window
fp = __builtin__.open(fn, 'r')
w = textwin.open_readonly(fn, fp.read())
w.fn = fn
return w
def open(fn): # Open a file window
fp = __builtin__.open(fn, 'r')
w = textwin.open(fn, fp.read())
w.fn = fn
return w

View file

@ -1,207 +0,0 @@
# A class to help applications that do fancy text formatting.
# You create an instance each time you must redraw the window.
# Set the initial left, top and right coordinates;
# then feed it words, font changes and vertical movements.
#
# This class should eventually be extended to support much fancier
# formatting, along the lines of TeX; for now, a very simple model
# is sufficient.
#
class formatter:
#
# Initialize a formatter instance.
# Pass the window's drawing object, and left, top, right
# coordinates of the drawing space as arguments.
#
def __init__(self, d, left, top, right):
self.d = d # Drawing object
self.left = left # Left margin
self.right = right # Right margin
self.v = top # Top of current line
self.center = 0
self.justify = 1
self.setfont('') # Default font
self._reset() # Prepare for new line
#
# Reset for start of fresh line.
#
def _reset(self):
self.boxes = [] # Boxes and glue still to be output
self.sum_width = 0 # Total width of boxes
self.sum_space = 0 # Total space between boxes
self.sum_stretch = 0 # Total stretch for space between boxes
self.max_ascent = 0 # Max ascent of current line
self.max_descent = 0 # Max descent of current line
self.avail_width = self.right - self.left
self.hang_indent = 0
#
# Set the current font, and compute some values from it.
#
def setfont(self, font):
self.font = font
self.d.setfont(font)
self.font_space = self.d.textwidth(' ')
self.font_ascent = self.d.baseline()
self.font_descent = self.d.lineheight() - self.font_ascent
#
# Add a word to the list of boxes; first flush if line is full.
# Space and stretch factors are expressed in fractions
# of the current font's space width.
# (Two variations: one without, one with explicit stretch factor.)
#
def addword(self, word, spacefactor):
self.addwordstretch(word, spacefactor, spacefactor)
#
def addwordstretch(self, word, spacefactor, stretchfactor):
width = self.d.textwidth(word)
if width > self.avail_width:
self._flush(1)
space = int(float(self.font_space) * float(spacefactor))
stretch = int(float(self.font_space) * float(stretchfactor))
box = (self.font, word, width, space, stretch)
self.boxes.append(box)
self.sum_width = self.sum_width + width
self.sum_space = self.sum_space + space
self.sum_stretch = self.sum_stretch + stretch
self.max_ascent = max(self.font_ascent, self.max_ascent)
self.max_descent = max(self.font_descent, self.max_descent)
self.avail_width = self.avail_width - width - space
#
# Flush current line and start a new one.
# Flushing twice is harmless (i.e. does not introduce a blank line).
# (Two versions: the internal one has a parameter for justification.)
#
def flush(self):
self._flush(0)
#
def _flush(self, justify):
if not self.boxes:
return
#
# Compute amount of stretch needed.
#
if justify and self.justify or self.center:
#
# Compute extra space to fill;
# this is avail_width plus glue from last box.
# Also compute available stretch.
#
last_box = self.boxes[len(self.boxes)-1]
font, word, width, space, stretch = last_box
tot_extra = self.avail_width + space
tot_stretch = self.sum_stretch - stretch
else:
tot_extra = tot_stretch = 0
#
# Output the boxes.
#
baseline = self.v + self.max_ascent
h = self.left + self.hang_indent
if self.center:
h = h + tot_extra / 2
tot_extra = tot_stretch = 0
for font, word, width, space, stretch in self.boxes:
self.d.setfont(font)
v = baseline - self.d.baseline()
self.d.text((h, v), word)
h = h + width + space
if tot_extra > 0 and tot_stretch > 0:
extra = stretch * tot_extra / tot_stretch
h = h + extra
tot_extra = tot_extra - extra
tot_stretch = tot_stretch - stretch
#
# Prepare for next line.
#
self.v = baseline + self.max_descent
self.d.setfont(self.font)
self._reset()
#
# Add vertical space; first flush.
# Vertical space is expressed in fractions of the current
# font's line height.
#
def vspace(self, lines):
self.vspacepixels(int(lines * self.d.lineheight()))
#
# Add vertical space given in pixels.
#
def vspacepixels(self, dv):
self.flush()
self.v = self.v + dv
#
# Set temporary (hanging) indent, for paragraph start.
# First flush.
#
def tempindent(self, space):
self.flush()
hang = int(float(self.font_space) * float(space))
self.hang_indent = hang
self.avail_width = self.avail_width - hang
#
# Add (permanent) left indentation. First flush.
#
def addleftindent(self, space):
self.flush()
self.left = self.left \
+ int(float(self.font_space) * float(space))
self._reset()
#
# Test procedure
#
def test():
import stdwin, stdwinq
from stdwinevents import *
try:
import mac
# Mac font assignments:
font1 = 'times', '', 12
font2 = 'times', 'b', 14
except ImportError:
# X11R4 font assignments
font1 = '*times-medium-r-*-120-*'
font2 = '*times-bold-r-*-140-*'
words = \
['The','quick','brown','fox','jumps','over','the','lazy','dog.']
words = words * 2
stage = 0
stages = [(0,0,'ragged'), (1,0,'justified'), (0,1,'centered')]
justify, center, title = stages[stage]
stdwin.setdefwinsize(300,200)
w = stdwin.open(title)
winsize = w.getwinsize()
while 1:
type, window, detail = stdwinq.getevent()
if type == WE_CLOSE:
break
elif type == WE_SIZE:
newsize = w.getwinsize()
if newsize <> winsize:
w.change((0,0), winsize)
winsize = newsize
w.change((0,0), winsize)
elif type == WE_MOUSE_DOWN:
stage = (stage + 1) % len(stages)
justify, center, title = stages[stage]
w.settitle(title)
w.change((0, 0), (1000, 1000))
elif type == WE_DRAW:
width, height = winsize
f = formatter(w.begindrawing(), 0, 0, width)
f.center = center
f.justify = justify
if not center:
f.tempindent(5)
for font in font1, font2, font1:
f.setfont(font)
for word in words:
space = 1 + (word[-1:] == '.')
f.addword(word, space)
if center and space > 1:
f.flush()
f.flush()
height = f.v
del f
w.setdocsize(0, height)

View file

@ -1,110 +0,0 @@
# Module 'gwin'
# Generic stdwin windows
# This is used as a base class from which to derive other window types.
# XXX DON'T USE THIS CODE ANY MORE! It is ages old!
import stdwin, stdwinq
from stdwinevents import *
from mainloop import mainloop, register, unregister, windows
# Open a window
def open(title): # Open a generic window
w = stdwin.open(title)
stdwin.setdefwinsize(0, 0)
# Set default event handlers
w.draw = nop
w.char = nop
w.mdown = nop
w.mmove = nop
w.mup = nop
w.m2down = m2down
w.m2up = m2up
w.size = nop
w.move = nop
w.activate = w.deactivate = nop
w.timer = nop
# default command handlers
w.close = close
w.tab = tab
w.enter = enter
w.backspace = backspace
w.arrow = arrow
w.kleft = w.kup = w.kright = w.kdown = nop
w.dispatch = treatevent
register(w)
return w
def treatevent(e): # Handle a stdwin event
type, w, detail = e
if type == WE_DRAW:
w.draw(w, detail)
elif type == WE_MENU:
m, item = detail
m.action[item](w, m, item)
elif type == WE_COMMAND:
treatcommand(w, detail)
elif type == WE_CHAR:
w.char(w, detail)
elif type == WE_MOUSE_DOWN:
if detail[1] > 1: w.m2down(w, detail)
else: w.mdown(w, detail)
elif type == WE_MOUSE_MOVE:
w.mmove(w, detail)
elif type == WE_MOUSE_UP:
if detail[1] > 1: w.m2up(w, detail)
else: w.mup(w, detail)
elif type == WE_SIZE:
w.size(w, w.getwinsize())
elif type == WE_ACTIVATE:
w.activate(w)
elif type == WE_DEACTIVATE:
w.deactivate(w)
elif type == WE_MOVE:
w.move(w)
elif type == WE_TIMER:
w.timer(w)
elif type == WE_CLOSE:
w.close(w)
def treatcommand(w, type): # Handle a we_command event
if type == WC_CLOSE:
w.close(w)
elif type == WC_RETURN:
w.enter(w)
elif type == WC_TAB:
w.tab(w)
elif type == WC_BACKSPACE:
w.backspace(w)
elif type in (WC_LEFT, WC_UP, WC_RIGHT, WC_DOWN):
w.arrow(w, type)
# Methods
def close(w): # Close method
unregister(w)
del w.close # Delete our close function
w.close() # Call the close method
def arrow(w, detail): # Arrow key method
if detail == WC_LEFT:
w.kleft(w)
elif detail == WC_UP:
w.kup(w)
elif detail == WC_RIGHT:
w.kright(w)
elif detail == WC_DOWN:
w.kdown(w)
# Trivial methods
def tab(w): w.char(w, '\t')
def enter(w): w.char(w, '\n') # 'return' is a Python reserved word
def backspace(w): w.char(w, '\b')
def m2down(w, detail): w.mdown(w, detail)
def m2up(w, detail): w.mup(w, detail)
def nop(*args): pass

View file

@ -1,47 +0,0 @@
# Module 'listwin'
# List windows, a subclass of gwin
import gwin
import stdwin
def maxlinewidth(a): # Compute maximum textwidth of lines in a sequence
max = 0
for line in a:
width = stdwin.textwidth(line)
if width > max: max = width
return max
def action(w, string, i, detail): # Default item selection method
pass
def mup(w, detail): # Mouse up method
(h, v), clicks, button, mask = detail
i = divmod(v, w.lineheight)[0]
if 0 <= i < len(w.data):
w.action(w, w.data[i], i, detail)
def draw(w, ((left, top), (right, bottom))): # Text window draw method
data = w.data
d = w.begindrawing()
lh = w.lineheight
itop = top/lh
ibot = (bottom-1)/lh + 1
if itop < 0: itop = 0
if ibot > len(data): ibot = len(data)
for i in range(itop, ibot): d.text((0, i*lh), data[i])
def open(title, data): # Display a list of texts in a window
lineheight = stdwin.lineheight()
h, v = maxlinewidth(data), len(data)*lineheight
h0, v0 = h + stdwin.textwidth(' '), v + lineheight
if h0 > stdwin.textwidth(' ')*80: h0 = 0
if v0 > stdwin.lineheight()*24: v0 = 0
stdwin.setdefwinsize(h0, v0)
w = gwin.open(title)
w.setdocsize(h, v)
w.lineheight = lineheight
w.data = data
w.draw = draw
w.action = action
w.mup = mup
return w

View file

@ -1,256 +0,0 @@
# Standard main loop for *all* STDWIN applications.
# This requires that applications:
# - register their windows on creation and unregister them when closed
# - have a 'dispatch' function as a window member
import stdwin, stdwinq
from stdwinevents import *
# List of windows known to the main loop.
#
windows = []
# Last window that ever received an event
#
last_window = None
# Function to register a window.
#
def register(win):
# First test the dispatch function by passing it a null event --
# this catches registration of unconforming windows.
win.dispatch((WE_NULL, win, None))
if win not in windows:
windows.append(win)
# Function to unregister a window.
# It is not an error to unregister an already unregistered window
# (this is useful for cleanup actions).
#
def unregister(win):
global last_window
if win == last_window:
last_window = None
if win in windows:
windows.remove(win) # Not in 0.9.1
# 0.9.1 solution:
#for i in range(len(windows)):
# if windows[i] = win:
# del windows[i]
# break
# Interfaces used by WindowSched.
#
def countwindows():
return len(windows)
#
def anywindow():
if windows:
return windows[0]
else:
return None
# NEW: register any number of file descriptors
#
fdlist = []
select_args = None
select_handlers = None
#
def registerfd(fd, mode, handler):
if mode not in ('r', 'w', 'x'):
raise ValueError, 'mode must be r, w or x'
if type(fd) <> type(0):
fd = fd.fileno() # If this fails it's not a proper select arg
for i in range(len(fdlist)):
if fdlist[i][:2] == (fd, mode):
raise ValueError, \
'(fd, mode) combination already registered'
fdlist.append((fd, mode, handler))
make_select_args()
#
def unregisterfd(fd, *args):
if type(fd) <> type(0):
fd = fd.fileno() # If this fails it's not a proper select arg
args = (fd,) + args
n = len(args)
for i in range(len(fdlist)):
if fdlist[i][:n] == args:
del fdlist[i]
make_select_args()
#
def make_select_args():
global select_args, select_handlers
rlist, wlist, xlist = [], [], []
rhandlers, whandlers, xhandlers = {}, {}, {}
for fd, mode, handler in fdlist:
if mode == 'r':
rlist.append(fd)
rhandlers[`fd`] = handler
if mode == 'w':
wlist.append(fd)
whandlers[`fd`] = handler
if mode == 'x':
xlist.append(fd)
xhandlers[`fd`] = handler
if rlist or wlist or xlist:
select_args = rlist, wlist, xlist
select_handlers = rhandlers, whandlers, xhandlers
else:
select_args = None
select_handlers = None
#
def do_select():
import select
reply = apply(select.select, select_args)
for mode in 0, 1, 2:
list = reply[mode]
for fd in list:
handler = select_handlers[mode][`fd`]
handler(fd, 'rwx'[mode])
# Event processing main loop.
# Return when there are no windows left, or when an unhandled
# exception occurs. (It is safe to restart the main loop after
# an unsuccessful exit.)
# Python's stdwin.getevent() turns WE_COMMAND/WC_CANCEL events
# into KeyboardInterrupt exceptions; these are turned back in events.
#
recursion_level = 0 # Hack to make it reentrant
def mainloop():
global recursion_level
recursion_level = recursion_level + 1
try:
stdwin_select_handler() # Process events already in queue
while 1:
if windows and not fdlist:
while windows and not fdlist:
try:
event = stdwinq.getevent()
except KeyboardInterrupt:
event = (WE_COMMAND, \
None, WC_CANCEL)
dispatch(event)
elif windows and fdlist:
fd = stdwin.fileno()
if recursion_level == 1:
registerfd(fd, 'r', stdwin_select_handler)
try:
while windows:
do_select()
stdwin_select_handler()
finally:
if recursion_level == 1:
unregisterfd(fd)
elif fdlist:
while fdlist and not windows:
do_select()
else:
break
finally:
recursion_level = recursion_level - 1
# Check for events without ever blocking
#
def check():
stdwin_select_handler()
# XXX Should check for socket stuff as well
# Handle stdwin events until none are left
#
def stdwin_select_handler(*args):
while 1:
try:
event = stdwinq.pollevent()
except KeyboardInterrupt:
event = (WE_COMMAND, None, WC_CANCEL)
if event is None:
break
dispatch(event)
# Run a modal dialog loop for a window. The dialog window must have
# been registered first. This prohibits most events (except size/draw
# events) to other windows. The modal dialog loop ends when the
# dialog window unregisters itself.
#
passthrough = WE_SIZE, WE_DRAW
beeping = WE_MOUSE_DOWN, WE_COMMAND, WE_CHAR, WE_KEY, WE_CLOSE, WE_MENU
#
def modaldialog(window):
if window not in windows:
raise ValueError, 'modaldialog window not registered'
while window in windows:
try:
event = stdwinq.getevent()
except KeyboardInterrupt:
event = WE_COMMAND, None, WC_CANCEL
etype, ewindow, edetail = event
if etype not in passthrough and ewindow <> window:
if etype in beeping:
stdwin.fleep()
continue
dispatch(event)
# Dispatch a single event.
# Events for the no window in particular are sent to the active window
# or to the last window that received an event (these hacks are for the
# WE_LOST_SEL event, which is directed to no particular window).
# Windows not in the windows list don't get their events:
# events for such windows are silently ignored.
#
def dispatch(event):
global last_window
if event[1] == None:
active = stdwin.getactive()
if active: last_window = active
else:
last_window = event[1]
if last_window in windows:
last_window.dispatch(event)
# Dialog base class
#
class Dialog:
#
def __init__(self, title):
self.window = stdwin.open(title)
self.window.dispatch = self.dispatch
register(self.window)
#
def close(self):
unregister(self.window)
del self.window.dispatch
self.window.close()
#
def dispatch(self, event):
etype, ewindow, edetail = event
if etype == WE_CLOSE:
self.close()
# Standard modal dialogs
# XXX implemented using stdwin dialogs for now
#
def askstr(prompt, default):
return stdwin.askstr(prompt, default)
#
def askync(prompt, yesorno):
return stdwin.askync(prompt, yesorno)
#
def askfile(prompt, default, new):
return stdwin.askfile(prompt, default, new)
#
def message(msg):
stdwin.message(msg)

View file

@ -1,89 +0,0 @@
# Module 'rect'.
#
# Operations on rectangles.
# There is some normalization: all results return the object 'empty'
# if their result would contain no points.
# Exception.
#
error = 'rect.error'
# The empty rectangle.
#
empty = (0, 0), (0, 0)
# Check if a rectangle is empty.
#
def is_empty(r):
(left, top), (right, bottom) = r
return left >= right or top >= bottom
# Compute the intersection or two or more rectangles.
# This works with a list or tuple argument.
#
def intersect(list):
if not list: raise error, 'intersect called with empty list'
if is_empty(list[0]): return empty
(left, top), (right, bottom) = list[0]
for rect in list[1:]:
if is_empty(rect):
return empty
(l, t), (r, b) = rect
if left < l: left = l
if top < t: top = t
if right > r: right = r
if bottom > b: bottom = b
if is_empty(((left, top), (right, bottom))):
return empty
return (left, top), (right, bottom)
# Compute the smallest rectangle containing all given rectangles.
# This works with a list or tuple argument.
#
def union(list):
(left, top), (right, bottom) = list[0]
for (l, t), (r, b) in list[1:]:
if not is_empty(((l, t), (r, b))):
if l < left: left = l
if t < top: top = t
if r > right: right = r
if b > bottom: bottom = b
res = (left, top), (right, bottom)
if is_empty(res):
return empty
return res
# Check if a point is in a rectangle.
#
def pointinrect((h, v), ((left, top), (right, bottom))):
return left <= h < right and top <= v < bottom
# Return a rectangle that is dh, dv inside another
#
def inset(((left, top), (right, bottom)), (dh, dv)):
left = left + dh
top = top + dv
right = right - dh
bottom = bottom - dv
r = (left, top), (right, bottom)
if is_empty(r):
return empty
else:
return r
# Conversions between rectangles and 'geometry tuples',
# given as origin (h, v) and dimensions (width, height).
#
def rect2geom((left, top), (right, bottom)):
return (left, top), (right-left, bottom-top)
def geom2rect((h, v), (width, height)):
return (h, v), (h+width, v+height)

View file

@ -1,129 +0,0 @@
# srcwin.py -- a source listing window
import stdwin
from stdwinevents import *
import basewin
WIDTH = 40
MAXHEIGHT = 24
class TextWindow(basewin.BaseWindow):
def __init__(self, title, contents):
self.contents = contents
self.linecount = countlines(self.contents)
#
self.lineheight = lh = stdwin.lineheight()
self.leftmargin = self.getmargin()
self.top = 0
self.rightmargin = 30000 # Infinity
self.bottom = lh * self.linecount
#
width = WIDTH*stdwin.textwidth('0')
height = lh*min(MAXHEIGHT, self.linecount)
stdwin.setdefwinsize(width, height)
basewin.BaseWindow.__init__(self, title)
#
self.win.setdocsize(0, self.bottom)
self.initeditor()
def initeditor(self):
r = (self.leftmargin, self.top), (self.rightmargin, self.bottom)
self.editor = self.win.textcreate(r)
self.editor.settext(self.contents)
def closeeditor(self):
self.editor.close()
# def reopen(self):
# self.closeeditor()
# basewin.BaseWindow.reopen(self)
# self.initeditor()
# Override the following two methods to format line numbers differently
def getmark(self, lineno):
return `lineno`
def getmargin(self):
return stdwin.textwidth(`self.linecount + 1` + ' ')
# Event dispatcher, called from mainloop.mainloop()
def dispatch(self, event):
if event[0] == WE_NULL: return # Dummy tested by mainloop
if event[0] == WE_DRAW or not self.editor.event(event):
basewin.BaseWindow.dispatch(self, event)
# Event handlers
def close(self):
self.closeeditor()
basewin.BaseWindow.close(self)
def draw(self, detail):
dummy = self.editor.draw(detail)
# Draw line numbers
(left, top), (right, bottom) = detail
topline = top/self.lineheight
botline = bottom/self.lineheight + 1
botline = min(self.linecount, botline)
d = self.win.begindrawing()
try:
h, v = 0, self.lineheight * topline
for lineno in range(topline+1, botline+1):
d.text((h, v), self.getmark(lineno))
v = v + self.lineheight
finally:
d.close()
# Calls from outside
def changemark(self, lineno): # redraw the mark for a line
left = 0
top = (lineno-1) * self.lineheight
right = self.leftmargin
bottom = lineno * self.lineheight
d = self.win.begindrawing()
try:
d.erase((left, top), (right, bottom))
d.text((left, top), self.getmark(lineno))
finally:
d.close()
def showline(self, lineno): # scroll to make a line visible
left = 0
top = (lineno-1) * self.lineheight
right = self.leftmargin
bottom = lineno * self.lineheight
self.win.show((left, top), (right, bottom))
# Subroutine to count the number of lines in a string
def countlines(text):
n = 0
for c in text:
if c == '\n': n = n+1
if text and text[-1] != '\n': n = n+1 # Partial last line
return n
class SourceWindow(TextWindow):
def __init__(self, filename):
self.filename = filename
f = open(self.filename, 'r')
contents = f.read()
f.close()
TextWindow.__init__(self, self.filename, contents)
# ------------------------------ testing ------------------------------
TESTFILE = 'srcwin.py'
def test():
import mainloop
sw = SourceWindow(TESTFILE)
mainloop.mainloop()

View file

@ -1,61 +0,0 @@
# Module 'stdwinevents' -- Constants for stdwin event types
#
# Suggested usage:
# from stdwinevents import *
# The function stdwin.getevent() returns a tuple containing:
# (type, window, detail)
# where detail may be <no value> or a value depending on type, see below:
# Values for type:
WE_NULL = 0 # not reported -- means 'no event' internally
WE_ACTIVATE = 1 # detail is None
WE_CHAR = 2 # detail is the character
WE_COMMAND = 3 # detail is one of the WC_* constants below
WE_MOUSE_DOWN = 4 # detail is ((h, v), clicks, button, mask)
WE_MOUSE_MOVE = 5 # ditto
WE_MOUSE_UP = 6 # ditto
WE_MENU = 7 # detail is (menu, item)
WE_SIZE = 8 # detail is (width, height)
WE_MOVE = 9 # not reported -- reserved for future use
WE_DRAW = 10 # detail is ((left, top), (right, bottom))
WE_TIMER = 11 # detail is None
WE_DEACTIVATE = 12 # detail is None
WE_EXTERN = 13 # detail is None
WE_KEY = 14 # detail is ???
WE_LOST_SEL = 15 # detail is selection number
WE_CLOSE = 16 # detail is None
# Values for detail when type is WE_COMMAND:
WC_CLOSE = 1 # obsolete; now reported as WE_CLOSE
WC_LEFT = 2 # left arrow key
WC_RIGHT = 3 # right arrow key
WC_UP = 4 # up arrow key
WC_DOWN = 5 # down arrow key
WC_CANCEL = 6 # not reported -- turned into KeyboardInterrupt
WC_BACKSPACE = 7 # backspace key
WC_TAB = 8 # tab key
WC_RETURN = 9 # return or enter key
# Selection numbers
WS_CLIPBOARD = 0
WS_PRIMARY = 1
WS_SECONDARY = 2
# Modifier masks in key and mouse events
WM_SHIFT = (1 << 0)
WM_LOCK = (1 << 1)
WM_CONTROL = (1 << 2)
WM_META = (1 << 3)
WM_OPTION = (1 << 4)
WM_NUM = (1 << 5)
WM_BUTTON1 = (1 << 8)
WM_BUTTON2 = (1 << 9)
WM_BUTTON3 = (1 << 10)
WM_BUTTON4 = (1 << 11)
WM_BUTTON5 = (1 << 12)

View file

@ -1,53 +0,0 @@
# Replacements for getevent() and pollevent(),
# and new functions ungetevent() and sync().
# Every library module should ideally use this instead of
# stdwin.{get,poll}event(), so applications can use the services
# of ungetevent() and sync().
import stdwin
# Events read ahead are stored in this queue.
#
queue = []
# Replacement for getevent().
#
def getevent():
if queue:
event = queue[0]
del queue[0]
return event
else:
return stdwin.getevent()
# Replacement for pollevent().
#
def pollevent():
if queue:
return getevent()
else:
return stdwin.pollevent()
# Push an event back in the queue.
#
def ungetevent(event):
queue.insert(0, event)
# Synchronize the display. It turns out that this is the way to
# force STDWIN to call XSync(), which some (esoteric) applications need.
# (This is stronger than just flushing -- it actually waits for a
# positive response from the X server on the last command issued.)
#
def sync():
while 1:
event = stdwin.pollevent()
if not event: break
queue.append(event)

View file

@ -1,236 +0,0 @@
# Module 'tablewin'
# Display a table, with per-item actions:
# A1 | A2 | A3 | .... | AN
# B1 | B2 | B3 | .... | BN
# C1 | C2 | C3 | .... | CN
# .. | .. | .. | .... | ..
# Z1 | Z2 | Z3 | .... | ZN
# Not all columns need to have the same length.
# The data structure is a list of columns;
# each column is a list of items.
# Each item is a pair of a string and an action procedure.
# The first item may be a column title.
import stdwin
import gwin
from stdwinevents import *
def open(title, data): # Public function to open a table window
#
# Set geometry parameters (one day, these may be changeable)
#
margin = stdwin.textwidth(' ')
lineheight = stdwin.lineheight()
#
# Geometry calculations
#
colstarts = [0]
totwidth = 0
maxrows = 0
for coldata in data:
# Height calculations
rows = len(coldata)
if rows > maxrows: maxrows = rows
# Width calculations
width = colwidth(coldata) + margin
totwidth = totwidth + width
colstarts.append(totwidth)
#
# Calculate document and window height
#
docwidth, docheight = totwidth, maxrows*lineheight
winwidth, winheight = docwidth, docheight
if winwidth > stdwin.textwidth('n')*100: winwidth = 0
if winheight > stdwin.lineheight()*30: winheight = 0
#
# Create the window
#
stdwin.setdefwinsize(winwidth, winheight)
w = gwin.open(title)
#
# Set properties and override methods
#
w.data = data
w.margin = margin
w.lineheight = lineheight
w.colstarts = colstarts
w.totwidth = totwidth
w.maxrows = maxrows
w.selection = (-1, -1)
w.lastselection = (-1, -1)
w.selshown = 0
w.setdocsize(docwidth, docheight)
w.draw = draw
w.mup = mup
w.arrow = arrow
#
# Return
#
return w
def update(w, data): # Change the data
#
# Hide selection
#
hidesel(w, w.begindrawing())
#
# Get old geometry parameters
#
margin = w.margin
lineheight = w.lineheight
#
# Geometry calculations
#
colstarts = [0]
totwidth = 0
maxrows = 0
for coldata in data:
# Height calculations
rows = len(coldata)
if rows > maxrows: maxrows = rows
# Width calculations
width = colwidth(coldata) + margin
totwidth = totwidth + width
colstarts.append(totwidth)
#
# Calculate document and window height
#
docwidth, docheight = totwidth, maxrows*lineheight
#
# Set changed properties and change window size
#
w.data = data
w.colstarts = colstarts
w.totwidth = totwidth
w.maxrows = maxrows
w.change((0, 0), (10000, 10000))
w.setdocsize(docwidth, docheight)
w.change((0, 0), (docwidth, docheight))
#
# Show selection, or forget it if out of range
#
showsel(w, w.begindrawing())
if not w.selshown: w.selection = (-1, -1)
def colwidth(coldata): # Subroutine to calculate column width
maxwidth = 0
for string, action in coldata:
width = stdwin.textwidth(string)
if width > maxwidth: maxwidth = width
return maxwidth
def draw(w, ((left, top), (right, bottom))): # Draw method
ileft = whichcol(w, left)
iright = whichcol(w, right-1) + 1
if iright > len(w.data): iright = len(w.data)
itop = divmod(top, w.lineheight)[0]
if itop < 0: itop = 0
ibottom, remainder = divmod(bottom, w.lineheight)
if remainder: ibottom = ibottom + 1
d = w.begindrawing()
if ileft <= w.selection[0] < iright:
if itop <= w.selection[1] < ibottom:
hidesel(w, d)
d.erase((left, top), (right, bottom))
for i in range(ileft, iright):
col = w.data[i]
jbottom = len(col)
if ibottom < jbottom: jbottom = ibottom
h = w.colstarts[i]
v = itop * w.lineheight
for j in range(itop, jbottom):
string, action = col[j]
d.text((h, v), string)
v = v + w.lineheight
showsel(w, d)
def mup(w, detail): # Mouse up method
(h, v), nclicks, button, mask = detail
icol = whichcol(w, h)
if 0 <= icol < len(w.data):
irow = divmod(v, w.lineheight)[0]
col = w.data[icol]
if 0 <= irow < len(col):
string, action = col[irow]
action(w, string, (icol, irow), detail)
def whichcol(w, h): # Return column number (may be >= len(w.data))
for icol in range(0, len(w.data)):
if h < w.colstarts[icol+1]:
return icol
return len(w.data)
def arrow(w, type):
if type == WC_LEFT:
incr = -1, 0
elif type == WC_UP:
incr = 0, -1
elif type == WC_RIGHT:
incr = 1, 0
elif type == WC_DOWN:
incr = 0, 1
else:
return
icol, irow = w.lastselection
icol = icol + incr[0]
if icol < 0: icol = len(w.data)-1
if icol >= len(w.data): icol = 0
if 0 <= icol < len(w.data):
irow = irow + incr[1]
if irow < 0: irow = len(w.data[icol]) - 1
if irow >= len(w.data[icol]): irow = 0
else:
irow = 0
if 0 <= icol < len(w.data) and 0 <= irow < len(w.data[icol]):
w.lastselection = icol, irow
string, action = w.data[icol][irow]
detail = (0, 0), 1, 1, 1
action(w, string, (icol, irow), detail)
# Selection management
# TO DO: allow multiple selected entries
def select(w, selection): # Public function to set the item selection
d = w.begindrawing()
hidesel(w, d)
w.selection = selection
showsel(w, d)
if w.selshown: lastselection = selection
def hidesel(w, d): # Hide the selection, if shown
if w.selshown: invertsel(w, d)
def showsel(w, d): # Show the selection, if hidden
if not w.selshown: invertsel(w, d)
def invertsel(w, d): # Invert the selection, if valid
icol, irow = w.selection
if 0 <= icol < len(w.data) and 0 <= irow < len(w.data[icol]):
left = w.colstarts[icol]
right = w.colstarts[icol+1]
top = irow * w.lineheight
bottom = (irow+1) * w.lineheight
d.invert((left, top), (right, bottom))
w.selshown = (not w.selshown)
# Demonstration
def demo_action(w, string, (icol, irow), detail): # Action function for demo
select(w, (irow, icol))
def demo(): # Demonstration
da = demo_action # shorthand
col0 = [('a1', da), ('bbb1', da), ('c1', da)]
col1 = [('a2', da), ('bbb2', da)]
col2 = [('a3', da), ('b3', da), ('c3', da), ('d4', da), ('d5', da)]
col3 = []
for i in range(1, 31): col3.append(('xxx' + `i`, da))
data = [col0, col1, col2, col3]
w = open('tablewin.demo', data)
gwin.mainloop()
return w

View file

@ -1,117 +0,0 @@
# Module 'textwin'
# Text windows, a subclass of gwin
import stdwin
import gwin
from stdwinevents import *
def fixsize(w):
docwidth, docheight = w.text.getrect()[1]
winheight = w.getwinsize()[1]
if winheight > docheight: docheight = winheight
w.setdocsize(0, docheight)
fixeditmenu(w)
def cut(w, m, id):
s = w.text.getfocustext()
if s:
stdwin.setcutbuffer(0, s)
w.text.replace('')
fixsize(w)
def copy(w, m, id):
s = w.text.getfocustext()
if s:
stdwin.setcutbuffer(0, s)
fixeditmenu(w)
def paste(w, m, id):
w.text.replace(stdwin.getcutbuffer(0))
fixsize(w)
def addeditmenu(w):
m = w.editmenu = w.menucreate('Edit')
m.action = []
m.additem('Cut', 'X')
m.action.append(cut)
m.additem('Copy', 'C')
m.action.append(copy)
m.additem('Paste', 'V')
m.action.append(paste)
def fixeditmenu(w):
m = w.editmenu
f = w.text.getfocus()
can_copy = (f[0] < f[1])
m.enable(1, can_copy)
if not w.readonly:
m.enable(0, can_copy)
m.enable(2, (stdwin.getcutbuffer(0) <> ''))
def draw(w, area): # Draw method
w.text.draw(area)
def size(w, newsize): # Size method
w.text.move((0, 0), newsize)
fixsize(w)
def close(w): # Close method
del w.text # Break circular ref
gwin.close(w)
def char(w, c): # Char method
w.text.replace(c)
fixsize(w)
def backspace(w): # Backspace method
void = w.text.event(WE_COMMAND, w, WC_BACKSPACE)
fixsize(w)
def arrow(w, detail): # Arrow method
w.text.arrow(detail)
fixeditmenu(w)
def mdown(w, detail): # Mouse down method
void = w.text.event(WE_MOUSE_DOWN, w, detail)
fixeditmenu(w)
def mmove(w, detail): # Mouse move method
void = w.text.event(WE_MOUSE_MOVE, w, detail)
def mup(w, detail): # Mouse up method
void = w.text.event(WE_MOUSE_UP, w, detail)
fixeditmenu(w)
def activate(w): # Activate method
fixeditmenu(w)
def open(title, str): # Display a string in a window
w = gwin.open(title)
w.readonly = 0
w.text = w.textcreate((0, 0), w.getwinsize())
w.text.replace(str)
w.text.setfocus(0, 0)
addeditmenu(w)
fixsize(w)
w.draw = draw
w.size = size
w.close = close
w.mdown = mdown
w.mmove = mmove
w.mup = mup
w.char = char
w.backspace = backspace
w.arrow = arrow
w.activate = activate
return w
def open_readonly(title, str): # Same with char input disabled
w = open(title, str)
w.readonly = 1
w.char = w.backspace = gwin.nop
# Disable Cut and Paste menu item; leave Copy alone
w.editmenu.enable(0, 0)
w.editmenu.enable(2, 0)
return w

View file

@ -1,316 +0,0 @@
# wdb.py -- a window-based Python debugger
# XXX To do:
# - don't fall out of bottom frame
import stdwin
from stdwinevents import *
import sys
import basewin
import bdb
import repr
WIDTH = 40
HEIGHT = 8
WdbDone = 'wdb.WdbDone' # Exception to continue execution
class Wdb(bdb.Bdb, basewin.BaseWindow): # Window debugger
def __init__(self):
self.sourcewindows = {}
self.framewindows = {}
bdb.Bdb.__init__(self)
width = WIDTH*stdwin.textwidth('0')
height = HEIGHT*stdwin.lineheight()
stdwin.setdefwinsize(width, height)
basewin.BaseWindow.__init__(self, '--Stack--')
self.closed = 0
def reset(self):
if self.closed: raise RuntimeError, 'already closed'
bdb.Bdb.reset(self)
self.forget()
def forget(self):
self.lineno = None
self.stack = []
self.curindex = 0
self.curframe = None
for fn in self.sourcewindows.keys():
self.sourcewindows[fn].resetlineno()
def setup(self, f, t):
self.forget()
self.stack, self.curindex = self.get_stack(f, t)
self.curframe = self.stack[self.curindex][0]
# Build a list of current frames
cfl = []
for f, i in self.stack: cfl.append(f)
# Remove deactivated frame windows
for name in self.framewindows.keys():
fw = self.framewindows[name]
if fw.frame not in cfl: fw.close()
else: fw.refreshframe()
# Refresh the stack window
self.refreshstack()
# Override Bdb methods (except user_call, for now)
def user_line(self, frame):
# This function is called when we stop or break at this line
self.interaction(frame, None)
def user_return(self, frame, return_value):
# This function is called when a return trap is set here
frame.f_locals['__return__'] = return_value
self.settitle('--Return--')
self.interaction(frame, None)
if not self.closed:
self.settitle('--Stack--')
def user_exception(self, frame, (exc_type, exc_value, exc_traceback)):
# This function is called if an exception occurs,
# but only if we are to stop at or just below this level
frame.f_locals['__exception__'] = exc_type, exc_value
if type(exc_type) == type(''):
exc_type_name = exc_type
else: exc_type_name = exc_type.__name__
self.settitle(exc_type_name + ': ' + repr.repr(exc_value))
stdwin.fleep()
self.interaction(frame, exc_traceback)
if not self.closed:
self.settitle('--Stack--')
# Change the title
def settitle(self, title):
self.savetitle = self.win.gettitle()
self.win.settitle(title)
# General interaction function
def interaction(self, frame, traceback):
import mainloop
self.popup()
self.setup(frame, traceback)
try:
mainloop.mainloop()
except WdbDone:
pass
self.forget()
# Functions whose name is do_X for some character X
# are callable directly from the keyboard.
def do_up(self):
if self.curindex == 0:
stdwin.fleep()
else:
self.curindex = self.curindex - 1
self.curframe = self.stack[self.curindex][0]
self.refreshstack()
do_u = do_up
def do_down(self):
if self.curindex + 1 == len(self.stack):
stdwin.fleep()
else:
self.curindex = self.curindex + 1
self.curframe = self.stack[self.curindex][0]
self.refreshstack()
do_d = do_down
def do_step(self):
self.set_step()
raise WdbDone
do_s = do_step
def do_next(self):
self.set_next(self.curframe)
raise WdbDone
do_n = do_next
def do_return(self):
self.set_return(self.curframe)
raise WdbDone
do_r = do_return
def do_continue(self):
self.set_continue()
raise WdbDone
do_c = do_cont = do_continue
def do_quit(self):
self.close()
raise WdbDone
do_q = do_quit
def do_list(self):
fn = self.curframe.f_code.co_filename
if not self.sourcewindows.has_key(fn):
import wdbsrcwin
try:
self.sourcewindows[fn] = wdbsrcwin. \
DebuggerSourceWindow(self, fn)
except IOError:
stdwin.fleep()
return
w = self.sourcewindows[fn]
lineno = self.stack[self.curindex][1]
w.setlineno(lineno)
w.popup()
do_l = do_list
def do_frame(self):
name = 'locals' + `self.curframe`[16:-1]
if self.framewindows.has_key(name):
self.framewindows[name].popup()
else:
import wdbframewin
self.framewindows[name] = \
wdbframewin.FrameWindow(self, \
self.curframe, \
self.curframe.f_locals, name)
do_f = do_frame
def do_globalframe(self):
name = 'globals' + `self.curframe`[16:-1]
if self.framewindows.has_key(name):
self.framewindows[name].popup()
else:
import wdbframewin
self.framewindows[name] = \
wdbframewin.FrameWindow(self, \
self.curframe, \
self.curframe.f_globals, name)
do_g = do_globalframe
# Link between the debugger and the window
def refreshstack(self):
height = stdwin.lineheight() * (1 + len(self.stack))
self.win.setdocsize((0, height))
self.refreshall() # XXX be more subtle later
# Also pass the information on to the source windows
filename = self.curframe.f_code.co_filename
lineno = self.curframe.f_lineno
for fn in self.sourcewindows.keys():
w = self.sourcewindows[fn]
if fn == filename:
w.setlineno(lineno)
else:
w.resetlineno()
# The remaining methods override BaseWindow methods
def close(self):
if not self.closed:
basewin.BaseWindow.close(self)
self.closed = 1
for key in self.sourcewindows.keys():
self.sourcewindows[key].close()
for key in self.framewindows.keys():
self.framewindows[key].close()
self.set_quit()
def char(self, detail):
try:
func = eval('self.do_' + detail)
except (AttributeError, SyntaxError):
stdwin.fleep()
return
func()
def command(self, detail):
if detail == WC_UP:
self.do_up()
elif detail == WC_DOWN:
self.do_down()
def mouse_down(self, detail):
(h, v), clicks, button, mask = detail
i = v / stdwin.lineheight()
if 0 <= i < len(self.stack):
if i != self.curindex:
self.curindex = i
self.curframe = self.stack[self.curindex][0]
self.refreshstack()
elif clicks == 2:
self.do_frame()
else:
stdwin.fleep()
def draw(self, detail):
import linecache, string
d = self.win.begindrawing()
try:
h, v = 0, 0
for f, lineno in self.stack:
fn = f.f_code.co_filename
if f is self.curframe:
s = '> '
else:
s = ' '
s = s + fn + '(' + `lineno` + ')'
s = s + f.f_code.co_name
if f.f_locals.has_key('__args__'):
args = f.f_locals['__args__']
if args is not None:
s = s + repr.repr(args)
if f.f_locals.has_key('__return__'):
rv = f.f_locals['__return__']
s = s + '->'
s = s + repr.repr(rv)
line = linecache.getline(fn, lineno)
if line: s = s + ': ' + string.strip(line)
d.text((h, v), s)
v = v + d.lineheight()
finally:
d.close()
# Simplified interface
def run(statement, globals=None, locals=None):
x = Wdb()
try: x.run(statement, globals, locals)
finally: x.close()
def runeval(expression, globals=None, locals=None):
x = Wdb()
try: return x.runeval(expression, globals, locals)
finally: x.close()
def runctx(statement, globals, locals):
# B/W compatibility
run(statement, globals, locals)
def runcall(*args):
x = Wdb()
try: return apply(x.runcall, args)
finally: x.close()
def set_trace():
Wdb().set_trace()
# Post-Mortem interface
def post_mortem(traceback):
x = Wdb()
x.reset()
x.interaction(None, traceback)
def pm():
import sys
post_mortem(sys.last_traceback)
# Main program for testing
TESTCMD = 'import x; x.main()'
def test():
run(TESTCMD)

View file

@ -1,146 +0,0 @@
# wdbframewin.py -- frame window for wdb.py
# XXX To do:
# - display function name in window title
# - execute arbitrary statements instead of just evaluating expressions
# - allow setting variables by editing their values
import stdwin
from stdwinevents import *
import basewin
import sys
WIDTH = 40
MINHEIGHT = 8
MAXHEIGHT = 16
class FrameWindow(basewin.BaseWindow):
def __init__(self, debugger, frame, dict, name):
self.debugger = debugger
self.frame = frame # Not used except for identity tests
self.dict = dict
self.name = name
nl = max(MINHEIGHT, len(self.dict) + 5)
nl = min(nl, MAXHEIGHT)
width = WIDTH*stdwin.textwidth('0')
height = nl*stdwin.lineheight()
stdwin.setdefwinsize(width, height)
basewin.BaseWindow.__init__(
self, '--Frame ' + name + '--')
# XXX Should use current function name
self.initeditor()
self.displaylist = ['>>>', '', '-'*WIDTH]
self.refreshframe()
def initeditor(self):
r = (stdwin.textwidth('>>> '), 0), (30000, stdwin.lineheight())
self.editor = self.win.textcreate(r)
def closeeditor(self):
self.editor.close()
def dispatch(self, event):
type, win, detail = event
if type == WE_NULL: return # Dummy tested by mainloop
if type in (WE_DRAW, WE_COMMAND) \
or not self.editor.event(event):
basewin.BaseWindow.dispatch(self, event)
def close(self):
del self.debugger.framewindows[self.name]
del self.debugger, self.dict
self.closeeditor()
basewin.BaseWindow.close(self)
def command(self, detail):
if detail == WC_RETURN:
self.re_eval()
else:
dummy = self.editor.event(WE_COMMAND, \
self.win, detail)
def mouse_down(self, detail):
(h, v), clicks, button, mask = detail
if clicks != 2:
return
i = v / stdwin.lineheight()
if 5 <= i < len(self.displaylist):
import string
name = string.splitfields(self.displaylist[i],' = ')[0]
if not self.dict.has_key(name):
stdwin.fleep()
return
value = self.dict[name]
if not hasattr(value, '__dict__'):
stdwin.fleep()
return
name = 'instance ' + `value`
if self.debugger.framewindows.has_key(name):
self.debugger.framewindows[name].popup()
else:
self.debugger.framewindows[name] = \
FrameWindow(self.debugger,
self.frame, value.__dict__,
name)
return
stdwin.fleep()
def re_eval(self):
import string, repr
expr = string.strip(self.editor.gettext())
if expr == '':
output = ''
else:
globals = self.frame.f_globals
globals['__privileged__'] = 1
locals = self.dict
try:
value = eval(expr, globals, locals)
output = repr.repr(value)
except:
if type(sys.exc_type) == type(''):
exc_type_name = sys.exc_type
else: exc_type_name = sys.exc_type.__name__
output = exc_type_name + ': ' + `sys.exc_value`
self.displaylist[1] = output
lh = stdwin.lineheight()
r = (-10, 0), (30000, 2*lh)
self.win.change(r)
self.editor.setfocus(0, len(expr))
def draw(self, detail):
(left, top), (right, bottom) = detail
dummy = self.editor.draw(detail)
d = self.win.begindrawing()
try:
lh = d.lineheight()
h, v = 0, 0
for line in self.displaylist:
if v+lh > top and v < bottom:
d.text((h, v), line)
v = v + lh
finally:
d.close()
def refreshframe(self):
import repr
del self.displaylist[3:]
self.re_eval()
names = self.dict.keys()
for key, label in ('__args__', 'Args: '), \
('__return__', 'Return: '):
if self.dict.has_key(key):
names.remove(key)
value = self.dict[key]
label = label + repr.repr(value)
self.displaylist.append(label)
names.sort()
for name in names:
value = self.dict[name]
line = name + ' = ' + repr.repr(value)
self.displaylist.append(line)
self.win.setdocsize(0, \
stdwin.lineheight() * len(self.displaylist))
self.refreshall() # XXX Be more subtle later

View file

@ -1,100 +0,0 @@
# wdbsrcwin.py -- source window for wdb
import stdwin
from stdwinevents import *
import srcwin
class DebuggerSourceWindow(srcwin.SourceWindow):
def __init__(self, debugger, filename):
self.debugger = debugger
self.curlineno = 0
self.focus = 0
srcwin.SourceWindow.__init__(self, filename)
def close(self):
del self.debugger.sourcewindows[self.filename]
del self.debugger
srcwin.SourceWindow.close(self)
def dispatch(self, event):
type, win, detail = event
if type == WE_CHAR:
self.char(detail)
elif type == WE_COMMAND:
self.command(detail)
elif type == WE_MOUSE_DOWN:
self.mouse_down(detail)
else:
srcwin.SourceWindow.dispatch(self, event)
def char(self, detail):
self.debugger.char(detail)
def command(self, detail):
self.debugger.command(detail)
def mouse_down(self, detail):
(h, v), clicks, button, mask = detail
if h >= self.leftmargin:
srcwin.SourceWindow.dispatch(self, \
(WE_MOUSE_DOWN, self.win, detail))
return
lineno = v/self.lineheight + 1
if 1 <= lineno <= self.linecount:
if self.debugger.get_break(self.filename, lineno):
f = self.debugger.clear_break
else:
f = self.debugger.set_break
err = f(self.filename, lineno)
if err: stdwin.message(err)
else: self.changemark(lineno)
else:
stdwin.fleep()
def getmark(self, lineno):
s = `lineno`
if lineno == self.focus:
s = '[' + s + ']'
else:
s = ' ' + s + ' '
if lineno == self.curlineno:
s = s + '->'
else:
s = s + ' '
br = self.debugger.breaks
if br.has_key(self.filename) and lineno in br[self.filename]:
s = s + 'B'
else:
s = s + ' '
return s
def getmargin(self):
return stdwin.textwidth('[' + `self.linecount+1` + ']->B ')
def setlineno(self, newlineno):
if newlineno != self.curlineno:
oldlineno = self.curlineno
self.curlineno = newlineno
self.changemark(oldlineno)
self.changemark(newlineno)
if newlineno != 0:
self.showline(newlineno)
def resetlineno(self):
self.setlineno(0)
def setfocus(self, newfocus):
if newfocus != self.focus:
oldfocus = self.focus
self.focus = newfocus
self.changemark(oldfocus)
self.changemark(newfocus)
if newfocus != 0:
self.showline(newfocus)
def resetfocus(self):
self.setfocus(0)
# XXX Should get rid of focus stuff again

View file

@ -1,185 +0,0 @@
# This module exports classes for the various canvas item types
from Tkinter import Canvas, _cnfmerge, _flatten
class CanvasItem:
def __init__(self, canvas, itemType, *args, **kw):
self.canvas = canvas
self.id = canvas._create(itemType, args, kw)
if not hasattr(canvas, 'items'):
canvas.items = {}
canvas.items[self.id] = self
def __str__(self):
return str(self.id)
def __repr__(self):
return '<%s, id=%d>' % (self.__class__.__name__, self.id)
def delete(self):
del self.canvas.items[self.id]
self.canvas.delete(self.id)
def __getitem__(self, key):
v = self.canvas.tk.split(self.canvas.tk.call(
self.canvas._w, 'itemconfigure',
self.id, '-' + key))
return v[4]
cget = __getitem__
def __setitem__(self, key, value):
self.canvas.itemconfig(self.id, {key: value})
def keys(self):
if not hasattr(self, '_keys'):
self._keys = map(lambda x, tk=self.canvas.tk:
tk.splitlist(x)[0][1:],
self.canvas.tk.splitlist(
self.canvas._do(
'itemconfigure',
(self.id,))))
return self._keys
def has_key(self, key):
return key in self.keys()
def addtag(self, tag, option='withtag'):
self.canvas.addtag(tag, option, self.id)
def bbox(self):
x1, y1, x2, y2 = self.canvas.bbox(self.id)
return (x1, y1), (x2, y2)
def bind(self, sequence=None, command=None):
return self.canvas.tag_bind(self.id, sequence, command)
def unbind(self, sequence):
self.canvas.tag_bind(self.id, sequence, '')
def config(self, cnf={}, **kw):
return self.canvas.itemconfig(self.id, _cnfmerge((cnf, kw)))
def coords(self, pts = ()):
flat = ()
for x, y in pts: flat = flat + (x, y)
return apply(self.canvas.coords, (self.id,) + flat)
def dchars(self, first, last=None):
self.canvas.dchars(self.id, first, last)
def dtag(self, ttd):
self.canvas.dtag(self.id, ttd)
def focus(self):
self.canvas.focus(self.id)
def gettags(self):
return self.canvas.gettags(self.id)
def icursor(self, index):
self.canvas.icursor(self.id, index)
def index(self, index):
return self.canvas.index(self.id, index)
def insert(self, beforethis, string):
self.canvas.insert(self.id, beforethis, string)
def lower(self, belowthis=None):
self.canvas.lower(self.id, belowthis)
def move(self, xamount, yamount):
self.canvas.move(self.id, xamount, yamount)
def tkraise(self, abovethis=None):
self.canvas.tkraise(self.id, abovethis)
raise_ = tkraise # BW compat
def scale(self, xorigin, yorigin, xscale, yscale):
self.canvas.scale(self.id, xorigin, yorigin, xscale, yscale)
def type(self):
return self.canvas.type(self.id)
class Arc(CanvasItem):
def __init__(self, canvas, *args, **kw):
apply(CanvasItem.__init__, (self, canvas, 'arc') + args, kw)
class Bitmap(CanvasItem):
def __init__(self, canvas, *args, **kw):
apply(CanvasItem.__init__, (self, canvas, 'bitmap') + args, kw)
class ImageItem(CanvasItem):
def __init__(self, canvas, *args, **kw):
apply(CanvasItem.__init__, (self, canvas, 'image') + args, kw)
class Line(CanvasItem):
def __init__(self, canvas, *args, **kw):
apply(CanvasItem.__init__, (self, canvas, 'line') + args, kw)
class Oval(CanvasItem):
def __init__(self, canvas, *args, **kw):
apply(CanvasItem.__init__, (self, canvas, 'oval') + args, kw)
class Polygon(CanvasItem):
def __init__(self, canvas, *args, **kw):
apply(CanvasItem.__init__, (self, canvas, 'polygon') + args, kw)
class Rectangle(CanvasItem):
def __init__(self, canvas, *args, **kw):
apply(CanvasItem.__init__, (self, canvas, 'rectangle') + args, kw)
# XXX "Text" is taken by the Text widget...
class CanvasText(CanvasItem):
def __init__(self, canvas, *args, **kw):
apply(CanvasItem.__init__, (self, canvas, 'text') + args, kw)
class Window(CanvasItem):
def __init__(self, canvas, *args, **kw):
apply(CanvasItem.__init__, (self, canvas, 'window') + args, kw)
class Group:
def __init__(self, canvas, tag=None):
if not tag:
tag = 'Group%d' % id(self)
self.tag = self.id = tag
self.canvas = canvas
self.canvas.dtag(self.tag)
def str(self):
return self.tag
__str__ = str
def _do(self, cmd, *args):
return self.canvas._do(cmd, (self.tag,) + _flatten(args))
def addtag_above(self, tagOrId):
self._do('addtag', 'above', tagOrId)
def addtag_all(self):
self._do('addtag', 'all')
def addtag_below(self, tagOrId):
self._do('addtag', 'below', tagOrId)
def addtag_closest(self, x, y, halo=None, start=None):
self._do('addtag', 'closest', x, y, halo, start)
def addtag_enclosed(self, x1, y1, x2, y2):
self._do('addtag', 'enclosed', x1, y1, x2, y2)
def addtag_overlapping(self, x1, y1, x2, y2):
self._do('addtag', 'overlapping', x1, y1, x2, y2)
def addtag_withtag(self, tagOrId):
self._do('addtag', 'withtag', tagOrId)
def bbox(self):
return self._getints(self._do('bbox'))
def bind(self, sequence=None, command=None):
return self.canvas.tag_bind(self.id, sequence, command)
def unbind(self, sequence):
self.canvas.tag_bind(self.id, sequence, '')
def coords(self, *pts):
return self._do('coords', pts)
def dchars(self, first, last=None):
self._do('dchars', first, last)
def delete(self):
self._do('delete')
def dtag(self, tagToDelete=None):
self._do('dtag', tagToDelete)
def focus(self):
self._do('focus')
def gettags(self):
return self.canvas.tk.splitlist(self._do('gettags', self.tag))
def icursor(self, index):
return self._do('icursor', index)
def index(self, index):
return self.canvas.tk.getint(self._do('index', index))
def insert(self, beforeThis, string):
self._do('insert', beforeThis, string)
def config(self, cnf={}, **kw):
return self.canvas.itemconfigure(self.tag, _cnfmerge((cnf,kw)))
def lower(self, belowThis=None):
self._do('lower', belowThis)
def move(self, xAmount, yAmount):
self._do('move', xAmount, yAmount)
def tkraise(self, aboveThis=None):
self._do('raise', aboveThis)
lift = tkraise
def scale(self, xOrigin, yOrigin, xScale, yScale):
self._do('scale', xOrigin, yOrigin, xScale, yScale)
def select_adjust(self, index):
self.canvas._do('select', ('adjust', self.tag, index))
def select_from(self, index):
self.canvas._do('select', ('from', self.tag, index))
def select_to(self, index):
self.canvas._do('select', ('to', self.tag, index))
def type(self):
return self._do('type')

View file

@ -1,49 +0,0 @@
# Dialog.py -- Tkinter interface to the tk_dialog script.
from Tkinter import *
from Tkinter import _cnfmerge
if TkVersion <= 3.6:
DIALOG_ICON = 'warning'
else:
DIALOG_ICON = 'questhead'
class Dialog(Widget):
def __init__(self, master=None, cnf={}, **kw):
cnf = _cnfmerge((cnf, kw))
self.widgetName = '__dialog__'
Widget._setup(self, master, cnf)
self.num = self.tk.getint(
apply(self.tk.call,
('tk_dialog', self._w,
cnf['title'], cnf['text'],
cnf['bitmap'], cnf['default'])
+ cnf['strings']))
try: Widget.destroy(self)
except TclError: pass
def destroy(self): pass
def _test():
d = Dialog(None, {'title': 'File Modified',
'text':
'File "Python.h" has been modified'
' since the last time it was saved.'
' Do you want to save it before'
' exiting the application.',
'bitmap': DIALOG_ICON,
'default': 0,
'strings': ('Save File',
'Discard Changes',
'Return to Editor')})
print d.num
if __name__ == '__main__':
t = Button(None, {'text': 'Test',
'command': _test,
Pack: {}})
q = Button(None, {'text': 'Quit',
'command': t.quit,
Pack: {}})
t.mainloop()

View file

@ -1,269 +0,0 @@
"""File selection dialog classes.
Classes:
- FileDialog
- LoadFileDialog
- SaveFileDialog
"""
from Tkinter import *
from Dialog import Dialog
import os
import fnmatch
dialogstates = {}
class FileDialog:
"""Standard file selection dialog -- no checks on selected file.
Usage:
d = FileDialog(master)
file = d.go(dir_or_file, pattern, default, key)
if file is None: ...canceled...
else: ...open file...
All arguments to go() are optional.
The 'key' argument specifies a key in the global dictionary
'dialogstates', which keeps track of the values for the directory
and pattern arguments, overriding the values passed in (it does
not keep track of the default argument!). If no key is specified,
the dialog keeps no memory of previous state. Note that memory is
kept even when the dialog is cancelled. (All this emulates the
behavior of the Macintosh file selection dialogs.)
"""
title = "File Selection Dialog"
def __init__(self, master, title=None):
if title is None: title = self.title
self.master = master
self.directory = None
self.top = Toplevel(master)
self.top.title(title)
self.top.iconname(title)
self.botframe = Frame(self.top)
self.botframe.pack(side=BOTTOM, fill=X)
self.selection = Entry(self.top)
self.selection.pack(side=BOTTOM, fill=X)
self.selection.bind('<Return>', self.ok_event)
self.filter = Entry(self.top)
self.filter.pack(side=TOP, fill=X)
self.filter.bind('<Return>', self.filter_command)
self.midframe = Frame(self.top)
self.midframe.pack(expand=YES, fill=BOTH)
self.filesbar = Scrollbar(self.midframe)
self.filesbar.pack(side=RIGHT, fill=Y)
self.files = Listbox(self.midframe, exportselection=0,
yscrollcommand=(self.filesbar, 'set'))
self.files.pack(side=RIGHT, expand=YES, fill=BOTH)
btags = self.files.bindtags()
self.files.bindtags(btags[1:] + btags[:1])
self.files.bind('<ButtonRelease-1>', self.files_select_event)
self.files.bind('<Double-ButtonRelease-1>', self.files_double_event)
self.filesbar.config(command=(self.files, 'yview'))
self.dirsbar = Scrollbar(self.midframe)
self.dirsbar.pack(side=LEFT, fill=Y)
self.dirs = Listbox(self.midframe, exportselection=0,
yscrollcommand=(self.dirsbar, 'set'))
self.dirs.pack(side=LEFT, expand=YES, fill=BOTH)
self.dirsbar.config(command=(self.dirs, 'yview'))
btags = self.dirs.bindtags()
self.dirs.bindtags(btags[1:] + btags[:1])
self.dirs.bind('<ButtonRelease-1>', self.dirs_select_event)
self.dirs.bind('<Double-ButtonRelease-1>', self.dirs_double_event)
self.ok_button = Button(self.botframe,
text="OK",
command=self.ok_command)
self.ok_button.pack(side=LEFT)
self.filter_button = Button(self.botframe,
text="Filter",
command=self.filter_command)
self.filter_button.pack(side=LEFT, expand=YES)
self.cancel_button = Button(self.botframe,
text="Cancel",
command=self.cancel_command)
self.cancel_button.pack(side=RIGHT)
self.top.protocol('WM_DELETE_WINDOW', self.cancel_command)
# XXX Are the following okay for a general audience?
self.top.bind('<Alt-w>', self.cancel_command)
self.top.bind('<Alt-W>', self.cancel_command)
def go(self, dir_or_file=os.curdir, pattern="*", default="", key=None):
if key and dialogstates.has_key(key):
self.directory, pattern = dialogstates[key]
else:
dir_or_file = os.path.expanduser(dir_or_file)
if os.path.isdir(dir_or_file):
self.directory = dir_or_file
else:
self.directory, default = os.path.split(dir_or_file)
self.set_filter(self.directory, pattern)
self.set_selection(default)
self.filter_command()
self.selection.focus_set()
self.top.grab_set()
self.how = None
self.master.mainloop() # Exited by self.quit(how)
if key: dialogstates[key] = self.get_filter()
self.top.destroy()
return self.how
def quit(self, how=None):
self.how = how
self.master.quit() # Exit mainloop()
def dirs_double_event(self, event):
self.filter_command()
def dirs_select_event(self, event):
dir, pat = self.get_filter()
subdir = self.dirs.get('active')
dir = os.path.normpath(os.path.join(self.directory, subdir))
self.set_filter(dir, pat)
def files_double_event(self, event):
self.ok_command()
def files_select_event(self, event):
file = self.files.get('active')
self.set_selection(file)
def ok_event(self, event):
self.ok_command()
def ok_command(self):
self.quit(self.get_selection())
def filter_command(self, event=None):
dir, pat = self.get_filter()
try:
names = os.listdir(dir)
except os.error:
self.master.bell()
return
self.directory = dir
self.set_filter(dir, pat)
names.sort()
subdirs = [os.pardir]
matchingfiles = []
for name in names:
fullname = os.path.join(dir, name)
if os.path.isdir(fullname):
subdirs.append(name)
elif fnmatch.fnmatch(name, pat):
matchingfiles.append(name)
self.dirs.delete(0, END)
for name in subdirs:
self.dirs.insert(END, name)
self.files.delete(0, END)
for name in matchingfiles:
self.files.insert(END, name)
head, tail = os.path.split(self.get_selection())
if tail == os.curdir: tail = ''
self.set_selection(tail)
def get_filter(self):
filter = self.filter.get()
filter = os.path.expanduser(filter)
if filter[-1:] == os.sep or os.path.isdir(filter):
filter = os.path.join(filter, "*")
return os.path.split(filter)
def get_selection(self):
file = self.selection.get()
file = os.path.expanduser(file)
return file
def cancel_command(self, event=None):
self.quit()
def set_filter(self, dir, pat):
if not os.path.isabs(dir):
try:
pwd = os.getcwd()
except os.error:
pwd = None
if pwd:
dir = os.path.join(pwd, dir)
dir = os.path.normpath(dir)
self.filter.delete(0, END)
self.filter.insert(END, os.path.join(dir or os.curdir, pat or "*"))
def set_selection(self, file):
self.selection.delete(0, END)
self.selection.insert(END, os.path.join(self.directory, file))
class LoadFileDialog(FileDialog):
"""File selection dialog which checks that the file exists."""
title = "Load File Selection Dialog"
def ok_command(self):
file = self.get_selection()
if not os.path.isfile(file):
self.master.bell()
else:
self.quit(file)
class SaveFileDialog(FileDialog):
"""File selection dialog which checks that the file may be created."""
title = "Save File Selection Dialog"
def ok_command(self):
file = self.get_selection()
if os.path.exists(file):
if os.path.isdir(file):
self.master.bell()
return
d = Dialog(self.top,
title="Overwrite Existing File Question",
text="Overwrite existing file %s?" % `file`,
bitmap='questhead',
default=1,
strings=("Yes", "Cancel"))
if d.num != 0:
return
else:
head, tail = os.path.split(file)
if not os.path.isdir(head):
self.master.bell()
return
self.quit(file)
def test():
"""Simple test program."""
root = Tk()
root.withdraw()
fd = LoadFileDialog(root)
loadfile = fd.go(key="test")
fd = SaveFileDialog(root)
savefile = fd.go(key="test")
print loadfile, savefile
if __name__ == '__main__':
test()

View file

@ -1,37 +0,0 @@
# A ScrolledText widget feels like a text widget but also has a
# vertical scroll bar on its right. (Later, options may be added to
# add a horizontal bar as well, to make the bars disappear
# automatically when not needed, to move them to the other side of the
# window, etc.)
#
# Configuration options are passed to the Text widget.
# A Frame widget is inserted between the master and the text, to hold
# the Scrollbar widget.
# Most methods calls are inherited from the Text widget; Pack methods
# are redirected to the Frame widget however.
from Tkinter import *
from Tkinter import _cnfmerge
class ScrolledText(Text):
def __init__(self, master=None, cnf={}, **kw):
if kw:
cnf = _cnfmerge((cnf, kw))
fcnf = {}
for k in cnf.keys():
if type(k) == ClassType or k == 'name':
fcnf[k] = cnf[k]
del cnf[k]
self.frame = apply(Frame, (master,), fcnf)
self.vbar = Scrollbar(self.frame, name='vbar')
self.vbar.pack(side=RIGHT, fill=Y)
cnf['name'] = 'text'
apply(Text.__init__, (self, self.frame), cnf)
self.pack(side=LEFT, fill=BOTH, expand=1)
self['yscrollcommand'] = self.vbar.set
self.vbar['command'] = self.yview
# Copy Pack methods of self.frame -- hack!
for m in Pack.__dict__.keys():
if m[0] != '_' and m != 'config':
setattr(self, m, getattr(self.frame, m))

View file

@ -1,103 +0,0 @@
"""A simple but flexible modal dialog box."""
from Tkinter import *
class SimpleDialog:
def __init__(self, master,
text='', buttons=[], default=None, cancel=None,
title=None, class_=None):
if class_:
self.root = Toplevel(master, class_=class_)
else:
self.root = Toplevel(master)
if title:
self.root.title(title)
self.root.iconname(title)
self.message = Message(self.root, text=text, aspect=400)
self.message.pack(expand=1, fill=BOTH)
self.frame = Frame(self.root)
self.frame.pack()
self.num = default
self.cancel = cancel
self.default = default
self.root.bind('<Return>', self.return_event)
for num in range(len(buttons)):
s = buttons[num]
b = Button(self.frame, text=s,
command=(lambda self=self, num=num: self.done(num)))
if num == default:
b.config(relief=RIDGE, borderwidth=8)
b.pack(side=LEFT, fill=BOTH, expand=1)
self.root.protocol('WM_DELETE_WINDOW', self.wm_delete_window)
self._set_transient(master)
def _set_transient(self, master, relx=0.5, rely=0.3):
widget = self.root
widget.withdraw() # Remain invisible while we figure out the geometry
widget.transient(master)
widget.update_idletasks() # Actualize geometry information
if master.winfo_ismapped():
m_width = master.winfo_width()
m_height = master.winfo_height()
m_x = master.winfo_rootx()
m_y = master.winfo_rooty()
else:
m_width = master.winfo_screenwidth()
m_height = master.winfo_screenheight()
m_x = m_y = 0
w_width = widget.winfo_reqwidth()
w_height = widget.winfo_reqheight()
x = m_x + (m_width - w_width) * relx
y = m_y + (m_height - w_height) * rely
widget.geometry("+%d+%d" % (x, y))
widget.deiconify() # Become visible at the desired location
def go(self):
self.root.grab_set()
self.root.mainloop()
self.root.destroy()
return self.num
def return_event(self, event):
if self.default is None:
self.root.bell()
else:
self.done(self.default)
def wm_delete_window(self):
if self.cancel is None:
self.root.bell()
else:
self.done(self.cancel)
def done(self, num):
self.num = num
self.root.quit()
def test():
root = Tk()
def doit(root=root):
d = SimpleDialog(root,
text="This is a test dialog. "
"Would this have been an actual dialog, "
"the buttons below would have been glowing "
"in soft pink light.\n"
"Do you believe this?",
buttons=["Yes", "No", "Cancel"],
default=0,
cancel=2,
title="Test Dialog")
print d.go()
t = Button(root, text='Test', command=doit)
t.pack()
q = Button(root, text='Quit', command=t.quit)
q.pack()
t.mainloop()
if __name__ == '__main__':
test()

View file

@ -1,77 +0,0 @@
# Symbolic constants for Tk
# Booleans
NO=FALSE=OFF=0
YES=TRUE=ON=1
# -anchor
N='n'
S='s'
W='w'
E='e'
NW='nw'
SW='sw'
NE='ne'
SE='se'
CENTER='center'
# -fill
NONE='none'
X='x'
Y='y'
BOTH='both'
# -side
LEFT='left'
TOP='top'
RIGHT='right'
BOTTOM='bottom'
# -relief
RAISED='raised'
SUNKEN='sunken'
FLAT='flat'
RIDGE='ridge'
GROOVE='groove'
# -orient
HORIZONTAL='horizontal'
VERTICAL='vertical'
# -tabs
NUMERIC='numeric'
# -wrap
CHAR='char'
WORD='word'
# -align
BASELINE='baseline'
# Special tags, marks and insert positions
SEL='sel'
SEL_FIRST='sel.first'
SEL_LAST='sel.last'
END='end'
INSERT='insert'
CURRENT='current'
ANCHOR='anchor'
ALL='all' # e.g. Canvas.delete(ALL)
# Text widget and button states
NORMAL='normal'
DISABLED='disabled'
ACTIVE='active'
# Menu item types
CASCADE='cascade'
CHECKBUTTON='checkbutton'
COMMAND='command'
RADIOBUTTON='radiobutton'
SEPARATOR='separator'
# Selection modes for list boxes
SINGLE='single'
BROWSE='browse'
MULTIPLE='multiple'
EXTENDED='extended'

File diff suppressed because it is too large Load diff

View file

@ -1,73 +0,0 @@
#
# Instant Python
# $Id$
#
# tk common colour chooser dialogue
#
# this module provides an interface to the native color dialogue
# available in Tk 4.2 and newer.
#
# written by Fredrik Lundh, May 1997
#
#
# options (all have default values):
#
# - initialcolor: colour to mark as selected when dialog is displayed
# (given as an RGB triplet or a Tk color string)
#
# - parent: which window to place the dialog on top of
#
# - title: dialog title
#
# FIXME: as of Tk 8.0a2, the Unix colour picker is really ugly, and
# doesn't seem to work properly on true colour displays. maybe we
# should use the instant python version instead?
from tkCommonDialog import Dialog
#
# color chooser class
class Chooser(Dialog):
"Ask for a color"
command = "tk_chooseColor"
def _fixoptions(self):
try:
# make sure initialcolor is a tk color string
color = self.options["initialcolor"]
if type(color) == type(()):
# assume an RGB triplet
self.options["initialcolor"] = "%02x%02x%02x" % color
except KeyError:
pass
def _fixresult(self, widget, result):
# to simplify application code, the color chooser returns
# an RGB tuple together with the Tk color string
if not result:
return None, None # cancelled
r, g, b = widget.winfo_rgb(result)
return (r/256, g/256, b/256), result
#
# convenience stuff
def askcolor(color = None, **options):
"Ask for a color"
return apply(Chooser, (), options).show()
# --------------------------------------------------------------------
# test stuff
if __name__ == "__main__":
print "color", askcolor()

View file

@ -1,64 +0,0 @@
#
# Instant Python
# $Id$
#
# base class for tk common dialogues
#
# this module provides a base class for accessing the common
# dialogues available in Tk 4.2 and newer. use tkFileDialog,
# tkColorChooser, and tkMessageBox to access the individual
# dialogs.
#
# written by Fredrik Lundh, May 1997
#
from Tkinter import *
import os
class Dialog:
command = None
def __init__(self, master=None, **options):
# FIXME: should this be placed on the module level instead?
if TkVersion < 4.2:
raise TclError, "this module requires Tk 4.2 or newer"
self.master = master
self.options = options
def _fixoptions(self):
pass # hook
def _fixresult(self, widget, result):
return result # hook
def show(self, **options):
# update instance options
for k, v in options.items():
self.options[k] = v
self._fixoptions()
# we need a dummy widget to properly process the options
# (at least as long as we use Tkinter 1.63)
w = Frame(self.master)
try:
s = apply(w.tk.call, (self.command,) + w._options(self.options))
s = self._fixresult(w, s)
finally:
try:
# get rid of the widget
w.destroy()
except:
pass
return s

View file

@ -1,106 +0,0 @@
#
# Instant Python
# $Id$
#
# tk common file dialogues
#
# this module provides interfaces to the native file dialogues
# available in Tk 4.2 and newer.
#
# written by Fredrik Lundh, May 1997.
#
#
# options (all have default values):
#
# - defaultextension: added to filename if not explicitly given
#
# - filetypes: sequence of (label, pattern) tuples. the same pattern
# may occur with several patterns. use "*" as pattern to indicate
# all files.
#
# - initialdir: initial directory. preserved by dialog instance.
#
# - initialfile: initial file (ignored by the open dialog). preserved
# by dialog instance.
#
# - parent: which window to place the dialog on top of
#
# - title: dialog title
#
from tkCommonDialog import Dialog
class _Dialog(Dialog):
def _fixoptions(self):
try:
# make sure "filetypes" is a tuple
self.options["filetypes"] = tuple(self.options["filetypes"])
except KeyError:
pass
def _fixresult(self, widget, result):
if result:
# keep directory and filename until next time
import os
path, file = os.path.split(result)
self.options["initialdir"] = path
self.options["initialfile"] = file
self.filename = result # compatibility
return result
#
# file dialogs
class Open(_Dialog):
"Ask for a filename to open"
command = "tk_getOpenFile"
class SaveAs(_Dialog):
"Ask for a filename to save as"
command = "tk_getSaveFile"
#
# convenience stuff
def askopenfilename(**options):
"Ask for a filename to open"
return apply(Open, (), options).show()
def asksaveasfilename(**options):
"Ask for a filename to save as"
return apply(SaveAs, (), options).show()
# FIXME: are the following two perhaps a bit too convenient?
def askopenfile(mode = "r", **options):
"Ask for a filename to open, and returned the opened file"
filename = apply(Open, (), options).show()
if filename:
return open(filename, mode)
return None
def asksaveasfile(mode = "w", **options):
"Ask for a filename to save as, and returned the opened file"
filename = apply(SaveAs, (), options).show()
if filename:
return open(filename, mode)
return None
# --------------------------------------------------------------------
# test stuff
if __name__ == "__main__":
print "open", askopenfilename(filetypes=[("all filez", "*")])
print "saveas", asksaveasfilename()

View file

@ -1,120 +0,0 @@
#
# Instant Python
# $Id$
#
# tk common message boxes
#
# this module provides an interface to the native message boxes
# available in Tk 4.2 and newer.
#
# written by Fredrik Lundh, May 1997
#
#
# options (all have default values):
#
# - default: which button to make default (one of the reply codes)
#
# - icon: which icon to display (see below)
#
# - message: the message to display
#
# - parent: which window to place the dialog on top of
#
# - title: dialog title
#
# - type: dialog type; that is, which buttons to display (see below)
#
from tkCommonDialog import Dialog
#
# constants
# icons
ERROR = "error"
INFO = "info"
QUESTION = "question"
WARNING = "warning"
# types
ABORTRETRYIGNORE = "abortretryignore"
OK = "ok"
OKCANCEL = "okcancel"
RETRYCANCEL = "retrycancel"
YESNO = "yesno"
YESNOCANCEL = "yesnocancel"
# replies
ABORT = "abort"
RETRY = "retry"
IGNORE = "ignore"
OK = "ok"
CANCEL = "cancel"
YES = "yes"
NO = "no"
#
# message dialog class
class Message(Dialog):
"A message box"
command = "tk_messageBox"
#
# convenience stuff
def _show(title=None, message=None, icon=None, type=None, **options):
if icon: options["icon"] = icon
if type: options["type"] = type
if title: options["title"] = title
if message: options["message"] = message
return apply(Message, (), options).show()
def showinfo(title=None, message=None, **options):
"Show an info message"
return apply(_show, (title, message, INFO, OK), options)
def showwarning(title=None, message=None, **options):
"Show a warning message"
return apply(_show, (title, message, WARNING, OK), options)
def showerror(title=None, message=None, **options):
"Show an error message"
return apply(_show, (title, message, ERROR, OK), options)
def askquestion(title=None, message=None, **options):
"Ask a question"
return apply(_show, (title, message, QUESTION, YESNO), options)
def askokcancel(title=None, message=None, **options):
"Ask if operation should proceed; return true if the answer is ok"
s = apply(_show, (title, message, QUESTION, OKCANCEL), options)
return s == OK
def askyesno(title=None, message=None, **options):
"Ask a question; return true if the answer is yes"
s = apply(_show, (title, message, QUESTION, YESNO), options)
return s == YES
def askretrycancel(title=None, message=None, **options):
"Ask if operation should be retried; return true if the answer is yes"
s = apply(_show, (title, message, WARNING, RETRYCANCEL), options)
return s == RETRY
# --------------------------------------------------------------------
# test stuff
if __name__ == "__main__":
print "info", showinfo("Spam", "Egg Information")
print "warning", showwarning("Spam", "Egg Warning")
print "error", showerror("Spam", "Egg Alert")
print "question", askquestion("Spam", "Question?")
print "proceed", askokcancel("Spam", "Proceed?")
print "yes/no", askyesno("Spam", "Got it?")
print "try again", askretrycancel("Spam", "Try again?")

View file

@ -1,220 +0,0 @@
#
# An Introduction to Tkinter
# tkSimpleDialog.py
#
# Copyright (c) 1997 by Fredrik Lundh
#
# fredrik@pythonware.com
# http://www.pythonware.com
#
# --------------------------------------------------------------------
# dialog base class
from Tkinter import *
import os
class Dialog(Toplevel):
def __init__(self, parent, title = None):
Toplevel.__init__(self, parent)
self.transient(parent)
if title:
self.title(title)
self.parent = parent
self.result = None
body = Frame(self)
self.initial_focus = self.body(body)
body.pack(padx=5, pady=5)
self.buttonbox()
self.grab_set()
if not self.initial_focus:
self.initial_focus = self
self.protocol("WM_DELETE_WINDOW", self.cancel)
self.geometry("+%d+%d" % (parent.winfo_rootx()+50,
parent.winfo_rooty()+50))
self.initial_focus.focus_set()
self.wait_window(self)
#
# construction hooks
def body(self, master):
# create dialog body. return widget that should have
# initial focus. this method should be overridden
pass
def buttonbox(self):
# add standard button box. override if you don't want the
# standard buttons
box = Frame(self)
w = Button(box, text="OK", width=10, command=self.ok, default=ACTIVE)
w.pack(side=LEFT, padx=5, pady=5)
w = Button(box, text="Cancel", width=10, command=self.cancel)
w.pack(side=LEFT, padx=5, pady=5)
self.bind("<Return>", self.ok)
self.bind("<Escape>", self.cancel)
box.pack()
#
# standard button semantics
def ok(self, event=None):
if not self.validate():
self.initial_focus.focus_set() # put focus back
return
self.withdraw()
self.update_idletasks()
self.apply()
self.cancel()
def cancel(self, event=None):
# put focus back to the parent window
self.parent.focus_set()
self.destroy()
#
# command hooks
def validate(self):
return 1 # override
def apply(self):
pass # override
# --------------------------------------------------------------------
# convenience dialogues
import string
class _QueryDialog(Dialog):
def __init__(self, title, prompt,
initialvalue=None,
minvalue = None, maxvalue = None,
parent = None):
from Tkinter import _default_root
if not parent:
parent = _default_root
self.prompt = prompt
self.minvalue = minvalue
self.maxvalue = maxvalue
self.initialvalue = initialvalue
Dialog.__init__(self, parent, title)
def body(self, master):
w = Label(master, text=self.prompt, justify=LEFT)
w.grid(row=0, padx=5, sticky=W)
self.entry = Entry(master, name="entry")
self.entry.grid(row=1, padx=5, sticky=W+E)
if self.initialvalue:
self.entry.insert(0, self.initialvalue)
self.entry.select_range(0, END)
return self.entry
def validate(self):
import tkMessageBox
try:
result = self.getresult()
except ValueError:
tkMessageBox.showwarning(
"Illegal value",
self.errormessage + "\nPlease try again",
parent = self
)
return 0
if self.minvalue is not None and result < self.minvalue:
tkMessageBox.showwarning(
"Too small",
"The allowed minimum value is %s. "
"Please try again." % self.minvalue,
parent = self
)
return 0
if self.maxvalue is not None and result > self.maxvalue:
tkMessageBox.showwarning(
"Too large",
"The allowed maximum value is %s. "
"Please try again." % self.maxvalue,
parent = self
)
return 0
self.result = result
return 1
class _QueryInteger(_QueryDialog):
errormessage = "Not an integer."
def getresult(self):
return string.atoi(self.entry.get())
def askinteger(title, prompt, **kw):
d = apply(_QueryInteger, (title, prompt), kw)
return d.result
class _QueryFloat(_QueryDialog):
errormessage = "Not a floating point value."
def getresult(self):
return string.atof(self.entry.get())
def askfloat(title, prompt, **kw):
d = apply(_QueryFloat, (title, prompt), kw)
return d.result
class _QueryString(_QueryDialog):
def getresult(self):
return self.entry.get()
def askstring(title, prompt, **kw):
d = apply(_QueryString, (title, prompt), kw)
return d.result
if __name__ == "__main__":
root = Tk()
root.update()
print askinteger("Spam", "Egg count", initialvalue=12*12)
print askfloat("Spam", "Egg weight\n(in tons)", minvalue=1, maxvalue=100)
print askstring("Spam", "Egg label")