Initial revision

This commit is contained in:
Guido van Rossum 1990-11-05 19:44:36 +00:00
parent 0c89ec778d
commit 2e44967104
10 changed files with 812 additions and 0 deletions

View File

@ -0,0 +1,53 @@
# 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.
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 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 minsize(self, m): 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

52
Lib/lib-stdwin/HVSplit.py Normal file
View File

@ -0,0 +1,52 @@
# HVSplit contains generic code for HSplit and VSplit.
# HSplit and VSplit are specializations to either dimension.
from Split import Split
class HVSplit() = Split():
#
def create(self, (parent, hv)):
# hv is 0 or 1 for HSplit or VSplit
self = Split.create(self, parent)
self.hv = hv
return self
#
def minsize(self, m):
hv, vh = self.hv, 1 - self.hv
size = [0, 0]
for c in self.children:
csize = c.minsize(m)
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
size = self.minsize(mf())
# XXX not yet used! Later for stretching
maxsize_hv = bounds[1][hv] - bounds[0][hv]
origin = [self.bounds[0][0], self.bounds[0][1]]
for c in self.children:
size = c.minsize(mf())
corner = [0, 0]
corner[vh] = bounds[1][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))

113
Lib/lib-stdwin/Split.py Normal file
View File

@ -0,0 +1,113 @@
# Generic Split implementation.
# Use as a base class for other splits.
Error = 'Split.Error' # Exception
import rect
from util import remove
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.timer_interest = []
self.mouse_focus = 0
return self
#
# Downcalls from parent to child
#
def destroy(self):
self.parent = 0
for child in self.children:
child.destroy()
self.children[:] = []
self.mouse_interest[:] = []
self.timer_interest[:] = []
self.mouse_focus = 0
#
def minsize(self, m): return unimpl()
def getbounds(self): return unimpl()
def setbounds(self, bounds): unimpl()
def draw(self, args):
# (Could avoid calls to children outside the area)
for child in self.children:
child.draw(args)
#
# Downcalls only made after certain upcalls
#
def mouse_down(self, detail):
if self.mouse_focus:
self.mouse_focus.mouse_down(detail)
p = detail[0]
for child in self.mouse_interest:
if rect.pointinrect(p, child.getbounds()):
self.mouse_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 = 0
#
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'
remove(child, self.children)
if child in self.mouse_interest:
remove(child, self.mouse_interest)
if child in self.timer_interest:
remove(child, self.timer_interest)
if child = self.mouse_focus:
self.mouse_focus = 0
#
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 in self.mouse_interest:
remove(child, self.mouse_interest)
if not self.mouse_interest:
self.parent.no_mouse(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:
remove(child, self.timer_interest)
if not self.timer_interest:
self.parent.no_timer(self)
#
# The rest are transparent:
#
def begindrawing(self):
return self.parent.begindrawing()
def beginmeasuring(self):
return self.parent.beginmeasuring()
#
def change(self, area):
self.parent.change(area)
def scroll(self, args):
self.parent.scroll(args)
def settimer(self, itimer):
self.parent.settimer(itimer)

View File

@ -0,0 +1,96 @@
# 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 = 0 # No child yet
#
# Downcalls from parent to child
#
def destroy(self):
del self.parent
if self.child: self.child.destroy()
del self.child
#
def minsize(self, m):
if not self.child:
return 0, 0
else:
return self.child.minsize(m)
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 draw(self, args):
if self.child:
self.child.draw(args)
#
# 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 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 begindrawing(self):
return self.parent.begindrawing()
def beginmeasuring(self):
return self.parent.beginmeasuring()
#
def change(self, area):
self.parent.change(area)
def scroll(self, args):
self.parent.scroll(args)
def settimer(self, itimer):
self.parent.settimer(itimer)

View File

@ -0,0 +1,92 @@
# 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.
import stdwin
from stdwinevents import *
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.child = 0 # i.e., no child yet
self.win = 0 # i.e., no window yet
self.itimer = 0
self.do_mouse = 0
self.do_timer = 0
return self
#
def need_mouse(self, child): self.do_mouse = 1
def no_mouse(self, child): self.do_mouse = 0
#
def need_timer(self, child): self.do_timer = 1
def no_timer(self, child): self.do_timer = 0
#
def realize(self):
if self.win:
raise Error, 'realize(): called twice'
if not self.child:
raise Error, 'realize(): no child'
size = self.child.minsize(self.beginmeasuring())
self.size = max(self.size[0], size[0]), \
max(self.size[1], size[1])
stdwin.setdefwinsize(self.size)
self.win = stdwin.open(self.title)
if self.itimer:
self.win.settimer(self.itimer)
bounds = (0, 0), self.win.getwinsize()
self.child.setbounds(bounds)
#
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 change(self, area):
if self.win:
self.win.change(area)
#
def scroll(self, args):
if self.win:
self.win.scroll(args)
#
def settimer(self, itimer):
if self.win:
self.win.settimer(itimer)
else:
self.itimer = itimer
#
# Only call dispatch if we have a child
#
def dispatch(self, (type, win, detail)):
if win <> self.win:
return
elif type = WE_DRAW:
d = self.win.begindrawing()
self.child.draw(d, 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 = WE_TIMER:
if self.do_timer: self.child.timer()
elif type = WE_SIZE:
self.win.change((0, 0), (10000, 10000)) # XXX
bounds = (0, 0), self.win.getwinsize()
self.child.setbounds(bounds)
#

53
Lib/stdwin/Abstract.py Executable file
View File

@ -0,0 +1,53 @@
# 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.
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 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 minsize(self, m): 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

52
Lib/stdwin/HVSplit.py Executable file
View File

@ -0,0 +1,52 @@
# HVSplit contains generic code for HSplit and VSplit.
# HSplit and VSplit are specializations to either dimension.
from Split import Split
class HVSplit() = Split():
#
def create(self, (parent, hv)):
# hv is 0 or 1 for HSplit or VSplit
self = Split.create(self, parent)
self.hv = hv
return self
#
def minsize(self, m):
hv, vh = self.hv, 1 - self.hv
size = [0, 0]
for c in self.children:
csize = c.minsize(m)
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
size = self.minsize(mf())
# XXX not yet used! Later for stretching
maxsize_hv = bounds[1][hv] - bounds[0][hv]
origin = [self.bounds[0][0], self.bounds[0][1]]
for c in self.children:
size = c.minsize(mf())
corner = [0, 0]
corner[vh] = bounds[1][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))

113
Lib/stdwin/Split.py Executable file
View File

@ -0,0 +1,113 @@
# Generic Split implementation.
# Use as a base class for other splits.
Error = 'Split.Error' # Exception
import rect
from util import remove
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.timer_interest = []
self.mouse_focus = 0
return self
#
# Downcalls from parent to child
#
def destroy(self):
self.parent = 0
for child in self.children:
child.destroy()
self.children[:] = []
self.mouse_interest[:] = []
self.timer_interest[:] = []
self.mouse_focus = 0
#
def minsize(self, m): return unimpl()
def getbounds(self): return unimpl()
def setbounds(self, bounds): unimpl()
def draw(self, args):
# (Could avoid calls to children outside the area)
for child in self.children:
child.draw(args)
#
# Downcalls only made after certain upcalls
#
def mouse_down(self, detail):
if self.mouse_focus:
self.mouse_focus.mouse_down(detail)
p = detail[0]
for child in self.mouse_interest:
if rect.pointinrect(p, child.getbounds()):
self.mouse_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 = 0
#
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'
remove(child, self.children)
if child in self.mouse_interest:
remove(child, self.mouse_interest)
if child in self.timer_interest:
remove(child, self.timer_interest)
if child = self.mouse_focus:
self.mouse_focus = 0
#
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 in self.mouse_interest:
remove(child, self.mouse_interest)
if not self.mouse_interest:
self.parent.no_mouse(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:
remove(child, self.timer_interest)
if not self.timer_interest:
self.parent.no_timer(self)
#
# The rest are transparent:
#
def begindrawing(self):
return self.parent.begindrawing()
def beginmeasuring(self):
return self.parent.beginmeasuring()
#
def change(self, area):
self.parent.change(area)
def scroll(self, args):
self.parent.scroll(args)
def settimer(self, itimer):
self.parent.settimer(itimer)

96
Lib/stdwin/TransParent.py Executable file
View File

@ -0,0 +1,96 @@
# 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 = 0 # No child yet
#
# Downcalls from parent to child
#
def destroy(self):
del self.parent
if self.child: self.child.destroy()
del self.child
#
def minsize(self, m):
if not self.child:
return 0, 0
else:
return self.child.minsize(m)
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 draw(self, args):
if self.child:
self.child.draw(args)
#
# 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 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 begindrawing(self):
return self.parent.begindrawing()
def beginmeasuring(self):
return self.parent.beginmeasuring()
#
def change(self, area):
self.parent.change(area)
def scroll(self, args):
self.parent.scroll(args)
def settimer(self, itimer):
self.parent.settimer(itimer)

92
Lib/stdwin/WindowParent.py Executable file
View File

@ -0,0 +1,92 @@
# 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.
import stdwin
from stdwinevents import *
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.child = 0 # i.e., no child yet
self.win = 0 # i.e., no window yet
self.itimer = 0
self.do_mouse = 0
self.do_timer = 0
return self
#
def need_mouse(self, child): self.do_mouse = 1
def no_mouse(self, child): self.do_mouse = 0
#
def need_timer(self, child): self.do_timer = 1
def no_timer(self, child): self.do_timer = 0
#
def realize(self):
if self.win:
raise Error, 'realize(): called twice'
if not self.child:
raise Error, 'realize(): no child'
size = self.child.minsize(self.beginmeasuring())
self.size = max(self.size[0], size[0]), \
max(self.size[1], size[1])
stdwin.setdefwinsize(self.size)
self.win = stdwin.open(self.title)
if self.itimer:
self.win.settimer(self.itimer)
bounds = (0, 0), self.win.getwinsize()
self.child.setbounds(bounds)
#
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 change(self, area):
if self.win:
self.win.change(area)
#
def scroll(self, args):
if self.win:
self.win.scroll(args)
#
def settimer(self, itimer):
if self.win:
self.win.settimer(itimer)
else:
self.itimer = itimer
#
# Only call dispatch if we have a child
#
def dispatch(self, (type, win, detail)):
if win <> self.win:
return
elif type = WE_DRAW:
d = self.win.begindrawing()
self.child.draw(d, 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 = WE_TIMER:
if self.do_timer: self.child.timer()
elif type = WE_SIZE:
self.win.change((0, 0), (10000, 10000)) # XXX
bounds = (0, 0), self.win.getwinsize()
self.child.setbounds(bounds)
#