mirror of
https://github.com/python/cpython.git
synced 2025-09-26 18:29:57 +00:00
More cleanup: Move some demos into a dedicated Tools/demo dir, move 2to3 demo to Tools, and remove all the other Demo content.
This commit is contained in:
parent
6f17e2df29
commit
7fafbc95c0
164 changed files with 25 additions and 12436 deletions
62
Demo/README
62
Demo/README
|
@ -1,62 +0,0 @@
|
||||||
This directory contains various demonstrations of what you can do with
|
|
||||||
Python. They were all written by me except where explicitly stated
|
|
||||||
otherwise -- in general, demos contributed by others ends up in the
|
|
||||||
../Contrib directory, unless I think they're of utmost general
|
|
||||||
importance (like Matt Conway's Tk demos).
|
|
||||||
|
|
||||||
A fair number of utilities that are useful when while developing
|
|
||||||
Python code can be found in the ../Tools directory -- some of these
|
|
||||||
can also be considered good examples of how to write Python code.
|
|
||||||
|
|
||||||
Finally, in order to save disk space and net bandwidth, not all
|
|
||||||
subdirectories listed here are distributed. They are listed just
|
|
||||||
in case I change my mind about them.
|
|
||||||
|
|
||||||
|
|
||||||
cgi CGI examples.
|
|
||||||
|
|
||||||
classes Some examples of how to use classes.
|
|
||||||
|
|
||||||
comparisons A set of responses to a really old language-comparison
|
|
||||||
challenge.
|
|
||||||
|
|
||||||
curses A set of curses demos.
|
|
||||||
|
|
||||||
distutils Test for using transparent 2to3 conversion in distutils.
|
|
||||||
|
|
||||||
embed An example of embedding Python in another application
|
|
||||||
(see also pysvr).
|
|
||||||
|
|
||||||
imputil Demonstration subclasses of imputil.Importer.
|
|
||||||
|
|
||||||
md5test Test program for the optional md5 module.
|
|
||||||
|
|
||||||
newmetaclasses Demonstration of metaclasses.
|
|
||||||
|
|
||||||
parser Example using the parser module.
|
|
||||||
|
|
||||||
pysvr An example of embedding Python in a threaded
|
|
||||||
application.
|
|
||||||
|
|
||||||
rpc A set of classes for building clients and servers for
|
|
||||||
Sun RPC.
|
|
||||||
|
|
||||||
scripts Some useful Python scripts that I put in my bin
|
|
||||||
directory. No optional built-in modules needed.
|
|
||||||
|
|
||||||
sockets Examples for the new built-in module 'socket'.
|
|
||||||
|
|
||||||
threads Demos that use the 'thread' module. (Currently these
|
|
||||||
only run on SGIs, but this may change in the future.)
|
|
||||||
|
|
||||||
tix Demos using the Tix widget set addition to Tkinter.
|
|
||||||
|
|
||||||
tkinter Demos using the Tk interface (including Matt Conway's
|
|
||||||
excellent set of demos).
|
|
||||||
|
|
||||||
turtle Demos for the "turtle" module.
|
|
||||||
|
|
||||||
xml Some XML demos.
|
|
||||||
|
|
||||||
zlib Some demos for the zlib module (see also the standard
|
|
||||||
library module gzip.py).
|
|
|
@ -1,304 +0,0 @@
|
||||||
# Complex numbers
|
|
||||||
# ---------------
|
|
||||||
|
|
||||||
# [Now that Python has a complex data type built-in, this is not very
|
|
||||||
# useful, but it's still a nice example class]
|
|
||||||
|
|
||||||
# This module represents complex numbers as instances of the class Complex.
|
|
||||||
# A Complex instance z has two data attribues, z.re (the real part) and z.im
|
|
||||||
# (the imaginary part). In fact, z.re and z.im can have any value -- all
|
|
||||||
# arithmetic operators work regardless of the type of z.re and z.im (as long
|
|
||||||
# as they support numerical operations).
|
|
||||||
#
|
|
||||||
# The following functions exist (Complex is actually a class):
|
|
||||||
# Complex([re [,im]) -> creates a complex number from a real and an imaginary part
|
|
||||||
# IsComplex(z) -> true iff z is a complex number (== has .re and .im attributes)
|
|
||||||
# ToComplex(z) -> a complex number equal to z; z itself if IsComplex(z) is true
|
|
||||||
# if z is a tuple(re, im) it will also be converted
|
|
||||||
# PolarToComplex([r [,phi [,fullcircle]]]) ->
|
|
||||||
# the complex number z for which r == z.radius() and phi == z.angle(fullcircle)
|
|
||||||
# (r and phi default to 0)
|
|
||||||
# exp(z) -> returns the complex exponential of z. Equivalent to pow(math.e,z).
|
|
||||||
#
|
|
||||||
# Complex numbers have the following methods:
|
|
||||||
# z.abs() -> absolute value of z
|
|
||||||
# z.radius() == z.abs()
|
|
||||||
# z.angle([fullcircle]) -> angle from positive X axis; fullcircle gives units
|
|
||||||
# z.phi([fullcircle]) == z.angle(fullcircle)
|
|
||||||
#
|
|
||||||
# These standard functions and unary operators accept complex arguments:
|
|
||||||
# abs(z)
|
|
||||||
# -z
|
|
||||||
# +z
|
|
||||||
# not z
|
|
||||||
# repr(z) == `z`
|
|
||||||
# str(z)
|
|
||||||
# hash(z) -> a combination of hash(z.re) and hash(z.im) such that if z.im is zero
|
|
||||||
# the result equals hash(z.re)
|
|
||||||
# Note that hex(z) and oct(z) are not defined.
|
|
||||||
#
|
|
||||||
# These conversions accept complex arguments only if their imaginary part is zero:
|
|
||||||
# int(z)
|
|
||||||
# float(z)
|
|
||||||
#
|
|
||||||
# The following operators accept two complex numbers, or one complex number
|
|
||||||
# and one real number (int, long or float):
|
|
||||||
# z1 + z2
|
|
||||||
# z1 - z2
|
|
||||||
# z1 * z2
|
|
||||||
# z1 / z2
|
|
||||||
# pow(z1, z2)
|
|
||||||
# cmp(z1, z2)
|
|
||||||
# Note that z1 % z2 and divmod(z1, z2) are not defined,
|
|
||||||
# nor are shift and mask operations.
|
|
||||||
#
|
|
||||||
# The standard module math does not support complex numbers.
|
|
||||||
# The cmath modules should be used instead.
|
|
||||||
#
|
|
||||||
# Idea:
|
|
||||||
# add a class Polar(r, phi) and mixed-mode arithmetic which
|
|
||||||
# chooses the most appropriate type for the result:
|
|
||||||
# Complex for +,-,cmp
|
|
||||||
# Polar for *,/,pow
|
|
||||||
|
|
||||||
import math
|
|
||||||
import sys
|
|
||||||
|
|
||||||
twopi = math.pi*2.0
|
|
||||||
halfpi = math.pi/2.0
|
|
||||||
|
|
||||||
def IsComplex(obj):
|
|
||||||
return hasattr(obj, 're') and hasattr(obj, 'im')
|
|
||||||
|
|
||||||
def ToComplex(obj):
|
|
||||||
if IsComplex(obj):
|
|
||||||
return obj
|
|
||||||
elif isinstance(obj, tuple):
|
|
||||||
return Complex(*obj)
|
|
||||||
else:
|
|
||||||
return Complex(obj)
|
|
||||||
|
|
||||||
def PolarToComplex(r = 0, phi = 0, fullcircle = twopi):
|
|
||||||
phi = phi * (twopi / fullcircle)
|
|
||||||
return Complex(math.cos(phi)*r, math.sin(phi)*r)
|
|
||||||
|
|
||||||
def Re(obj):
|
|
||||||
if IsComplex(obj):
|
|
||||||
return obj.re
|
|
||||||
return obj
|
|
||||||
|
|
||||||
def Im(obj):
|
|
||||||
if IsComplex(obj):
|
|
||||||
return obj.im
|
|
||||||
return 0
|
|
||||||
|
|
||||||
class Complex:
|
|
||||||
|
|
||||||
def __init__(self, re=0, im=0):
|
|
||||||
_re = 0
|
|
||||||
_im = 0
|
|
||||||
if IsComplex(re):
|
|
||||||
_re = re.re
|
|
||||||
_im = re.im
|
|
||||||
else:
|
|
||||||
_re = re
|
|
||||||
if IsComplex(im):
|
|
||||||
_re = _re - im.im
|
|
||||||
_im = _im + im.re
|
|
||||||
else:
|
|
||||||
_im = _im + im
|
|
||||||
# this class is immutable, so setting self.re directly is
|
|
||||||
# not possible.
|
|
||||||
self.__dict__['re'] = _re
|
|
||||||
self.__dict__['im'] = _im
|
|
||||||
|
|
||||||
def __setattr__(self, name, value):
|
|
||||||
raise TypeError('Complex numbers are immutable')
|
|
||||||
|
|
||||||
def __hash__(self):
|
|
||||||
if not self.im:
|
|
||||||
return hash(self.re)
|
|
||||||
return hash((self.re, self.im))
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
if not self.im:
|
|
||||||
return 'Complex(%r)' % (self.re,)
|
|
||||||
else:
|
|
||||||
return 'Complex(%r, %r)' % (self.re, self.im)
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
if not self.im:
|
|
||||||
return repr(self.re)
|
|
||||||
else:
|
|
||||||
return 'Complex(%r, %r)' % (self.re, self.im)
|
|
||||||
|
|
||||||
def __neg__(self):
|
|
||||||
return Complex(-self.re, -self.im)
|
|
||||||
|
|
||||||
def __pos__(self):
|
|
||||||
return self
|
|
||||||
|
|
||||||
def __abs__(self):
|
|
||||||
return math.hypot(self.re, self.im)
|
|
||||||
|
|
||||||
def __int__(self):
|
|
||||||
if self.im:
|
|
||||||
raise ValueError("can't convert Complex with nonzero im to int")
|
|
||||||
return int(self.re)
|
|
||||||
|
|
||||||
def __float__(self):
|
|
||||||
if self.im:
|
|
||||||
raise ValueError("can't convert Complex with nonzero im to float")
|
|
||||||
return float(self.re)
|
|
||||||
|
|
||||||
def __eq__(self, other):
|
|
||||||
other = ToComplex(other)
|
|
||||||
return (self.re, self.im) == (other.re, other.im)
|
|
||||||
|
|
||||||
def __bool__(self):
|
|
||||||
return not (self.re == self.im == 0)
|
|
||||||
|
|
||||||
abs = radius = __abs__
|
|
||||||
|
|
||||||
def angle(self, fullcircle = twopi):
|
|
||||||
return (fullcircle/twopi) * ((halfpi - math.atan2(self.re, self.im)) % twopi)
|
|
||||||
|
|
||||||
phi = angle
|
|
||||||
|
|
||||||
def __add__(self, other):
|
|
||||||
other = ToComplex(other)
|
|
||||||
return Complex(self.re + other.re, self.im + other.im)
|
|
||||||
|
|
||||||
__radd__ = __add__
|
|
||||||
|
|
||||||
def __sub__(self, other):
|
|
||||||
other = ToComplex(other)
|
|
||||||
return Complex(self.re - other.re, self.im - other.im)
|
|
||||||
|
|
||||||
def __rsub__(self, other):
|
|
||||||
other = ToComplex(other)
|
|
||||||
return other - self
|
|
||||||
|
|
||||||
def __mul__(self, other):
|
|
||||||
other = ToComplex(other)
|
|
||||||
return Complex(self.re*other.re - self.im*other.im,
|
|
||||||
self.re*other.im + self.im*other.re)
|
|
||||||
|
|
||||||
__rmul__ = __mul__
|
|
||||||
|
|
||||||
def __truediv__(self, other):
|
|
||||||
other = ToComplex(other)
|
|
||||||
d = float(other.re*other.re + other.im*other.im)
|
|
||||||
if not d: raise ZeroDivisionError('Complex division')
|
|
||||||
return Complex((self.re*other.re + self.im*other.im) / d,
|
|
||||||
(self.im*other.re - self.re*other.im) / d)
|
|
||||||
|
|
||||||
def __rtruediv__(self, other):
|
|
||||||
other = ToComplex(other)
|
|
||||||
return other / self
|
|
||||||
|
|
||||||
def __pow__(self, n, z=None):
|
|
||||||
if z is not None:
|
|
||||||
raise TypeError('Complex does not support ternary pow()')
|
|
||||||
if IsComplex(n):
|
|
||||||
if n.im:
|
|
||||||
if self.im: raise TypeError('Complex to the Complex power')
|
|
||||||
else: return exp(math.log(self.re)*n)
|
|
||||||
n = n.re
|
|
||||||
r = pow(self.abs(), n)
|
|
||||||
phi = n*self.angle()
|
|
||||||
return Complex(math.cos(phi)*r, math.sin(phi)*r)
|
|
||||||
|
|
||||||
def __rpow__(self, base):
|
|
||||||
base = ToComplex(base)
|
|
||||||
return pow(base, self)
|
|
||||||
|
|
||||||
def exp(z):
|
|
||||||
r = math.exp(z.re)
|
|
||||||
return Complex(math.cos(z.im)*r,math.sin(z.im)*r)
|
|
||||||
|
|
||||||
|
|
||||||
def checkop(expr, a, b, value, fuzz = 1e-6):
|
|
||||||
print(' ', a, 'and', b, end=' ')
|
|
||||||
try:
|
|
||||||
result = eval(expr)
|
|
||||||
except Exception as e:
|
|
||||||
print('!!\t!!\t!! error: {}'.format(e))
|
|
||||||
return
|
|
||||||
print('->', result)
|
|
||||||
if isinstance(result, str) or isinstance(value, str):
|
|
||||||
ok = (result == value)
|
|
||||||
else:
|
|
||||||
ok = abs(result - value) <= fuzz
|
|
||||||
if not ok:
|
|
||||||
print('!!\t!!\t!! should be', value, 'diff', abs(result - value))
|
|
||||||
|
|
||||||
def test():
|
|
||||||
print('test constructors')
|
|
||||||
constructor_test = (
|
|
||||||
# "expect" is an array [re,im] "got" the Complex.
|
|
||||||
( (0,0), Complex() ),
|
|
||||||
( (0,0), Complex() ),
|
|
||||||
( (1,0), Complex(1) ),
|
|
||||||
( (0,1), Complex(0,1) ),
|
|
||||||
( (1,2), Complex(Complex(1,2)) ),
|
|
||||||
( (1,3), Complex(Complex(1,2),1) ),
|
|
||||||
( (0,0), Complex(0,Complex(0,0)) ),
|
|
||||||
( (3,4), Complex(3,Complex(4)) ),
|
|
||||||
( (-1,3), Complex(1,Complex(3,2)) ),
|
|
||||||
( (-7,6), Complex(Complex(1,2),Complex(4,8)) ) )
|
|
||||||
cnt = [0,0]
|
|
||||||
for t in constructor_test:
|
|
||||||
cnt[0] += 1
|
|
||||||
if ((t[0][0]!=t[1].re)or(t[0][1]!=t[1].im)):
|
|
||||||
print(" expected", t[0], "got", t[1])
|
|
||||||
cnt[1] += 1
|
|
||||||
print(" ", cnt[1], "of", cnt[0], "tests failed")
|
|
||||||
# test operators
|
|
||||||
testsuite = {
|
|
||||||
'a+b': [
|
|
||||||
(1, 10, 11),
|
|
||||||
(1, Complex(0,10), Complex(1,10)),
|
|
||||||
(Complex(0,10), 1, Complex(1,10)),
|
|
||||||
(Complex(0,10), Complex(1), Complex(1,10)),
|
|
||||||
(Complex(1), Complex(0,10), Complex(1,10)),
|
|
||||||
],
|
|
||||||
'a-b': [
|
|
||||||
(1, 10, -9),
|
|
||||||
(1, Complex(0,10), Complex(1,-10)),
|
|
||||||
(Complex(0,10), 1, Complex(-1,10)),
|
|
||||||
(Complex(0,10), Complex(1), Complex(-1,10)),
|
|
||||||
(Complex(1), Complex(0,10), Complex(1,-10)),
|
|
||||||
],
|
|
||||||
'a*b': [
|
|
||||||
(1, 10, 10),
|
|
||||||
(1, Complex(0,10), Complex(0, 10)),
|
|
||||||
(Complex(0,10), 1, Complex(0,10)),
|
|
||||||
(Complex(0,10), Complex(1), Complex(0,10)),
|
|
||||||
(Complex(1), Complex(0,10), Complex(0,10)),
|
|
||||||
],
|
|
||||||
'a/b': [
|
|
||||||
(1., 10, 0.1),
|
|
||||||
(1, Complex(0,10), Complex(0, -0.1)),
|
|
||||||
(Complex(0, 10), 1, Complex(0, 10)),
|
|
||||||
(Complex(0, 10), Complex(1), Complex(0, 10)),
|
|
||||||
(Complex(1), Complex(0,10), Complex(0, -0.1)),
|
|
||||||
],
|
|
||||||
'pow(a,b)': [
|
|
||||||
(1, 10, 1),
|
|
||||||
(1, Complex(0,10), 1),
|
|
||||||
(Complex(0,10), 1, Complex(0,10)),
|
|
||||||
(Complex(0,10), Complex(1), Complex(0,10)),
|
|
||||||
(Complex(1), Complex(0,10), 1),
|
|
||||||
(2, Complex(4,0), 16),
|
|
||||||
],
|
|
||||||
}
|
|
||||||
for expr in sorted(testsuite):
|
|
||||||
print(expr + ':')
|
|
||||||
t = (expr,)
|
|
||||||
for item in testsuite[expr]:
|
|
||||||
checkop(*(t+item))
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
test()
|
|
|
@ -1,227 +0,0 @@
|
||||||
"""
|
|
||||||
Class Date supplies date objects that support date arithmetic.
|
|
||||||
|
|
||||||
Date(month,day,year) returns a Date object. An instance prints as,
|
|
||||||
e.g., 'Mon 16 Aug 1993'.
|
|
||||||
|
|
||||||
Addition, subtraction, comparison operators, min, max, and sorting
|
|
||||||
all work as expected for date objects: int+date or date+int returns
|
|
||||||
the date `int' days from `date'; date+date raises an exception;
|
|
||||||
date-int returns the date `int' days before `date'; date2-date1 returns
|
|
||||||
an integer, the number of days from date1 to date2; int-date raises an
|
|
||||||
exception; date1 < date2 is true iff date1 occurs before date2 (&
|
|
||||||
similarly for other comparisons); min(date1,date2) is the earlier of
|
|
||||||
the two dates and max(date1,date2) the later; and date objects can be
|
|
||||||
used as dictionary keys.
|
|
||||||
|
|
||||||
Date objects support one visible method, date.weekday(). This returns
|
|
||||||
the day of the week the date falls on, as a string.
|
|
||||||
|
|
||||||
Date objects also have 4 read-only data attributes:
|
|
||||||
.month in 1..12
|
|
||||||
.day in 1..31
|
|
||||||
.year int or long int
|
|
||||||
.ord the ordinal of the date relative to an arbitrary staring point
|
|
||||||
|
|
||||||
The Dates module also supplies function today(), which returns the
|
|
||||||
current date as a date object.
|
|
||||||
|
|
||||||
Those entranced by calendar trivia will be disappointed, as no attempt
|
|
||||||
has been made to accommodate the Julian (etc) system. On the other
|
|
||||||
hand, at least this package knows that 2000 is a leap year but 2100
|
|
||||||
isn't, and works fine for years with a hundred decimal digits <wink>.
|
|
||||||
|
|
||||||
Tim Peters tim@ksr.com
|
|
||||||
not speaking for Kendall Square Research Corp
|
|
||||||
|
|
||||||
Adapted to Python 1.1 (where some hacks to overcome coercion are unnecessary)
|
|
||||||
by Guido van Rossum
|
|
||||||
|
|
||||||
Note that as of Python 2.3, a datetime module is included in the stardard
|
|
||||||
library.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import functools
|
|
||||||
|
|
||||||
_MONTH_NAMES = [ 'January', 'February', 'March', 'April', 'May',
|
|
||||||
'June', 'July', 'August', 'September', 'October',
|
|
||||||
'November', 'December' ]
|
|
||||||
|
|
||||||
_DAY_NAMES = [ 'Friday', 'Saturday', 'Sunday', 'Monday',
|
|
||||||
'Tuesday', 'Wednesday', 'Thursday' ]
|
|
||||||
|
|
||||||
_DAYS_IN_MONTH = [ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ]
|
|
||||||
|
|
||||||
_DAYS_BEFORE_MONTH = []
|
|
||||||
dbm = 0
|
|
||||||
for dim in _DAYS_IN_MONTH:
|
|
||||||
_DAYS_BEFORE_MONTH.append(dbm)
|
|
||||||
dbm = dbm + dim
|
|
||||||
del dbm, dim
|
|
||||||
|
|
||||||
def _is_leap(year): # 1 if leap year, else 0
|
|
||||||
if year % 4 != 0: return 0
|
|
||||||
if year % 400 == 0: return 1
|
|
||||||
return year % 100 != 0
|
|
||||||
|
|
||||||
def _days_in_year(year): # number of days in year
|
|
||||||
return 365 + _is_leap(year)
|
|
||||||
|
|
||||||
def _days_before_year(year): # number of days before year
|
|
||||||
return year*365 + (year+3)//4 - (year+99)//100 + (year+399)//400
|
|
||||||
|
|
||||||
def _days_in_month(month, year): # number of days in month of year
|
|
||||||
if month == 2 and _is_leap(year): return 29
|
|
||||||
return _DAYS_IN_MONTH[month-1]
|
|
||||||
|
|
||||||
def _days_before_month(month, year): # number of days in year before month
|
|
||||||
return _DAYS_BEFORE_MONTH[month-1] + (month > 2 and _is_leap(year))
|
|
||||||
|
|
||||||
def _date2num(date): # compute ordinal of date.month,day,year
|
|
||||||
return _days_before_year(date.year) + \
|
|
||||||
_days_before_month(date.month, date.year) + \
|
|
||||||
date.day
|
|
||||||
|
|
||||||
_DI400Y = _days_before_year(400) # number of days in 400 years
|
|
||||||
|
|
||||||
def _num2date(n): # return date with ordinal n
|
|
||||||
if not isinstance(n, int):
|
|
||||||
raise TypeError('argument must be integer: %r' % type(n))
|
|
||||||
|
|
||||||
# Get uninitialized Date object. This is necesary because once
|
|
||||||
# attributes are set, they cannot be changed.
|
|
||||||
ans = Date.__new__(Date)
|
|
||||||
ans.ord = n
|
|
||||||
|
|
||||||
n400 = (n-1)//_DI400Y # # of 400-year blocks preceding
|
|
||||||
year, n = 400 * n400, n - _DI400Y * n400
|
|
||||||
more = n // 365
|
|
||||||
dby = _days_before_year(more)
|
|
||||||
if dby >= n:
|
|
||||||
more = more - 1
|
|
||||||
dby = dby - _days_in_year(more)
|
|
||||||
year, n = year + more, n - dby
|
|
||||||
month = min(n//29 + 1, 12)
|
|
||||||
dbm = _days_before_month(month, year)
|
|
||||||
if dbm >= n:
|
|
||||||
month = month - 1
|
|
||||||
dbm = dbm - _days_in_month(month, year)
|
|
||||||
|
|
||||||
ans.month, ans.day, ans.year = month, n-dbm, year
|
|
||||||
return ans
|
|
||||||
|
|
||||||
def _num2day(n): # return weekday name of day with ordinal n
|
|
||||||
return _DAY_NAMES[n % 7]
|
|
||||||
|
|
||||||
@functools.total_ordering
|
|
||||||
class Date:
|
|
||||||
def __init__(self, month, day, year):
|
|
||||||
if not 1 <= month <= 12:
|
|
||||||
raise ValueError('month must be in 1..12: %r' % (month,))
|
|
||||||
dim = _days_in_month(month, year)
|
|
||||||
if not 1 <= day <= dim:
|
|
||||||
raise ValueError('day must be in 1..%r: %r' % (dim, day))
|
|
||||||
self.month, self.day, self.year = map(int, (month, day, year))
|
|
||||||
self.ord = _date2num(self)
|
|
||||||
|
|
||||||
# don't allow setting existing attributes
|
|
||||||
def __setattr__(self, name, value):
|
|
||||||
if name in self.__dict__:
|
|
||||||
raise AttributeError('read-only attribute ' + name)
|
|
||||||
self.__dict__[name] = value
|
|
||||||
|
|
||||||
def __eq__(self, other):
|
|
||||||
return self.ord == other.ord
|
|
||||||
|
|
||||||
def __lt__(self, other):
|
|
||||||
return self.ord < other.ord
|
|
||||||
|
|
||||||
# define a hash function so dates can be used as dictionary keys
|
|
||||||
def __hash__(self):
|
|
||||||
return hash(self.ord)
|
|
||||||
|
|
||||||
# print as, e.g., Mon 16 Aug 1993
|
|
||||||
def __repr__(self):
|
|
||||||
return '%.3s %2d %.3s %r' % (
|
|
||||||
self.weekday(),
|
|
||||||
self.day,
|
|
||||||
_MONTH_NAMES[self.month-1],
|
|
||||||
self.year)
|
|
||||||
|
|
||||||
# Python 1.1 coerces neither int+date nor date+int
|
|
||||||
def __add__(self, n):
|
|
||||||
if not isinstance(n, int):
|
|
||||||
raise TypeError('can\'t add %r to date' % type(n))
|
|
||||||
return _num2date(self.ord + n)
|
|
||||||
__radd__ = __add__ # handle int+date
|
|
||||||
|
|
||||||
# Python 1.1 coerces neither date-int nor date-date
|
|
||||||
def __sub__(self, other):
|
|
||||||
if isinstance(other, int): # date-int
|
|
||||||
return _num2date(self.ord - other)
|
|
||||||
else:
|
|
||||||
return self.ord - other.ord # date-date
|
|
||||||
|
|
||||||
# complain about int-date
|
|
||||||
def __rsub__(self, other):
|
|
||||||
raise TypeError('Can\'t subtract date from integer')
|
|
||||||
|
|
||||||
def weekday(self):
|
|
||||||
return _num2day(self.ord)
|
|
||||||
|
|
||||||
def today():
|
|
||||||
import time
|
|
||||||
local = time.localtime(time.time())
|
|
||||||
return Date(local[1], local[2], local[0])
|
|
||||||
|
|
||||||
class DateTestError(Exception):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def test(firstyear, lastyear):
|
|
||||||
a = Date(9,30,1913)
|
|
||||||
b = Date(9,30,1914)
|
|
||||||
if repr(a) != 'Tue 30 Sep 1913':
|
|
||||||
raise DateTestError('__repr__ failure')
|
|
||||||
if (not a < b) or a == b or a > b or b != b:
|
|
||||||
raise DateTestError('__cmp__ failure')
|
|
||||||
if a+365 != b or 365+a != b:
|
|
||||||
raise DateTestError('__add__ failure')
|
|
||||||
if b-a != 365 or b-365 != a:
|
|
||||||
raise DateTestError('__sub__ failure')
|
|
||||||
try:
|
|
||||||
x = 1 - a
|
|
||||||
raise DateTestError('int-date should have failed')
|
|
||||||
except TypeError:
|
|
||||||
pass
|
|
||||||
try:
|
|
||||||
x = a + b
|
|
||||||
raise DateTestError('date+date should have failed')
|
|
||||||
except TypeError:
|
|
||||||
pass
|
|
||||||
if a.weekday() != 'Tuesday':
|
|
||||||
raise DateTestError('weekday() failure')
|
|
||||||
if max(a,b) is not b or min(a,b) is not a:
|
|
||||||
raise DateTestError('min/max failure')
|
|
||||||
d = {a-1:b, b:a+1}
|
|
||||||
if d[b-366] != b or d[a+(b-a)] != Date(10,1,1913):
|
|
||||||
raise DateTestError('dictionary failure')
|
|
||||||
|
|
||||||
# verify date<->number conversions for first and last days for
|
|
||||||
# all years in firstyear .. lastyear
|
|
||||||
|
|
||||||
lord = _days_before_year(firstyear)
|
|
||||||
y = firstyear
|
|
||||||
while y <= lastyear:
|
|
||||||
ford = lord + 1
|
|
||||||
lord = ford + _days_in_year(y) - 1
|
|
||||||
fd, ld = Date(1,1,y), Date(12,31,y)
|
|
||||||
if (fd.ord,ld.ord) != (ford,lord):
|
|
||||||
raise DateTestError('date->num failed', y)
|
|
||||||
fd, ld = _num2date(ford), _num2date(lord)
|
|
||||||
if (1,1,y,12,31,y) != \
|
|
||||||
(fd.month,fd.day,fd.year,ld.month,ld.day,ld.year):
|
|
||||||
raise DateTestError('num->date failed', y)
|
|
||||||
y = y + 1
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
test(1850, 2150)
|
|
|
@ -1,11 +0,0 @@
|
||||||
Examples of classes that implement special operators (see reference manual):
|
|
||||||
|
|
||||||
Complex.py Complex numbers
|
|
||||||
Dates.py Date manipulation package by Tim Peters
|
|
||||||
Range.py Example of a generator: re-implement built-in range()
|
|
||||||
Rev.py Yield the reverse of a sequence
|
|
||||||
Vec.py A simple vector class
|
|
||||||
bitvec.py A bit-vector class by Jan-Hein B\"uhrman
|
|
||||||
|
|
||||||
(For straightforward examples of basic class features, such as use of
|
|
||||||
methods and inheritance, see the library code.)
|
|
|
@ -1,93 +0,0 @@
|
||||||
"""Example of a generator: re-implement the built-in range function
|
|
||||||
without actually constructing the list of values.
|
|
||||||
|
|
||||||
OldStyleRange is coded in the way required to work in a 'for' loop before
|
|
||||||
iterators were introduced into the language; using __getitem__ and __len__ .
|
|
||||||
|
|
||||||
"""
|
|
||||||
def handleargs(arglist):
|
|
||||||
"""Take list of arguments and extract/create proper start, stop, and step
|
|
||||||
values and return in a tuple"""
|
|
||||||
try:
|
|
||||||
if len(arglist) == 1:
|
|
||||||
return 0, int(arglist[0]), 1
|
|
||||||
elif len(arglist) == 2:
|
|
||||||
return int(arglist[0]), int(arglist[1]), 1
|
|
||||||
elif len(arglist) == 3:
|
|
||||||
if arglist[2] == 0:
|
|
||||||
raise ValueError("step argument must not be zero")
|
|
||||||
return tuple(int(x) for x in arglist)
|
|
||||||
else:
|
|
||||||
raise TypeError("range() accepts 1-3 arguments, given", len(arglist))
|
|
||||||
except TypeError:
|
|
||||||
raise TypeError("range() arguments must be numbers or strings "
|
|
||||||
"representing numbers")
|
|
||||||
|
|
||||||
def genrange(*a):
|
|
||||||
"""Function to implement 'range' as a generator"""
|
|
||||||
start, stop, step = handleargs(a)
|
|
||||||
value = start
|
|
||||||
while value < stop:
|
|
||||||
yield value
|
|
||||||
value += step
|
|
||||||
|
|
||||||
class oldrange:
|
|
||||||
"""Class implementing a range object.
|
|
||||||
To the user the instances feel like immutable sequences
|
|
||||||
(and you can't concatenate or slice them)
|
|
||||||
|
|
||||||
Done using the old way (pre-iterators; __len__ and __getitem__) to have an
|
|
||||||
object be used by a 'for' loop.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, *a):
|
|
||||||
""" Initialize start, stop, and step values along with calculating the
|
|
||||||
nubmer of values (what __len__ will return) in the range"""
|
|
||||||
self.start, self.stop, self.step = handleargs(a)
|
|
||||||
self.len = max(0, (self.stop - self.start) // self.step)
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
"""implement repr(x) which is also used by print"""
|
|
||||||
return 'range(%r, %r, %r)' % (self.start, self.stop, self.step)
|
|
||||||
|
|
||||||
def __len__(self):
|
|
||||||
"""implement len(x)"""
|
|
||||||
return self.len
|
|
||||||
|
|
||||||
def __getitem__(self, i):
|
|
||||||
"""implement x[i]"""
|
|
||||||
if 0 <= i <= self.len:
|
|
||||||
return self.start + self.step * i
|
|
||||||
else:
|
|
||||||
raise IndexError('range[i] index out of range')
|
|
||||||
|
|
||||||
|
|
||||||
def test():
|
|
||||||
import time, builtins
|
|
||||||
#Just a quick sanity check
|
|
||||||
correct_result = list(builtins.range(5, 100, 3))
|
|
||||||
oldrange_result = list(oldrange(5, 100, 3))
|
|
||||||
genrange_result = list(genrange(5, 100, 3))
|
|
||||||
if genrange_result != correct_result or oldrange_result != correct_result:
|
|
||||||
raise Exception("error in implementation:\ncorrect = %s"
|
|
||||||
"\nold-style = %s\ngenerator = %s" %
|
|
||||||
(correct_result, oldrange_result, genrange_result))
|
|
||||||
print("Timings for range(1000):")
|
|
||||||
t1 = time.time()
|
|
||||||
for i in oldrange(1000):
|
|
||||||
pass
|
|
||||||
t2 = time.time()
|
|
||||||
for i in genrange(1000):
|
|
||||||
pass
|
|
||||||
t3 = time.time()
|
|
||||||
for i in builtins.range(1000):
|
|
||||||
pass
|
|
||||||
t4 = time.time()
|
|
||||||
print(t2-t1, 'sec (old-style class)')
|
|
||||||
print(t3-t2, 'sec (generator)')
|
|
||||||
print(t4-t3, 'sec (built-in)')
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
test()
|
|
|
@ -1,93 +0,0 @@
|
||||||
'''
|
|
||||||
A class which presents the reverse of a sequence without duplicating it.
|
|
||||||
From: "Steven D. Majewski" <sdm7g@elvis.med.virginia.edu>
|
|
||||||
|
|
||||||
It works on mutable or inmutable sequences.
|
|
||||||
|
|
||||||
>>> Rev('Hello World!')
|
|
||||||
!dlroW olleH
|
|
||||||
|
|
||||||
The .forw is so you can use anonymous sequences in __init__, and still
|
|
||||||
keep a reference the forward sequence. )
|
|
||||||
If you give it a non-anonymous mutable sequence, the reverse sequence
|
|
||||||
will track the updated values. ( but not reassignment! - another
|
|
||||||
good reason to use anonymous values in creating the sequence to avoid
|
|
||||||
confusion. Maybe it should be change to copy input sequence to break
|
|
||||||
the connection completely ? )
|
|
||||||
|
|
||||||
>>> nnn = list(range(3))
|
|
||||||
>>> rnn = Rev(nnn)
|
|
||||||
>>> for n in rnn: n
|
|
||||||
...
|
|
||||||
2
|
|
||||||
1
|
|
||||||
0
|
|
||||||
>>> for n in range(4, 6): nnn.append(n) # update nnn
|
|
||||||
...
|
|
||||||
>>> for n in rnn: n # prints reversed updated values
|
|
||||||
...
|
|
||||||
5
|
|
||||||
4
|
|
||||||
2
|
|
||||||
1
|
|
||||||
0
|
|
||||||
>>> nnn = nnn[1:-1]
|
|
||||||
>>> nnn
|
|
||||||
[1, 2, 4]
|
|
||||||
>>> for n in rnn: n # prints reversed values of old nnn
|
|
||||||
...
|
|
||||||
5
|
|
||||||
4
|
|
||||||
2
|
|
||||||
1
|
|
||||||
0
|
|
||||||
|
|
||||||
#
|
|
||||||
>>> WH = Rev('Hello World!')
|
|
||||||
>>> print(WH.forw, WH.back)
|
|
||||||
Hello World! !dlroW olleH
|
|
||||||
>>> nnn = Rev(list(range(1, 10)))
|
|
||||||
>>> print(nnn.forw)
|
|
||||||
[1, 2, 3, 4, 5, 6, 7, 8, 9]
|
|
||||||
>>> print(nnn.back)
|
|
||||||
[9, 8, 7, 6, 5, 4, 3, 2, 1]
|
|
||||||
|
|
||||||
>>> Rev(nnn)
|
|
||||||
<1, 2, 3, 4, 5, 6, 7, 8, 9>
|
|
||||||
|
|
||||||
'''
|
|
||||||
|
|
||||||
class Rev:
|
|
||||||
def __init__(self, seq):
|
|
||||||
self.forw = seq
|
|
||||||
self.back = self
|
|
||||||
|
|
||||||
def __len__(self):
|
|
||||||
return len(self.forw)
|
|
||||||
|
|
||||||
def __getitem__(self, j):
|
|
||||||
return self.forw[-(j + 1)]
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
seq = self.forw
|
|
||||||
if isinstance(seq, list):
|
|
||||||
wrap = '[]'
|
|
||||||
sep = ', '
|
|
||||||
elif isinstance(seq, tuple):
|
|
||||||
wrap = '()'
|
|
||||||
sep = ', '
|
|
||||||
elif isinstance(seq, str):
|
|
||||||
wrap = ''
|
|
||||||
sep = ''
|
|
||||||
else:
|
|
||||||
wrap = '<>'
|
|
||||||
sep = ', '
|
|
||||||
outstrs = [str(item) for item in self.back]
|
|
||||||
return wrap[:1] + sep.join(outstrs) + wrap[-1:]
|
|
||||||
|
|
||||||
def _test():
|
|
||||||
import doctest, Rev
|
|
||||||
return doctest.testmod(Rev)
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
_test()
|
|
|
@ -1,322 +0,0 @@
|
||||||
#
|
|
||||||
# this is a rather strict implementation of a bit vector class
|
|
||||||
# it is accessed the same way as an array of python-ints, except
|
|
||||||
# the value must be 0 or 1
|
|
||||||
#
|
|
||||||
|
|
||||||
import sys; rprt = sys.stderr.write #for debugging
|
|
||||||
|
|
||||||
class error(Exception):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
def _check_value(value):
|
|
||||||
if type(value) != type(0) or not 0 <= value < 2:
|
|
||||||
raise error('bitvec() items must have int value 0 or 1')
|
|
||||||
|
|
||||||
|
|
||||||
import math
|
|
||||||
|
|
||||||
def _compute_len(param):
|
|
||||||
mant, l = math.frexp(float(param))
|
|
||||||
bitmask = 1 << l
|
|
||||||
if bitmask <= param:
|
|
||||||
raise ValueError('(param, l) = %r' % ((param, l),))
|
|
||||||
while l:
|
|
||||||
bitmask = bitmask >> 1
|
|
||||||
if param & bitmask:
|
|
||||||
break
|
|
||||||
l = l - 1
|
|
||||||
return l
|
|
||||||
|
|
||||||
|
|
||||||
def _check_key(len, key):
|
|
||||||
if type(key) != type(0):
|
|
||||||
raise TypeError('sequence subscript not int')
|
|
||||||
if key < 0:
|
|
||||||
key = key + len
|
|
||||||
if not 0 <= key < len:
|
|
||||||
raise IndexError('list index out of range')
|
|
||||||
return key
|
|
||||||
|
|
||||||
def _check_slice(len, i, j):
|
|
||||||
#the type is ok, Python already checked that
|
|
||||||
i, j = max(i, 0), min(len, j)
|
|
||||||
if i > j:
|
|
||||||
i = j
|
|
||||||
return i, j
|
|
||||||
|
|
||||||
|
|
||||||
class BitVec:
|
|
||||||
|
|
||||||
def __init__(self, *params):
|
|
||||||
self._data = 0
|
|
||||||
self._len = 0
|
|
||||||
if not len(params):
|
|
||||||
pass
|
|
||||||
elif len(params) == 1:
|
|
||||||
param, = params
|
|
||||||
if type(param) == type([]):
|
|
||||||
value = 0
|
|
||||||
bit_mask = 1
|
|
||||||
for item in param:
|
|
||||||
# strict check
|
|
||||||
#_check_value(item)
|
|
||||||
if item:
|
|
||||||
value = value | bit_mask
|
|
||||||
bit_mask = bit_mask << 1
|
|
||||||
self._data = value
|
|
||||||
self._len = len(param)
|
|
||||||
elif type(param) == type(0):
|
|
||||||
if param < 0:
|
|
||||||
raise error('bitvec() can\'t handle negative longs')
|
|
||||||
self._data = param
|
|
||||||
self._len = _compute_len(param)
|
|
||||||
else:
|
|
||||||
raise error('bitvec() requires array or long parameter')
|
|
||||||
elif len(params) == 2:
|
|
||||||
param, length = params
|
|
||||||
if type(param) == type(0):
|
|
||||||
if param < 0:
|
|
||||||
raise error('can\'t handle negative longs')
|
|
||||||
self._data = param
|
|
||||||
if type(length) != type(0):
|
|
||||||
raise error('bitvec()\'s 2nd parameter must be int')
|
|
||||||
computed_length = _compute_len(param)
|
|
||||||
if computed_length > length:
|
|
||||||
print('warning: bitvec() value is longer than the length indicates, truncating value')
|
|
||||||
self._data = self._data & \
|
|
||||||
((1 << length) - 1)
|
|
||||||
self._len = length
|
|
||||||
else:
|
|
||||||
raise error('bitvec() requires array or long parameter')
|
|
||||||
else:
|
|
||||||
raise error('bitvec() requires 0 -- 2 parameter(s)')
|
|
||||||
|
|
||||||
|
|
||||||
def append(self, item):
|
|
||||||
#_check_value(item)
|
|
||||||
#self[self._len:self._len] = [item]
|
|
||||||
self[self._len:self._len] = \
|
|
||||||
BitVec(int(not not item), 1)
|
|
||||||
|
|
||||||
|
|
||||||
def count(self, value):
|
|
||||||
#_check_value(value)
|
|
||||||
if value:
|
|
||||||
data = self._data
|
|
||||||
else:
|
|
||||||
data = (~self)._data
|
|
||||||
count = 0
|
|
||||||
while data:
|
|
||||||
data, count = data >> 1, count + (data & 1 != 0)
|
|
||||||
return count
|
|
||||||
|
|
||||||
|
|
||||||
def index(self, value):
|
|
||||||
#_check_value(value):
|
|
||||||
if value:
|
|
||||||
data = self._data
|
|
||||||
else:
|
|
||||||
data = (~self)._data
|
|
||||||
index = 0
|
|
||||||
if not data:
|
|
||||||
raise ValueError('list.index(x): x not in list')
|
|
||||||
while not (data & 1):
|
|
||||||
data, index = data >> 1, index + 1
|
|
||||||
return index
|
|
||||||
|
|
||||||
|
|
||||||
def insert(self, index, item):
|
|
||||||
#_check_value(item)
|
|
||||||
#self[index:index] = [item]
|
|
||||||
self[index:index] = BitVec(int(not not item), 1)
|
|
||||||
|
|
||||||
|
|
||||||
def remove(self, value):
|
|
||||||
del self[self.index(value)]
|
|
||||||
|
|
||||||
|
|
||||||
def reverse(self):
|
|
||||||
#ouch, this one is expensive!
|
|
||||||
#for i in self._len>>1: self[i], self[l-i] = self[l-i], self[i]
|
|
||||||
data, result = self._data, 0
|
|
||||||
for i in range(self._len):
|
|
||||||
if not data:
|
|
||||||
result = result << (self._len - i)
|
|
||||||
break
|
|
||||||
result, data = (result << 1) | (data & 1), data >> 1
|
|
||||||
self._data = result
|
|
||||||
|
|
||||||
|
|
||||||
def sort(self):
|
|
||||||
c = self.count(1)
|
|
||||||
self._data = ((1 << c) - 1) << (self._len - c)
|
|
||||||
|
|
||||||
|
|
||||||
def copy(self):
|
|
||||||
return BitVec(self._data, self._len)
|
|
||||||
|
|
||||||
|
|
||||||
def seq(self):
|
|
||||||
result = []
|
|
||||||
for i in self:
|
|
||||||
result.append(i)
|
|
||||||
return result
|
|
||||||
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
##rprt('<bitvec class instance object>.' + '__repr__()\n')
|
|
||||||
return 'bitvec(%r, %r)' % (self._data, self._len)
|
|
||||||
|
|
||||||
def __cmp__(self, other, *rest):
|
|
||||||
#rprt('%r.__cmp__%r\n' % (self, (other,) + rest))
|
|
||||||
if type(other) != type(self):
|
|
||||||
other = bitvec(other, *rest)
|
|
||||||
#expensive solution... recursive binary, with slicing
|
|
||||||
length = self._len
|
|
||||||
if length == 0 or other._len == 0:
|
|
||||||
return cmp(length, other._len)
|
|
||||||
if length != other._len:
|
|
||||||
min_length = min(length, other._len)
|
|
||||||
return cmp(self[:min_length], other[:min_length]) or \
|
|
||||||
cmp(self[min_length:], other[min_length:])
|
|
||||||
#the lengths are the same now...
|
|
||||||
if self._data == other._data:
|
|
||||||
return 0
|
|
||||||
if length == 1:
|
|
||||||
return cmp(self[0], other[0])
|
|
||||||
else:
|
|
||||||
length = length >> 1
|
|
||||||
return cmp(self[:length], other[:length]) or \
|
|
||||||
cmp(self[length:], other[length:])
|
|
||||||
|
|
||||||
|
|
||||||
def __len__(self):
|
|
||||||
#rprt('%r.__len__()\n' % (self,))
|
|
||||||
return self._len
|
|
||||||
|
|
||||||
def __getitem__(self, key):
|
|
||||||
#rprt('%r.__getitem__(%r)\n' % (self, key))
|
|
||||||
key = _check_key(self._len, key)
|
|
||||||
return self._data & (1 << key) != 0
|
|
||||||
|
|
||||||
def __setitem__(self, key, value):
|
|
||||||
#rprt('%r.__setitem__(%r, %r)\n' % (self, key, value))
|
|
||||||
key = _check_key(self._len, key)
|
|
||||||
#_check_value(value)
|
|
||||||
if value:
|
|
||||||
self._data = self._data | (1 << key)
|
|
||||||
else:
|
|
||||||
self._data = self._data & ~(1 << key)
|
|
||||||
|
|
||||||
def __delitem__(self, key):
|
|
||||||
#rprt('%r.__delitem__(%r)\n' % (self, key))
|
|
||||||
key = _check_key(self._len, key)
|
|
||||||
#el cheapo solution...
|
|
||||||
self._data = self[:key]._data | self[key+1:]._data >> key
|
|
||||||
self._len = self._len - 1
|
|
||||||
|
|
||||||
def __getslice__(self, i, j):
|
|
||||||
#rprt('%r.__getslice__(%r, %r)\n' % (self, i, j))
|
|
||||||
i, j = _check_slice(self._len, i, j)
|
|
||||||
if i >= j:
|
|
||||||
return BitVec(0, 0)
|
|
||||||
if i:
|
|
||||||
ndata = self._data >> i
|
|
||||||
else:
|
|
||||||
ndata = self._data
|
|
||||||
nlength = j - i
|
|
||||||
if j != self._len:
|
|
||||||
#we'll have to invent faster variants here
|
|
||||||
#e.g. mod_2exp
|
|
||||||
ndata = ndata & ((1 << nlength) - 1)
|
|
||||||
return BitVec(ndata, nlength)
|
|
||||||
|
|
||||||
def __setslice__(self, i, j, sequence, *rest):
|
|
||||||
#rprt('%s.__setslice__%r\n' % (self, (i, j, sequence) + rest))
|
|
||||||
i, j = _check_slice(self._len, i, j)
|
|
||||||
if type(sequence) != type(self):
|
|
||||||
sequence = bitvec(sequence, *rest)
|
|
||||||
#sequence is now of our own type
|
|
||||||
ls_part = self[:i]
|
|
||||||
ms_part = self[j:]
|
|
||||||
self._data = ls_part._data | \
|
|
||||||
((sequence._data | \
|
|
||||||
(ms_part._data << sequence._len)) << ls_part._len)
|
|
||||||
self._len = self._len - j + i + sequence._len
|
|
||||||
|
|
||||||
def __delslice__(self, i, j):
|
|
||||||
#rprt('%r.__delslice__(%r, %r)\n' % (self, i, j))
|
|
||||||
i, j = _check_slice(self._len, i, j)
|
|
||||||
if i == 0 and j == self._len:
|
|
||||||
self._data, self._len = 0, 0
|
|
||||||
elif i < j:
|
|
||||||
self._data = self[:i]._data | (self[j:]._data >> i)
|
|
||||||
self._len = self._len - j + i
|
|
||||||
|
|
||||||
def __add__(self, other):
|
|
||||||
#rprt('%r.__add__(%r)\n' % (self, other))
|
|
||||||
retval = self.copy()
|
|
||||||
retval[self._len:self._len] = other
|
|
||||||
return retval
|
|
||||||
|
|
||||||
def __mul__(self, multiplier):
|
|
||||||
#rprt('%r.__mul__(%r)\n' % (self, multiplier))
|
|
||||||
if type(multiplier) != type(0):
|
|
||||||
raise TypeError('sequence subscript not int')
|
|
||||||
if multiplier <= 0:
|
|
||||||
return BitVec(0, 0)
|
|
||||||
elif multiplier == 1:
|
|
||||||
return self.copy()
|
|
||||||
#handle special cases all 0 or all 1...
|
|
||||||
if self._data == 0:
|
|
||||||
return BitVec(0, self._len * multiplier)
|
|
||||||
elif (~self)._data == 0:
|
|
||||||
return ~BitVec(0, self._len * multiplier)
|
|
||||||
#otherwise el cheapo again...
|
|
||||||
retval = BitVec(0, 0)
|
|
||||||
while multiplier:
|
|
||||||
retval, multiplier = retval + self, multiplier - 1
|
|
||||||
return retval
|
|
||||||
|
|
||||||
def __and__(self, otherseq, *rest):
|
|
||||||
#rprt('%r.__and__%r\n' % (self, (otherseq,) + rest))
|
|
||||||
if type(otherseq) != type(self):
|
|
||||||
otherseq = bitvec(otherseq, *rest)
|
|
||||||
#sequence is now of our own type
|
|
||||||
return BitVec(self._data & otherseq._data, \
|
|
||||||
min(self._len, otherseq._len))
|
|
||||||
|
|
||||||
|
|
||||||
def __xor__(self, otherseq, *rest):
|
|
||||||
#rprt('%r.__xor__%r\n' % (self, (otherseq,) + rest))
|
|
||||||
if type(otherseq) != type(self):
|
|
||||||
otherseq = bitvec(otherseq, *rest)
|
|
||||||
#sequence is now of our own type
|
|
||||||
return BitVec(self._data ^ otherseq._data, \
|
|
||||||
max(self._len, otherseq._len))
|
|
||||||
|
|
||||||
|
|
||||||
def __or__(self, otherseq, *rest):
|
|
||||||
#rprt('%r.__or__%r\n' % (self, (otherseq,) + rest))
|
|
||||||
if type(otherseq) != type(self):
|
|
||||||
otherseq = bitvec(otherseq, *rest)
|
|
||||||
#sequence is now of our own type
|
|
||||||
return BitVec(self._data | otherseq._data, \
|
|
||||||
max(self._len, otherseq._len))
|
|
||||||
|
|
||||||
|
|
||||||
def __invert__(self):
|
|
||||||
#rprt('%r.__invert__()\n' % (self,))
|
|
||||||
return BitVec(~self._data & ((1 << self._len) - 1), \
|
|
||||||
self._len)
|
|
||||||
|
|
||||||
def __int__(self):
|
|
||||||
return int(self._data)
|
|
||||||
|
|
||||||
def __float__(self):
|
|
||||||
return float(self._data)
|
|
||||||
|
|
||||||
|
|
||||||
bitvec = BitVec
|
|
|
@ -1,25 +0,0 @@
|
||||||
This is a collection of demos and tests for the curses module.
|
|
||||||
|
|
||||||
ncurses demos
|
|
||||||
=============
|
|
||||||
|
|
||||||
These demos are converted from the C versions in the ncurses
|
|
||||||
distribution, and were contributed by Thomas Gellekum <tg@FreeBSD.org>
|
|
||||||
I didn't strive for a `pythonic' style, but bluntly copied the
|
|
||||||
originals. I won't attempt to `beautify' the program anytime soon, but
|
|
||||||
I wouldn't mind someone else making an effort in that direction, of
|
|
||||||
course.
|
|
||||||
|
|
||||||
ncurses.py -- currently only a panels demo
|
|
||||||
rain.py -- raindrops keep falling on my desktop
|
|
||||||
tclock.py -- ASCII clock, by Howard Jones
|
|
||||||
xmas.py -- I'm dreaming of an ASCII christmas
|
|
||||||
|
|
||||||
Please submit bugfixes and new contributions to the Python bug tracker.
|
|
||||||
|
|
||||||
|
|
||||||
Other demos
|
|
||||||
===========
|
|
||||||
|
|
||||||
life.py -- Simple game of Life
|
|
||||||
repeat.py -- Repeatedly execute a shell command (like watch(1))
|
|
|
@ -1,80 +0,0 @@
|
||||||
#! /usr/bin/env python3
|
|
||||||
|
|
||||||
"""repeat [-i SECONDS] <shell-command>
|
|
||||||
|
|
||||||
This simple program repeatedly (at 1-second intervals) executes the
|
|
||||||
shell command given on the command line and displays the output (or as
|
|
||||||
much of it as fits on the screen). It uses curses to paint each new
|
|
||||||
output on top of the old output, so that if nothing changes, the
|
|
||||||
screen doesn't change. This is handy to watch for changes in e.g. a
|
|
||||||
directory or process listing.
|
|
||||||
|
|
||||||
The -i option lets you override the sleep time between executions.
|
|
||||||
|
|
||||||
To end, hit Control-C.
|
|
||||||
"""
|
|
||||||
|
|
||||||
# Author: Guido van Rossum
|
|
||||||
|
|
||||||
# Disclaimer: there's a Linux program named 'watch' that does the same
|
|
||||||
# thing. Honestly, I didn't know of its existence when I wrote this!
|
|
||||||
|
|
||||||
# To do: add features until it has the same functionality as watch(1);
|
|
||||||
# then compare code size and development time.
|
|
||||||
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
import time
|
|
||||||
import curses
|
|
||||||
import getopt
|
|
||||||
|
|
||||||
def main():
|
|
||||||
interval = 1.0
|
|
||||||
try:
|
|
||||||
opts, args = getopt.getopt(sys.argv[1:], "hi:")
|
|
||||||
except getopt.error as err:
|
|
||||||
print(err, file=sys.stderr)
|
|
||||||
sys.exit(2)
|
|
||||||
if not args:
|
|
||||||
print(__doc__)
|
|
||||||
sys.exit(0)
|
|
||||||
for opt, arg in opts:
|
|
||||||
if opt == "-i":
|
|
||||||
interval = float(arg)
|
|
||||||
if opt == "-h":
|
|
||||||
print(__doc__)
|
|
||||||
sys.exit(0)
|
|
||||||
cmd = " ".join(args)
|
|
||||||
cmd_really = cmd + " 2>&1"
|
|
||||||
p = os.popen(cmd_really, "r")
|
|
||||||
text = p.read()
|
|
||||||
sts = p.close()
|
|
||||||
text = addsts(interval, cmd, text, sts)
|
|
||||||
w = curses.initscr()
|
|
||||||
try:
|
|
||||||
while True:
|
|
||||||
w.erase()
|
|
||||||
try:
|
|
||||||
w.addstr(text)
|
|
||||||
except curses.error:
|
|
||||||
pass
|
|
||||||
w.refresh()
|
|
||||||
time.sleep(interval)
|
|
||||||
p = os.popen(cmd_really, "r")
|
|
||||||
text = p.read()
|
|
||||||
sts = p.close()
|
|
||||||
text = addsts(interval, cmd, text, sts)
|
|
||||||
finally:
|
|
||||||
curses.endwin()
|
|
||||||
|
|
||||||
def addsts(interval, cmd, text, sts):
|
|
||||||
now = time.strftime("%H:%M:%S")
|
|
||||||
text = "%s, every %g sec: %s\n%s" % (now, interval, cmd, text)
|
|
||||||
if sts:
|
|
||||||
msg = "Exit status: %d; signal: %d" % (sts>>8, sts&0xFF)
|
|
||||||
if text and not text.endswith("\n"):
|
|
||||||
msg = "\n" + msg
|
|
||||||
text += msg
|
|
||||||
return text
|
|
||||||
|
|
||||||
main()
|
|
|
@ -1,57 +0,0 @@
|
||||||
# Makefile for embedded Python use demo.
|
|
||||||
# (This version originally written on Red Hat Linux 6.1;
|
|
||||||
# edit lines marked with XXX.)
|
|
||||||
|
|
||||||
# XXX The compiler you are using
|
|
||||||
CC= gcc
|
|
||||||
|
|
||||||
# XXX Top of the build tree and source tree
|
|
||||||
blddir= ../..
|
|
||||||
srcdir= ../..
|
|
||||||
|
|
||||||
# Python version
|
|
||||||
VERSION= 3.2
|
|
||||||
|
|
||||||
# Compiler flags
|
|
||||||
OPT= -g
|
|
||||||
INCLUDES= -I$(srcdir)/Include -I$(blddir)
|
|
||||||
CFLAGS= $(OPT)
|
|
||||||
CPPFLAGS= $(INCLUDES)
|
|
||||||
|
|
||||||
# The Python library
|
|
||||||
LIBPYTHON= $(blddir)/libpython$(VERSION).a
|
|
||||||
|
|
||||||
# XXX edit LIBS (in particular) to match $(blddir)/Makefile
|
|
||||||
LIBS= -lnsl -ldl -lreadline -lieee -lpthread -lutil
|
|
||||||
LDFLAGS= -Xlinker -export-dynamic
|
|
||||||
SYSLIBS= -lm
|
|
||||||
MODLIBS=
|
|
||||||
ALLLIBS= $(LIBPYTHON) $(MODLIBS) $(LIBS) $(SYSLIBS)
|
|
||||||
|
|
||||||
# Build the demo applications
|
|
||||||
all: demo loop importexc
|
|
||||||
demo: demo.o
|
|
||||||
$(CC) $(LDFLAGS) demo.o $(ALLLIBS) -o demo
|
|
||||||
|
|
||||||
loop: loop.o
|
|
||||||
$(CC) $(LDFLAGS) loop.o $(ALLLIBS) -o loop
|
|
||||||
|
|
||||||
importexc: importexc.o
|
|
||||||
$(CC) $(LDFLAGS) importexc.o $(ALLLIBS) -o importexc
|
|
||||||
|
|
||||||
# Administrative targets
|
|
||||||
|
|
||||||
test: demo
|
|
||||||
./demo
|
|
||||||
|
|
||||||
COMMAND="print 'hello world'"
|
|
||||||
looptest: loop
|
|
||||||
./loop $(COMMAND)
|
|
||||||
|
|
||||||
clean:
|
|
||||||
-rm -f *.o core
|
|
||||||
|
|
||||||
clobber: clean
|
|
||||||
-rm -f *~ @* '#'* demo loop importexc
|
|
||||||
|
|
||||||
realclean: clobber
|
|
|
@ -1,19 +0,0 @@
|
||||||
This directory show how to embed the Python interpreter in your own
|
|
||||||
application. The file demo.c shows you all that is needed in your C
|
|
||||||
code.
|
|
||||||
|
|
||||||
To build it, you may have to edit the Makefile:
|
|
||||||
|
|
||||||
1) set blddir to the directory where you built Python, if it isn't in
|
|
||||||
the source directory (../..)
|
|
||||||
|
|
||||||
2) change the variables that together define the list of libraries
|
|
||||||
(MODLIBS, LIBS, SYSLIBS) to link with, to match their definitions in
|
|
||||||
$(blddir)/Modules/Makefile
|
|
||||||
|
|
||||||
An additional test program, loop.c, is used to experiment with memory
|
|
||||||
leakage caused by repeated initialization and finalization of the
|
|
||||||
interpreter. It can be build by saying "make loop" and tested with
|
|
||||||
"make looptest". Command line usage is "./loop <python-command>",
|
|
||||||
e.g. "./loop 'print 2+2'" should spit out an endless number of lines
|
|
||||||
containing the number 4.
|
|
|
@ -1,89 +0,0 @@
|
||||||
/* Example of embedding Python in another program */
|
|
||||||
|
|
||||||
#include "Python.h"
|
|
||||||
|
|
||||||
PyObject* PyInit_xyzzy(void); /* Forward */
|
|
||||||
|
|
||||||
main(int argc, char **argv)
|
|
||||||
{
|
|
||||||
/* Ignore passed-in argc/argv. If desired, conversion
|
|
||||||
should use mbstowcs to convert them. */
|
|
||||||
wchar_t *args[] = {L"embed", L"hello", 0};
|
|
||||||
|
|
||||||
/* Pass argv[0] to the Python interpreter */
|
|
||||||
Py_SetProgramName(args[0]);
|
|
||||||
|
|
||||||
/* Add a static module */
|
|
||||||
PyImport_AppendInittab("xyzzy", PyInit_xyzzy);
|
|
||||||
|
|
||||||
/* Initialize the Python interpreter. Required. */
|
|
||||||
Py_Initialize();
|
|
||||||
|
|
||||||
/* Define sys.argv. It is up to the application if you
|
|
||||||
want this; you can also leave it undefined (since the Python
|
|
||||||
code is generally not a main program it has no business
|
|
||||||
touching sys.argv...)
|
|
||||||
|
|
||||||
If the third argument is true, sys.path is modified to include
|
|
||||||
either the directory containing the script named by argv[0], or
|
|
||||||
the current working directory. This can be risky; if you run
|
|
||||||
an application embedding Python in a directory controlled by
|
|
||||||
someone else, attackers could put a Trojan-horse module in the
|
|
||||||
directory (say, a file named os.py) that your application would
|
|
||||||
then import and run.
|
|
||||||
*/
|
|
||||||
PySys_SetArgvEx(2, args, 0);
|
|
||||||
|
|
||||||
/* Do some application specific code */
|
|
||||||
printf("Hello, brave new world\n\n");
|
|
||||||
|
|
||||||
/* Execute some Python statements (in module __main__) */
|
|
||||||
PyRun_SimpleString("import sys\n");
|
|
||||||
PyRun_SimpleString("print(sys.builtin_module_names)\n");
|
|
||||||
PyRun_SimpleString("print(sys.modules.keys())\n");
|
|
||||||
PyRun_SimpleString("print(sys.executable)\n");
|
|
||||||
PyRun_SimpleString("print(sys.argv)\n");
|
|
||||||
|
|
||||||
/* Note that you can call any public function of the Python
|
|
||||||
interpreter here, e.g. call_object(). */
|
|
||||||
|
|
||||||
/* Some more application specific code */
|
|
||||||
printf("\nGoodbye, cruel world\n");
|
|
||||||
|
|
||||||
/* Exit, cleaning up the interpreter */
|
|
||||||
Py_Exit(0);
|
|
||||||
/*NOTREACHED*/
|
|
||||||
}
|
|
||||||
|
|
||||||
/* A static module */
|
|
||||||
|
|
||||||
/* 'self' is not used */
|
|
||||||
static PyObject *
|
|
||||||
xyzzy_foo(PyObject *self, PyObject* args)
|
|
||||||
{
|
|
||||||
return PyLong_FromLong(42L);
|
|
||||||
}
|
|
||||||
|
|
||||||
static PyMethodDef xyzzy_methods[] = {
|
|
||||||
{"foo", xyzzy_foo, METH_NOARGS,
|
|
||||||
"Return the meaning of everything."},
|
|
||||||
{NULL, NULL} /* sentinel */
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct PyModuleDef xyzzymodule = {
|
|
||||||
{}, /* m_base */
|
|
||||||
"xyzzy", /* m_name */
|
|
||||||
0, /* m_doc */
|
|
||||||
0, /* m_size */
|
|
||||||
xyzzy_methods, /* m_methods */
|
|
||||||
0, /* m_reload */
|
|
||||||
0, /* m_traverse */
|
|
||||||
0, /* m_clear */
|
|
||||||
0, /* m_free */
|
|
||||||
};
|
|
||||||
|
|
||||||
PyObject*
|
|
||||||
PyInit_xyzzy(void)
|
|
||||||
{
|
|
||||||
return PyModule_Create(&xyzzymodule);
|
|
||||||
}
|
|
|
@ -1,23 +0,0 @@
|
||||||
#include <Python.h>
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
char* cmd = "import codecs, encodings.utf_8, types; print(types)";
|
|
||||||
#else
|
|
||||||
char* cmd = "import types; print(types)";
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
printf("Initialize interpreter\n");
|
|
||||||
Py_Initialize();
|
|
||||||
PyEval_InitThreads();
|
|
||||||
PyRun_SimpleString(cmd);
|
|
||||||
Py_EndInterpreter(PyThreadState_Get());
|
|
||||||
|
|
||||||
printf("\nInitialize subinterpreter\n");
|
|
||||||
Py_NewInterpreter();
|
|
||||||
PyRun_SimpleString(cmd);
|
|
||||||
Py_Finalize();
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
|
@ -1,33 +0,0 @@
|
||||||
/* Simple program that repeatedly calls Py_Initialize(), does something, and
|
|
||||||
then calls Py_Finalize(). This should help finding leaks related to
|
|
||||||
initialization. */
|
|
||||||
|
|
||||||
#include "Python.h"
|
|
||||||
|
|
||||||
main(int argc, char **argv)
|
|
||||||
{
|
|
||||||
int count = -1;
|
|
||||||
char *command;
|
|
||||||
|
|
||||||
if (argc < 2 || argc > 3) {
|
|
||||||
fprintf(stderr, "usage: loop <python-command> [count]\n");
|
|
||||||
exit(2);
|
|
||||||
}
|
|
||||||
command = argv[1];
|
|
||||||
|
|
||||||
if (argc == 3) {
|
|
||||||
count = atoi(argv[2]);
|
|
||||||
}
|
|
||||||
|
|
||||||
Py_SetProgramName(L"loop");
|
|
||||||
|
|
||||||
/* uncomment this if you don't want to load site.py */
|
|
||||||
/* Py_NoSiteFlag = 1; */
|
|
||||||
|
|
||||||
while (count == -1 || --count >= 0 ) {
|
|
||||||
Py_Initialize();
|
|
||||||
PyRun_SimpleString(command);
|
|
||||||
Py_Finalize();
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
|
@ -1,177 +0,0 @@
|
||||||
"""Enumeration metaclass."""
|
|
||||||
|
|
||||||
class EnumMetaclass(type):
|
|
||||||
"""Metaclass for enumeration.
|
|
||||||
|
|
||||||
To define your own enumeration, do something like
|
|
||||||
|
|
||||||
class Color(Enum):
|
|
||||||
red = 1
|
|
||||||
green = 2
|
|
||||||
blue = 3
|
|
||||||
|
|
||||||
Now, Color.red, Color.green and Color.blue behave totally
|
|
||||||
different: they are enumerated values, not integers.
|
|
||||||
|
|
||||||
Enumerations cannot be instantiated; however they can be
|
|
||||||
subclassed.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(cls, name, bases, dict):
|
|
||||||
super(EnumMetaclass, cls).__init__(name, bases, dict)
|
|
||||||
cls._members = []
|
|
||||||
for attr in dict.keys():
|
|
||||||
if not (attr.startswith('__') and attr.endswith('__')):
|
|
||||||
enumval = EnumInstance(name, attr, dict[attr])
|
|
||||||
setattr(cls, attr, enumval)
|
|
||||||
cls._members.append(attr)
|
|
||||||
|
|
||||||
def __getattr__(cls, name):
|
|
||||||
if name == "__members__":
|
|
||||||
return cls._members
|
|
||||||
raise AttributeError(name)
|
|
||||||
|
|
||||||
def __repr__(cls):
|
|
||||||
s1 = s2 = ""
|
|
||||||
enumbases = [base.__name__ for base in cls.__bases__
|
|
||||||
if isinstance(base, EnumMetaclass) and not base is Enum]
|
|
||||||
if enumbases:
|
|
||||||
s1 = "(%s)" % ", ".join(enumbases)
|
|
||||||
enumvalues = ["%s: %d" % (val, getattr(cls, val))
|
|
||||||
for val in cls._members]
|
|
||||||
if enumvalues:
|
|
||||||
s2 = ": {%s}" % ", ".join(enumvalues)
|
|
||||||
return "%s%s%s" % (cls.__name__, s1, s2)
|
|
||||||
|
|
||||||
class FullEnumMetaclass(EnumMetaclass):
|
|
||||||
"""Metaclass for full enumerations.
|
|
||||||
|
|
||||||
A full enumeration displays all the values defined in base classes.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(cls, name, bases, dict):
|
|
||||||
super(FullEnumMetaclass, cls).__init__(name, bases, dict)
|
|
||||||
for obj in cls.__mro__:
|
|
||||||
if isinstance(obj, EnumMetaclass):
|
|
||||||
for attr in obj._members:
|
|
||||||
# XXX inefficient
|
|
||||||
if not attr in cls._members:
|
|
||||||
cls._members.append(attr)
|
|
||||||
|
|
||||||
class EnumInstance(int):
|
|
||||||
"""Class to represent an enumeration value.
|
|
||||||
|
|
||||||
EnumInstance('Color', 'red', 12) prints as 'Color.red' and behaves
|
|
||||||
like the integer 12 when compared, but doesn't support arithmetic.
|
|
||||||
|
|
||||||
XXX Should it record the actual enumeration rather than just its
|
|
||||||
name?
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __new__(cls, classname, enumname, value):
|
|
||||||
return int.__new__(cls, value)
|
|
||||||
|
|
||||||
def __init__(self, classname, enumname, value):
|
|
||||||
self.__classname = classname
|
|
||||||
self.__enumname = enumname
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
return "EnumInstance(%s, %s, %d)" % (self.__classname, self.__enumname,
|
|
||||||
self)
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return "%s.%s" % (self.__classname, self.__enumname)
|
|
||||||
|
|
||||||
class Enum(metaclass=EnumMetaclass):
|
|
||||||
pass
|
|
||||||
|
|
||||||
class FullEnum(metaclass=FullEnumMetaclass):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def _test():
|
|
||||||
|
|
||||||
class Color(Enum):
|
|
||||||
red = 1
|
|
||||||
green = 2
|
|
||||||
blue = 3
|
|
||||||
|
|
||||||
print(Color.red)
|
|
||||||
|
|
||||||
print(repr(Color.red))
|
|
||||||
print(Color.red == Color.red)
|
|
||||||
print(Color.red == Color.blue)
|
|
||||||
print(Color.red == 1)
|
|
||||||
print(Color.red == 2)
|
|
||||||
|
|
||||||
class ExtendedColor(Color):
|
|
||||||
white = 0
|
|
||||||
orange = 4
|
|
||||||
yellow = 5
|
|
||||||
purple = 6
|
|
||||||
black = 7
|
|
||||||
|
|
||||||
print(ExtendedColor.orange)
|
|
||||||
print(ExtendedColor.red)
|
|
||||||
|
|
||||||
print(Color.red == ExtendedColor.red)
|
|
||||||
|
|
||||||
class OtherColor(Enum):
|
|
||||||
white = 4
|
|
||||||
blue = 5
|
|
||||||
|
|
||||||
class MergedColor(Color, OtherColor):
|
|
||||||
pass
|
|
||||||
|
|
||||||
print(MergedColor.red)
|
|
||||||
print(MergedColor.white)
|
|
||||||
|
|
||||||
print(Color)
|
|
||||||
print(ExtendedColor)
|
|
||||||
print(OtherColor)
|
|
||||||
print(MergedColor)
|
|
||||||
|
|
||||||
def _test2():
|
|
||||||
|
|
||||||
class Color(FullEnum):
|
|
||||||
red = 1
|
|
||||||
green = 2
|
|
||||||
blue = 3
|
|
||||||
|
|
||||||
print(Color.red)
|
|
||||||
|
|
||||||
print(repr(Color.red))
|
|
||||||
print(Color.red == Color.red)
|
|
||||||
print(Color.red == Color.blue)
|
|
||||||
print(Color.red == 1)
|
|
||||||
print(Color.red == 2)
|
|
||||||
|
|
||||||
class ExtendedColor(Color):
|
|
||||||
white = 0
|
|
||||||
orange = 4
|
|
||||||
yellow = 5
|
|
||||||
purple = 6
|
|
||||||
black = 7
|
|
||||||
|
|
||||||
print(ExtendedColor.orange)
|
|
||||||
print(ExtendedColor.red)
|
|
||||||
|
|
||||||
print(Color.red == ExtendedColor.red)
|
|
||||||
|
|
||||||
class OtherColor(FullEnum):
|
|
||||||
white = 4
|
|
||||||
blue = 5
|
|
||||||
|
|
||||||
class MergedColor(Color, OtherColor):
|
|
||||||
pass
|
|
||||||
|
|
||||||
print(MergedColor.red)
|
|
||||||
print(MergedColor.white)
|
|
||||||
|
|
||||||
print(Color)
|
|
||||||
print(ExtendedColor)
|
|
||||||
print(OtherColor)
|
|
||||||
print(MergedColor)
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
_test()
|
|
||||||
_test2()
|
|
|
@ -1,22 +0,0 @@
|
||||||
This directory contains a collection of executable Python scripts.
|
|
||||||
|
|
||||||
See also the Tools/scripts directory!
|
|
||||||
|
|
||||||
beer.py Print the classic 'bottles of beer' list
|
|
||||||
eqfix.py Fix .py files to use the correct equality test operator
|
|
||||||
fact.py Factorize numbers
|
|
||||||
find-uname.py Search for Unicode characters using regexps
|
|
||||||
from.py Summarize mailbox
|
|
||||||
lpwatch.py Watch BSD line printer queues
|
|
||||||
makedir.py Like mkdir -p
|
|
||||||
markov.py Markov chain simulation of words or characters
|
|
||||||
mboxconvert.py Convert MH or MMDF mailboxes to unix mailbox format
|
|
||||||
morse.py Produce morse code (as an AIFF file)
|
|
||||||
newslist.py List all newsgroups on a NNTP server as HTML pages
|
|
||||||
pi.py Print all digits of pi -- given enough time and memory
|
|
||||||
pp.py Emulate some Perl command line options
|
|
||||||
primes.py Print prime numbers
|
|
||||||
queens.py Dijkstra's solution to Wirth's "N Queens problem"
|
|
||||||
script.py Equivalent to BSD script(1) -- by Steen Lumholt
|
|
||||||
unbirthday.py Print unbirthday count
|
|
||||||
update.py Update a bunch of files according to a script
|
|
|
@ -1,49 +0,0 @@
|
||||||
#! /usr/bin/env python3
|
|
||||||
|
|
||||||
# Factorize numbers.
|
|
||||||
# The algorithm is not efficient, but easy to understand.
|
|
||||||
# If there are large factors, it will take forever to find them,
|
|
||||||
# because we try all odd numbers between 3 and sqrt(n)...
|
|
||||||
|
|
||||||
import sys
|
|
||||||
from math import sqrt
|
|
||||||
|
|
||||||
def fact(n):
|
|
||||||
if n < 1:
|
|
||||||
raise ValueError('fact() argument should be >= 1')
|
|
||||||
if n == 1:
|
|
||||||
return [] # special case
|
|
||||||
res = []
|
|
||||||
# Treat even factors special, so we can use i += 2 later
|
|
||||||
while n % 2 == 0:
|
|
||||||
res.append(2)
|
|
||||||
n //= 2
|
|
||||||
# Try odd numbers up to sqrt(n)
|
|
||||||
limit = sqrt(n+1)
|
|
||||||
i = 3
|
|
||||||
while i <= limit:
|
|
||||||
if n % i == 0:
|
|
||||||
res.append(i)
|
|
||||||
n //= i
|
|
||||||
limit = sqrt(n+1)
|
|
||||||
else:
|
|
||||||
i += 2
|
|
||||||
if n != 1:
|
|
||||||
res.append(n)
|
|
||||||
return res
|
|
||||||
|
|
||||||
def main():
|
|
||||||
if len(sys.argv) > 1:
|
|
||||||
source = sys.argv[1:]
|
|
||||||
else:
|
|
||||||
source = iter(input, '')
|
|
||||||
for arg in source:
|
|
||||||
try:
|
|
||||||
n = int(arg)
|
|
||||||
except ValueError:
|
|
||||||
print(arg, 'is not an integer')
|
|
||||||
else:
|
|
||||||
print(n, fact(n))
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
main()
|
|
|
@ -1,106 +0,0 @@
|
||||||
#! /usr/bin/env python3
|
|
||||||
|
|
||||||
# Calculate your unbirthday count (see Alice in Wonderland).
|
|
||||||
# This is defined as the number of days from your birth until today
|
|
||||||
# that weren't your birthday. (The day you were born is not counted).
|
|
||||||
# Leap years make it interesting.
|
|
||||||
|
|
||||||
import sys
|
|
||||||
import time
|
|
||||||
import calendar
|
|
||||||
|
|
||||||
def main():
|
|
||||||
if sys.argv[1:]:
|
|
||||||
year = int(sys.argv[1])
|
|
||||||
else:
|
|
||||||
year = int(input('In which year were you born? '))
|
|
||||||
if 0 <= year < 100:
|
|
||||||
print("I'll assume that by", year, end=' ')
|
|
||||||
year = year + 1900
|
|
||||||
print('you mean', year, 'and not the early Christian era')
|
|
||||||
elif not (1850 <= year <= time.localtime()[0]):
|
|
||||||
print("It's hard to believe you were born in", year)
|
|
||||||
return
|
|
||||||
|
|
||||||
if sys.argv[2:]:
|
|
||||||
month = int(sys.argv[2])
|
|
||||||
else:
|
|
||||||
month = int(input('And in which month? (1-12) '))
|
|
||||||
if not (1 <= month <= 12):
|
|
||||||
print('There is no month numbered', month)
|
|
||||||
return
|
|
||||||
|
|
||||||
if sys.argv[3:]:
|
|
||||||
day = int(sys.argv[3])
|
|
||||||
else:
|
|
||||||
day = int(input('And on what day of that month? (1-31) '))
|
|
||||||
if month == 2 and calendar.isleap(year):
|
|
||||||
maxday = 29
|
|
||||||
else:
|
|
||||||
maxday = calendar.mdays[month]
|
|
||||||
if not (1 <= day <= maxday):
|
|
||||||
print('There are no', day, 'days in that month!')
|
|
||||||
return
|
|
||||||
|
|
||||||
bdaytuple = (year, month, day)
|
|
||||||
bdaydate = mkdate(bdaytuple)
|
|
||||||
print('You were born on', format(bdaytuple))
|
|
||||||
|
|
||||||
todaytuple = time.localtime()[:3]
|
|
||||||
todaydate = mkdate(todaytuple)
|
|
||||||
print('Today is', format(todaytuple))
|
|
||||||
|
|
||||||
if bdaytuple > todaytuple:
|
|
||||||
print('You are a time traveler. Go back to the future!')
|
|
||||||
return
|
|
||||||
|
|
||||||
if bdaytuple == todaytuple:
|
|
||||||
print('You were born today. Have a nice life!')
|
|
||||||
return
|
|
||||||
|
|
||||||
days = todaydate - bdaydate
|
|
||||||
print('You have lived', days, 'days')
|
|
||||||
|
|
||||||
age = 0
|
|
||||||
for y in range(year, todaytuple[0] + 1):
|
|
||||||
if bdaytuple < (y, month, day) <= todaytuple:
|
|
||||||
age = age + 1
|
|
||||||
|
|
||||||
print('You are', age, 'years old')
|
|
||||||
|
|
||||||
if todaytuple[1:] == bdaytuple[1:]:
|
|
||||||
print('Congratulations! Today is your', nth(age), 'birthday')
|
|
||||||
print('Yesterday was your', end=' ')
|
|
||||||
else:
|
|
||||||
print('Today is your', end=' ')
|
|
||||||
print(nth(days - age), 'unbirthday')
|
|
||||||
|
|
||||||
def format(date):
|
|
||||||
(year, month, day) = date
|
|
||||||
return '%d %s %d' % (day, calendar.month_name[month], year)
|
|
||||||
|
|
||||||
def nth(n):
|
|
||||||
if n == 1: return '1st'
|
|
||||||
if n == 2: return '2nd'
|
|
||||||
if n == 3: return '3rd'
|
|
||||||
return '%dth' % n
|
|
||||||
|
|
||||||
def mkdate(date):
|
|
||||||
# January 1st, in 0 A.D. is arbitrarily defined to be day 1,
|
|
||||||
# even though that day never actually existed and the calendar
|
|
||||||
# was different then...
|
|
||||||
(year, month, day) = date
|
|
||||||
days = year*365 # years, roughly
|
|
||||||
days = days + (year+3)//4 # plus leap years, roughly
|
|
||||||
days = days - (year+99)//100 # minus non-leap years every century
|
|
||||||
days = days + (year+399)//400 # plus leap years every 4 centirues
|
|
||||||
for i in range(1, month):
|
|
||||||
if i == 2 and calendar.isleap(year):
|
|
||||||
days = days + 29
|
|
||||||
else:
|
|
||||||
days = days + calendar.mdays[i]
|
|
||||||
days = days + day
|
|
||||||
return days
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
main()
|
|
|
@ -1,14 +0,0 @@
|
||||||
This directory contains some demonstrations of the socket module:
|
|
||||||
|
|
||||||
broadcast.py Broadcast the time to radio.py.
|
|
||||||
echosvr.py About the simplest TCP server possible.
|
|
||||||
finger.py Client for the 'finger' protocol.
|
|
||||||
ftp.py A very simple ftp client.
|
|
||||||
gopher.py A simple gopher client.
|
|
||||||
mcast.py IPv4/v6 multicast example
|
|
||||||
radio.py Receive time broadcasts from broadcast.py.
|
|
||||||
telnet.py Client for the 'telnet' protocol.
|
|
||||||
throughput.py Client and server to measure TCP throughput.
|
|
||||||
unixclient.py Unix socket example, client side
|
|
||||||
unixserver.py Unix socket example, server side
|
|
||||||
udpecho.py Client and server for the UDP echo protocol.
|
|
|
@ -1,15 +0,0 @@
|
||||||
# Send UDP broadcast packets
|
|
||||||
|
|
||||||
MYPORT = 50000
|
|
||||||
|
|
||||||
import sys, time
|
|
||||||
from socket import *
|
|
||||||
|
|
||||||
s = socket(AF_INET, SOCK_DGRAM)
|
|
||||||
s.bind(('', 0))
|
|
||||||
s.setsockopt(SOL_SOCKET, SO_BROADCAST, 1)
|
|
||||||
|
|
||||||
while 1:
|
|
||||||
data = repr(time.time()) + '\n'
|
|
||||||
s.sendto(data, ('<broadcast>', MYPORT))
|
|
||||||
time.sleep(2)
|
|
|
@ -1,31 +0,0 @@
|
||||||
#! /usr/bin/env python3
|
|
||||||
|
|
||||||
# Python implementation of an 'echo' tcp server: echo all data it receives.
|
|
||||||
#
|
|
||||||
# This is the simplest possible server, servicing a single request only.
|
|
||||||
|
|
||||||
import sys
|
|
||||||
from socket import *
|
|
||||||
|
|
||||||
# The standard echo port isn't very useful, it requires root permissions!
|
|
||||||
# ECHO_PORT = 7
|
|
||||||
ECHO_PORT = 50000 + 7
|
|
||||||
BUFSIZE = 1024
|
|
||||||
|
|
||||||
def main():
|
|
||||||
if len(sys.argv) > 1:
|
|
||||||
port = int(eval(sys.argv[1]))
|
|
||||||
else:
|
|
||||||
port = ECHO_PORT
|
|
||||||
s = socket(AF_INET, SOCK_STREAM)
|
|
||||||
s.bind(('', port))
|
|
||||||
s.listen(1)
|
|
||||||
conn, (remotehost, remoteport) = s.accept()
|
|
||||||
print('connected by', remotehost, remoteport)
|
|
||||||
while 1:
|
|
||||||
data = conn.recv(BUFSIZE)
|
|
||||||
if not data:
|
|
||||||
break
|
|
||||||
conn.send(data)
|
|
||||||
|
|
||||||
main()
|
|
|
@ -1,58 +0,0 @@
|
||||||
#! /usr/bin/env python3
|
|
||||||
|
|
||||||
# Python interface to the Internet finger daemon.
|
|
||||||
#
|
|
||||||
# Usage: finger [options] [user][@host] ...
|
|
||||||
#
|
|
||||||
# If no host is given, the finger daemon on the local host is contacted.
|
|
||||||
# Options are passed uninterpreted to the finger daemon!
|
|
||||||
|
|
||||||
|
|
||||||
import sys, string
|
|
||||||
from socket import *
|
|
||||||
|
|
||||||
|
|
||||||
# Hardcode the number of the finger port here.
|
|
||||||
# It's not likely to change soon...
|
|
||||||
#
|
|
||||||
FINGER_PORT = 79
|
|
||||||
|
|
||||||
|
|
||||||
# Function to do one remote finger invocation.
|
|
||||||
# Output goes directly to stdout (although this can be changed).
|
|
||||||
#
|
|
||||||
def finger(host, args):
|
|
||||||
s = socket(AF_INET, SOCK_STREAM)
|
|
||||||
s.connect((host, FINGER_PORT))
|
|
||||||
s.send(args + '\n')
|
|
||||||
while 1:
|
|
||||||
buf = s.recv(1024)
|
|
||||||
if not buf: break
|
|
||||||
sys.stdout.write(buf)
|
|
||||||
sys.stdout.flush()
|
|
||||||
|
|
||||||
|
|
||||||
# Main function: argument parsing.
|
|
||||||
#
|
|
||||||
def main():
|
|
||||||
options = ''
|
|
||||||
i = 1
|
|
||||||
while i < len(sys.argv) and sys.argv[i][:1] == '-':
|
|
||||||
options = options + sys.argv[i] + ' '
|
|
||||||
i = i+1
|
|
||||||
args = sys.argv[i:]
|
|
||||||
if not args:
|
|
||||||
args = ['']
|
|
||||||
for arg in args:
|
|
||||||
if '@' in arg:
|
|
||||||
at = string.index(arg, '@')
|
|
||||||
host = arg[at+1:]
|
|
||||||
arg = arg[:at]
|
|
||||||
else:
|
|
||||||
host = ''
|
|
||||||
finger(host, options + arg)
|
|
||||||
|
|
||||||
|
|
||||||
# Call the main function.
|
|
||||||
#
|
|
||||||
main()
|
|
|
@ -1,152 +0,0 @@
|
||||||
# A simple FTP client.
|
|
||||||
#
|
|
||||||
# The information to write this program was gathered from RFC 959,
|
|
||||||
# but this is not a complete implementation! Yet it shows how a simple
|
|
||||||
# FTP client can be built, and you are welcome to extend it to suit
|
|
||||||
# it to your needs...
|
|
||||||
#
|
|
||||||
# How it works (assuming you've read the RFC):
|
|
||||||
#
|
|
||||||
# User commands are passed uninterpreted to the server. However, the
|
|
||||||
# user never needs to send a PORT command. Rather, the client opens a
|
|
||||||
# port right away and sends the appropriate PORT command to the server.
|
|
||||||
# When a response code 150 is received, this port is used to receive
|
|
||||||
# the data (which is written to stdout in this version), and when the
|
|
||||||
# data is exhausted, a new port is opened and a corresponding PORT
|
|
||||||
# command sent. In order to avoid errors when reusing ports quickly
|
|
||||||
# (and because there is no s.getsockname() method in Python yet) we
|
|
||||||
# cycle through a number of ports in the 50000 range.
|
|
||||||
|
|
||||||
|
|
||||||
import sys, posix, string
|
|
||||||
from socket import *
|
|
||||||
|
|
||||||
|
|
||||||
BUFSIZE = 1024
|
|
||||||
|
|
||||||
# Default port numbers used by the FTP protocol.
|
|
||||||
#
|
|
||||||
FTP_PORT = 21
|
|
||||||
FTP_DATA_PORT = FTP_PORT - 1
|
|
||||||
|
|
||||||
# Change the data port to something not needing root permissions.
|
|
||||||
#
|
|
||||||
FTP_DATA_PORT = FTP_DATA_PORT + 50000
|
|
||||||
|
|
||||||
|
|
||||||
# Main program (called at the end of this file).
|
|
||||||
#
|
|
||||||
def main():
|
|
||||||
hostname = sys.argv[1]
|
|
||||||
control(hostname)
|
|
||||||
|
|
||||||
|
|
||||||
# Control process (user interface and user protocol interpreter).
|
|
||||||
#
|
|
||||||
def control(hostname):
|
|
||||||
#
|
|
||||||
# Create control connection
|
|
||||||
#
|
|
||||||
s = socket(AF_INET, SOCK_STREAM)
|
|
||||||
s.connect((hostname, FTP_PORT))
|
|
||||||
f = s.makefile('r') # Reading the replies is easier from a file...
|
|
||||||
#
|
|
||||||
# Control loop
|
|
||||||
#
|
|
||||||
r = None
|
|
||||||
while 1:
|
|
||||||
code = getreply(f)
|
|
||||||
if code in ('221', 'EOF'): break
|
|
||||||
if code == '150':
|
|
||||||
getdata(r)
|
|
||||||
code = getreply(f)
|
|
||||||
r = None
|
|
||||||
if not r:
|
|
||||||
r = newdataport(s, f)
|
|
||||||
cmd = getcommand()
|
|
||||||
if not cmd: break
|
|
||||||
s.send(cmd + '\r\n')
|
|
||||||
|
|
||||||
|
|
||||||
# Create a new data port and send a PORT command to the server for it.
|
|
||||||
# (Cycle through a number of ports to avoid problems with reusing
|
|
||||||
# a port within a short time.)
|
|
||||||
#
|
|
||||||
nextport = 0
|
|
||||||
#
|
|
||||||
def newdataport(s, f):
|
|
||||||
global nextport
|
|
||||||
port = nextport + FTP_DATA_PORT
|
|
||||||
nextport = (nextport+1) % 16
|
|
||||||
r = socket(AF_INET, SOCK_STREAM)
|
|
||||||
r.bind((gethostbyname(gethostname()), port))
|
|
||||||
r.listen(1)
|
|
||||||
sendportcmd(s, f, port)
|
|
||||||
return r
|
|
||||||
|
|
||||||
|
|
||||||
# Send an appropriate port command.
|
|
||||||
#
|
|
||||||
def sendportcmd(s, f, port):
|
|
||||||
hostname = gethostname()
|
|
||||||
hostaddr = gethostbyname(hostname)
|
|
||||||
hbytes = string.splitfields(hostaddr, '.')
|
|
||||||
pbytes = [repr(port//256), repr(port%256)]
|
|
||||||
bytes = hbytes + pbytes
|
|
||||||
cmd = 'PORT ' + string.joinfields(bytes, ',')
|
|
||||||
s.send(cmd + '\r\n')
|
|
||||||
code = getreply(f)
|
|
||||||
|
|
||||||
|
|
||||||
# Process an ftp reply and return the 3-digit reply code (as a string).
|
|
||||||
# The reply should be a line of text starting with a 3-digit number.
|
|
||||||
# If the 4th char is '-', it is a multi-line reply and is
|
|
||||||
# terminate by a line starting with the same 3-digit number.
|
|
||||||
# Any text while receiving the reply is echoed to the file.
|
|
||||||
#
|
|
||||||
def getreply(f):
|
|
||||||
line = f.readline()
|
|
||||||
if not line: return 'EOF'
|
|
||||||
print(line, end=' ')
|
|
||||||
code = line[:3]
|
|
||||||
if line[3:4] == '-':
|
|
||||||
while 1:
|
|
||||||
line = f.readline()
|
|
||||||
if not line: break # Really an error
|
|
||||||
print(line, end=' ')
|
|
||||||
if line[:3] == code and line[3:4] != '-': break
|
|
||||||
return code
|
|
||||||
|
|
||||||
|
|
||||||
# Get the data from the data connection.
|
|
||||||
#
|
|
||||||
def getdata(r):
|
|
||||||
print('(accepting data connection)')
|
|
||||||
conn, host = r.accept()
|
|
||||||
print('(data connection accepted)')
|
|
||||||
while 1:
|
|
||||||
data = conn.recv(BUFSIZE)
|
|
||||||
if not data: break
|
|
||||||
sys.stdout.write(data)
|
|
||||||
print('(end of data connection)')
|
|
||||||
|
|
||||||
def raw_input(prompt):
|
|
||||||
sys.stdout.write(prompt)
|
|
||||||
sys.stdout.flush()
|
|
||||||
return sys.stdin.readline()
|
|
||||||
|
|
||||||
# Get a command from the user.
|
|
||||||
#
|
|
||||||
def getcommand():
|
|
||||||
try:
|
|
||||||
while 1:
|
|
||||||
line = input('ftp.py> ')
|
|
||||||
if line: return line
|
|
||||||
except EOFError:
|
|
||||||
return ''
|
|
||||||
|
|
||||||
|
|
||||||
# Call the main program.
|
|
||||||
#
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main()
|
|
|
@ -1,352 +0,0 @@
|
||||||
#! /usr/bin/env python3
|
|
||||||
|
|
||||||
# A simple gopher client.
|
|
||||||
#
|
|
||||||
# Usage: gopher [ [selector] host [port] ]
|
|
||||||
|
|
||||||
import sys
|
|
||||||
import os
|
|
||||||
import socket
|
|
||||||
|
|
||||||
# Default selector, host and port
|
|
||||||
DEF_SELECTOR = ''
|
|
||||||
DEF_HOST = 'gopher.micro.umn.edu'
|
|
||||||
DEF_PORT = 70
|
|
||||||
|
|
||||||
# Recognized file types
|
|
||||||
T_TEXTFILE = '0'
|
|
||||||
T_MENU = '1'
|
|
||||||
T_CSO = '2'
|
|
||||||
T_ERROR = '3'
|
|
||||||
T_BINHEX = '4'
|
|
||||||
T_DOS = '5'
|
|
||||||
T_UUENCODE = '6'
|
|
||||||
T_SEARCH = '7'
|
|
||||||
T_TELNET = '8'
|
|
||||||
T_BINARY = '9'
|
|
||||||
T_REDUNDANT = '+'
|
|
||||||
T_SOUND = 's'
|
|
||||||
|
|
||||||
# Dictionary mapping types to strings
|
|
||||||
typename = {'0': '<TEXT>', '1': '<DIR>', '2': '<CSO>', '3': '<ERROR>', \
|
|
||||||
'4': '<BINHEX>', '5': '<DOS>', '6': '<UUENCODE>', '7': '<SEARCH>', \
|
|
||||||
'8': '<TELNET>', '9': '<BINARY>', '+': '<REDUNDANT>', 's': '<SOUND>'}
|
|
||||||
|
|
||||||
# Oft-used characters and strings
|
|
||||||
CRLF = '\r\n'
|
|
||||||
TAB = '\t'
|
|
||||||
|
|
||||||
# Open a TCP connection to a given host and port
|
|
||||||
def open_socket(host, port):
|
|
||||||
if not port:
|
|
||||||
port = DEF_PORT
|
|
||||||
elif type(port) == type(''):
|
|
||||||
port = int(port)
|
|
||||||
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
||||||
s.connect((host, port))
|
|
||||||
return s
|
|
||||||
|
|
||||||
# Send a selector to a given host and port, return a file with the reply
|
|
||||||
def send_request(selector, host, port):
|
|
||||||
s = open_socket(host, port)
|
|
||||||
s.send(selector + CRLF)
|
|
||||||
s.shutdown(1)
|
|
||||||
return s.makefile('r')
|
|
||||||
|
|
||||||
# Get a menu in the form of a list of entries
|
|
||||||
def get_menu(selector, host, port):
|
|
||||||
f = send_request(selector, host, port)
|
|
||||||
list = []
|
|
||||||
while 1:
|
|
||||||
line = f.readline()
|
|
||||||
if not line:
|
|
||||||
print('(Unexpected EOF from server)')
|
|
||||||
break
|
|
||||||
if line[-2:] == CRLF:
|
|
||||||
line = line[:-2]
|
|
||||||
elif line[-1:] in CRLF:
|
|
||||||
line = line[:-1]
|
|
||||||
if line == '.':
|
|
||||||
break
|
|
||||||
if not line:
|
|
||||||
print('(Empty line from server)')
|
|
||||||
continue
|
|
||||||
typechar = line[0]
|
|
||||||
parts = line[1:].split(TAB)
|
|
||||||
if len(parts) < 4:
|
|
||||||
print('(Bad line from server: %r)' % (line,))
|
|
||||||
continue
|
|
||||||
if len(parts) > 4:
|
|
||||||
print('(Extra info from server: %r)' % (parts[4:],))
|
|
||||||
parts.insert(0, typechar)
|
|
||||||
list.append(parts)
|
|
||||||
f.close()
|
|
||||||
return list
|
|
||||||
|
|
||||||
# Get a text file as a list of lines, with trailing CRLF stripped
|
|
||||||
def get_textfile(selector, host, port):
|
|
||||||
list = []
|
|
||||||
get_alt_textfile(selector, host, port, list.append)
|
|
||||||
return list
|
|
||||||
|
|
||||||
# Get a text file and pass each line to a function, with trailing CRLF stripped
|
|
||||||
def get_alt_textfile(selector, host, port, func):
|
|
||||||
f = send_request(selector, host, port)
|
|
||||||
while 1:
|
|
||||||
line = f.readline()
|
|
||||||
if not line:
|
|
||||||
print('(Unexpected EOF from server)')
|
|
||||||
break
|
|
||||||
if line[-2:] == CRLF:
|
|
||||||
line = line[:-2]
|
|
||||||
elif line[-1:] in CRLF:
|
|
||||||
line = line[:-1]
|
|
||||||
if line == '.':
|
|
||||||
break
|
|
||||||
if line[:2] == '..':
|
|
||||||
line = line[1:]
|
|
||||||
func(line)
|
|
||||||
f.close()
|
|
||||||
|
|
||||||
# Get a binary file as one solid data block
|
|
||||||
def get_binary(selector, host, port):
|
|
||||||
f = send_request(selector, host, port)
|
|
||||||
data = f.read()
|
|
||||||
f.close()
|
|
||||||
return data
|
|
||||||
|
|
||||||
# Get a binary file and pass each block to a function
|
|
||||||
def get_alt_binary(selector, host, port, func, blocksize):
|
|
||||||
f = send_request(selector, host, port)
|
|
||||||
while 1:
|
|
||||||
data = f.read(blocksize)
|
|
||||||
if not data:
|
|
||||||
break
|
|
||||||
func(data)
|
|
||||||
|
|
||||||
# A *very* simple interactive browser
|
|
||||||
|
|
||||||
# Browser main command, has default arguments
|
|
||||||
def browser(*args):
|
|
||||||
selector = DEF_SELECTOR
|
|
||||||
host = DEF_HOST
|
|
||||||
port = DEF_PORT
|
|
||||||
n = len(args)
|
|
||||||
if n > 0 and args[0]:
|
|
||||||
selector = args[0]
|
|
||||||
if n > 1 and args[1]:
|
|
||||||
host = args[1]
|
|
||||||
if n > 2 and args[2]:
|
|
||||||
port = args[2]
|
|
||||||
if n > 3:
|
|
||||||
raise RuntimeError('too many args')
|
|
||||||
try:
|
|
||||||
browse_menu(selector, host, port)
|
|
||||||
except socket.error as msg:
|
|
||||||
print('Socket error:', msg)
|
|
||||||
sys.exit(1)
|
|
||||||
except KeyboardInterrupt:
|
|
||||||
print('\n[Goodbye]')
|
|
||||||
|
|
||||||
# Browse a menu
|
|
||||||
def browse_menu(selector, host, port):
|
|
||||||
list = get_menu(selector, host, port)
|
|
||||||
while 1:
|
|
||||||
print('----- MENU -----')
|
|
||||||
print('Selector:', repr(selector))
|
|
||||||
print('Host:', host, ' Port:', port)
|
|
||||||
print()
|
|
||||||
for i in range(len(list)):
|
|
||||||
item = list[i]
|
|
||||||
typechar, description = item[0], item[1]
|
|
||||||
print(repr(i+1).rjust(3) + ':', description, end=' ')
|
|
||||||
if typechar in typename:
|
|
||||||
print(typename[typechar])
|
|
||||||
else:
|
|
||||||
print('<TYPE=' + repr(typechar) + '>')
|
|
||||||
print()
|
|
||||||
while 1:
|
|
||||||
try:
|
|
||||||
str = input('Choice [CR == up a level]: ')
|
|
||||||
except EOFError:
|
|
||||||
print()
|
|
||||||
return
|
|
||||||
if not str:
|
|
||||||
return
|
|
||||||
try:
|
|
||||||
choice = int(str)
|
|
||||||
except ValueError:
|
|
||||||
print('Choice must be a number; try again:')
|
|
||||||
continue
|
|
||||||
if not 0 < choice <= len(list):
|
|
||||||
print('Choice out of range; try again:')
|
|
||||||
continue
|
|
||||||
break
|
|
||||||
item = list[choice-1]
|
|
||||||
typechar = item[0]
|
|
||||||
[i_selector, i_host, i_port] = item[2:5]
|
|
||||||
if typechar in typebrowser:
|
|
||||||
browserfunc = typebrowser[typechar]
|
|
||||||
try:
|
|
||||||
browserfunc(i_selector, i_host, i_port)
|
|
||||||
except (IOError, socket.error):
|
|
||||||
t, v, tb = sys.exc_info()
|
|
||||||
print('***', t, ':', v)
|
|
||||||
else:
|
|
||||||
print('Unsupported object type')
|
|
||||||
|
|
||||||
# Browse a text file
|
|
||||||
def browse_textfile(selector, host, port):
|
|
||||||
x = None
|
|
||||||
try:
|
|
||||||
p = os.popen('${PAGER-more}', 'w')
|
|
||||||
x = SaveLines(p)
|
|
||||||
get_alt_textfile(selector, host, port, x.writeln)
|
|
||||||
except IOError as msg:
|
|
||||||
print('IOError:', msg)
|
|
||||||
if x:
|
|
||||||
x.close()
|
|
||||||
f = open_savefile()
|
|
||||||
if not f:
|
|
||||||
return
|
|
||||||
x = SaveLines(f)
|
|
||||||
try:
|
|
||||||
get_alt_textfile(selector, host, port, x.writeln)
|
|
||||||
print('Done.')
|
|
||||||
except IOError as msg:
|
|
||||||
print('IOError:', msg)
|
|
||||||
x.close()
|
|
||||||
|
|
||||||
def raw_input(prompt):
|
|
||||||
sys.stdout.write(prompt)
|
|
||||||
sys.stdout.flush()
|
|
||||||
return sys.stdin.readline()
|
|
||||||
|
|
||||||
# Browse a search index
|
|
||||||
def browse_search(selector, host, port):
|
|
||||||
while 1:
|
|
||||||
print('----- SEARCH -----')
|
|
||||||
print('Selector:', repr(selector))
|
|
||||||
print('Host:', host, ' Port:', port)
|
|
||||||
print()
|
|
||||||
try:
|
|
||||||
query = input('Query [CR == up a level]: ')
|
|
||||||
except EOFError:
|
|
||||||
print()
|
|
||||||
break
|
|
||||||
query = query.strip()
|
|
||||||
if not query:
|
|
||||||
break
|
|
||||||
if '\t' in query:
|
|
||||||
print('Sorry, queries cannot contain tabs')
|
|
||||||
continue
|
|
||||||
browse_menu(selector + TAB + query, host, port)
|
|
||||||
|
|
||||||
# "Browse" telnet-based information, i.e. open a telnet session
|
|
||||||
def browse_telnet(selector, host, port):
|
|
||||||
if selector:
|
|
||||||
print('Log in as', repr(selector))
|
|
||||||
if type(port) != type(''):
|
|
||||||
port = repr(port)
|
|
||||||
sts = os.system('set -x; exec telnet ' + host + ' ' + port)
|
|
||||||
if sts:
|
|
||||||
print('Exit status:', sts)
|
|
||||||
|
|
||||||
# "Browse" a binary file, i.e. save it to a file
|
|
||||||
def browse_binary(selector, host, port):
|
|
||||||
f = open_savefile()
|
|
||||||
if not f:
|
|
||||||
return
|
|
||||||
x = SaveWithProgress(f)
|
|
||||||
get_alt_binary(selector, host, port, x.write, 8*1024)
|
|
||||||
x.close()
|
|
||||||
|
|
||||||
# "Browse" a sound file, i.e. play it or save it
|
|
||||||
def browse_sound(selector, host, port):
|
|
||||||
browse_binary(selector, host, port)
|
|
||||||
|
|
||||||
# Dictionary mapping types to browser functions
|
|
||||||
typebrowser = {'0': browse_textfile, '1': browse_menu, \
|
|
||||||
'4': browse_binary, '5': browse_binary, '6': browse_textfile, \
|
|
||||||
'7': browse_search, \
|
|
||||||
'8': browse_telnet, '9': browse_binary, 's': browse_sound}
|
|
||||||
|
|
||||||
# Class used to save lines, appending a newline to each line
|
|
||||||
class SaveLines:
|
|
||||||
def __init__(self, f):
|
|
||||||
self.f = f
|
|
||||||
def writeln(self, line):
|
|
||||||
self.f.write(line + '\n')
|
|
||||||
def close(self):
|
|
||||||
sts = self.f.close()
|
|
||||||
if sts:
|
|
||||||
print('Exit status:', sts)
|
|
||||||
|
|
||||||
# Class used to save data while showing progress
|
|
||||||
class SaveWithProgress:
|
|
||||||
def __init__(self, f):
|
|
||||||
self.f = f
|
|
||||||
def write(self, data):
|
|
||||||
sys.stdout.write('#')
|
|
||||||
sys.stdout.flush()
|
|
||||||
self.f.write(data)
|
|
||||||
def close(self):
|
|
||||||
print()
|
|
||||||
sts = self.f.close()
|
|
||||||
if sts:
|
|
||||||
print('Exit status:', sts)
|
|
||||||
|
|
||||||
# Ask for and open a save file, or return None if not to save
|
|
||||||
def open_savefile():
|
|
||||||
try:
|
|
||||||
savefile = input( \
|
|
||||||
'Save as file [CR == don\'t save; |pipeline or ~user/... OK]: ')
|
|
||||||
except EOFError:
|
|
||||||
print()
|
|
||||||
return None
|
|
||||||
savefile = savefile.strip()
|
|
||||||
if not savefile:
|
|
||||||
return None
|
|
||||||
if savefile[0] == '|':
|
|
||||||
cmd = savefile[1:].strip()
|
|
||||||
try:
|
|
||||||
p = os.popen(cmd, 'w')
|
|
||||||
except IOError as msg:
|
|
||||||
print(repr(cmd), ':', msg)
|
|
||||||
return None
|
|
||||||
print('Piping through', repr(cmd), '...')
|
|
||||||
return p
|
|
||||||
if savefile[0] == '~':
|
|
||||||
savefile = os.path.expanduser(savefile)
|
|
||||||
try:
|
|
||||||
f = open(savefile, 'w')
|
|
||||||
except IOError as msg:
|
|
||||||
print(repr(savefile), ':', msg)
|
|
||||||
return None
|
|
||||||
print('Saving to', repr(savefile), '...')
|
|
||||||
return f
|
|
||||||
|
|
||||||
# Test program
|
|
||||||
def test():
|
|
||||||
if sys.argv[4:]:
|
|
||||||
print('usage: gopher [ [selector] host [port] ]')
|
|
||||||
sys.exit(2)
|
|
||||||
elif sys.argv[3:]:
|
|
||||||
browser(sys.argv[1], sys.argv[2], sys.argv[3])
|
|
||||||
elif sys.argv[2:]:
|
|
||||||
try:
|
|
||||||
port = int(sys.argv[2])
|
|
||||||
selector = ''
|
|
||||||
host = sys.argv[1]
|
|
||||||
except ValueError:
|
|
||||||
selector = sys.argv[1]
|
|
||||||
host = sys.argv[2]
|
|
||||||
port = ''
|
|
||||||
browser(selector, host, port)
|
|
||||||
elif sys.argv[1:]:
|
|
||||||
browser('', sys.argv[1])
|
|
||||||
else:
|
|
||||||
browser()
|
|
||||||
|
|
||||||
# Call the test program as a main program
|
|
||||||
test()
|
|
|
@ -1,14 +0,0 @@
|
||||||
# Receive UDP packets transmitted by a broadcasting service
|
|
||||||
|
|
||||||
MYPORT = 50000
|
|
||||||
|
|
||||||
import sys
|
|
||||||
from socket import *
|
|
||||||
|
|
||||||
s = socket(AF_INET, SOCK_DGRAM)
|
|
||||||
s.bind(('', MYPORT))
|
|
||||||
|
|
||||||
while 1:
|
|
||||||
data, wherefrom = s.recvfrom(1500, 0)
|
|
||||||
sys.stderr.write(repr(wherefrom) + '\n')
|
|
||||||
sys.stdout.write(data)
|
|
|
@ -1,109 +0,0 @@
|
||||||
#! /usr/bin/env python3
|
|
||||||
|
|
||||||
# Minimal interface to the Internet telnet protocol.
|
|
||||||
#
|
|
||||||
# It refuses all telnet options and does not recognize any of the other
|
|
||||||
# telnet commands, but can still be used to connect in line-by-line mode.
|
|
||||||
# It's also useful to play with a number of other services,
|
|
||||||
# like time, finger, smtp and even ftp.
|
|
||||||
#
|
|
||||||
# Usage: telnet host [port]
|
|
||||||
#
|
|
||||||
# The port may be a service name or a decimal port number;
|
|
||||||
# it defaults to 'telnet'.
|
|
||||||
|
|
||||||
|
|
||||||
import sys, posix, time
|
|
||||||
from socket import *
|
|
||||||
|
|
||||||
BUFSIZE = 1024
|
|
||||||
|
|
||||||
# Telnet protocol characters
|
|
||||||
|
|
||||||
IAC = chr(255) # Interpret as command
|
|
||||||
DONT = chr(254)
|
|
||||||
DO = chr(253)
|
|
||||||
WONT = chr(252)
|
|
||||||
WILL = chr(251)
|
|
||||||
|
|
||||||
def main():
|
|
||||||
host = sys.argv[1]
|
|
||||||
try:
|
|
||||||
hostaddr = gethostbyname(host)
|
|
||||||
except error:
|
|
||||||
sys.stderr.write(sys.argv[1] + ': bad host name\n')
|
|
||||||
sys.exit(2)
|
|
||||||
#
|
|
||||||
if len(sys.argv) > 2:
|
|
||||||
servname = sys.argv[2]
|
|
||||||
else:
|
|
||||||
servname = 'telnet'
|
|
||||||
#
|
|
||||||
if '0' <= servname[:1] <= '9':
|
|
||||||
port = eval(servname)
|
|
||||||
else:
|
|
||||||
try:
|
|
||||||
port = getservbyname(servname, 'tcp')
|
|
||||||
except error:
|
|
||||||
sys.stderr.write(servname + ': bad tcp service name\n')
|
|
||||||
sys.exit(2)
|
|
||||||
#
|
|
||||||
s = socket(AF_INET, SOCK_STREAM)
|
|
||||||
#
|
|
||||||
try:
|
|
||||||
s.connect((host, port))
|
|
||||||
except error as msg:
|
|
||||||
sys.stderr.write('connect failed: ' + repr(msg) + '\n')
|
|
||||||
sys.exit(1)
|
|
||||||
#
|
|
||||||
pid = posix.fork()
|
|
||||||
#
|
|
||||||
if pid == 0:
|
|
||||||
# child -- read stdin, write socket
|
|
||||||
while 1:
|
|
||||||
line = sys.stdin.readline()
|
|
||||||
s.send(line)
|
|
||||||
else:
|
|
||||||
# parent -- read socket, write stdout
|
|
||||||
iac = 0 # Interpret next char as command
|
|
||||||
opt = '' # Interpret next char as option
|
|
||||||
while 1:
|
|
||||||
data = s.recv(BUFSIZE)
|
|
||||||
if not data:
|
|
||||||
# EOF; kill child and exit
|
|
||||||
sys.stderr.write( '(Closed by remote host)\n')
|
|
||||||
posix.kill(pid, 9)
|
|
||||||
sys.exit(1)
|
|
||||||
cleandata = ''
|
|
||||||
for c in data:
|
|
||||||
if opt:
|
|
||||||
print(ord(c))
|
|
||||||
s.send(opt + c)
|
|
||||||
opt = ''
|
|
||||||
elif iac:
|
|
||||||
iac = 0
|
|
||||||
if c == IAC:
|
|
||||||
cleandata = cleandata + c
|
|
||||||
elif c in (DO, DONT):
|
|
||||||
if c == DO: print('(DO)', end=' ')
|
|
||||||
else: print('(DONT)', end=' ')
|
|
||||||
opt = IAC + WONT
|
|
||||||
elif c in (WILL, WONT):
|
|
||||||
if c == WILL: print('(WILL)', end=' ')
|
|
||||||
else: print('(WONT)', end=' ')
|
|
||||||
opt = IAC + DONT
|
|
||||||
else:
|
|
||||||
print('(command)', ord(c))
|
|
||||||
elif c == IAC:
|
|
||||||
iac = 1
|
|
||||||
print('(IAC)', end=' ')
|
|
||||||
else:
|
|
||||||
cleandata = cleandata + c
|
|
||||||
sys.stdout.write(cleandata)
|
|
||||||
sys.stdout.flush()
|
|
||||||
|
|
||||||
|
|
||||||
try:
|
|
||||||
main()
|
|
||||||
except KeyboardInterrupt:
|
|
||||||
pass
|
|
|
@ -1,93 +0,0 @@
|
||||||
#! /usr/bin/env python3
|
|
||||||
|
|
||||||
# Test network throughput.
|
|
||||||
#
|
|
||||||
# Usage:
|
|
||||||
# 1) on host_A: throughput -s [port] # start a server
|
|
||||||
# 2) on host_B: throughput -c count host_A [port] # start a client
|
|
||||||
#
|
|
||||||
# The server will service multiple clients until it is killed.
|
|
||||||
#
|
|
||||||
# The client performs one transfer of count*BUFSIZE bytes and
|
|
||||||
# measures the time it takes (roundtrip!).
|
|
||||||
|
|
||||||
|
|
||||||
import sys, time
|
|
||||||
from socket import *
|
|
||||||
|
|
||||||
MY_PORT = 50000 + 42
|
|
||||||
|
|
||||||
BUFSIZE = 1024
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
if len(sys.argv) < 2:
|
|
||||||
usage()
|
|
||||||
if sys.argv[1] == '-s':
|
|
||||||
server()
|
|
||||||
elif sys.argv[1] == '-c':
|
|
||||||
client()
|
|
||||||
else:
|
|
||||||
usage()
|
|
||||||
|
|
||||||
|
|
||||||
def usage():
|
|
||||||
sys.stdout = sys.stderr
|
|
||||||
print('Usage: (on host_A) throughput -s [port]')
|
|
||||||
print('and then: (on host_B) throughput -c count host_A [port]')
|
|
||||||
sys.exit(2)
|
|
||||||
|
|
||||||
|
|
||||||
def server():
|
|
||||||
if len(sys.argv) > 2:
|
|
||||||
port = eval(sys.argv[2])
|
|
||||||
else:
|
|
||||||
port = MY_PORT
|
|
||||||
s = socket(AF_INET, SOCK_STREAM)
|
|
||||||
s.bind(('', port))
|
|
||||||
s.listen(1)
|
|
||||||
print('Server ready...')
|
|
||||||
while 1:
|
|
||||||
conn, (host, remoteport) = s.accept()
|
|
||||||
while 1:
|
|
||||||
data = conn.recv(BUFSIZE)
|
|
||||||
if not data:
|
|
||||||
break
|
|
||||||
del data
|
|
||||||
conn.send('OK\n')
|
|
||||||
conn.close()
|
|
||||||
print('Done with', host, 'port', remoteport)
|
|
||||||
|
|
||||||
|
|
||||||
def client():
|
|
||||||
if len(sys.argv) < 4:
|
|
||||||
usage()
|
|
||||||
count = int(eval(sys.argv[2]))
|
|
||||||
host = sys.argv[3]
|
|
||||||
if len(sys.argv) > 4:
|
|
||||||
port = eval(sys.argv[4])
|
|
||||||
else:
|
|
||||||
port = MY_PORT
|
|
||||||
testdata = 'x' * (BUFSIZE-1) + '\n'
|
|
||||||
t1 = time.time()
|
|
||||||
s = socket(AF_INET, SOCK_STREAM)
|
|
||||||
t2 = time.time()
|
|
||||||
s.connect((host, port))
|
|
||||||
t3 = time.time()
|
|
||||||
i = 0
|
|
||||||
while i < count:
|
|
||||||
i = i+1
|
|
||||||
s.send(testdata)
|
|
||||||
s.shutdown(1) # Send EOF
|
|
||||||
t4 = time.time()
|
|
||||||
data = s.recv(BUFSIZE)
|
|
||||||
t5 = time.time()
|
|
||||||
print(data)
|
|
||||||
print('Raw timers:', t1, t2, t3, t4, t5)
|
|
||||||
print('Intervals:', t2-t1, t3-t2, t4-t3, t5-t4)
|
|
||||||
print('Total:', t5-t1)
|
|
||||||
print('Throughput:', round((BUFSIZE*count*0.001) / (t5-t1), 3), end=' ')
|
|
||||||
print('K/sec.')
|
|
||||||
|
|
||||||
|
|
||||||
main()
|
|
|
@ -1,64 +0,0 @@
|
||||||
#! /usr/bin/env python3
|
|
||||||
|
|
||||||
# Client and server for udp (datagram) echo.
|
|
||||||
#
|
|
||||||
# Usage: udpecho -s [port] (to start a server)
|
|
||||||
# or: udpecho -c host [port] <file (client)
|
|
||||||
|
|
||||||
import sys
|
|
||||||
from socket import *
|
|
||||||
|
|
||||||
ECHO_PORT = 50000 + 7
|
|
||||||
BUFSIZE = 1024
|
|
||||||
|
|
||||||
def main():
|
|
||||||
if len(sys.argv) < 2:
|
|
||||||
usage()
|
|
||||||
if sys.argv[1] == '-s':
|
|
||||||
server()
|
|
||||||
elif sys.argv[1] == '-c':
|
|
||||||
client()
|
|
||||||
else:
|
|
||||||
usage()
|
|
||||||
|
|
||||||
def usage():
|
|
||||||
sys.stdout = sys.stderr
|
|
||||||
print('Usage: udpecho -s [port] (server)')
|
|
||||||
print('or: udpecho -c host [port] <file (client)')
|
|
||||||
sys.exit(2)
|
|
||||||
|
|
||||||
def server():
|
|
||||||
if len(sys.argv) > 2:
|
|
||||||
port = eval(sys.argv[2])
|
|
||||||
else:
|
|
||||||
port = ECHO_PORT
|
|
||||||
s = socket(AF_INET, SOCK_DGRAM)
|
|
||||||
s.bind(('', port))
|
|
||||||
print('udp echo server ready')
|
|
||||||
while 1:
|
|
||||||
data, addr = s.recvfrom(BUFSIZE)
|
|
||||||
print('server received %r from %r' % (data, addr))
|
|
||||||
s.sendto(data, addr)
|
|
||||||
|
|
||||||
def client():
|
|
||||||
if len(sys.argv) < 3:
|
|
||||||
usage()
|
|
||||||
host = sys.argv[2]
|
|
||||||
if len(sys.argv) > 3:
|
|
||||||
port = eval(sys.argv[3])
|
|
||||||
else:
|
|
||||||
port = ECHO_PORT
|
|
||||||
addr = host, port
|
|
||||||
s = socket(AF_INET, SOCK_DGRAM)
|
|
||||||
s.bind(('', 0))
|
|
||||||
print('udp echo client ready, reading stdin')
|
|
||||||
while 1:
|
|
||||||
line = sys.stdin.readline()
|
|
||||||
if not line:
|
|
||||||
break
|
|
||||||
print('addr = ', addr)
|
|
||||||
s.sendto(bytes(line, 'ascii'), addr)
|
|
||||||
data, fromaddr = s.recvfrom(BUFSIZE)
|
|
||||||
print('client received %r from %r' % (data, fromaddr))
|
|
||||||
|
|
||||||
main()
|
|
|
@ -1,14 +0,0 @@
|
||||||
# Send UDP broadcast packets
|
|
||||||
|
|
||||||
MYPORT = 50000
|
|
||||||
|
|
||||||
import sys, time
|
|
||||||
from socket import *
|
|
||||||
|
|
||||||
s = socket(AF_INET, SOCK_DGRAM)
|
|
||||||
s.bind(('', 0))
|
|
||||||
|
|
||||||
while 1:
|
|
||||||
data = repr(time.time()) + '\n'
|
|
||||||
s.sendto(data, ('', MYPORT))
|
|
||||||
time.sleep(2)
|
|
|
@ -1,12 +0,0 @@
|
||||||
# Echo client demo using Unix sockets
|
|
||||||
# Piet van Oostrum
|
|
||||||
|
|
||||||
from socket import *
|
|
||||||
|
|
||||||
FILE = 'unix-socket'
|
|
||||||
s = socket(AF_UNIX, SOCK_STREAM)
|
|
||||||
s.connect(FILE)
|
|
||||||
s.send(b'Hello, world')
|
|
||||||
data = s.recv(1024)
|
|
||||||
s.close()
|
|
||||||
print('Received', repr(data))
|
|
|
@ -1,24 +0,0 @@
|
||||||
# Echo server demo using Unix sockets (handles one connection only)
|
|
||||||
# Piet van Oostrum
|
|
||||||
|
|
||||||
import os
|
|
||||||
from socket import *
|
|
||||||
|
|
||||||
FILE = 'unix-socket'
|
|
||||||
s = socket(AF_UNIX, SOCK_STREAM)
|
|
||||||
s.bind(FILE)
|
|
||||||
|
|
||||||
print('Sock name is: ['+s.getsockname()+']')
|
|
||||||
|
|
||||||
# Wait for a connection
|
|
||||||
s.listen(1)
|
|
||||||
conn, addr = s.accept()
|
|
||||||
|
|
||||||
while True:
|
|
||||||
data = conn.recv(1024)
|
|
||||||
if not data:
|
|
||||||
break
|
|
||||||
conn.send(data)
|
|
||||||
|
|
||||||
conn.close()
|
|
||||||
os.unlink(FILE)
|
|
|
@ -1,89 +0,0 @@
|
||||||
$Id$
|
|
||||||
|
|
||||||
Installing Tix.py
|
|
||||||
----------------
|
|
||||||
|
|
||||||
0) To use Tix.py, you need Tcl/Tk (V8.3.3), Tix (V8.1.1) and Python (V2.1.1).
|
|
||||||
Tix.py has been written and tested on a Intel Pentium running RH Linux 5.2
|
|
||||||
and Mandrake Linux 7.0 and Windows with the above mentioned packages.
|
|
||||||
|
|
||||||
Older versions, e.g. Tix 4.1 and Tk 8.0, might also work.
|
|
||||||
|
|
||||||
There is nothing OS-specific in Tix.py itself so it should work on
|
|
||||||
any machine with Tix and Python installed. You can get Tcl and Tk
|
|
||||||
from http://dev.scriptics.com and Tix from http://tix.sourceforge.net.
|
|
||||||
|
|
||||||
1) Build and install Tcl/Tk 8.3. Build and install Tix 8.1.
|
|
||||||
Ensure that Tix is properly installed by running tixwish and executing
|
|
||||||
the demo programs. Under Unix, use the --enable-shared configure option
|
|
||||||
for all three. We recommend tcl8.3.3 for this release of Tix.py.
|
|
||||||
|
|
||||||
2a) If you have a distribution like ActiveState with a tcl subdirectory
|
|
||||||
of $PYTHONHOME, which contains the directories tcl8.3 and tk8.3,
|
|
||||||
make a directory tix8.1 as well. Recursively copy the files from
|
|
||||||
<tix>/library to $PYTHONHOME/lib/tix8.1, and copy the dynamic library
|
|
||||||
(tix8183.dll or libtix8.1.8.3.so) to the same place as the tcl dynamic
|
|
||||||
libraries ($PYTHONHOME/Dlls or lib/python-2.1/lib-dynload). In this
|
|
||||||
case you are all installed, and you can skip to the end.
|
|
||||||
|
|
||||||
2b) Modify Modules/Setup.dist and setup.py to change the version of the
|
|
||||||
tix library from tix4.1.8.0 to tix8.1.8.3
|
|
||||||
These modified files can be used for Tkinter with or without Tix.
|
|
||||||
|
|
||||||
3) The default is to build dynamically, and use the Tcl 'package require'.
|
|
||||||
To build statically, modify the Modules/Setup file to link in the Tix
|
|
||||||
library according to the comments in the file. On Linux this looks like:
|
|
||||||
|
|
||||||
# *** Always uncomment this (leave the leading underscore in!):
|
|
||||||
_tkinter _tkinter.c tkappinit.c -DWITH_APPINIT \
|
|
||||||
# *** Uncomment and edit to reflect where your Tcl/Tk libraries are:
|
|
||||||
-L/usr/local/lib \
|
|
||||||
# *** Uncomment and edit to reflect where your Tcl/Tk headers are:
|
|
||||||
-I/usr/local/include \
|
|
||||||
# *** Uncomment and edit to reflect where your X11 header files are:
|
|
||||||
-I/usr/X11R6/include \
|
|
||||||
# *** Or uncomment this for Solaris:
|
|
||||||
# -I/usr/openwin/include \
|
|
||||||
# *** Uncomment and edit for BLT extension only:
|
|
||||||
# -DWITH_BLT -I/usr/local/blt/blt8.0-unoff/include -lBLT8.0 \
|
|
||||||
# *** Uncomment and edit for PIL (TkImaging) extension only:
|
|
||||||
# (See http://www.pythonware.com/products/pil/ for more info)
|
|
||||||
# -DWITH_PIL -I../Extensions/Imaging/libImaging tkImaging.c \
|
|
||||||
# *** Uncomment and edit for TOGL extension only:
|
|
||||||
# -DWITH_TOGL togl.c \
|
|
||||||
# *** Uncomment and edit for Tix extension only:
|
|
||||||
-DWITH_TIX -ltix8.1.8.3 \
|
|
||||||
# *** Uncomment and edit to reflect your Tcl/Tk versions:
|
|
||||||
-ltk8.3 -ltcl8.3 \
|
|
||||||
# *** Uncomment and edit to reflect where your X11 libraries are:
|
|
||||||
-L/usr/X11R6/lib \
|
|
||||||
# *** Or uncomment this for Solaris:
|
|
||||||
# -L/usr/openwin/lib \
|
|
||||||
# *** Uncomment these for TOGL extension only:
|
|
||||||
# -lGL -lGLU -lXext -lXmu \
|
|
||||||
# *** Uncomment for AIX:
|
|
||||||
# -lld \
|
|
||||||
# *** Always uncomment this; X11 libraries to link with:
|
|
||||||
-lX11
|
|
||||||
|
|
||||||
4) Rebuild Python and reinstall.
|
|
||||||
|
|
||||||
You should now have a working Tix implementation in Python. To see if all
|
|
||||||
is as it should be, run the 'tixwidgets.py' script in the Demo/tix directory.
|
|
||||||
Under X windows, do
|
|
||||||
/usr/local/bin/python Demo/tix/tixwidgets.py
|
|
||||||
|
|
||||||
If this does not work, you may need to tell python where to find
|
|
||||||
the Tcl, Tk and Tix library files. This is done by setting the
|
|
||||||
TCL_LIBRARY, TK_LIBRARY and TIX_LIBRARY environment variables. Try this:
|
|
||||||
|
|
||||||
env TCL_LIBRARY=/usr/local/lib/tcl8.3 \
|
|
||||||
TK_LIBRARY=/usr/local/lib/tk8.3 \
|
|
||||||
TIX_LIBRARY=/usr/local/lib/tix8.1 \
|
|
||||||
/usr/local/bin/python Demo/tix/tixwidgets.py
|
|
||||||
|
|
||||||
|
|
||||||
If you find any bugs or have suggestions for improvement, please report them
|
|
||||||
via http://tix.sourceforge.net
|
|
||||||
|
|
||||||
|
|
|
@ -1,19 +0,0 @@
|
||||||
About Tix.py
|
|
||||||
-----------
|
|
||||||
|
|
||||||
Tix.py is based on an idea of Jean-Marc Lugrin (lugrin@ms.com) who wrote
|
|
||||||
pytix (another Python-Tix marriage). Tix widgets are an attractive and
|
|
||||||
useful extension to Tk. See http://tix.sourceforge.net
|
|
||||||
for more details about Tix and how to get it.
|
|
||||||
|
|
||||||
Features:
|
|
||||||
1) It is almost complete.
|
|
||||||
2) Tix widgets are represented by classes in Python. Sub-widgets
|
|
||||||
are members of the mega-widget class. For example, if a
|
|
||||||
particular TixWidget (e.g. ScrolledText) has an embedded widget
|
|
||||||
(Text in this case), it is possible to call the methods of the
|
|
||||||
child directly.
|
|
||||||
3) The members of the class are created automatically. In the case
|
|
||||||
of widgets like ButtonBox, the members are added dynamically.
|
|
||||||
|
|
||||||
|
|
|
@ -1,50 +0,0 @@
|
||||||
/* XPM */
|
|
||||||
static char * about_xpm[] = {
|
|
||||||
"50 40 7 1",
|
|
||||||
" s None c None",
|
|
||||||
". c black",
|
|
||||||
"X c white",
|
|
||||||
"o c gray70",
|
|
||||||
"O c navy",
|
|
||||||
"+ c red",
|
|
||||||
"@ c yellow",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" ................................. ",
|
|
||||||
" ..XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXoo. ",
|
|
||||||
" .XooooooooooooooooooooooooooooooXo. ",
|
|
||||||
" .XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXooXo. ",
|
|
||||||
" ..oooooooooooooooooooooooooooooooXo. ",
|
|
||||||
" ...............................XoXo. ",
|
|
||||||
" .OOOOOOOOOOOOOOOOOOOOOOOOOOOOO.XoXo. ",
|
|
||||||
" .OOOOOOOOOOOOOOOOOOOOOOOOOOOOO.XoXo. ",
|
|
||||||
" .OOOOOOOOOOOOOOOOOOOOOOOOOOOOO.XoXo. ",
|
|
||||||
" .OOOOOOOOOOOOOOOOOOOOOOOOOOOOO.XoXo. ",
|
|
||||||
" .OOOOOOOOOOOOOOOOOOOOOOOOOOOOO.XoXo.++++ ",
|
|
||||||
" .OOOOOOOOOOOOOOOOOOOOOOOOOOOOO.XoXo+++ ",
|
|
||||||
" .OOOOOOOOOOOOOOOOOOOOOOOOOOOOO.Xo+++++ ",
|
|
||||||
" .OOOOOOOOOOOOOOOOOOOOOOOOOOOOO.Xo++++++ ",
|
|
||||||
" .OOOOOOOOOOOOOOOOOOOOOOOOOOOOO.Xo+++ + ",
|
|
||||||
" .OOOOO@@@@@OOOOOOOOOOOOOOOOOOO.Xo++. ",
|
|
||||||
" .OOOOOOO@OOOOO@OOOOOOOOOOOOOOO.XoXo. ",
|
|
||||||
" .OOOOOOO@OOOOOOOOOOOOOOOOOOOOO.XoXo. ",
|
|
||||||
" .OOOOOOO@OOOO@@OOO@OOO@OOOOOOO.XoXo. ",
|
|
||||||
" .OOOOOOO@OOOOO@OOOO@O@OOOOOOOO.XoXo. ",
|
|
||||||
" .OOOOOOO@OOOOO@OOOOO@OOOOOOOOO.XoXo. ",
|
|
||||||
" .OOOOOOO@OOOOO@OOOOO@OOOOOOOOO.XoXo. ",
|
|
||||||
" .OOOOOOO@OOOOO@OOOO@O@OOOOOOOO.XoXo. ",
|
|
||||||
" .OOOOOOO@OOOO@@@OO@OOO@OOOOOOO.XoXo. ",
|
|
||||||
" .OOOOOOOOOOOOOOOOOOOOOOOOOOOOO.XoXo. ",
|
|
||||||
" .OOOOOOOOOOOOOOOOOOOOOOOOOOOOO.XoXo. ",
|
|
||||||
" .OOOOOOOOOOOOOOOOOOOOOOOOOOOOO.XoXo. ",
|
|
||||||
" .OOOOOOOOOOOOOOOOOOOOOOOOOOOOO.XoXo. ",
|
|
||||||
" .OOOOOOOOOOOOOOOOOOOOOOOOOOOOO.XoXo. ",
|
|
||||||
" .OOOOOOOOOOOOOOOOOOOOOOOOOOOOO.XoXo. ",
|
|
||||||
" .OOOOOOOOOOOOOOOOOOOOOOOOOOOOO.Xo.. ",
|
|
||||||
" .OOOOOOOOOOOOOOOOOOOOOOOOOOOOO.Xo ",
|
|
||||||
" OOOOOOOOOOOOOOOOOOOOOOOOOOOOO.X. ",
|
|
||||||
" ............................. ",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" "};
|
|
|
@ -1,6 +0,0 @@
|
||||||
#define bold_width 16
|
|
||||||
#define bold_height 16
|
|
||||||
static unsigned char bold_bits[] = {
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0xfc, 0x07, 0xfc, 0x0f, 0x18, 0x1c, 0x18, 0x18,
|
|
||||||
0x18, 0x18, 0x18, 0x1c, 0xf8, 0x0f, 0xf8, 0x0f, 0x18, 0x18, 0x18, 0x30,
|
|
||||||
0x18, 0x30, 0x18, 0x38, 0xfc, 0x3f, 0xfc, 0x1f};
|
|
|
@ -1,6 +0,0 @@
|
||||||
#define capital_width 16
|
|
||||||
#define capital_height 16
|
|
||||||
static unsigned char capital_bits[] = {
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x08, 0x30, 0x0c, 0x30, 0x06,
|
|
||||||
0x30, 0x03, 0xb0, 0x01, 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x01, 0xb0, 0x03,
|
|
||||||
0x30, 0x07, 0x30, 0x0e, 0x30, 0x1c, 0x00, 0x00};
|
|
|
@ -1,6 +0,0 @@
|
||||||
#define centerj_width 16
|
|
||||||
#define centerj_height 16
|
|
||||||
static unsigned char centerj_bits[] = {
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x3e, 0x00, 0x00, 0xc0, 0x0d,
|
|
||||||
0x00, 0x00, 0x58, 0x77, 0x00, 0x00, 0xb0, 0x3b, 0x00, 0x00, 0xdc, 0xf7,
|
|
||||||
0x00, 0x00, 0xf0, 0x3e, 0x00, 0x00, 0xd8, 0x7e};
|
|
|
@ -1,14 +0,0 @@
|
||||||
#define combobox_width 32
|
|
||||||
#define combobox_height 32
|
|
||||||
static unsigned char combobox_bits[] = {
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0xfc, 0xff, 0xff, 0x3e, 0x04, 0x00, 0x80, 0x2a, 0x04, 0x00, 0x80, 0x2a,
|
|
||||||
0x04, 0x00, 0x80, 0x2a, 0x04, 0x00, 0x80, 0x2b, 0xfc, 0xff, 0xff, 0x3e,
|
|
||||||
0x08, 0x00, 0x00, 0x20, 0x08, 0x00, 0x00, 0x3e, 0x08, 0x00, 0x00, 0x2a,
|
|
||||||
0x28, 0x49, 0x00, 0x2a, 0x08, 0x00, 0x00, 0x3e, 0x08, 0x00, 0x00, 0x22,
|
|
||||||
0x08, 0x00, 0x00, 0x22, 0x28, 0x49, 0x12, 0x22, 0x08, 0x00, 0x00, 0x22,
|
|
||||||
0x08, 0x00, 0x00, 0x22, 0x08, 0x00, 0x00, 0x22, 0x28, 0x49, 0x02, 0x22,
|
|
||||||
0x08, 0x00, 0x00, 0x3e, 0x08, 0x00, 0x00, 0x2a, 0x08, 0x00, 0x00, 0x2a,
|
|
||||||
0xf8, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
|
|
@ -1,49 +0,0 @@
|
||||||
/* XPM */
|
|
||||||
static char * combobox_xpm[] = {
|
|
||||||
"50 40 6 1",
|
|
||||||
" s None c None",
|
|
||||||
". c black",
|
|
||||||
"X c white",
|
|
||||||
"o c #FFFF80808080",
|
|
||||||
"O c gray70",
|
|
||||||
"+ c #808000008080",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" .................................... XXXXXXX ",
|
|
||||||
" .ooooooooooooooooooooooooooooooooooX X . . ",
|
|
||||||
" .ooooooooooooooooooooooooooooooooooX X . . ",
|
|
||||||
" .oooo.oooooooooooooooooooooooooooooX X . . ",
|
|
||||||
" .oo.o..oo.o.oo.o.ooooooooooooooooooX X . . ",
|
|
||||||
" .o..o.o.o.oo.oo.oo.ooooooooooooooooX X ... . ",
|
|
||||||
" .oo.oo.oo.o.oo.ooo.ooooooooooooooooX X . . ",
|
|
||||||
" .ooooooooooooooooooooooooooooooooooX X . ",
|
|
||||||
" .XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX X...... ",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ",
|
|
||||||
" X............................................ ",
|
|
||||||
" X.OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOX.OOOOX. ",
|
|
||||||
" X.O+OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOX.OX OX. ",
|
|
||||||
" X.O++OOO+OO+++OOOOOOOOOOOOOOOOOOOOOOOX.X ..X. ",
|
|
||||||
" X.O+O+O+OOO+O+OOOOOOOOOOOOOOOOOOOOOOOX.OOOOX. ",
|
|
||||||
" X.O++OOO+OO+++OOOOOOOOOOOOOOOOOOOOOOOX.OOOOX. ",
|
|
||||||
" X.OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOX.XXXXX. ",
|
|
||||||
" X.O.....X..........................OOX.X .X. ",
|
|
||||||
" X.OX...XXX.X.XX.XX.................OOX.X .X. ",
|
|
||||||
" X.OX.X..X..X.XX..XX.X..............OOX.X .X. ",
|
|
||||||
" X.O.X...X..X.X...X..X..............OOX.X .X. ",
|
|
||||||
" X.OOOOOOOOOOOOOOOOOOOOOOOO+OOOOOOOOOOX.X .X. ",
|
|
||||||
" X.OOOOOOOOO+OOO+OOOOO+OOOO+OOOOOOOOOOX.X .X. ",
|
|
||||||
" X.O+++OO+OO+O+OO++O++OO+OO+OOOOOOOOOOX.X...X. ",
|
|
||||||
" X.OO+OO++OO+O+OO+OOO+OO+O++OOOOOOOOOOX.OOOOX. ",
|
|
||||||
" X.OOOOOOOO+OOOOO++OO+OOOOOOOOOOOOOOOOX.OOOOX. ",
|
|
||||||
" X.OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOX.X .X. ",
|
|
||||||
" X.OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOX.O .OX. ",
|
|
||||||
" X.OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOX.OOOOX. ",
|
|
||||||
" X.XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.XXXXX. ",
|
|
||||||
" X............................................ ",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" "};
|
|
|
@ -1,47 +0,0 @@
|
||||||
/* XPM */
|
|
||||||
static char * combobox_xpm[] = {
|
|
||||||
"50 40 4 1",
|
|
||||||
" s None c None",
|
|
||||||
". c black",
|
|
||||||
"X c #FFFF80808080",
|
|
||||||
"o c gray70",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" .................................... ....... ",
|
|
||||||
" .XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX. . . . ",
|
|
||||||
" .XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX. . . . ",
|
|
||||||
" .XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX. . . . ",
|
|
||||||
" .XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX. . . . ",
|
|
||||||
" .XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX. . ... . ",
|
|
||||||
" .XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX. . . . ",
|
|
||||||
" .XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX. . . ",
|
|
||||||
" .................................... ....... ",
|
|
||||||
" ",
|
|
||||||
" ............................................. ",
|
|
||||||
" .ooooooooooooooooooooooooooooooooooooo.ooooo. ",
|
|
||||||
" .ooooooooooooooooooooooooooooooooooooo.ooooo. ",
|
|
||||||
" .o...................................o.ooooo. ",
|
|
||||||
" .o...................................o.ooooo. ",
|
|
||||||
" .o...................................o.ooooo. ",
|
|
||||||
" .o...................................o.ooooo. ",
|
|
||||||
" .ooooooooooooooooooooooooooooooooooooo.ooooo. ",
|
|
||||||
" .ooooooooooooooooooooooooooooooooooooo.ooooo. ",
|
|
||||||
" .ooooooooooooooooooooooooooooooooooooo.ooooo. ",
|
|
||||||
" .ooooooooooooooooooooooooooooooooooooo.ooooo. ",
|
|
||||||
" .ooooooooooooooooooooooooooooooooooooo.ooooo. ",
|
|
||||||
" .ooooooooooooooooooooooooooooooooooooo.ooooo. ",
|
|
||||||
" .ooooooooooooooooooooooooooooooooooooo.ooooo. ",
|
|
||||||
" .ooooooooooooooooooooooooooooooooooooo.ooooo. ",
|
|
||||||
" .ooooooooooooooooooooooooooooooooooooo.ooooo. ",
|
|
||||||
" .ooooooooooooooooooooooooooooooooooooo.ooooo. ",
|
|
||||||
" .ooooooooooooooooooooooooooooooooooooo.ooooo. ",
|
|
||||||
" .ooooooooooooooooooooooooooooooooooooo.ooooo. ",
|
|
||||||
" .ooooooooooooooooooooooooooooooooooooo.ooooo. ",
|
|
||||||
" .ooooooooooooooooooooooooooooooooooooo.ooooo. ",
|
|
||||||
" ............................................. ",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" "};
|
|
|
@ -1,14 +0,0 @@
|
||||||
#define drivea_width 32
|
|
||||||
#define drivea_height 32
|
|
||||||
static unsigned char drivea_bits[] = {
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0xf8, 0xff, 0xff, 0x1f, 0x08, 0x00, 0x00, 0x18, 0xa8, 0xaa, 0xaa, 0x1a,
|
|
||||||
0x48, 0x55, 0xd5, 0x1d, 0xa8, 0xaa, 0xaa, 0x1b, 0x48, 0x55, 0x55, 0x1d,
|
|
||||||
0xa8, 0xfa, 0xaf, 0x1a, 0xc8, 0xff, 0xff, 0x1d, 0xa8, 0xfa, 0xaf, 0x1a,
|
|
||||||
0x48, 0x55, 0x55, 0x1d, 0xa8, 0xaa, 0xaa, 0x1a, 0x48, 0x55, 0x55, 0x1d,
|
|
||||||
0xa8, 0xaa, 0xaa, 0x1a, 0xf8, 0xff, 0xff, 0x1f, 0xf8, 0xff, 0xff, 0x1f,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
|
|
@ -1,43 +0,0 @@
|
||||||
/* XPM */
|
|
||||||
static char * drivea_xpm[] = {
|
|
||||||
/* width height ncolors chars_per_pixel */
|
|
||||||
"32 32 5 1",
|
|
||||||
/* colors */
|
|
||||||
" s None c None",
|
|
||||||
". c #000000000000",
|
|
||||||
"X c white",
|
|
||||||
"o c #c000c000c000",
|
|
||||||
"O c #800080008000",
|
|
||||||
/* pixels */
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" .......................... ",
|
|
||||||
" .XXXXXXXXXXXXXXXXXXXXXXXo. ",
|
|
||||||
" .XooooooooooooooooooooooO. ",
|
|
||||||
" .Xooooooooooooooooo..oooO. ",
|
|
||||||
" .Xooooooooooooooooo..oooO. ",
|
|
||||||
" .XooooooooooooooooooooooO. ",
|
|
||||||
" .Xoooooooo.......oooooooO. ",
|
|
||||||
" .Xoo...................oO. ",
|
|
||||||
" .Xoooooooo.......oooooooO. ",
|
|
||||||
" .XooooooooooooooooooooooO. ",
|
|
||||||
" .XooooooooooooooooooooooO. ",
|
|
||||||
" .XooooooooooooooooooooooO. ",
|
|
||||||
" .XooooooooooooooooooooooO. ",
|
|
||||||
" .oOOOOOOOOOOOOOOOOOOOOOOO. ",
|
|
||||||
" .......................... ",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" "};
|
|
|
@ -1,48 +0,0 @@
|
||||||
/* XPM */
|
|
||||||
static char * exit_xpm[] = {
|
|
||||||
"50 40 5 1",
|
|
||||||
" s None c None",
|
|
||||||
". c black",
|
|
||||||
"X c white",
|
|
||||||
"o c #000080800000",
|
|
||||||
"O c yellow",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" ....................................... ",
|
|
||||||
" .XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX. ",
|
|
||||||
" .XoooooooooooooooooooooooooooooooooooX. ",
|
|
||||||
" .XoooooooooooooooooooooooooooooooooooX. ",
|
|
||||||
" .XoooooooooooooooooooooooOoooooooooooX. ",
|
|
||||||
" .XoooooooooooooooooooooooOOooooooooooX. ",
|
|
||||||
" .XoooooooooooooooooooooooOOOoooooooooX. ",
|
|
||||||
" .XoooooOOOOOOOOOOOOOOOOOOOOOOooooooooX. ",
|
|
||||||
" .XoooooOOOOOOOOOOOOOOOOOOOOOOOoooooooX. ",
|
|
||||||
" .XoooooOOOOOOOOOOOOOOOOOOOOOOOOooooooX. ",
|
|
||||||
" .XoooooOOOOOOOOOOOOOOOOOOOOOOOOOoooooX. ",
|
|
||||||
" .XoooooOOOOOOOOOOOOOOOOOOOOOOOOooooooX. ",
|
|
||||||
" .XoooooOOOOOOOOOOOOOOOOOOOOOOOoooooooX. ",
|
|
||||||
" .XoooooOOOOOOOOOOOOOOOOOOOOOOooooooooX. ",
|
|
||||||
" .XoooooooooooooooooooooooOOOoooooooooX. ",
|
|
||||||
" .XoooooooooooooooooooooooOOooooooooooX. ",
|
|
||||||
" .XoooooooooooooooooooooooOoooooooooooX. ",
|
|
||||||
" .XoooooooooooooooooooooooooooooooooooX. ",
|
|
||||||
" .XoooooooooooooooooooooooooooooooooooX. ",
|
|
||||||
" .XoooooooooooooooooooooooooooooooooooX. ",
|
|
||||||
" .XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX. ",
|
|
||||||
" ....................................... ",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" "};
|
|
|
@ -1,14 +0,0 @@
|
||||||
#define filebox_width 32
|
|
||||||
#define filebox_height 32
|
|
||||||
static unsigned char filebox_bits[] = {
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0x3f, 0x04, 0x00, 0x00, 0x20,
|
|
||||||
0xe4, 0xff, 0xff, 0x27, 0x24, 0x00, 0x00, 0x24, 0x24, 0x00, 0x00, 0x24,
|
|
||||||
0xe4, 0xff, 0xff, 0x27, 0x04, 0x00, 0x00, 0x20, 0xe4, 0x7f, 0xfe, 0x27,
|
|
||||||
0x24, 0x50, 0x02, 0x25, 0x24, 0x40, 0x02, 0x24, 0x24, 0x50, 0x02, 0x25,
|
|
||||||
0x24, 0x40, 0x02, 0x24, 0x24, 0x50, 0x02, 0x25, 0x24, 0x40, 0x02, 0x24,
|
|
||||||
0x24, 0x50, 0x02, 0x25, 0xe4, 0x7f, 0xfe, 0x27, 0x04, 0x00, 0x00, 0x20,
|
|
||||||
0xe4, 0xff, 0xff, 0x27, 0x24, 0x00, 0x00, 0x24, 0x24, 0x00, 0x00, 0x24,
|
|
||||||
0xe4, 0xff, 0xff, 0x27, 0x04, 0x00, 0x00, 0x20, 0xfc, 0xff, 0xff, 0x3f,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
|
|
@ -1,49 +0,0 @@
|
||||||
/* XPM */
|
|
||||||
static char * filebox_xpm[] = {
|
|
||||||
"50 40 6 1",
|
|
||||||
" s None c None",
|
|
||||||
". c white",
|
|
||||||
"X c gray80",
|
|
||||||
"o c black",
|
|
||||||
"O c #FFFF80808080",
|
|
||||||
"+ c gray70",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" ............................................ ",
|
|
||||||
" .XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXo ",
|
|
||||||
" .XXooXooXoXooXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXo ",
|
|
||||||
" .XXooXooXoXooXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXo ",
|
|
||||||
" .XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXo ",
|
|
||||||
" .XXooooooooooooooooooooooooooooooooooooo.XXo ",
|
|
||||||
" .XXoOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO.XXo ",
|
|
||||||
" .XXoOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO.XXo ",
|
|
||||||
" .XX......................................XXo ",
|
|
||||||
" .XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXo ",
|
|
||||||
" .XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXo ",
|
|
||||||
" .XXoooooooooooooooo.XXXXoooooooooooooooo.XXo ",
|
|
||||||
" .XXo+++++++++++++++.XXXXo+++++++++++++++.XXo ",
|
|
||||||
" .XXo+++++++++++++++.XXXXo+++++++++++++++.XXo ",
|
|
||||||
" .XXo+++++++++++++++.XXXXo+++++++++++++++.XXo ",
|
|
||||||
" .XXo+++++++++++++++.XXXXo+++++++++++++++.XXo ",
|
|
||||||
" .XXo+++++++++++++++.XXXXo+++++++++++++++.XXo ",
|
|
||||||
" .XXo+++++++++++++++.XXXXo+++++++++++++++.XXo ",
|
|
||||||
" .XXo+++++++++++++++.XXXXo+++++++++++++++.XXo ",
|
|
||||||
" .XXo+++++++++++++++.XXXXo+++++++++++++++.XXo ",
|
|
||||||
" .XXo+++++++++++++++.XXXXo+++++++++++++++.XXo ",
|
|
||||||
" .XXo+++++++++++++++.XXXXo+++++++++++++++.XXo ",
|
|
||||||
" .XXo+++++++++++++++.XXXXo+++++++++++++++.XXo ",
|
|
||||||
" .XX.................XXXX.................XXo ",
|
|
||||||
" .XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXo ",
|
|
||||||
" .XXooXooXoXooXoXXXXXXXXXXXXXXXXXXXXXXXXXXXXo ",
|
|
||||||
" .XXooXooXoXooXoXooXXXXXXXXXXXXXXXXXXXXXXXXXo ",
|
|
||||||
" .XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXo ",
|
|
||||||
" .XXoooooooooooooooooooooooooooooooooooooo.Xo ",
|
|
||||||
" .XXoOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO.Xo ",
|
|
||||||
" .XXoOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO.Xo ",
|
|
||||||
" .XX.......................................Xo ",
|
|
||||||
" .XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXo ",
|
|
||||||
" .ooooooooooooooooooooooooooooooooooooooooooo ",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" "};
|
|
|
@ -1,6 +0,0 @@
|
||||||
#define italic_width 16
|
|
||||||
#define italic_height 16
|
|
||||||
static unsigned char italic_bits[] = {
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x80, 0x3f, 0x80, 0x3f, 0x00, 0x06, 0x00, 0x06,
|
|
||||||
0x00, 0x03, 0x00, 0x03, 0x80, 0x01, 0x80, 0x01, 0xc0, 0x00, 0xc0, 0x00,
|
|
||||||
0x60, 0x00, 0x60, 0x00, 0xfc, 0x01, 0xfc, 0x01};
|
|
|
@ -1,6 +0,0 @@
|
||||||
#define justify_width 16
|
|
||||||
#define justify_height 16
|
|
||||||
static unsigned char justify_bits[] = {
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xec, 0xdb, 0x00, 0x00, 0x7c, 0xdb,
|
|
||||||
0x00, 0x00, 0xbc, 0xf7, 0x00, 0x00, 0xdc, 0xde, 0x00, 0x00, 0x6c, 0xdf,
|
|
||||||
0x00, 0x00, 0x6c, 0xef, 0x00, 0x00, 0xdc, 0xdf};
|
|
|
@ -1,6 +0,0 @@
|
||||||
#define leftj_width 16
|
|
||||||
#define leftj_height 16
|
|
||||||
static unsigned char leftj_bits[] = {
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0x6d, 0x00, 0x00, 0xdc, 0x01,
|
|
||||||
0x00, 0x00, 0xec, 0x0e, 0x00, 0x00, 0xfc, 0x7e, 0x00, 0x00, 0xdc, 0x03,
|
|
||||||
0x00, 0x00, 0x6c, 0x3b, 0x00, 0x00, 0x6c, 0x1f};
|
|
|
@ -1,14 +0,0 @@
|
||||||
#define netw_width 32
|
|
||||||
#define netw_height 32
|
|
||||||
static unsigned char netw_bits[] = {
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x7f, 0x00, 0x00, 0x02, 0x40,
|
|
||||||
0x00, 0x00, 0xfa, 0x5f, 0x00, 0x00, 0x0a, 0x50, 0x00, 0x00, 0x0a, 0x52,
|
|
||||||
0x00, 0x00, 0x0a, 0x52, 0x00, 0x00, 0x8a, 0x51, 0x00, 0x00, 0x0a, 0x50,
|
|
||||||
0x00, 0x00, 0x4a, 0x50, 0x00, 0x00, 0x0a, 0x50, 0x00, 0x00, 0x0a, 0x50,
|
|
||||||
0x00, 0x00, 0xfa, 0x5f, 0x00, 0x00, 0x02, 0x40, 0xfe, 0x7f, 0x52, 0x55,
|
|
||||||
0x02, 0x40, 0xaa, 0x6a, 0xfa, 0x5f, 0xfe, 0x7f, 0x0a, 0x50, 0xfe, 0x7f,
|
|
||||||
0x0a, 0x52, 0x80, 0x00, 0x0a, 0x52, 0x80, 0x00, 0x8a, 0x51, 0x80, 0x00,
|
|
||||||
0x0a, 0x50, 0x80, 0x00, 0x4a, 0x50, 0x80, 0x00, 0x0a, 0x50, 0xe0, 0x03,
|
|
||||||
0x0a, 0x50, 0x20, 0x02, 0xfa, 0xdf, 0x3f, 0x03, 0x02, 0x40, 0xa0, 0x02,
|
|
||||||
0x52, 0x55, 0xe0, 0x03, 0xaa, 0x6a, 0x00, 0x00, 0xfe, 0x7f, 0x00, 0x00,
|
|
||||||
0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
|
|
@ -1,45 +0,0 @@
|
||||||
/* XPM */
|
|
||||||
static char * netw_xpm[] = {
|
|
||||||
/* width height ncolors chars_per_pixel */
|
|
||||||
"32 32 7 1",
|
|
||||||
/* colors */
|
|
||||||
" s None c None",
|
|
||||||
". c #000000000000",
|
|
||||||
"X c white",
|
|
||||||
"o c #c000c000c000",
|
|
||||||
"O c #404040",
|
|
||||||
"+ c blue",
|
|
||||||
"@ c red",
|
|
||||||
/* pixels */
|
|
||||||
" ",
|
|
||||||
" .............. ",
|
|
||||||
" .XXXXXXXXXXXX. ",
|
|
||||||
" .XooooooooooO. ",
|
|
||||||
" .Xo.......XoO. ",
|
|
||||||
" .Xo.++++o+XoO. ",
|
|
||||||
" .Xo.++++o+XoO. ",
|
|
||||||
" .Xo.++oo++XoO. ",
|
|
||||||
" .Xo.++++++XoO. ",
|
|
||||||
" .Xo.+o++++XoO. ",
|
|
||||||
" .Xo.++++++XoO. ",
|
|
||||||
" .Xo.XXXXXXXoO. ",
|
|
||||||
" .XooooooooooO. ",
|
|
||||||
" .Xo@ooo....oO. ",
|
|
||||||
" .............. .XooooooooooO. ",
|
|
||||||
" .XXXXXXXXXXXX. .XooooooooooO. ",
|
|
||||||
" .XooooooooooO. .OOOOOOOOOOOO. ",
|
|
||||||
" .Xo.......XoO. .............. ",
|
|
||||||
" .Xo.++++o+XoO. @ ",
|
|
||||||
" .Xo.++++o+XoO. @ ",
|
|
||||||
" .Xo.++oo++XoO. @ ",
|
|
||||||
" .Xo.++++++XoO. @ ",
|
|
||||||
" .Xo.+o++++XoO. @ ",
|
|
||||||
" .Xo.++++++XoO. ..... ",
|
|
||||||
" .Xo.XXXXXXXoO. .XXX. ",
|
|
||||||
" .XooooooooooO.@@@@@@.X O. ",
|
|
||||||
" .Xo@ooo....oO. .OOO. ",
|
|
||||||
" .XooooooooooO. ..... ",
|
|
||||||
" .XooooooooooO. ",
|
|
||||||
" .OOOOOOOOOOOO. ",
|
|
||||||
" .............. ",
|
|
||||||
" "};
|
|
|
@ -1,48 +0,0 @@
|
||||||
/* XPM */
|
|
||||||
static char * optmenu_xpm[] = {
|
|
||||||
"50 40 5 1",
|
|
||||||
" s None c None",
|
|
||||||
". c white",
|
|
||||||
"X c gray80",
|
|
||||||
"o c gray50",
|
|
||||||
"O c black",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" .............................. ",
|
|
||||||
" .XXXXXXXXXXXXXXXXXXXXXXXXXXXXo ",
|
|
||||||
" .XXXXXXXXXXXXXXXXXXXXXXXXXXXXo ",
|
|
||||||
" .XXXXXXXXXXXXXXXXXXXXXXXXXXXXo ",
|
|
||||||
" .XXXOXOXXOXXOXXXXOOXXXXXXXXXXo ",
|
|
||||||
" .XXXOXOXXOXOXXXOXXOXXXXXXXXXXo ",
|
|
||||||
" .XXXXOXXOXXOXXXOXXXOXXXXXXXXXo ",
|
|
||||||
" .XXXXOXXXOXXOOXXOXOXXXXXXXXXXo ",
|
|
||||||
" .XXXXXXXXXXXXXXXXXXXXXXXXXXXXo ",
|
|
||||||
" .XXXXXXXXXXXXXXXXXXXXXXXXXXXXo.............o ",
|
|
||||||
" .............................o o ",
|
|
||||||
" ..XXXOXXXXXOXXXXXXXXOXXXXXXXOo o ",
|
|
||||||
" ..XXOXOXOXXOXOXXXOXXOXXXXXXXOo ...... o ",
|
|
||||||
" ..XXXOXXXOXXOXXXOXXXOXXXXXXXOo . o o ",
|
|
||||||
" ..XXOXXXOXXXOXOXXOXXOXXXXXXXOo . o o ",
|
|
||||||
" ..XXXXXXXXXXXXXXXXXXXXXXXXXXOo .ooooo o ",
|
|
||||||
" .OOOOOOOOOOOOOOOOOOOOOOOOOOOOo o ",
|
|
||||||
" .XXXXXXXXXXXXXXXXXXXXXXXXXXXXo o ",
|
|
||||||
" .XXXXXXXXXXXXXXXXXXXXXXXXXXXXooooooooooooooo ",
|
|
||||||
" .XXXXOXXXXXOXXXXXXXXXXXXXXXXXo ",
|
|
||||||
" .XXXOXXXXXXXXXOXXXXXXXXXXXXXXo ",
|
|
||||||
" .XXXXOXXOXXOXOXOXXXXXXXXXXXXXo ",
|
|
||||||
" .XXXXXOXXOXOXXXXXXXXXXXXXXXXXo ",
|
|
||||||
" .XXXXXXXXXXXXXOXXXXXXXXXXXXXXo ",
|
|
||||||
" .XXXXXXXXXXXXXXXXXXXXXXXXXXXXo ",
|
|
||||||
" .XXXXXXXXXXXXXXXXXXXXXXXXXXXXo ",
|
|
||||||
" .XXXOXOXXXXXXXOXOXXXXXOXXXXXXo ",
|
|
||||||
" .XXXXXOXOXOXXOXXXXXOXXOXXXXXXo ",
|
|
||||||
" .XXXXOXXOXOXOXXXOXOXOXXOXXXXXo ",
|
|
||||||
" .XXXOXXXXOXXOXXXOXXOXXXXOXXXXo ",
|
|
||||||
" .XXXXXXXXXXXXXXXXXXXXXXXXXXXXo ",
|
|
||||||
" .XXXXXXXXXXXXXXXXXXXXXXXXXXXXo ",
|
|
||||||
" .XXXXXXXXXXXXXXXXXXXXXXXXXXXXo ",
|
|
||||||
" oooooooooooooooooooooooooooooo ",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" "};
|
|
|
@ -1,6 +0,0 @@
|
||||||
#define rightj_width 16
|
|
||||||
#define rightj_height 16
|
|
||||||
static unsigned char rightj_bits[] = {
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xdb, 0x00, 0x00, 0x70, 0xdb,
|
|
||||||
0x00, 0x00, 0x00, 0xef, 0x00, 0x00, 0xd8, 0xde, 0x00, 0x00, 0xc0, 0xdd,
|
|
||||||
0x00, 0x00, 0xa0, 0xef, 0x00, 0x00, 0xd8, 0xde};
|
|
|
@ -1,52 +0,0 @@
|
||||||
/* XPM */
|
|
||||||
static char * select_xpm[] = {
|
|
||||||
"50 40 9 1",
|
|
||||||
" s None c None",
|
|
||||||
". c black",
|
|
||||||
"X c gray95",
|
|
||||||
"o c gray50",
|
|
||||||
"O c gray70",
|
|
||||||
"+ c navy",
|
|
||||||
"@ c #000080800000",
|
|
||||||
"# c #808000000000",
|
|
||||||
"$ c white",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" .............................................. ",
|
|
||||||
" .XXXXXXXXXXooooooooooooXXXXXXXXXXXoXXXXXXXXXX. ",
|
|
||||||
" .X ooOOOOOOOOOOXX oX o. ",
|
|
||||||
" .X ooOOOOOOOOOOXX oX o. ",
|
|
||||||
" .X ++++ ooOOOOOOOOOOXX ... oX @ o. ",
|
|
||||||
" .X +++++ ooOOOOOOOOOOXX . . oX @@@ o. ",
|
|
||||||
" .X +++ + ooOOOOOOOOOOXX . . oX @ @ o. ",
|
|
||||||
" .X + + ooOO#####OOOXX . . oX @ @ o. ",
|
|
||||||
" .X + + ooOO#OOO##OOXX . oX @ @ o. ",
|
|
||||||
" .X + + ooO##OOOO##OXX . oX @ @ o. ",
|
|
||||||
" .X ++ ++ ooO###OOO#OOXX . oX @ @ o. ",
|
|
||||||
" .X +++++++ ooO#######OOXX . oX @ @ o. ",
|
|
||||||
" .X + + ooO##O#OO#OOXX . oX @ @ o. ",
|
|
||||||
" .X + ++ ooO##OOOOO#OXX . . oX @ @ o. ",
|
|
||||||
" .X + + ooOO#OOOOO#OXX . . oX @ @@ o. ",
|
|
||||||
" .X + ++ ooOO#OOOOO#OXX .... oX @@@@@ o. ",
|
|
||||||
" .X ooOO######OOXX oX o. ",
|
|
||||||
" .X ooOOOOOOOOOOXX $oX o. ",
|
|
||||||
" .XoooooooooooXXXXXXXXXXXoooooooooooXooooooooo. ",
|
|
||||||
" .............................................. ",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" "};
|
|
Binary file not shown.
Before Width: | Height: | Size: 11 KiB |
|
@ -1,6 +0,0 @@
|
||||||
#define underline_width 16
|
|
||||||
#define underline_height 16
|
|
||||||
static unsigned char underline_bits[] = {
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x1c, 0x38, 0x1c,
|
|
||||||
0x30, 0x0c, 0x30, 0x0c, 0x30, 0x0c, 0x30, 0x0c, 0x30, 0x0c, 0x70, 0x0e,
|
|
||||||
0xf0, 0x0f, 0xe0, 0x07, 0x00, 0x00, 0xf8, 0x1f};
|
|
|
@ -1,28 +0,0 @@
|
||||||
###
|
|
||||||
import tkinter.tix as tk
|
|
||||||
from pprint import pprint
|
|
||||||
|
|
||||||
r= tk.Tk()
|
|
||||||
r.title("test")
|
|
||||||
|
|
||||||
l=tk.Label(r, name="a_label")
|
|
||||||
l.pack()
|
|
||||||
|
|
||||||
class MyGrid(tk.Grid):
|
|
||||||
def __init__(self, *args, **kwargs):
|
|
||||||
kwargs['editnotify']= self.editnotify
|
|
||||||
tk.Grid.__init__(self, *args, **kwargs)
|
|
||||||
def editnotify(self, x, y):
|
|
||||||
return True
|
|
||||||
|
|
||||||
g = MyGrid(r, name="a_grid",
|
|
||||||
selectunit="cell")
|
|
||||||
g.pack(fill=tk.BOTH)
|
|
||||||
for x in range(5):
|
|
||||||
for y in range(5):
|
|
||||||
g.set(x,y,text=str((x,y)))
|
|
||||||
|
|
||||||
c = tk.Button(r, text="Close", command=r.destroy)
|
|
||||||
c.pack()
|
|
||||||
|
|
||||||
tk.mainloop()
|
|
|
@ -1,68 +0,0 @@
|
||||||
# -*-mode: python; fill-column: 75; tab-width: 8; coding: iso-latin-1-unix -*-
|
|
||||||
#
|
|
||||||
# $Id$
|
|
||||||
#
|
|
||||||
# Tix Demostration Program
|
|
||||||
#
|
|
||||||
# This sample program is structured in such a way so that it can be
|
|
||||||
# executed from the Tix demo program "tixwidgets.py": it must have a
|
|
||||||
# procedure called "RunSample". It should also have the "if" statment
|
|
||||||
# at the end of this file so that it can be run as a standalone
|
|
||||||
# program.
|
|
||||||
|
|
||||||
# This file demonstrates the use of the tixBalloon widget, which provides
|
|
||||||
# a interesting way to give help tips about elements in your user interface.
|
|
||||||
# Your can display the help message in a "balloon" and a status bar widget.
|
|
||||||
#
|
|
||||||
|
|
||||||
import tkinter.tix
|
|
||||||
|
|
||||||
TCL_ALL_EVENTS = 0
|
|
||||||
|
|
||||||
def RunSample (root):
|
|
||||||
balloon = DemoBalloon(root)
|
|
||||||
balloon.mainloop()
|
|
||||||
balloon.destroy()
|
|
||||||
|
|
||||||
class DemoBalloon:
|
|
||||||
def __init__(self, w):
|
|
||||||
self.root = w
|
|
||||||
self.exit = -1
|
|
||||||
|
|
||||||
z = w.winfo_toplevel()
|
|
||||||
z.wm_protocol("WM_DELETE_WINDOW", lambda self=self: self.quitcmd())
|
|
||||||
|
|
||||||
status = tkinter.tix.Label(w, width=40, relief=tkinter.tix.SUNKEN, bd=1)
|
|
||||||
status.pack(side=tkinter.tix.BOTTOM, fill=tkinter.tix.Y, padx=2, pady=1)
|
|
||||||
|
|
||||||
# Create two mysterious widgets that need balloon help
|
|
||||||
button1 = tkinter.tix.Button(w, text='Something Unexpected',
|
|
||||||
command=self.quitcmd)
|
|
||||||
button2 = tkinter.tix.Button(w, text='Something Else Unexpected')
|
|
||||||
button2['command'] = lambda w=button2: w.destroy()
|
|
||||||
button1.pack(side=tkinter.tix.TOP, expand=1)
|
|
||||||
button2.pack(side=tkinter.tix.TOP, expand=1)
|
|
||||||
|
|
||||||
# Create the balloon widget and associate it with the widgets that we want
|
|
||||||
# to provide tips for:
|
|
||||||
b = tkinter.tix.Balloon(w, statusbar=status)
|
|
||||||
|
|
||||||
b.bind_widget(button1, balloonmsg='Close Window',
|
|
||||||
statusmsg='Press this button to close this window')
|
|
||||||
b.bind_widget(button2, balloonmsg='Self-destruct button',
|
|
||||||
statusmsg='Press this button and it will destroy itself')
|
|
||||||
|
|
||||||
def quitcmd (self):
|
|
||||||
self.exit = 0
|
|
||||||
|
|
||||||
def mainloop(self):
|
|
||||||
foundEvent = 1
|
|
||||||
while self.exit < 0 and foundEvent > 0:
|
|
||||||
foundEvent = self.root.tk.dooneevent(TCL_ALL_EVENTS)
|
|
||||||
|
|
||||||
def destroy (self):
|
|
||||||
self.root.destroy()
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
root = tkinter.tix.Tk()
|
|
||||||
RunSample(root)
|
|
|
@ -1,44 +0,0 @@
|
||||||
# -*-mode: python; fill-column: 75; tab-width: 8; coding: iso-latin-1-unix -*-
|
|
||||||
#
|
|
||||||
# $Id$
|
|
||||||
#
|
|
||||||
# Tix Demostration Program
|
|
||||||
#
|
|
||||||
# This sample program is structured in such a way so that it can be
|
|
||||||
# executed from the Tix demo program "tixwidgets.py": it must have a
|
|
||||||
# procedure called "RunSample". It should also have the "if" statment
|
|
||||||
# at the end of this file so that it can be run as a standalone
|
|
||||||
# program.
|
|
||||||
|
|
||||||
# This file demonstrates the use of the tixButtonBox widget, which is a
|
|
||||||
# group of TK buttons. You can use it to manage the buttons in a dialog box,
|
|
||||||
# for example.
|
|
||||||
#
|
|
||||||
|
|
||||||
import tkinter.tix
|
|
||||||
|
|
||||||
def RunSample(w):
|
|
||||||
# Create the label on the top of the dialog box
|
|
||||||
#
|
|
||||||
top = tkinter.tix.Label(w, padx=20, pady=10, bd=1, relief=tkinter.tix.RAISED,
|
|
||||||
anchor=tkinter.tix.CENTER, text='This dialog box is\n a demonstration of the\n tixButtonBox widget')
|
|
||||||
|
|
||||||
# Create the button box and add a few buttons in it. Set the
|
|
||||||
# -width of all the buttons to the same value so that they
|
|
||||||
# appear in the same size.
|
|
||||||
#
|
|
||||||
# Note that the -text, -underline, -command and -width options are all
|
|
||||||
# standard options of the button widgets.
|
|
||||||
#
|
|
||||||
box = tkinter.tix.ButtonBox(w, orientation=tkinter.tix.HORIZONTAL)
|
|
||||||
box.add('ok', text='OK', underline=0, width=5,
|
|
||||||
command=lambda w=w: w.destroy())
|
|
||||||
box.add('close', text='Cancel', underline=0, width=5,
|
|
||||||
command=lambda w=w: w.destroy())
|
|
||||||
box.pack(side=tkinter.tix.BOTTOM, fill=tkinter.tix.X)
|
|
||||||
top.pack(side=tkinter.tix.TOP, fill=tkinter.tix.BOTH, expand=1)
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
root = tkinter.tix.Tk()
|
|
||||||
RunSample(root)
|
|
||||||
root.mainloop()
|
|
|
@ -1,196 +0,0 @@
|
||||||
# -*-mode: python; fill-column: 75; tab-width: 8; coding: iso-latin-1-unix -*-
|
|
||||||
#
|
|
||||||
# $Id$
|
|
||||||
#
|
|
||||||
# Tix Demostration Program
|
|
||||||
#
|
|
||||||
# This sample program is structured in such a way so that it can be
|
|
||||||
# executed from the Tix demo program "tixwidgets.py": it must have a
|
|
||||||
# procedure called "RunSample". It should also have the "if" statment
|
|
||||||
# at the end of this file so that it can be run as a standalone
|
|
||||||
# program.
|
|
||||||
|
|
||||||
# This file demonstrates the use of the compound images: it uses compound
|
|
||||||
# images to display a text string together with a pixmap inside
|
|
||||||
# buttons
|
|
||||||
#
|
|
||||||
|
|
||||||
import tkinter.tix
|
|
||||||
|
|
||||||
network_pixmap = """/* XPM */
|
|
||||||
static char * netw_xpm[] = {
|
|
||||||
/* width height ncolors chars_per_pixel */
|
|
||||||
"32 32 7 1",
|
|
||||||
/* colors */
|
|
||||||
" s None c None",
|
|
||||||
". c #000000000000",
|
|
||||||
"X c white",
|
|
||||||
"o c #c000c000c000",
|
|
||||||
"O c #404040",
|
|
||||||
"+ c blue",
|
|
||||||
"@ c red",
|
|
||||||
/* pixels */
|
|
||||||
" ",
|
|
||||||
" .............. ",
|
|
||||||
" .XXXXXXXXXXXX. ",
|
|
||||||
" .XooooooooooO. ",
|
|
||||||
" .Xo.......XoO. ",
|
|
||||||
" .Xo.++++o+XoO. ",
|
|
||||||
" .Xo.++++o+XoO. ",
|
|
||||||
" .Xo.++oo++XoO. ",
|
|
||||||
" .Xo.++++++XoO. ",
|
|
||||||
" .Xo.+o++++XoO. ",
|
|
||||||
" .Xo.++++++XoO. ",
|
|
||||||
" .Xo.XXXXXXXoO. ",
|
|
||||||
" .XooooooooooO. ",
|
|
||||||
" .Xo@ooo....oO. ",
|
|
||||||
" .............. .XooooooooooO. ",
|
|
||||||
" .XXXXXXXXXXXX. .XooooooooooO. ",
|
|
||||||
" .XooooooooooO. .OOOOOOOOOOOO. ",
|
|
||||||
" .Xo.......XoO. .............. ",
|
|
||||||
" .Xo.++++o+XoO. @ ",
|
|
||||||
" .Xo.++++o+XoO. @ ",
|
|
||||||
" .Xo.++oo++XoO. @ ",
|
|
||||||
" .Xo.++++++XoO. @ ",
|
|
||||||
" .Xo.+o++++XoO. @ ",
|
|
||||||
" .Xo.++++++XoO. ..... ",
|
|
||||||
" .Xo.XXXXXXXoO. .XXX. ",
|
|
||||||
" .XooooooooooO.@@@@@@.X O. ",
|
|
||||||
" .Xo@ooo....oO. .OOO. ",
|
|
||||||
" .XooooooooooO. ..... ",
|
|
||||||
" .XooooooooooO. ",
|
|
||||||
" .OOOOOOOOOOOO. ",
|
|
||||||
" .............. ",
|
|
||||||
" "};
|
|
||||||
"""
|
|
||||||
|
|
||||||
hard_disk_pixmap = """/* XPM */
|
|
||||||
static char * drivea_xpm[] = {
|
|
||||||
/* width height ncolors chars_per_pixel */
|
|
||||||
"32 32 5 1",
|
|
||||||
/* colors */
|
|
||||||
" s None c None",
|
|
||||||
". c #000000000000",
|
|
||||||
"X c white",
|
|
||||||
"o c #c000c000c000",
|
|
||||||
"O c #800080008000",
|
|
||||||
/* pixels */
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" .......................... ",
|
|
||||||
" .XXXXXXXXXXXXXXXXXXXXXXXo. ",
|
|
||||||
" .XooooooooooooooooooooooO. ",
|
|
||||||
" .Xooooooooooooooooo..oooO. ",
|
|
||||||
" .Xooooooooooooooooo..oooO. ",
|
|
||||||
" .XooooooooooooooooooooooO. ",
|
|
||||||
" .Xoooooooo.......oooooooO. ",
|
|
||||||
" .Xoo...................oO. ",
|
|
||||||
" .Xoooooooo.......oooooooO. ",
|
|
||||||
" .XooooooooooooooooooooooO. ",
|
|
||||||
" .XooooooooooooooooooooooO. ",
|
|
||||||
" .XooooooooooooooooooooooO. ",
|
|
||||||
" .XooooooooooooooooooooooO. ",
|
|
||||||
" .oOOOOOOOOOOOOOOOOOOOOOOO. ",
|
|
||||||
" .......................... ",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" "};
|
|
||||||
"""
|
|
||||||
|
|
||||||
network_bitmap = """
|
|
||||||
#define netw_width 32
|
|
||||||
#define netw_height 32
|
|
||||||
static unsigned char netw_bits[] = {
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x7f, 0x00, 0x00, 0x02, 0x40,
|
|
||||||
0x00, 0x00, 0xfa, 0x5f, 0x00, 0x00, 0x0a, 0x50, 0x00, 0x00, 0x0a, 0x52,
|
|
||||||
0x00, 0x00, 0x0a, 0x52, 0x00, 0x00, 0x8a, 0x51, 0x00, 0x00, 0x0a, 0x50,
|
|
||||||
0x00, 0x00, 0x4a, 0x50, 0x00, 0x00, 0x0a, 0x50, 0x00, 0x00, 0x0a, 0x50,
|
|
||||||
0x00, 0x00, 0xfa, 0x5f, 0x00, 0x00, 0x02, 0x40, 0xfe, 0x7f, 0x52, 0x55,
|
|
||||||
0x02, 0x40, 0xaa, 0x6a, 0xfa, 0x5f, 0xfe, 0x7f, 0x0a, 0x50, 0xfe, 0x7f,
|
|
||||||
0x0a, 0x52, 0x80, 0x00, 0x0a, 0x52, 0x80, 0x00, 0x8a, 0x51, 0x80, 0x00,
|
|
||||||
0x0a, 0x50, 0x80, 0x00, 0x4a, 0x50, 0x80, 0x00, 0x0a, 0x50, 0xe0, 0x03,
|
|
||||||
0x0a, 0x50, 0x20, 0x02, 0xfa, 0xdf, 0x3f, 0x03, 0x02, 0x40, 0xa0, 0x02,
|
|
||||||
0x52, 0x55, 0xe0, 0x03, 0xaa, 0x6a, 0x00, 0x00, 0xfe, 0x7f, 0x00, 0x00,
|
|
||||||
0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
|
||||||
"""
|
|
||||||
|
|
||||||
hard_disk_bitmap = """
|
|
||||||
#define drivea_width 32
|
|
||||||
#define drivea_height 32
|
|
||||||
static unsigned char drivea_bits[] = {
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0xf8, 0xff, 0xff, 0x1f, 0x08, 0x00, 0x00, 0x18, 0xa8, 0xaa, 0xaa, 0x1a,
|
|
||||||
0x48, 0x55, 0xd5, 0x1d, 0xa8, 0xaa, 0xaa, 0x1b, 0x48, 0x55, 0x55, 0x1d,
|
|
||||||
0xa8, 0xfa, 0xaf, 0x1a, 0xc8, 0xff, 0xff, 0x1d, 0xa8, 0xfa, 0xaf, 0x1a,
|
|
||||||
0x48, 0x55, 0x55, 0x1d, 0xa8, 0xaa, 0xaa, 0x1a, 0x48, 0x55, 0x55, 0x1d,
|
|
||||||
0xa8, 0xaa, 0xaa, 0x1a, 0xf8, 0xff, 0xff, 0x1f, 0xf8, 0xff, 0xff, 0x1f,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
|
||||||
"""
|
|
||||||
|
|
||||||
def RunSample(w):
|
|
||||||
w.img0 = tkinter.tix.Image('pixmap', data=network_pixmap)
|
|
||||||
if not w.img0:
|
|
||||||
w.img0 = tkinter.tix.Image('bitmap', data=network_bitmap)
|
|
||||||
w.img1 = tkinter.tix.Image('pixmap', data=hard_disk_pixmap)
|
|
||||||
if not w.img0:
|
|
||||||
w.img1 = tkinter.tix.Image('bitmap', data=hard_disk_bitmap)
|
|
||||||
|
|
||||||
hdd = tkinter.tix.Button(w, padx=4, pady=1, width=120)
|
|
||||||
net = tkinter.tix.Button(w, padx=4, pady=1, width=120)
|
|
||||||
|
|
||||||
# Create the first image: we create a line, then put a string,
|
|
||||||
# a space and a image into this line, from left to right.
|
|
||||||
# The result: we have a one-line image that consists of three
|
|
||||||
# individual items
|
|
||||||
#
|
|
||||||
# The tk.calls should be methods in Tix ...
|
|
||||||
w.hdd_img = tkinter.tix.Image('compound', window=hdd)
|
|
||||||
w.hdd_img.tk.call(str(w.hdd_img), 'add', 'line')
|
|
||||||
w.hdd_img.tk.call(str(w.hdd_img), 'add', 'text', '-text', 'Hard Disk',
|
|
||||||
'-underline', '0')
|
|
||||||
w.hdd_img.tk.call(str(w.hdd_img), 'add', 'space', '-width', '7')
|
|
||||||
w.hdd_img.tk.call(str(w.hdd_img), 'add', 'image', '-image', w.img1)
|
|
||||||
|
|
||||||
# Put this image into the first button
|
|
||||||
#
|
|
||||||
hdd['image'] = w.hdd_img
|
|
||||||
|
|
||||||
# Next button
|
|
||||||
w.net_img = tkinter.tix.Image('compound', window=net)
|
|
||||||
w.net_img.tk.call(str(w.net_img), 'add', 'line')
|
|
||||||
w.net_img.tk.call(str(w.net_img), 'add', 'text', '-text', 'Network',
|
|
||||||
'-underline', '0')
|
|
||||||
w.net_img.tk.call(str(w.net_img), 'add', 'space', '-width', '7')
|
|
||||||
w.net_img.tk.call(str(w.net_img), 'add', 'image', '-image', w.img0)
|
|
||||||
|
|
||||||
# Put this image into the first button
|
|
||||||
#
|
|
||||||
net['image'] = w.net_img
|
|
||||||
|
|
||||||
close = tkinter.tix.Button(w, pady=1, text='Close',
|
|
||||||
command=lambda w=w: w.destroy())
|
|
||||||
|
|
||||||
hdd.pack(side=tkinter.tix.LEFT, padx=10, pady=10, fill=tkinter.tix.Y, expand=1)
|
|
||||||
net.pack(side=tkinter.tix.LEFT, padx=10, pady=10, fill=tkinter.tix.Y, expand=1)
|
|
||||||
close.pack(side=tkinter.tix.LEFT, padx=10, pady=10, fill=tkinter.tix.Y, expand=1)
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
root = tkinter.tix.Tk()
|
|
||||||
RunSample(root)
|
|
||||||
root.mainloop()
|
|
|
@ -1,102 +0,0 @@
|
||||||
# -*-mode: python; fill-column: 75; tab-width: 8; coding: iso-latin-1-unix -*-
|
|
||||||
#
|
|
||||||
# $Id$
|
|
||||||
#
|
|
||||||
# Tix Demostration Program
|
|
||||||
#
|
|
||||||
# This sample program is structured in such a way so that it can be
|
|
||||||
# executed from the Tix demo program "tixwidgets.py": it must have a
|
|
||||||
# procedure called "RunSample". It should also have the "if" statment
|
|
||||||
# at the end of this file so that it can be run as a standalone
|
|
||||||
# program.
|
|
||||||
|
|
||||||
# This file demonstrates the use of the tixComboBox widget, which is close
|
|
||||||
# to the MS Window Combo Box control.
|
|
||||||
#
|
|
||||||
import tkinter.tix
|
|
||||||
|
|
||||||
def RunSample(w):
|
|
||||||
global demo_month, demo_year
|
|
||||||
|
|
||||||
top = tkinter.tix.Frame(w, bd=1, relief=tkinter.tix.RAISED)
|
|
||||||
|
|
||||||
demo_month = tkinter.tix.StringVar()
|
|
||||||
demo_year = tkinter.tix.StringVar()
|
|
||||||
|
|
||||||
# $w.top.a is a drop-down combo box. It is not editable -- who wants
|
|
||||||
# to invent new months?
|
|
||||||
#
|
|
||||||
# [Hint] The -options switch sets the options of the subwidgets.
|
|
||||||
# [Hint] We set the label.width subwidget option of both comboboxes to
|
|
||||||
# be 10 so that their labels appear to be aligned.
|
|
||||||
#
|
|
||||||
a = tkinter.tix.ComboBox(top, label="Month: ", dropdown=1,
|
|
||||||
command=select_month, editable=0, variable=demo_month,
|
|
||||||
options='listbox.height 6 label.width 10 label.anchor e')
|
|
||||||
|
|
||||||
# $w.top.b is a non-drop-down combo box. It is not editable: we provide
|
|
||||||
# four choices for the user, but he can enter an alternative year if he
|
|
||||||
# wants to.
|
|
||||||
#
|
|
||||||
# [Hint] Use the padY and anchor options of the label subwidget to
|
|
||||||
# align the label with the entry subwidget.
|
|
||||||
# [Hint] Notice that you should use padY (the NAME of the option) and not
|
|
||||||
# pady (the SWITCH of the option).
|
|
||||||
#
|
|
||||||
b = tkinter.tix.ComboBox(top, label="Year: ", dropdown=0,
|
|
||||||
command=select_year, editable=1, variable=demo_year,
|
|
||||||
options='listbox.height 4 label.padY 5 label.width 10 label.anchor ne')
|
|
||||||
|
|
||||||
a.pack(side=tkinter.tix.TOP, anchor=tkinter.tix.W)
|
|
||||||
b.pack(side=tkinter.tix.TOP, anchor=tkinter.tix.W)
|
|
||||||
|
|
||||||
a.insert(tkinter.tix.END, 'January')
|
|
||||||
a.insert(tkinter.tix.END, 'February')
|
|
||||||
a.insert(tkinter.tix.END, 'March')
|
|
||||||
a.insert(tkinter.tix.END, 'April')
|
|
||||||
a.insert(tkinter.tix.END, 'May')
|
|
||||||
a.insert(tkinter.tix.END, 'June')
|
|
||||||
a.insert(tkinter.tix.END, 'July')
|
|
||||||
a.insert(tkinter.tix.END, 'August')
|
|
||||||
a.insert(tkinter.tix.END, 'September')
|
|
||||||
a.insert(tkinter.tix.END, 'October')
|
|
||||||
a.insert(tkinter.tix.END, 'November')
|
|
||||||
a.insert(tkinter.tix.END, 'December')
|
|
||||||
|
|
||||||
b.insert(tkinter.tix.END, '1992')
|
|
||||||
b.insert(tkinter.tix.END, '1993')
|
|
||||||
b.insert(tkinter.tix.END, '1994')
|
|
||||||
b.insert(tkinter.tix.END, '1995')
|
|
||||||
b.insert(tkinter.tix.END, '1996')
|
|
||||||
|
|
||||||
# Use "tixSetSilent" to set the values of the combo box if you
|
|
||||||
# don't want your -command procedures (cbx:select_month and
|
|
||||||
# cbx:select_year) to be called.
|
|
||||||
#
|
|
||||||
a.set_silent('January')
|
|
||||||
b.set_silent('1995')
|
|
||||||
|
|
||||||
box = tkinter.tix.ButtonBox(w, orientation=tkinter.tix.HORIZONTAL)
|
|
||||||
box.add('ok', text='Ok', underline=0, width=6,
|
|
||||||
command=lambda w=w: ok_command(w))
|
|
||||||
box.add('cancel', text='Cancel', underline=0, width=6,
|
|
||||||
command=lambda w=w: w.destroy())
|
|
||||||
box.pack(side=tkinter.tix.BOTTOM, fill=tkinter.tix.X)
|
|
||||||
top.pack(side=tkinter.tix.TOP, fill=tkinter.tix.BOTH, expand=1)
|
|
||||||
|
|
||||||
def select_month(event=None):
|
|
||||||
# tixDemo:Status "Month = %s" % demo_month.get()
|
|
||||||
pass
|
|
||||||
|
|
||||||
def select_year(event=None):
|
|
||||||
# tixDemo:Status "Year = %s" % demo_year.get()
|
|
||||||
pass
|
|
||||||
|
|
||||||
def ok_command(w):
|
|
||||||
# tixDemo:Status "Month = %s, Year= %s" % (demo_month.get(), demo_year.get())
|
|
||||||
w.destroy()
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
root = tkinter.tix.Tk()
|
|
||||||
RunSample(root)
|
|
||||||
root.mainloop()
|
|
|
@ -1,122 +0,0 @@
|
||||||
# -*-mode: python; fill-column: 75; tab-width: 8; coding: iso-latin-1-unix -*-
|
|
||||||
#
|
|
||||||
# $Id$
|
|
||||||
#
|
|
||||||
# Tix Demostration Program
|
|
||||||
#
|
|
||||||
# This sample program is structured in such a way so that it can be
|
|
||||||
# executed from the Tix demo program "tixwidgets.py": it must have a
|
|
||||||
# procedure called "RunSample". It should also have the "if" statment
|
|
||||||
# at the end of this file so that it can be run as a standalone
|
|
||||||
# program.
|
|
||||||
|
|
||||||
# This file demonstrates the use of the tixControl widget -- it is an
|
|
||||||
# entry widget with up/down arrow buttons. You can use the arrow buttons
|
|
||||||
# to adjust the value inside the entry widget.
|
|
||||||
#
|
|
||||||
# This example program uses three Control widgets. One lets you select
|
|
||||||
# integer values; one lets you select floating point values and the last
|
|
||||||
# one lets you select a few names.
|
|
||||||
|
|
||||||
import tkinter.tix
|
|
||||||
|
|
||||||
TCL_ALL_EVENTS = 0
|
|
||||||
|
|
||||||
def RunSample (root):
|
|
||||||
control = DemoControl(root)
|
|
||||||
control.mainloop()
|
|
||||||
control.destroy()
|
|
||||||
|
|
||||||
class DemoControl:
|
|
||||||
def __init__(self, w):
|
|
||||||
self.root = w
|
|
||||||
self.exit = -1
|
|
||||||
|
|
||||||
global demo_maker, demo_thrust, demo_num_engines
|
|
||||||
|
|
||||||
demo_maker = tkinter.tix.StringVar()
|
|
||||||
demo_thrust = tkinter.tix.DoubleVar()
|
|
||||||
demo_num_engines = tkinter.tix.IntVar()
|
|
||||||
demo_maker.set('P&W')
|
|
||||||
demo_thrust.set(20000.0)
|
|
||||||
demo_num_engines.set(2)
|
|
||||||
|
|
||||||
top = tkinter.tix.Frame(w, bd=1, relief=tkinter.tix.RAISED)
|
|
||||||
|
|
||||||
# $w.top.a allows only integer values
|
|
||||||
#
|
|
||||||
# [Hint] The -options switch sets the options of the subwidgets.
|
|
||||||
# [Hint] We set the label.width subwidget option of the Controls to
|
|
||||||
# be 16 so that their labels appear to be aligned.
|
|
||||||
#
|
|
||||||
a = tkinter.tix.Control(top, label='Number of Engines: ', integer=1,
|
|
||||||
variable=demo_num_engines, min=1, max=4,
|
|
||||||
options='entry.width 10 label.width 20 label.anchor e')
|
|
||||||
|
|
||||||
b = tkinter.tix.Control(top, label='Thrust: ', integer=0,
|
|
||||||
min='10000.0', max='60000.0', step=500,
|
|
||||||
variable=demo_thrust,
|
|
||||||
options='entry.width 10 label.width 20 label.anchor e')
|
|
||||||
|
|
||||||
c = tkinter.tix.Control(top, label='Engine Maker: ', value='P&W',
|
|
||||||
variable=demo_maker,
|
|
||||||
options='entry.width 10 label.width 20 label.anchor e')
|
|
||||||
|
|
||||||
# We can't define these in the init because the widget 'c' doesn't
|
|
||||||
# exist yet and we need to reference it
|
|
||||||
c['incrcmd'] = lambda w=c: adjust_maker(w, 1)
|
|
||||||
c['decrcmd'] = lambda w=c: adjust_maker(w, -1)
|
|
||||||
c['validatecmd'] = lambda w=c: validate_maker(w)
|
|
||||||
|
|
||||||
a.pack(side=tkinter.tix.TOP, anchor=tkinter.tix.W)
|
|
||||||
b.pack(side=tkinter.tix.TOP, anchor=tkinter.tix.W)
|
|
||||||
c.pack(side=tkinter.tix.TOP, anchor=tkinter.tix.W)
|
|
||||||
|
|
||||||
box = tkinter.tix.ButtonBox(w, orientation=tkinter.tix.HORIZONTAL)
|
|
||||||
box.add('ok', text='Ok', underline=0, width=6,
|
|
||||||
command=self.okcmd)
|
|
||||||
box.add('cancel', text='Cancel', underline=0, width=6,
|
|
||||||
command=self.quitcmd)
|
|
||||||
box.pack(side=tkinter.tix.BOTTOM, fill=tkinter.tix.X)
|
|
||||||
top.pack(side=tkinter.tix.TOP, fill=tkinter.tix.BOTH, expand=1)
|
|
||||||
|
|
||||||
def okcmd (self):
|
|
||||||
# tixDemo:Status "Selected %d of %s engines each of thrust %d", (demo_num_engines.get(), demo_maker.get(), demo_thrust.get())
|
|
||||||
self.quitcmd()
|
|
||||||
|
|
||||||
def quitcmd (self):
|
|
||||||
self.exit = 0
|
|
||||||
|
|
||||||
def mainloop(self):
|
|
||||||
while self.exit < 0:
|
|
||||||
self.root.tk.dooneevent(TCL_ALL_EVENTS)
|
|
||||||
|
|
||||||
def destroy (self):
|
|
||||||
self.root.destroy()
|
|
||||||
|
|
||||||
maker_list = ['P&W', 'GE', 'Rolls Royce']
|
|
||||||
|
|
||||||
def adjust_maker(w, inc):
|
|
||||||
i = maker_list.index(demo_maker.get())
|
|
||||||
i = i + inc
|
|
||||||
if i >= len(maker_list):
|
|
||||||
i = 0
|
|
||||||
elif i < 0:
|
|
||||||
i = len(maker_list) - 1
|
|
||||||
|
|
||||||
# In Tcl/Tix we should return the string maker_list[i]. We can't
|
|
||||||
# do that in Tkinter so we set the global variable. (This works).
|
|
||||||
demo_maker.set(maker_list[i])
|
|
||||||
|
|
||||||
def validate_maker(w):
|
|
||||||
try:
|
|
||||||
i = maker_list.index(demo_maker.get())
|
|
||||||
except ValueError:
|
|
||||||
# Works here though. Why ? Beats me.
|
|
||||||
return maker_list[0]
|
|
||||||
# Works here though. Why ? Beats me.
|
|
||||||
return maker_list[i]
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
root = tkinter.tix.Tk()
|
|
||||||
RunSample(root)
|
|
|
@ -1,131 +0,0 @@
|
||||||
# -*-mode: python; fill-column: 75; tab-width: 8; coding: iso-latin-1-unix -*-
|
|
||||||
#
|
|
||||||
# $Id$
|
|
||||||
#
|
|
||||||
# Tix Demostration Program
|
|
||||||
#
|
|
||||||
# This sample program is structured in such a way so that it can be
|
|
||||||
# executed from the Tix demo program "tixwidgets.py": it must have a
|
|
||||||
# procedure called "RunSample". It should also have the "if" statment
|
|
||||||
# at the end of this file so that it can be run as a standalone
|
|
||||||
# program using tixwish.
|
|
||||||
|
|
||||||
# This file demonstrates the use of the tixDirList widget -- you can
|
|
||||||
# use it for the user to select a directory. For example, an installation
|
|
||||||
# program can use the tixDirList widget to ask the user to select the
|
|
||||||
# installation directory for an application.
|
|
||||||
#
|
|
||||||
|
|
||||||
import tkinter.tix, os, copy
|
|
||||||
from tkinter.constants import *
|
|
||||||
|
|
||||||
TCL_ALL_EVENTS = 0
|
|
||||||
|
|
||||||
def RunSample (root):
|
|
||||||
dirlist = DemoDirList(root)
|
|
||||||
dirlist.mainloop()
|
|
||||||
dirlist.destroy()
|
|
||||||
|
|
||||||
class DemoDirList:
|
|
||||||
def __init__(self, w):
|
|
||||||
self.root = w
|
|
||||||
self.exit = -1
|
|
||||||
|
|
||||||
z = w.winfo_toplevel()
|
|
||||||
z.wm_protocol("WM_DELETE_WINDOW", lambda self=self: self.quitcmd())
|
|
||||||
|
|
||||||
# Create the tixDirList and the tixLabelEntry widgets on the on the top
|
|
||||||
# of the dialog box
|
|
||||||
|
|
||||||
# bg = root.tk.eval('tix option get bg')
|
|
||||||
# adding bg=bg crashes Windows pythonw tk8.3.3 Python 2.1.0
|
|
||||||
|
|
||||||
top = tkinter.tix.Frame( w, relief=RAISED, bd=1)
|
|
||||||
|
|
||||||
# Create the DirList widget. By default it will show the current
|
|
||||||
# directory
|
|
||||||
#
|
|
||||||
#
|
|
||||||
top.dir = tkinter.tix.DirList(top)
|
|
||||||
top.dir.hlist['width'] = 40
|
|
||||||
|
|
||||||
# When the user presses the ".." button, the selected directory
|
|
||||||
# is "transferred" into the entry widget
|
|
||||||
#
|
|
||||||
top.btn = tkinter.tix.Button(top, text = " >> ", pady = 0)
|
|
||||||
|
|
||||||
# We use a LabelEntry to hold the installation directory. The user
|
|
||||||
# can choose from the DirList widget, or he can type in the directory
|
|
||||||
# manually
|
|
||||||
#
|
|
||||||
top.ent = tkinter.tix.LabelEntry(top, label="Installation Directory:",
|
|
||||||
labelside = 'top',
|
|
||||||
options = '''
|
|
||||||
entry.width 40
|
|
||||||
label.anchor w
|
|
||||||
''')
|
|
||||||
|
|
||||||
font = self.root.tk.eval('tix option get fixed_font')
|
|
||||||
# font = self.root.master.tix_option_get('fixed_font')
|
|
||||||
top.ent.entry['font'] = font
|
|
||||||
|
|
||||||
self.dlist_dir = copy.copy(os.curdir)
|
|
||||||
# This should work setting the entry's textvariable
|
|
||||||
top.ent.entry['textvariable'] = self.dlist_dir
|
|
||||||
top.btn['command'] = lambda dir=top.dir, ent=top.ent, self=self: \
|
|
||||||
self.copy_name(dir,ent)
|
|
||||||
|
|
||||||
# top.ent.entry.insert(0,'tix'+repr(self))
|
|
||||||
top.ent.entry.bind('<Return>', lambda self=self: self.okcmd () )
|
|
||||||
|
|
||||||
top.pack( expand='yes', fill='both', side=TOP)
|
|
||||||
top.dir.pack( expand=1, fill=BOTH, padx=4, pady=4, side=LEFT)
|
|
||||||
top.btn.pack( anchor='s', padx=4, pady=4, side=LEFT)
|
|
||||||
top.ent.pack( expand=1, fill=X, anchor='s', padx=4, pady=4, side=LEFT)
|
|
||||||
|
|
||||||
# Use a ButtonBox to hold the buttons.
|
|
||||||
#
|
|
||||||
box = tkinter.tix.ButtonBox (w, orientation='horizontal')
|
|
||||||
box.add ('ok', text='Ok', underline=0, width=6,
|
|
||||||
command = lambda self=self: self.okcmd () )
|
|
||||||
box.add ('cancel', text='Cancel', underline=0, width=6,
|
|
||||||
command = lambda self=self: self.quitcmd () )
|
|
||||||
|
|
||||||
box.pack( anchor='s', fill='x', side=BOTTOM)
|
|
||||||
|
|
||||||
def copy_name (self, dir, ent):
|
|
||||||
# This should work as it is the entry's textvariable
|
|
||||||
self.dlist_dir = dir.cget('value')
|
|
||||||
# but it isn't so I'll do it manually
|
|
||||||
ent.entry.delete(0,'end')
|
|
||||||
ent.entry.insert(0, self.dlist_dir)
|
|
||||||
|
|
||||||
def okcmd (self):
|
|
||||||
# tixDemo:Status "You have selected the directory" + self.dlist_dir
|
|
||||||
self.quitcmd()
|
|
||||||
|
|
||||||
def quitcmd (self):
|
|
||||||
self.exit = 0
|
|
||||||
|
|
||||||
def mainloop(self):
|
|
||||||
while self.exit < 0:
|
|
||||||
self.root.tk.dooneevent(TCL_ALL_EVENTS)
|
|
||||||
|
|
||||||
def destroy (self):
|
|
||||||
self.root.destroy()
|
|
||||||
|
|
||||||
# This "if" statement makes it possible to run this script file inside or
|
|
||||||
# outside of the main demo program "tixwidgets.py".
|
|
||||||
#
|
|
||||||
if __name__== '__main__' :
|
|
||||||
import tkinter.messagebox, traceback
|
|
||||||
|
|
||||||
try:
|
|
||||||
root=tkinter.tix.Tk()
|
|
||||||
RunSample(root)
|
|
||||||
except:
|
|
||||||
t, v, tb = sys.exc_info()
|
|
||||||
text = "Error running the demo script:\n"
|
|
||||||
for line in traceback.format_exception(t,v,tb):
|
|
||||||
text = text + line + '\n'
|
|
||||||
d = tkinter.messagebox.showerror ( 'Tix Demo Error', text)
|
|
|
@ -1,117 +0,0 @@
|
||||||
# -*-mode: python; fill-column: 75; tab-width: 8; coding: iso-latin-1-unix -*-
|
|
||||||
#
|
|
||||||
# $Id$
|
|
||||||
#
|
|
||||||
# Tix Demostration Program
|
|
||||||
#
|
|
||||||
# This sample program is structured in such a way so that it can be
|
|
||||||
# executed from the Tix demo program "tixwidgets.py": it must have a
|
|
||||||
# procedure called "RunSample". It should also have the "if" statment
|
|
||||||
# at the end of this file so that it can be run as a standalone
|
|
||||||
# program using tixwish.
|
|
||||||
|
|
||||||
# This file demonstrates the use of the tixDirTree widget -- you can
|
|
||||||
# use it for the user to select a directory. For example, an installation
|
|
||||||
# program can use the tixDirTree widget to ask the user to select the
|
|
||||||
# installation directory for an application.
|
|
||||||
#
|
|
||||||
|
|
||||||
import tkinter.tix, os, copy
|
|
||||||
from tkinter.constants import *
|
|
||||||
|
|
||||||
TCL_ALL_EVENTS = 0
|
|
||||||
|
|
||||||
def RunSample (root):
|
|
||||||
dirtree = DemoDirTree(root)
|
|
||||||
dirtree.mainloop()
|
|
||||||
dirtree.destroy()
|
|
||||||
|
|
||||||
class DemoDirTree:
|
|
||||||
def __init__(self, w):
|
|
||||||
self.root = w
|
|
||||||
self.exit = -1
|
|
||||||
|
|
||||||
z = w.winfo_toplevel()
|
|
||||||
z.wm_protocol("WM_DELETE_WINDOW", lambda self=self: self.quitcmd())
|
|
||||||
|
|
||||||
# Create the tixDirTree and the tixLabelEntry widgets on the on the top
|
|
||||||
# of the dialog box
|
|
||||||
|
|
||||||
# bg = root.tk.eval('tix option get bg')
|
|
||||||
# adding bg=bg crashes Windows pythonw tk8.3.3 Python 2.1.0
|
|
||||||
|
|
||||||
top = tkinter.tix.Frame( w, relief=RAISED, bd=1)
|
|
||||||
|
|
||||||
# Create the DirTree widget. By default it will show the current
|
|
||||||
# directory
|
|
||||||
#
|
|
||||||
#
|
|
||||||
top.dir = tkinter.tix.DirTree(top)
|
|
||||||
top.dir.hlist['width'] = 40
|
|
||||||
|
|
||||||
# When the user presses the ".." button, the selected directory
|
|
||||||
# is "transferred" into the entry widget
|
|
||||||
#
|
|
||||||
top.btn = tkinter.tix.Button(top, text = " >> ", pady = 0)
|
|
||||||
|
|
||||||
# We use a LabelEntry to hold the installation directory. The user
|
|
||||||
# can choose from the DirTree widget, or he can type in the directory
|
|
||||||
# manually
|
|
||||||
#
|
|
||||||
top.ent = tkinter.tix.LabelEntry(top, label="Installation Directory:",
|
|
||||||
labelside = 'top',
|
|
||||||
options = '''
|
|
||||||
entry.width 40
|
|
||||||
label.anchor w
|
|
||||||
''')
|
|
||||||
|
|
||||||
self.dlist_dir = copy.copy(os.curdir)
|
|
||||||
top.ent.entry['textvariable'] = self.dlist_dir
|
|
||||||
top.btn['command'] = lambda dir=top.dir, ent=top.ent, self=self: \
|
|
||||||
self.copy_name(dir,ent)
|
|
||||||
|
|
||||||
top.ent.entry.bind('<Return>', lambda self=self: self.okcmd () )
|
|
||||||
|
|
||||||
top.pack( expand='yes', fill='both', side=TOP)
|
|
||||||
top.dir.pack( expand=1, fill=BOTH, padx=4, pady=4, side=LEFT)
|
|
||||||
top.btn.pack( anchor='s', padx=4, pady=4, side=LEFT)
|
|
||||||
top.ent.pack( expand=1, fill=X, anchor='s', padx=4, pady=4, side=LEFT)
|
|
||||||
|
|
||||||
# Use a ButtonBox to hold the buttons.
|
|
||||||
#
|
|
||||||
box = tkinter.tix.ButtonBox (w, orientation='horizontal')
|
|
||||||
box.add ('ok', text='Ok', underline=0, width=6,
|
|
||||||
command = lambda self=self: self.okcmd () )
|
|
||||||
box.add ('cancel', text='Cancel', underline=0, width=6,
|
|
||||||
command = lambda self=self: self.quitcmd () )
|
|
||||||
|
|
||||||
box.pack( anchor='s', fill='x', side=BOTTOM)
|
|
||||||
|
|
||||||
def copy_name (self, dir, ent):
|
|
||||||
# This should work as it is the entry's textvariable
|
|
||||||
self.dlist_dir = dir.cget('value')
|
|
||||||
# but it isn't so I'll do it manually
|
|
||||||
ent.entry.delete(0,'end')
|
|
||||||
ent.entry.insert(0, self.dlist_dir)
|
|
||||||
|
|
||||||
def okcmd (self):
|
|
||||||
# tixDemo:Status "You have selected the directory" + self.dlist_dir
|
|
||||||
self.quitcmd()
|
|
||||||
|
|
||||||
def quitcmd (self):
|
|
||||||
# tixDemo:Status "You have selected the directory" + self.dlist_dir
|
|
||||||
self.exit = 0
|
|
||||||
|
|
||||||
def mainloop(self):
|
|
||||||
while self.exit < 0:
|
|
||||||
self.root.tk.dooneevent(TCL_ALL_EVENTS)
|
|
||||||
|
|
||||||
def destroy (self):
|
|
||||||
self.root.destroy()
|
|
||||||
|
|
||||||
# This "if" statement makes it possible to run this script file inside or
|
|
||||||
# outside of the main demo program "tixwidgets.py".
|
|
||||||
#
|
|
||||||
if __name__== '__main__' :
|
|
||||||
root=tkinter.tix.Tk()
|
|
||||||
RunSample(root)
|
|
|
@ -1,119 +0,0 @@
|
||||||
# -*-mode: python; fill-column: 75; tab-width: 8; coding: iso-latin-1-unix -*-
|
|
||||||
#
|
|
||||||
# $Id$
|
|
||||||
#
|
|
||||||
# Tix Demostration Program
|
|
||||||
#
|
|
||||||
# This sample program is structured in such a way so that it can be
|
|
||||||
# executed from the Tix demo program "tixwidgets.py": it must have a
|
|
||||||
# procedure called "RunSample". It should also have the "if" statment
|
|
||||||
# at the end of this file so that it can be run as a standalone
|
|
||||||
# program.
|
|
||||||
|
|
||||||
# This file demonstrates the use of the tixNoteBook widget, which allows
|
|
||||||
# you to lay out your interface using a "notebook" metaphore
|
|
||||||
#
|
|
||||||
import tkinter.tix
|
|
||||||
|
|
||||||
def RunSample(w):
|
|
||||||
global root
|
|
||||||
root = w
|
|
||||||
|
|
||||||
# We use these options to set the sizes of the subwidgets inside the
|
|
||||||
# notebook, so that they are well-aligned on the screen.
|
|
||||||
prefix = tkinter.tix.OptionName(w)
|
|
||||||
if prefix:
|
|
||||||
prefix = '*'+prefix
|
|
||||||
else:
|
|
||||||
prefix = ''
|
|
||||||
w.option_add(prefix+'*TixControl*entry.width', 10)
|
|
||||||
w.option_add(prefix+'*TixControl*label.width', 18)
|
|
||||||
w.option_add(prefix+'*TixControl*label.anchor', tkinter.tix.E)
|
|
||||||
w.option_add(prefix+'*TixNoteBook*tagPadX', 8)
|
|
||||||
|
|
||||||
# Create the notebook widget and set its backpagecolor to gray.
|
|
||||||
# Note that the -backpagecolor option belongs to the "nbframe"
|
|
||||||
# subwidget.
|
|
||||||
nb = tkinter.tix.NoteBook(w, name='nb', ipadx=6, ipady=6)
|
|
||||||
nb['bg'] = 'gray'
|
|
||||||
nb.nbframe['backpagecolor'] = 'gray'
|
|
||||||
|
|
||||||
# Create the two tabs on the notebook. The -underline option
|
|
||||||
# puts a underline on the first character of the labels of the tabs.
|
|
||||||
# Keyboard accelerators will be defined automatically according
|
|
||||||
# to the underlined character.
|
|
||||||
nb.add('hard_disk', label="Hard Disk", underline=0)
|
|
||||||
nb.add('network', label="Network", underline=0)
|
|
||||||
|
|
||||||
nb.pack(expand=1, fill=tkinter.tix.BOTH, padx=5, pady=5 ,side=tkinter.tix.TOP)
|
|
||||||
|
|
||||||
#----------------------------------------
|
|
||||||
# Create the first page
|
|
||||||
#----------------------------------------
|
|
||||||
# Create two frames: one for the common buttons, one for the
|
|
||||||
# other widgets
|
|
||||||
#
|
|
||||||
tab=nb.hard_disk
|
|
||||||
f = tkinter.tix.Frame(tab)
|
|
||||||
common = tkinter.tix.Frame(tab)
|
|
||||||
|
|
||||||
f.pack(side=tkinter.tix.LEFT, padx=2, pady=2, fill=tkinter.tix.BOTH, expand=1)
|
|
||||||
common.pack(side=tkinter.tix.RIGHT, padx=2, fill=tkinter.tix.Y)
|
|
||||||
|
|
||||||
a = tkinter.tix.Control(f, value=12, label='Access time: ')
|
|
||||||
w = tkinter.tix.Control(f, value=400, label='Write Throughput: ')
|
|
||||||
r = tkinter.tix.Control(f, value=400, label='Read Throughput: ')
|
|
||||||
c = tkinter.tix.Control(f, value=1021, label='Capacity: ')
|
|
||||||
|
|
||||||
a.pack(side=tkinter.tix.TOP, padx=20, pady=2)
|
|
||||||
w.pack(side=tkinter.tix.TOP, padx=20, pady=2)
|
|
||||||
r.pack(side=tkinter.tix.TOP, padx=20, pady=2)
|
|
||||||
c.pack(side=tkinter.tix.TOP, padx=20, pady=2)
|
|
||||||
|
|
||||||
# Create the common buttons
|
|
||||||
createCommonButtons(common)
|
|
||||||
|
|
||||||
#----------------------------------------
|
|
||||||
# Create the second page
|
|
||||||
#----------------------------------------
|
|
||||||
|
|
||||||
tab = nb.network
|
|
||||||
|
|
||||||
f = tkinter.tix.Frame(tab)
|
|
||||||
common = tkinter.tix.Frame(tab)
|
|
||||||
|
|
||||||
f.pack(side=tkinter.tix.LEFT, padx=2, pady=2, fill=tkinter.tix.BOTH, expand=1)
|
|
||||||
common.pack(side=tkinter.tix.RIGHT, padx=2, fill=tkinter.tix.Y)
|
|
||||||
|
|
||||||
a = tkinter.tix.Control(f, value=12, label='Access time: ')
|
|
||||||
w = tkinter.tix.Control(f, value=400, label='Write Throughput: ')
|
|
||||||
r = tkinter.tix.Control(f, value=400, label='Read Throughput: ')
|
|
||||||
c = tkinter.tix.Control(f, value=1021, label='Capacity: ')
|
|
||||||
u = tkinter.tix.Control(f, value=10, label='Users: ')
|
|
||||||
|
|
||||||
a.pack(side=tkinter.tix.TOP, padx=20, pady=2)
|
|
||||||
w.pack(side=tkinter.tix.TOP, padx=20, pady=2)
|
|
||||||
r.pack(side=tkinter.tix.TOP, padx=20, pady=2)
|
|
||||||
c.pack(side=tkinter.tix.TOP, padx=20, pady=2)
|
|
||||||
u.pack(side=tkinter.tix.TOP, padx=20, pady=2)
|
|
||||||
|
|
||||||
createCommonButtons(common)
|
|
||||||
|
|
||||||
def doDestroy():
|
|
||||||
global root
|
|
||||||
root.destroy()
|
|
||||||
|
|
||||||
def createCommonButtons(master):
|
|
||||||
ok = tkinter.tix.Button(master, name='ok', text='OK', width=6,
|
|
||||||
command=doDestroy)
|
|
||||||
cancel = tkinter.tix.Button(master, name='cancel',
|
|
||||||
text='Cancel', width=6,
|
|
||||||
command=doDestroy)
|
|
||||||
|
|
||||||
ok.pack(side=tkinter.tix.TOP, padx=2, pady=2)
|
|
||||||
cancel.pack(side=tkinter.tix.TOP, padx=2, pady=2)
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
root = tkinter.tix.Tk()
|
|
||||||
RunSample(root)
|
|
||||||
root.mainloop()
|
|
|
@ -1,68 +0,0 @@
|
||||||
# -*-mode: python; fill-column: 75; tab-width: 8; coding: iso-latin-1-unix -*-
|
|
||||||
#
|
|
||||||
# $Id$
|
|
||||||
#
|
|
||||||
# Tix Demostration Program
|
|
||||||
#
|
|
||||||
# This sample program is structured in such a way so that it can be
|
|
||||||
# executed from the Tix demo program "tixwidgets.py": it must have a
|
|
||||||
# procedure called "RunSample". It should also have the "if" statment
|
|
||||||
# at the end of this file so that it can be run as a standalone
|
|
||||||
# program.
|
|
||||||
|
|
||||||
# This file demonstrates the use of the tixOptionMenu widget -- you can
|
|
||||||
# use it for the user to choose from a fixed set of options
|
|
||||||
#
|
|
||||||
import tkinter.tix
|
|
||||||
|
|
||||||
options = {'text':'Plain Text', 'post':'PostScript', 'html':'HTML',
|
|
||||||
'tex':'LaTeX', 'rtf':'Rich Text Format'}
|
|
||||||
|
|
||||||
def RunSample(w):
|
|
||||||
global demo_opt_from, demo_opt_to
|
|
||||||
|
|
||||||
demo_opt_from = tkinter.tix.StringVar()
|
|
||||||
demo_opt_to = tkinter.tix.StringVar()
|
|
||||||
|
|
||||||
top = tkinter.tix.Frame(w, bd=1, relief=tkinter.tix.RAISED)
|
|
||||||
|
|
||||||
from_file = tkinter.tix.OptionMenu(top, label="From File Format : ",
|
|
||||||
variable=demo_opt_from,
|
|
||||||
options = 'label.width 19 label.anchor e menubutton.width 15')
|
|
||||||
|
|
||||||
to_file = tkinter.tix.OptionMenu(top, label="To File Format : ",
|
|
||||||
variable=demo_opt_to,
|
|
||||||
options='label.width 19 label.anchor e menubutton.width 15')
|
|
||||||
|
|
||||||
# Add the available options to the two OptionMenu widgets
|
|
||||||
#
|
|
||||||
# [Hint] You have to add the options first before you set the
|
|
||||||
# global variables "demo_opt_from" and "demo_opt_to". Otherwise
|
|
||||||
# the OptionMenu widget will complain about "unknown options"!
|
|
||||||
#
|
|
||||||
for opt in options.keys():
|
|
||||||
from_file.add_command(opt, label=options[opt])
|
|
||||||
to_file.add_command(opt, label=options[opt])
|
|
||||||
|
|
||||||
demo_opt_from.set('html')
|
|
||||||
demo_opt_to.set('post')
|
|
||||||
|
|
||||||
from_file.pack(side=tkinter.tix.TOP, anchor=tkinter.tix.W, pady=3, padx=6)
|
|
||||||
to_file.pack(side=tkinter.tix.TOP, anchor=tkinter.tix.W, pady=3, padx=6)
|
|
||||||
|
|
||||||
box = tkinter.tix.ButtonBox(w, orientation=tkinter.tix.HORIZONTAL)
|
|
||||||
box.add('ok', text='Ok', underline=0, width=6,
|
|
||||||
command=lambda w=w: ok_command(w))
|
|
||||||
box.add('cancel', text='Cancel', underline=0, width=6,
|
|
||||||
command=lambda w=w: w.destroy())
|
|
||||||
box.pack(side=tkinter.tix.BOTTOM, fill=tkinter.tix.X)
|
|
||||||
top.pack(side=tkinter.tix.TOP, fill=tkinter.tix.BOTH, expand=1)
|
|
||||||
|
|
||||||
def ok_command(w):
|
|
||||||
# tixDemo:Status "Convert file from %s to %s" % ( demo_opt_from.get(), demo_opt_to.get())
|
|
||||||
w.destroy()
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
root = tkinter.tix.Tk()
|
|
||||||
RunSample(root)
|
|
||||||
root.mainloop()
|
|
|
@ -1,98 +0,0 @@
|
||||||
# -*-mode: python; fill-column: 75; tab-width: 8; coding: iso-latin-1-unix -*-
|
|
||||||
#
|
|
||||||
# $Id$
|
|
||||||
#
|
|
||||||
# Tix Demostration Program
|
|
||||||
#
|
|
||||||
# This sample program is structured in such a way so that it can be
|
|
||||||
# executed from the Tix demo program "tixwidgets.py": it must have a
|
|
||||||
# procedure called "RunSample". It should also have the "if" statment
|
|
||||||
# at the end of this file so that it can be run as a standalone
|
|
||||||
# program.
|
|
||||||
|
|
||||||
# This file demonstrates the use of the tixPanedWindow widget. This program
|
|
||||||
# is a dummy news reader: the user can adjust the sizes of the list
|
|
||||||
# of artical names and the size of the text widget that shows the body
|
|
||||||
# of the article.
|
|
||||||
|
|
||||||
import tkinter.tix
|
|
||||||
|
|
||||||
TCL_ALL_EVENTS = 0
|
|
||||||
|
|
||||||
def RunSample (root):
|
|
||||||
panedwin = DemoPanedwin(root)
|
|
||||||
panedwin.mainloop()
|
|
||||||
panedwin.destroy()
|
|
||||||
|
|
||||||
class DemoPanedwin:
|
|
||||||
def __init__(self, w):
|
|
||||||
self.root = w
|
|
||||||
self.exit = -1
|
|
||||||
|
|
||||||
z = w.winfo_toplevel()
|
|
||||||
z.wm_protocol("WM_DELETE_WINDOW", lambda self=self: self.quitcmd())
|
|
||||||
|
|
||||||
group = tkinter.tix.LabelEntry(w, label='Newsgroup:', options='entry.width 25')
|
|
||||||
group.entry.insert(0,'comp.lang.python')
|
|
||||||
pane = tkinter.tix.PanedWindow(w, orientation='vertical')
|
|
||||||
|
|
||||||
p1 = pane.add('list', min=70, size=100)
|
|
||||||
p2 = pane.add('text', min=70)
|
|
||||||
list = tkinter.tix.ScrolledListBox(p1)
|
|
||||||
list.listbox['width'] = 80
|
|
||||||
list.listbox['height'] = 5
|
|
||||||
text = tkinter.tix.ScrolledText(p2)
|
|
||||||
text.text['width'] = 80
|
|
||||||
text.text['height'] = 20
|
|
||||||
|
|
||||||
list.listbox.insert(tkinter.tix.END, " 12324 Re: Tkinter is good for your health")
|
|
||||||
list.listbox.insert(tkinter.tix.END, "+ 12325 Re: Tkinter is good for your health")
|
|
||||||
list.listbox.insert(tkinter.tix.END, "+ 12326 Re: Tix is even better for your health (Was: Tkinter is good...)")
|
|
||||||
list.listbox.insert(tkinter.tix.END, " 12327 Re: Tix is even better for your health (Was: Tkinter is good...)")
|
|
||||||
list.listbox.insert(tkinter.tix.END, "+ 12328 Re: Tix is even better for your health (Was: Tkinter is good...)")
|
|
||||||
list.listbox.insert(tkinter.tix.END, " 12329 Re: Tix is even better for your health (Was: Tkinter is good...)")
|
|
||||||
list.listbox.insert(tkinter.tix.END, "+ 12330 Re: Tix is even better for your health (Was: Tkinter is good...)")
|
|
||||||
|
|
||||||
text.text['bg'] = list.listbox['bg']
|
|
||||||
text.text['wrap'] = 'none'
|
|
||||||
text.text.insert(tkinter.tix.END, """
|
|
||||||
Mon, 19 Jun 1995 11:39:52 comp.lang.python Thread 34 of 220
|
|
||||||
Lines 353 A new way to put text and bitmaps together iNo responses
|
|
||||||
ioi@blue.seas.upenn.edu Ioi K. Lam at University of Pennsylvania
|
|
||||||
|
|
||||||
Hi,
|
|
||||||
|
|
||||||
I have implemented a new image type called "compound". It allows you
|
|
||||||
to glue together a bunch of bitmaps, images and text strings together
|
|
||||||
to form a bigger image. Then you can use this image with widgets that
|
|
||||||
support the -image option. For example, you can display a text string string
|
|
||||||
together with a bitmap, at the same time, inside a TK button widget.
|
|
||||||
""")
|
|
||||||
text.text['state'] = 'disabled'
|
|
||||||
|
|
||||||
list.pack(expand=1, fill=tkinter.tix.BOTH, padx=4, pady=6)
|
|
||||||
text.pack(expand=1, fill=tkinter.tix.BOTH, padx=4, pady=6)
|
|
||||||
|
|
||||||
group.pack(side=tkinter.tix.TOP, padx=3, pady=3, fill=tkinter.tix.BOTH)
|
|
||||||
pane.pack(side=tkinter.tix.TOP, padx=3, pady=3, fill=tkinter.tix.BOTH, expand=1)
|
|
||||||
|
|
||||||
box = tkinter.tix.ButtonBox(w, orientation=tkinter.tix.HORIZONTAL)
|
|
||||||
box.add('ok', text='Ok', underline=0, width=6,
|
|
||||||
command=self.quitcmd)
|
|
||||||
box.add('cancel', text='Cancel', underline=0, width=6,
|
|
||||||
command=self.quitcmd)
|
|
||||||
box.pack(side=tkinter.tix.BOTTOM, fill=tkinter.tix.X)
|
|
||||||
|
|
||||||
def quitcmd (self):
|
|
||||||
self.exit = 0
|
|
||||||
|
|
||||||
def mainloop(self):
|
|
||||||
while self.exit < 0:
|
|
||||||
self.root.tk.dooneevent(TCL_ALL_EVENTS)
|
|
||||||
|
|
||||||
def destroy (self):
|
|
||||||
self.root.destroy()
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
root = tkinter.tix.Tk()
|
|
||||||
RunSample(root)
|
|
|
@ -1,57 +0,0 @@
|
||||||
# -*-mode: python; fill-column: 75; tab-width: 8; coding: iso-latin-1-unix -*-
|
|
||||||
#
|
|
||||||
# $Id$
|
|
||||||
#
|
|
||||||
# Tix Demostration Program
|
|
||||||
#
|
|
||||||
# This sample program is structured in such a way so that it can be
|
|
||||||
# executed from the Tix demo program "tixwidgets.py": it must have a
|
|
||||||
# procedure called "RunSample". It should also have the "if" statment
|
|
||||||
# at the end of this file so that it can be run as a standalone
|
|
||||||
# program using tixwish.
|
|
||||||
|
|
||||||
# This file demonstrates the use of the tixPopupMenu widget.
|
|
||||||
#
|
|
||||||
import tkinter.tix
|
|
||||||
|
|
||||||
def RunSample(w):
|
|
||||||
# We create the frame and the button, then we'll bind the PopupMenu
|
|
||||||
# to both widgets. The result is, when you press the right mouse
|
|
||||||
# button over $w.top or $w.top.but, the PopupMenu will come up.
|
|
||||||
#
|
|
||||||
top = tkinter.tix.Frame(w, relief=tkinter.tix.RAISED, bd=1)
|
|
||||||
but = tkinter.tix.Button(top, text='Press the right mouse button over this button or its surrounding area')
|
|
||||||
but.pack(expand=1, fill=tkinter.tix.BOTH, padx=50, pady=50)
|
|
||||||
|
|
||||||
p = tkinter.tix.PopupMenu(top, title='Popup Test')
|
|
||||||
p.bind_widget(top)
|
|
||||||
p.bind_widget(but)
|
|
||||||
|
|
||||||
# Set the entries inside the PopupMenu widget.
|
|
||||||
# [Hint] You have to manipulate the "menu" subwidget.
|
|
||||||
# $w.top.p itself is NOT a menu widget.
|
|
||||||
# [Hint] Watch carefully how the sub-menu is created
|
|
||||||
#
|
|
||||||
p.menu.add_command(label='Desktop', underline=0)
|
|
||||||
p.menu.add_command(label='Select', underline=0)
|
|
||||||
p.menu.add_command(label='Find', underline=0)
|
|
||||||
p.menu.add_command(label='System', underline=1)
|
|
||||||
p.menu.add_command(label='Help', underline=0)
|
|
||||||
m1 = tkinter.tix.Menu(p.menu)
|
|
||||||
m1.add_command(label='Hello')
|
|
||||||
p.menu.add_cascade(label='More', menu=m1)
|
|
||||||
|
|
||||||
but.pack(side=tkinter.tix.TOP, padx=40, pady=50)
|
|
||||||
|
|
||||||
box = tkinter.tix.ButtonBox(w, orientation=tkinter.tix.HORIZONTAL)
|
|
||||||
box.add('ok', text='Ok', underline=0, width=6,
|
|
||||||
command=lambda w=w: w.destroy())
|
|
||||||
box.add('cancel', text='Cancel', underline=0, width=6,
|
|
||||||
command=lambda w=w: w.destroy())
|
|
||||||
box.pack(side=tkinter.tix.BOTTOM, fill=tkinter.tix.X)
|
|
||||||
top.pack(side=tkinter.tix.TOP, fill=tkinter.tix.BOTH, expand=1)
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
root = tkinter.tix.Tk()
|
|
||||||
RunSample(root)
|
|
||||||
root.mainloop()
|
|
|
@ -1,131 +0,0 @@
|
||||||
# -*-mode: python; fill-column: 75; tab-width: 8; coding: iso-latin-1-unix -*-
|
|
||||||
#
|
|
||||||
# $Id$
|
|
||||||
#
|
|
||||||
# Tix Demostration Program
|
|
||||||
#
|
|
||||||
# This sample program is structured in such a way so that it can be
|
|
||||||
# executed from the Tix demo program "tixwidgets.py": it must have a
|
|
||||||
# procedure called "RunSample". It should also have the "if" statment
|
|
||||||
# at the end of this file so that it can be run as a standalone
|
|
||||||
# program using tixwish.
|
|
||||||
|
|
||||||
# This file demonstrates the use of the tixScrolledHList widget.
|
|
||||||
#
|
|
||||||
|
|
||||||
import tkinter.tix
|
|
||||||
|
|
||||||
TCL_ALL_EVENTS = 0
|
|
||||||
|
|
||||||
def RunSample (root):
|
|
||||||
shlist = DemoSHList(root)
|
|
||||||
shlist.mainloop()
|
|
||||||
shlist.destroy()
|
|
||||||
|
|
||||||
class DemoSHList:
|
|
||||||
def __init__(self, w):
|
|
||||||
self.root = w
|
|
||||||
self.exit = -1
|
|
||||||
|
|
||||||
z = w.winfo_toplevel()
|
|
||||||
z.wm_protocol("WM_DELETE_WINDOW", lambda self=self: self.quitcmd())
|
|
||||||
|
|
||||||
# We create the frame and the ScrolledHList widget
|
|
||||||
# at the top of the dialog box
|
|
||||||
#
|
|
||||||
top = tkinter.tix.Frame( w, relief=tkinter.tix.RAISED, bd=1)
|
|
||||||
|
|
||||||
# Put a simple hierachy into the HList (two levels). Use colors and
|
|
||||||
# separator widgets (frames) to make the list look fancy
|
|
||||||
#
|
|
||||||
top.a = tkinter.tix.ScrolledHList(top)
|
|
||||||
top.a.pack( expand=1, fill=tkinter.tix.BOTH, padx=10, pady=10, side=tkinter.tix.TOP)
|
|
||||||
|
|
||||||
# This is our little relational database
|
|
||||||
#
|
|
||||||
bosses = [
|
|
||||||
('jeff', 'Jeff Waxman'),
|
|
||||||
('john', 'John Lee'),
|
|
||||||
('peter', 'Peter Kenson')
|
|
||||||
]
|
|
||||||
|
|
||||||
employees = [
|
|
||||||
('alex', 'john', 'Alex Kellman'),
|
|
||||||
('alan', 'john', 'Alan Adams'),
|
|
||||||
('andy', 'peter', 'Andreas Crawford'),
|
|
||||||
('doug', 'jeff', 'Douglas Bloom'),
|
|
||||||
('jon', 'peter', 'Jon Baraki'),
|
|
||||||
('chris', 'jeff', 'Chris Geoffrey'),
|
|
||||||
('chuck', 'jeff', 'Chuck McLean')
|
|
||||||
]
|
|
||||||
|
|
||||||
hlist=top.a.hlist
|
|
||||||
|
|
||||||
# Let configure the appearance of the HList subwidget
|
|
||||||
#
|
|
||||||
hlist.config( separator='.', width=25, drawbranch=0, indent=10)
|
|
||||||
|
|
||||||
count=0
|
|
||||||
for boss,name in bosses :
|
|
||||||
if count :
|
|
||||||
f=tkinter.tix.Frame(hlist, name='sep%d' % count, height=2, width=150,
|
|
||||||
bd=2, relief=tkinter.tix.SUNKEN )
|
|
||||||
|
|
||||||
hlist.add_child( itemtype=tkinter.tix.WINDOW,
|
|
||||||
window=f, state=tkinter.tix.DISABLED )
|
|
||||||
|
|
||||||
hlist.add(boss, itemtype=tkinter.tix.TEXT, text=name)
|
|
||||||
count = count+1
|
|
||||||
|
|
||||||
|
|
||||||
for person,boss,name in employees :
|
|
||||||
# '.' is the separator character we chose above
|
|
||||||
#
|
|
||||||
key= boss + '.' + person
|
|
||||||
# ^^^^ ^^^^^^
|
|
||||||
# parent entryPath / child's name
|
|
||||||
|
|
||||||
hlist.add( key, text=name )
|
|
||||||
|
|
||||||
# [Hint] Make sure the keys (e.g. 'boss.person') you choose
|
|
||||||
# are unique names. If you cannot be sure of this (because of
|
|
||||||
# the structure of your database, e.g.) you can use the
|
|
||||||
# "add_child" command instead:
|
|
||||||
#
|
|
||||||
# hlist.addchild( boss, text=name)
|
|
||||||
# ^^^^
|
|
||||||
# parent entryPath
|
|
||||||
|
|
||||||
|
|
||||||
# Use a ButtonBox to hold the buttons.
|
|
||||||
#
|
|
||||||
box= tkinter.tix.ButtonBox(top, orientation=tkinter.tix.HORIZONTAL )
|
|
||||||
box.add( 'ok', text='Ok', underline=0, width=6,
|
|
||||||
command = self.okcmd)
|
|
||||||
|
|
||||||
box.add( 'cancel', text='Cancel', underline=0, width=6,
|
|
||||||
command = self.quitcmd)
|
|
||||||
|
|
||||||
box.pack( side=tkinter.tix.BOTTOM, fill=tkinter.tix.X)
|
|
||||||
top.pack( side=tkinter.tix.TOP, fill=tkinter.tix.BOTH, expand=1 )
|
|
||||||
|
|
||||||
def okcmd (self):
|
|
||||||
self.quitcmd()
|
|
||||||
|
|
||||||
def quitcmd (self):
|
|
||||||
self.exit = 0
|
|
||||||
|
|
||||||
def mainloop(self):
|
|
||||||
while self.exit < 0:
|
|
||||||
self.root.tk.dooneevent(TCL_ALL_EVENTS)
|
|
||||||
|
|
||||||
def destroy (self):
|
|
||||||
self.root.destroy()
|
|
||||||
|
|
||||||
|
|
||||||
# This "if" statement makes it possible to run this script file inside or
|
|
||||||
# outside of the main demo program "tixwidgets.py".
|
|
||||||
#
|
|
||||||
if __name__== '__main__' :
|
|
||||||
root=tkinter.tix.Tk()
|
|
||||||
RunSample(root)
|
|
|
@ -1,168 +0,0 @@
|
||||||
# -*-mode: python; fill-column: 75; tab-width: 8; coding: iso-latin-1-unix -*-
|
|
||||||
#
|
|
||||||
# $Id$
|
|
||||||
#
|
|
||||||
# Tix Demostration Program
|
|
||||||
#
|
|
||||||
# This sample program is structured in such a way so that it can be
|
|
||||||
# executed from the Tix demo program "tixwidget": it must have a
|
|
||||||
# procedure called "RunSample". It should also have the "if" statment
|
|
||||||
# at the end of this file so that it can be run as a standalone
|
|
||||||
# program using tixwish.
|
|
||||||
|
|
||||||
# This file demonstrates how to use multiple columns and multiple styles
|
|
||||||
# in the tixHList widget
|
|
||||||
#
|
|
||||||
# In a tixHList widget, you can have one ore more columns.
|
|
||||||
#
|
|
||||||
|
|
||||||
import tkinter.tix
|
|
||||||
|
|
||||||
TCL_ALL_EVENTS = 0
|
|
||||||
|
|
||||||
def RunSample (root):
|
|
||||||
shlist = DemoSHList(root)
|
|
||||||
shlist.mainloop()
|
|
||||||
shlist.destroy()
|
|
||||||
|
|
||||||
class DemoSHList:
|
|
||||||
def __init__(self, w):
|
|
||||||
self.root = w
|
|
||||||
self.exit = -1
|
|
||||||
|
|
||||||
z = w.winfo_toplevel()
|
|
||||||
z.wm_protocol("WM_DELETE_WINDOW", lambda self=self: self.quitcmd())
|
|
||||||
|
|
||||||
# We create the frame and the ScrolledHList widget
|
|
||||||
# at the top of the dialog box
|
|
||||||
#
|
|
||||||
top = tkinter.tix.Frame( w, relief=tkinter.tix.RAISED, bd=1)
|
|
||||||
|
|
||||||
# Put a simple hierachy into the HList (two levels). Use colors and
|
|
||||||
# separator widgets (frames) to make the list look fancy
|
|
||||||
#
|
|
||||||
top.a = tkinter.tix.ScrolledHList(top, options='hlist.columns 3 hlist.header 1' )
|
|
||||||
top.a.pack( expand=1, fill=tkinter.tix.BOTH, padx=10, pady=10, side=tkinter.tix.TOP)
|
|
||||||
|
|
||||||
hlist=top.a.hlist
|
|
||||||
|
|
||||||
# Create the title for the HList widget
|
|
||||||
# >> Notice that we have set the hlist.header subwidget option to true
|
|
||||||
# so that the header is displayed
|
|
||||||
#
|
|
||||||
|
|
||||||
boldfont=hlist.tk.call('tix','option','get','bold_font')
|
|
||||||
|
|
||||||
# First some styles for the headers
|
|
||||||
style={}
|
|
||||||
style['header'] = tkinter.tix.DisplayStyle(tkinter.tix.TEXT, refwindow=hlist,
|
|
||||||
anchor=tkinter.tix.CENTER, padx=8, pady=2, font = boldfont )
|
|
||||||
|
|
||||||
hlist.header_create(0, itemtype=tkinter.tix.TEXT, text='Name',
|
|
||||||
style=style['header'])
|
|
||||||
hlist.header_create(1, itemtype=tkinter.tix.TEXT, text='Position',
|
|
||||||
style=style['header'])
|
|
||||||
|
|
||||||
# Notice that we use 3 columns in the hlist widget. This way when the user
|
|
||||||
# expands the windows wide, the right side of the header doesn't look
|
|
||||||
# chopped off. The following line ensures that the 3 column header is
|
|
||||||
# not shown unless the hlist window is wider than its contents.
|
|
||||||
#
|
|
||||||
hlist.column_width(2,0)
|
|
||||||
|
|
||||||
# This is our little relational database
|
|
||||||
#
|
|
||||||
boss = ('doe', 'John Doe', 'Director')
|
|
||||||
|
|
||||||
managers = [
|
|
||||||
('jeff', 'Jeff Waxman', 'Manager'),
|
|
||||||
('john', 'John Lee', 'Manager'),
|
|
||||||
('peter', 'Peter Kenson', 'Manager')
|
|
||||||
]
|
|
||||||
|
|
||||||
employees = [
|
|
||||||
('alex', 'john', 'Alex Kellman', 'Clerk'),
|
|
||||||
('alan', 'john', 'Alan Adams', 'Clerk'),
|
|
||||||
('andy', 'peter', 'Andreas Crawford', 'Salesman'),
|
|
||||||
('doug', 'jeff', 'Douglas Bloom', 'Clerk'),
|
|
||||||
('jon', 'peter', 'Jon Baraki', 'Salesman'),
|
|
||||||
('chris', 'jeff', 'Chris Geoffrey', 'Clerk'),
|
|
||||||
('chuck', 'jeff', 'Chuck McLean', 'Cleaner')
|
|
||||||
]
|
|
||||||
|
|
||||||
style['mgr_name'] = tkinter.tix.DisplayStyle(tkinter.tix.TEXT, refwindow=hlist)
|
|
||||||
|
|
||||||
style['mgr_posn'] = tkinter.tix.DisplayStyle(tkinter.tix.TEXT, padx=8, refwindow=hlist)
|
|
||||||
|
|
||||||
style['empl_name'] = tkinter.tix.DisplayStyle(tkinter.tix.TEXT, refwindow=hlist)
|
|
||||||
|
|
||||||
style['empl_posn'] = tkinter.tix.DisplayStyle(tkinter.tix.TEXT, padx=8, refwindow=hlist)
|
|
||||||
|
|
||||||
# Let configure the appearance of the HList subwidget
|
|
||||||
#
|
|
||||||
hlist.config(separator='.', width=25, drawbranch=0, indent=10)
|
|
||||||
hlist.column_width(0, chars=20)
|
|
||||||
|
|
||||||
# Create the boss
|
|
||||||
#
|
|
||||||
hlist.add ('.', itemtype=tkinter.tix.TEXT, text=boss[1],
|
|
||||||
style=style['mgr_name'])
|
|
||||||
hlist.item_create('.', 1, itemtype=tkinter.tix.TEXT, text=boss[2],
|
|
||||||
style=style['mgr_posn'])
|
|
||||||
|
|
||||||
# Create the managers
|
|
||||||
#
|
|
||||||
|
|
||||||
for key,name,posn in managers :
|
|
||||||
e= '.'+ key
|
|
||||||
hlist.add(e, itemtype=tkinter.tix.TEXT, text=name,
|
|
||||||
style=style['mgr_name'])
|
|
||||||
hlist.item_create(e, 1, itemtype=tkinter.tix.TEXT, text=posn,
|
|
||||||
style=style['mgr_posn'])
|
|
||||||
|
|
||||||
|
|
||||||
for key,mgr,name,posn in employees :
|
|
||||||
# "." is the separator character we chose above
|
|
||||||
|
|
||||||
entrypath = '.' + mgr + '.' + key
|
|
||||||
|
|
||||||
# ^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^
|
|
||||||
# parent entryPath / child's name
|
|
||||||
|
|
||||||
hlist.add(entrypath, text=name, style=style['empl_name'])
|
|
||||||
hlist.item_create(entrypath, 1, itemtype=tkinter.tix.TEXT,
|
|
||||||
text = posn, style = style['empl_posn'] )
|
|
||||||
|
|
||||||
|
|
||||||
# Use a ButtonBox to hold the buttons.
|
|
||||||
#
|
|
||||||
box= tkinter.tix.ButtonBox(top, orientation=tkinter.tix.HORIZONTAL )
|
|
||||||
box.add( 'ok', text='Ok', underline=0, width=6,
|
|
||||||
command = self.okcmd )
|
|
||||||
|
|
||||||
box.add( 'cancel', text='Cancel', underline=0, width=6,
|
|
||||||
command = self.quitcmd )
|
|
||||||
|
|
||||||
box.pack( side=tkinter.tix.BOTTOM, fill=tkinter.tix.X)
|
|
||||||
top.pack( side=tkinter.tix.TOP, fill=tkinter.tix.BOTH, expand=1 )
|
|
||||||
|
|
||||||
def okcmd (self):
|
|
||||||
self.quitcmd()
|
|
||||||
|
|
||||||
def quitcmd (self):
|
|
||||||
self.exit = 0
|
|
||||||
|
|
||||||
def mainloop(self):
|
|
||||||
while self.exit < 0:
|
|
||||||
self.root.tk.dooneevent(TCL_ALL_EVENTS)
|
|
||||||
|
|
||||||
def destroy (self):
|
|
||||||
self.root.destroy()
|
|
||||||
|
|
||||||
|
|
||||||
# This "if" statement makes it possible to run this script file inside or
|
|
||||||
# outside of the main demo program "tixwidgets.py".
|
|
||||||
#
|
|
||||||
if __name__== '__main__' :
|
|
||||||
root=tkinter.tix.Tk()
|
|
||||||
RunSample(root)
|
|
|
@ -1,80 +0,0 @@
|
||||||
# -*-mode: python; fill-column: 75; tab-width: 8; coding: iso-latin-1-unix -*-
|
|
||||||
#
|
|
||||||
# $Id$
|
|
||||||
#
|
|
||||||
# Tix Demostration Program
|
|
||||||
#
|
|
||||||
# This sample program is structured in such a way so that it can be
|
|
||||||
# executed from the Tix demo program "tixwidgets.py": it must have a
|
|
||||||
# procedure called "RunSample". It should also have the "if" statment
|
|
||||||
# at the end of this file so that it can be run as a standalone
|
|
||||||
# program.
|
|
||||||
|
|
||||||
# This file demonstrates how to use the TixTree widget to display
|
|
||||||
# dynamic hierachical data (the files in the Unix file system)
|
|
||||||
#
|
|
||||||
|
|
||||||
import tkinter.tix, os
|
|
||||||
|
|
||||||
def RunSample(w):
|
|
||||||
top = tkinter.tix.Frame(w, relief=tkinter.tix.RAISED, bd=1)
|
|
||||||
tree = tkinter.tix.Tree(top, options='separator "/"')
|
|
||||||
tree.pack(expand=1, fill=tkinter.tix.BOTH, padx=10, pady=10, side=tkinter.tix.LEFT)
|
|
||||||
tree['opencmd'] = lambda dir=None, w=tree: opendir(w, dir)
|
|
||||||
|
|
||||||
# The / directory is added in the "open" mode. The user can open it
|
|
||||||
# and then browse its subdirectories ...
|
|
||||||
adddir(tree, "/")
|
|
||||||
|
|
||||||
box = tkinter.tix.ButtonBox(w, orientation=tkinter.tix.HORIZONTAL)
|
|
||||||
box.add('ok', text='Ok', underline=0, command=w.destroy, width=6)
|
|
||||||
box.add('cancel', text='Cancel', underline=0, command=w.destroy, width=6)
|
|
||||||
box.pack(side=tkinter.tix.BOTTOM, fill=tkinter.tix.X)
|
|
||||||
top.pack(side=tkinter.tix.TOP, fill=tkinter.tix.BOTH, expand=1)
|
|
||||||
|
|
||||||
def adddir(tree, dir):
|
|
||||||
if dir == '/':
|
|
||||||
text = '/'
|
|
||||||
else:
|
|
||||||
text = os.path.basename(dir)
|
|
||||||
tree.hlist.add(dir, itemtype=tkinter.tix.IMAGETEXT, text=text,
|
|
||||||
image=tree.tk.call('tix', 'getimage', 'folder'))
|
|
||||||
try:
|
|
||||||
os.listdir(dir)
|
|
||||||
tree.setmode(dir, 'open')
|
|
||||||
except os.error:
|
|
||||||
# No read permission ?
|
|
||||||
pass
|
|
||||||
|
|
||||||
# This function is called whenever the user presses the (+) indicator or
|
|
||||||
# double clicks on a directory whose mode is "open". It loads the files
|
|
||||||
# inside that directory into the Tree widget.
|
|
||||||
#
|
|
||||||
# Note we didn't specify the closecmd option for the Tree widget, so it
|
|
||||||
# performs the default action when the user presses the (-) indicator or
|
|
||||||
# double clicks on a directory whose mode is "close": hide all of its child
|
|
||||||
# entries
|
|
||||||
def opendir(tree, dir):
|
|
||||||
entries = tree.hlist.info_children(dir)
|
|
||||||
if entries:
|
|
||||||
# We have already loaded this directory. Let's just
|
|
||||||
# show all the child entries
|
|
||||||
#
|
|
||||||
# Note: since we load the directory only once, it will not be
|
|
||||||
# refreshed if the you add or remove files from this
|
|
||||||
# directory.
|
|
||||||
#
|
|
||||||
for entry in entries:
|
|
||||||
tree.hlist.show_entry(entry)
|
|
||||||
files = os.listdir(dir)
|
|
||||||
for file in files:
|
|
||||||
if os.path.isdir(dir + '/' + file):
|
|
||||||
adddir(tree, dir + '/' + file)
|
|
||||||
else:
|
|
||||||
tree.hlist.add(dir + '/' + file, itemtype=tkinter.tix.IMAGETEXT, text=file,
|
|
||||||
image=tree.tk.call('tix', 'getimage', 'file'))
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
root = tkinter.tix.Tk()
|
|
||||||
RunSample(root)
|
|
||||||
root.mainloop()
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,11 +0,0 @@
|
||||||
Several collections of example code for Tkinter.
|
|
||||||
|
|
||||||
See the toplevel README for an explanation of the difference between
|
|
||||||
Tkinter and _tkinter, how to enable the Python Tk interface, and where
|
|
||||||
to get Matt Conway's lifesaver document.
|
|
||||||
|
|
||||||
Subdirectories:
|
|
||||||
|
|
||||||
guido my original example set (fairly random collection)
|
|
||||||
matt Matt Conway's examples, to go with his lifesaver document
|
|
||||||
ttk Examples using the ttk module
|
|
|
@ -1,460 +0,0 @@
|
||||||
|
|
||||||
# The options of a widget are described by the following attributes
|
|
||||||
# of the Pack and Widget dialogs:
|
|
||||||
#
|
|
||||||
# Dialog.current: {name: value}
|
|
||||||
# -- changes during Widget's lifetime
|
|
||||||
#
|
|
||||||
# Dialog.options: {name: (default, klass)}
|
|
||||||
# -- depends on widget class only
|
|
||||||
#
|
|
||||||
# Dialog.classes: {klass: (v0, v1, v2, ...) | 'boolean' | 'other'}
|
|
||||||
# -- totally static, though different between PackDialog and WidgetDialog
|
|
||||||
# (but even that could be unified)
|
|
||||||
|
|
||||||
from tkinter import *
|
|
||||||
|
|
||||||
|
|
||||||
class Option:
|
|
||||||
|
|
||||||
varclass = StringVar # May be overridden
|
|
||||||
|
|
||||||
def __init__(self, dialog, option):
|
|
||||||
self.dialog = dialog
|
|
||||||
self.option = option
|
|
||||||
self.master = dialog.top
|
|
||||||
self.default, self.klass = dialog.options[option]
|
|
||||||
self.var = self.varclass(self.master)
|
|
||||||
self.frame = Frame(self.master)
|
|
||||||
self.frame.pack(fill=X)
|
|
||||||
self.label = Label(self.frame, text=(option + ":"))
|
|
||||||
self.label.pack(side=LEFT)
|
|
||||||
self.update()
|
|
||||||
self.addoption()
|
|
||||||
|
|
||||||
def refresh(self):
|
|
||||||
self.dialog.refresh()
|
|
||||||
self.update()
|
|
||||||
|
|
||||||
def update(self):
|
|
||||||
try:
|
|
||||||
self.current = self.dialog.current[self.option]
|
|
||||||
except KeyError:
|
|
||||||
self.current = self.default
|
|
||||||
self.var.set(self.current)
|
|
||||||
|
|
||||||
def set(self, e=None): # Should be overridden
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class BooleanOption(Option):
|
|
||||||
|
|
||||||
varclass = BooleanVar
|
|
||||||
|
|
||||||
def addoption(self):
|
|
||||||
self.button = Checkbutton(self.frame,
|
|
||||||
text='on/off',
|
|
||||||
onvalue=1,
|
|
||||||
offvalue=0,
|
|
||||||
variable=self.var,
|
|
||||||
relief=RAISED,
|
|
||||||
borderwidth=2,
|
|
||||||
command=self.set)
|
|
||||||
self.button.pack(side=RIGHT)
|
|
||||||
|
|
||||||
|
|
||||||
class EnumOption(Option):
|
|
||||||
|
|
||||||
def addoption(self):
|
|
||||||
self.button = Menubutton(self.frame,
|
|
||||||
textvariable=self.var,
|
|
||||||
relief=RAISED, borderwidth=2)
|
|
||||||
self.button.pack(side=RIGHT)
|
|
||||||
self.menu = Menu(self.button)
|
|
||||||
self.button['menu'] = self.menu
|
|
||||||
for v in self.dialog.classes[self.klass]:
|
|
||||||
self.menu.add_radiobutton(
|
|
||||||
label=v,
|
|
||||||
variable=self.var,
|
|
||||||
value=v,
|
|
||||||
command=self.set)
|
|
||||||
|
|
||||||
|
|
||||||
class StringOption(Option):
|
|
||||||
|
|
||||||
def addoption(self):
|
|
||||||
self.entry = Entry(self.frame,
|
|
||||||
textvariable=self.var,
|
|
||||||
width=10,
|
|
||||||
relief=SUNKEN,
|
|
||||||
borderwidth=2)
|
|
||||||
self.entry.pack(side=RIGHT, fill=X, expand=1)
|
|
||||||
self.entry.bind('<Return>', self.set)
|
|
||||||
|
|
||||||
|
|
||||||
class ReadonlyOption(Option):
|
|
||||||
|
|
||||||
def addoption(self):
|
|
||||||
self.label = Label(self.frame, textvariable=self.var,
|
|
||||||
anchor=E)
|
|
||||||
self.label.pack(side=RIGHT)
|
|
||||||
|
|
||||||
|
|
||||||
class Dialog:
|
|
||||||
|
|
||||||
def __init__(self, master):
|
|
||||||
self.master = master
|
|
||||||
self.fixclasses()
|
|
||||||
self.refresh()
|
|
||||||
self.top = Toplevel(self.master)
|
|
||||||
self.top.title(self.__class__.__name__)
|
|
||||||
self.top.minsize(1, 1)
|
|
||||||
self.addchoices()
|
|
||||||
|
|
||||||
def refresh(self): pass # Must override
|
|
||||||
|
|
||||||
def fixclasses(self): pass # May override
|
|
||||||
|
|
||||||
def addchoices(self):
|
|
||||||
self.choices = {}
|
|
||||||
list = []
|
|
||||||
for k, dc in self.options.items():
|
|
||||||
list.append((k, dc))
|
|
||||||
list.sort()
|
|
||||||
for k, (d, c) in list:
|
|
||||||
try:
|
|
||||||
cl = self.classes[c]
|
|
||||||
except KeyError:
|
|
||||||
cl = 'unknown'
|
|
||||||
if type(cl) is tuple:
|
|
||||||
cl = self.enumoption
|
|
||||||
elif cl == 'boolean':
|
|
||||||
cl = self.booleanoption
|
|
||||||
elif cl == 'readonly':
|
|
||||||
cl = self.readonlyoption
|
|
||||||
else:
|
|
||||||
cl = self.stringoption
|
|
||||||
self.choices[k] = cl(self, k)
|
|
||||||
|
|
||||||
# Must override:
|
|
||||||
options = {}
|
|
||||||
classes = {}
|
|
||||||
|
|
||||||
# May override:
|
|
||||||
booleanoption = BooleanOption
|
|
||||||
stringoption = StringOption
|
|
||||||
enumoption = EnumOption
|
|
||||||
readonlyoption = ReadonlyOption
|
|
||||||
|
|
||||||
|
|
||||||
class PackDialog(Dialog):
|
|
||||||
|
|
||||||
def __init__(self, widget):
|
|
||||||
self.widget = widget
|
|
||||||
Dialog.__init__(self, widget)
|
|
||||||
|
|
||||||
def refresh(self):
|
|
||||||
self.current = self.widget.info()
|
|
||||||
self.current['.class'] = self.widget.winfo_class()
|
|
||||||
self.current['.name'] = self.widget._w
|
|
||||||
|
|
||||||
class packoption: # Mix-in class
|
|
||||||
def set(self, e=None):
|
|
||||||
self.current = self.var.get()
|
|
||||||
try:
|
|
||||||
self.dialog.widget.pack(**{self.option: self.current})
|
|
||||||
except TclError as msg:
|
|
||||||
print(msg)
|
|
||||||
self.refresh()
|
|
||||||
|
|
||||||
class booleanoption(packoption, BooleanOption): pass
|
|
||||||
class enumoption(packoption, EnumOption): pass
|
|
||||||
class stringoption(packoption, StringOption): pass
|
|
||||||
class readonlyoption(packoption, ReadonlyOption): pass
|
|
||||||
|
|
||||||
options = {
|
|
||||||
'.class': (None, 'Class'),
|
|
||||||
'.name': (None, 'Name'),
|
|
||||||
'after': (None, 'Widget'),
|
|
||||||
'anchor': ('center', 'Anchor'),
|
|
||||||
'before': (None, 'Widget'),
|
|
||||||
'expand': ('no', 'Boolean'),
|
|
||||||
'fill': ('none', 'Fill'),
|
|
||||||
'in': (None, 'Widget'),
|
|
||||||
'ipadx': (0, 'Pad'),
|
|
||||||
'ipady': (0, 'Pad'),
|
|
||||||
'padx': (0, 'Pad'),
|
|
||||||
'pady': (0, 'Pad'),
|
|
||||||
'side': ('top', 'Side'),
|
|
||||||
}
|
|
||||||
|
|
||||||
classes = {
|
|
||||||
'Anchor': (N, NE, E, SE, S, SW, W, NW, CENTER),
|
|
||||||
'Boolean': 'boolean',
|
|
||||||
'Class': 'readonly',
|
|
||||||
'Expand': 'boolean',
|
|
||||||
'Fill': (NONE, X, Y, BOTH),
|
|
||||||
'Name': 'readonly',
|
|
||||||
'Pad': 'pixel',
|
|
||||||
'Side': (TOP, RIGHT, BOTTOM, LEFT),
|
|
||||||
'Widget': 'readonly',
|
|
||||||
}
|
|
||||||
|
|
||||||
class RemotePackDialog(PackDialog):
|
|
||||||
|
|
||||||
def __init__(self, master, app, widget):
|
|
||||||
self.master = master
|
|
||||||
self.app = app
|
|
||||||
self.widget = widget
|
|
||||||
self.refresh()
|
|
||||||
self.top = Toplevel(self.master)
|
|
||||||
self.top.title(self.app + ' PackDialog')
|
|
||||||
self.top.minsize(1, 1)
|
|
||||||
self.addchoices()
|
|
||||||
|
|
||||||
def refresh(self):
|
|
||||||
try:
|
|
||||||
words = self.master.tk.splitlist(
|
|
||||||
self.master.send(self.app,
|
|
||||||
'pack',
|
|
||||||
'info',
|
|
||||||
self.widget))
|
|
||||||
except TclError as msg:
|
|
||||||
print(msg)
|
|
||||||
return
|
|
||||||
dict = {}
|
|
||||||
for i in range(0, len(words), 2):
|
|
||||||
key = words[i][1:]
|
|
||||||
value = words[i+1]
|
|
||||||
dict[key] = value
|
|
||||||
dict['.class'] = self.master.send(self.app,
|
|
||||||
'winfo',
|
|
||||||
'class',
|
|
||||||
self.widget)
|
|
||||||
dict['.name'] = self.widget
|
|
||||||
self.current = dict
|
|
||||||
|
|
||||||
class remotepackoption: # Mix-in class
|
|
||||||
def set(self, e=None):
|
|
||||||
self.current = self.var.get()
|
|
||||||
try:
|
|
||||||
self.dialog.master.send(
|
|
||||||
self.dialog.app,
|
|
||||||
'pack',
|
|
||||||
'config',
|
|
||||||
self.dialog.widget,
|
|
||||||
'-'+self.option,
|
|
||||||
self.dialog.master.tk.merge(
|
|
||||||
self.current))
|
|
||||||
except TclError as msg:
|
|
||||||
print(msg)
|
|
||||||
self.refresh()
|
|
||||||
|
|
||||||
class booleanoption(remotepackoption, BooleanOption): pass
|
|
||||||
class enumoption(remotepackoption, EnumOption): pass
|
|
||||||
class stringoption(remotepackoption, StringOption): pass
|
|
||||||
class readonlyoption(remotepackoption, ReadonlyOption): pass
|
|
||||||
|
|
||||||
|
|
||||||
class WidgetDialog(Dialog):
|
|
||||||
|
|
||||||
def __init__(self, widget):
|
|
||||||
self.widget = widget
|
|
||||||
self.klass = widget.winfo_class()
|
|
||||||
Dialog.__init__(self, widget)
|
|
||||||
|
|
||||||
def fixclasses(self):
|
|
||||||
if self.klass in self.addclasses:
|
|
||||||
classes = {}
|
|
||||||
for c in (self.classes,
|
|
||||||
self.addclasses[self.klass]):
|
|
||||||
for k in c.keys():
|
|
||||||
classes[k] = c[k]
|
|
||||||
self.classes = classes
|
|
||||||
|
|
||||||
def refresh(self):
|
|
||||||
self.configuration = self.widget.config()
|
|
||||||
self.update()
|
|
||||||
self.current['.class'] = self.widget.winfo_class()
|
|
||||||
self.current['.name'] = self.widget._w
|
|
||||||
|
|
||||||
def update(self):
|
|
||||||
self.current = {}
|
|
||||||
self.options = {}
|
|
||||||
for k, v in self.configuration.items():
|
|
||||||
if len(v) > 4:
|
|
||||||
self.current[k] = v[4]
|
|
||||||
self.options[k] = v[3], v[2] # default, klass
|
|
||||||
self.options['.class'] = (None, 'Class')
|
|
||||||
self.options['.name'] = (None, 'Name')
|
|
||||||
|
|
||||||
class widgetoption: # Mix-in class
|
|
||||||
def set(self, e=None):
|
|
||||||
self.current = self.var.get()
|
|
||||||
try:
|
|
||||||
self.dialog.widget[self.option] = self.current
|
|
||||||
except TclError as msg:
|
|
||||||
print(msg)
|
|
||||||
self.refresh()
|
|
||||||
|
|
||||||
class booleanoption(widgetoption, BooleanOption): pass
|
|
||||||
class enumoption(widgetoption, EnumOption): pass
|
|
||||||
class stringoption(widgetoption, StringOption): pass
|
|
||||||
class readonlyoption(widgetoption, ReadonlyOption): pass
|
|
||||||
|
|
||||||
# Universal classes
|
|
||||||
classes = {
|
|
||||||
'Anchor': (N, NE, E, SE, S, SW, W, NW, CENTER),
|
|
||||||
'Aspect': 'integer',
|
|
||||||
'Background': 'color',
|
|
||||||
'Bitmap': 'bitmap',
|
|
||||||
'BorderWidth': 'pixel',
|
|
||||||
'Class': 'readonly',
|
|
||||||
'CloseEnough': 'double',
|
|
||||||
'Command': 'command',
|
|
||||||
'Confine': 'boolean',
|
|
||||||
'Cursor': 'cursor',
|
|
||||||
'CursorWidth': 'pixel',
|
|
||||||
'DisabledForeground': 'color',
|
|
||||||
'ExportSelection': 'boolean',
|
|
||||||
'Font': 'font',
|
|
||||||
'Foreground': 'color',
|
|
||||||
'From': 'integer',
|
|
||||||
'Geometry': 'geometry',
|
|
||||||
'Height': 'pixel',
|
|
||||||
'InsertWidth': 'time',
|
|
||||||
'Justify': (LEFT, CENTER, RIGHT),
|
|
||||||
'Label': 'string',
|
|
||||||
'Length': 'pixel',
|
|
||||||
'MenuName': 'widget',
|
|
||||||
'Name': 'readonly',
|
|
||||||
'OffTime': 'time',
|
|
||||||
'OnTime': 'time',
|
|
||||||
'Orient': (HORIZONTAL, VERTICAL),
|
|
||||||
'Pad': 'pixel',
|
|
||||||
'Relief': (RAISED, SUNKEN, FLAT, RIDGE, GROOVE),
|
|
||||||
'RepeatDelay': 'time',
|
|
||||||
'RepeatInterval': 'time',
|
|
||||||
'ScrollCommand': 'command',
|
|
||||||
'ScrollIncrement': 'pixel',
|
|
||||||
'ScrollRegion': 'rectangle',
|
|
||||||
'ShowValue': 'boolean',
|
|
||||||
'SetGrid': 'boolean',
|
|
||||||
'Sliderforeground': 'color',
|
|
||||||
'SliderLength': 'pixel',
|
|
||||||
'Text': 'string',
|
|
||||||
'TickInterval': 'integer',
|
|
||||||
'To': 'integer',
|
|
||||||
'Underline': 'index',
|
|
||||||
'Variable': 'variable',
|
|
||||||
'Value': 'string',
|
|
||||||
'Width': 'pixel',
|
|
||||||
'Wrap': (NONE, CHAR, WORD),
|
|
||||||
}
|
|
||||||
|
|
||||||
# Classes that (may) differ per widget type
|
|
||||||
_tristate = {'State': (NORMAL, ACTIVE, DISABLED)}
|
|
||||||
_bistate = {'State': (NORMAL, DISABLED)}
|
|
||||||
addclasses = {
|
|
||||||
'Button': _tristate,
|
|
||||||
'Radiobutton': _tristate,
|
|
||||||
'Checkbutton': _tristate,
|
|
||||||
'Entry': _bistate,
|
|
||||||
'Text': _bistate,
|
|
||||||
'Menubutton': _tristate,
|
|
||||||
'Slider': _bistate,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class RemoteWidgetDialog(WidgetDialog):
|
|
||||||
|
|
||||||
def __init__(self, master, app, widget):
|
|
||||||
self.app = app
|
|
||||||
self.widget = widget
|
|
||||||
self.klass = master.send(self.app,
|
|
||||||
'winfo',
|
|
||||||
'class',
|
|
||||||
self.widget)
|
|
||||||
Dialog.__init__(self, master)
|
|
||||||
|
|
||||||
def refresh(self):
|
|
||||||
try:
|
|
||||||
items = self.master.tk.splitlist(
|
|
||||||
self.master.send(self.app,
|
|
||||||
self.widget,
|
|
||||||
'config'))
|
|
||||||
except TclError as msg:
|
|
||||||
print(msg)
|
|
||||||
return
|
|
||||||
dict = {}
|
|
||||||
for item in items:
|
|
||||||
words = self.master.tk.splitlist(item)
|
|
||||||
key = words[0][1:]
|
|
||||||
value = (key,) + words[1:]
|
|
||||||
dict[key] = value
|
|
||||||
self.configuration = dict
|
|
||||||
self.update()
|
|
||||||
self.current['.class'] = self.klass
|
|
||||||
self.current['.name'] = self.widget
|
|
||||||
|
|
||||||
class remotewidgetoption: # Mix-in class
|
|
||||||
def set(self, e=None):
|
|
||||||
self.current = self.var.get()
|
|
||||||
try:
|
|
||||||
self.dialog.master.send(
|
|
||||||
self.dialog.app,
|
|
||||||
self.dialog.widget,
|
|
||||||
'config',
|
|
||||||
'-'+self.option,
|
|
||||||
self.current)
|
|
||||||
except TclError as msg:
|
|
||||||
print(msg)
|
|
||||||
self.refresh()
|
|
||||||
|
|
||||||
class booleanoption(remotewidgetoption, BooleanOption): pass
|
|
||||||
class enumoption(remotewidgetoption, EnumOption): pass
|
|
||||||
class stringoption(remotewidgetoption, StringOption): pass
|
|
||||||
class readonlyoption(remotewidgetoption, ReadonlyOption): pass
|
|
||||||
|
|
||||||
|
|
||||||
def test():
|
|
||||||
import sys
|
|
||||||
root = Tk()
|
|
||||||
root.minsize(1, 1)
|
|
||||||
if sys.argv[1:]:
|
|
||||||
remotetest(root, sys.argv[1])
|
|
||||||
else:
|
|
||||||
frame = Frame(root, name='frame')
|
|
||||||
frame.pack(expand=1, fill=BOTH)
|
|
||||||
button = Button(frame, name='button', text='button')
|
|
||||||
button.pack(expand=1)
|
|
||||||
canvas = Canvas(frame, name='canvas')
|
|
||||||
canvas.pack()
|
|
||||||
fpd = PackDialog(frame)
|
|
||||||
fwd = WidgetDialog(frame)
|
|
||||||
bpd = PackDialog(button)
|
|
||||||
bwd = WidgetDialog(button)
|
|
||||||
cpd = PackDialog(canvas)
|
|
||||||
cwd = WidgetDialog(canvas)
|
|
||||||
root.mainloop()
|
|
||||||
|
|
||||||
def remotetest(root, app):
|
|
||||||
from listtree import listtree
|
|
||||||
list = listtree(root, app)
|
|
||||||
list.bind('<Any-Double-1>', opendialogs)
|
|
||||||
list.app = app # Pass it on to handler
|
|
||||||
|
|
||||||
def opendialogs(e):
|
|
||||||
list = e.widget
|
|
||||||
sel = list.curselection()
|
|
||||||
for i in sel:
|
|
||||||
item = list.get(i)
|
|
||||||
widget = item.split()[0]
|
|
||||||
RemoteWidgetDialog(list, list.app, widget)
|
|
||||||
if widget == '.': continue
|
|
||||||
try:
|
|
||||||
RemotePackDialog(list, list.app, widget)
|
|
||||||
except TclError as msg:
|
|
||||||
print(msg)
|
|
||||||
|
|
||||||
test()
|
|
|
@ -1,50 +0,0 @@
|
||||||
# Brownian motion -- an example of a multi-threaded Tkinter program.
|
|
||||||
|
|
||||||
from tkinter import *
|
|
||||||
import random
|
|
||||||
import threading
|
|
||||||
import time
|
|
||||||
import sys
|
|
||||||
|
|
||||||
WIDTH = 400
|
|
||||||
HEIGHT = 300
|
|
||||||
SIGMA = 10
|
|
||||||
BUZZ = 2
|
|
||||||
RADIUS = 2
|
|
||||||
LAMBDA = 10
|
|
||||||
FILL = 'red'
|
|
||||||
|
|
||||||
stop = 0 # Set when main loop exits
|
|
||||||
|
|
||||||
def particle(canvas):
|
|
||||||
r = RADIUS
|
|
||||||
x = random.gauss(WIDTH/2.0, SIGMA)
|
|
||||||
y = random.gauss(HEIGHT/2.0, SIGMA)
|
|
||||||
p = canvas.create_oval(x-r, y-r, x+r, y+r, fill=FILL)
|
|
||||||
while not stop:
|
|
||||||
dx = random.gauss(0, BUZZ)
|
|
||||||
dy = random.gauss(0, BUZZ)
|
|
||||||
dt = random.expovariate(LAMBDA)
|
|
||||||
try:
|
|
||||||
canvas.move(p, dx, dy)
|
|
||||||
except TclError:
|
|
||||||
break
|
|
||||||
time.sleep(dt)
|
|
||||||
|
|
||||||
def main():
|
|
||||||
global stop
|
|
||||||
root = Tk()
|
|
||||||
canvas = Canvas(root, width=WIDTH, height=HEIGHT)
|
|
||||||
canvas.pack(fill='both', expand=1)
|
|
||||||
np = 30
|
|
||||||
if sys.argv[1:]:
|
|
||||||
np = int(sys.argv[1])
|
|
||||||
for i in range(np):
|
|
||||||
t = threading.Thread(target=particle, args=(canvas,))
|
|
||||||
t.start()
|
|
||||||
try:
|
|
||||||
root.mainloop()
|
|
||||||
finally:
|
|
||||||
stop = 1
|
|
||||||
|
|
||||||
main()
|
|
|
@ -1,55 +0,0 @@
|
||||||
# Brownian motion -- an example of a NON multi-threaded Tkinter program ;)
|
|
||||||
# By Michele Simoniato, inspired by brownian.py
|
|
||||||
|
|
||||||
from tkinter import *
|
|
||||||
import random
|
|
||||||
import sys
|
|
||||||
|
|
||||||
WIDTH = 400
|
|
||||||
HEIGHT = 300
|
|
||||||
SIGMA = 10
|
|
||||||
BUZZ = 2
|
|
||||||
RADIUS = 2
|
|
||||||
LAMBDA = 10
|
|
||||||
FILL = 'red'
|
|
||||||
|
|
||||||
stop = 0 # Set when main loop exits
|
|
||||||
root = None # main window
|
|
||||||
|
|
||||||
def particle(canvas): # particle = iterator over the moves
|
|
||||||
r = RADIUS
|
|
||||||
x = random.gauss(WIDTH/2.0, SIGMA)
|
|
||||||
y = random.gauss(HEIGHT/2.0, SIGMA)
|
|
||||||
p = canvas.create_oval(x-r, y-r, x+r, y+r, fill=FILL)
|
|
||||||
while not stop:
|
|
||||||
dx = random.gauss(0, BUZZ)
|
|
||||||
dy = random.gauss(0, BUZZ)
|
|
||||||
try:
|
|
||||||
canvas.move(p, dx, dy)
|
|
||||||
except TclError:
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
yield None
|
|
||||||
|
|
||||||
def move(particle): # move the particle at random time
|
|
||||||
next(particle)
|
|
||||||
dt = random.expovariate(LAMBDA)
|
|
||||||
root.after(int(dt*1000), move, particle)
|
|
||||||
|
|
||||||
def main():
|
|
||||||
global root, stop
|
|
||||||
root = Tk()
|
|
||||||
canvas = Canvas(root, width=WIDTH, height=HEIGHT)
|
|
||||||
canvas.pack(fill='both', expand=1)
|
|
||||||
np = 30
|
|
||||||
if sys.argv[1:]:
|
|
||||||
np = int(sys.argv[1])
|
|
||||||
for i in range(np): # start the dance
|
|
||||||
move(particle(canvas))
|
|
||||||
try:
|
|
||||||
root.mainloop()
|
|
||||||
finally:
|
|
||||||
stop = 1
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main()
|
|
|
@ -1,264 +0,0 @@
|
||||||
#! /usr/bin/env python3
|
|
||||||
|
|
||||||
from tkinter import *
|
|
||||||
|
|
||||||
|
|
||||||
# Since Canvas.Group is no longer present, the following class reproduces
|
|
||||||
# a subset of the old Group class that is used by this app.
|
|
||||||
|
|
||||||
class Group:
|
|
||||||
def __init__(self, canvas, tag=None):
|
|
||||||
if tag is None:
|
|
||||||
tag = 'Group%d' % id(self)
|
|
||||||
|
|
||||||
self.tag = self.id = tag
|
|
||||||
self.canvas = canvas
|
|
||||||
self.canvas.dtag(self.tag)
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return self.tag
|
|
||||||
|
|
||||||
def _do(self, cmd, *args):
|
|
||||||
return self.canvas.tk.call(self.canvas._w, cmd, self.tag, *args)
|
|
||||||
|
|
||||||
def addtag_withtag(self, tagOrId):
|
|
||||||
self._do('addtag', 'withtag', tagOrId)
|
|
||||||
|
|
||||||
def bind(self, sequence=None, command=None, add=None):
|
|
||||||
return self.canvas.tag_bind(self.id, sequence, command, add)
|
|
||||||
|
|
||||||
def move(self, x_amount, y_amount):
|
|
||||||
self._do('move', x_amount, y_amount)
|
|
||||||
|
|
||||||
def dtag(self, tagToDelete=None):
|
|
||||||
self._do('dtag', tagToDelete)
|
|
||||||
|
|
||||||
def tkraise(self, aboveThis=None):
|
|
||||||
self._do('raise', aboveThis)
|
|
||||||
|
|
||||||
|
|
||||||
class Object:
|
|
||||||
|
|
||||||
"""Base class for composite graphical objects.
|
|
||||||
|
|
||||||
Objects belong to a canvas, and can be moved around on the canvas.
|
|
||||||
They also belong to at most one ``pile'' of objects, and can be
|
|
||||||
transferred between piles (or removed from their pile).
|
|
||||||
|
|
||||||
Objects have a canonical ``x, y'' position which is moved when the
|
|
||||||
object is moved. Where the object is relative to this position
|
|
||||||
depends on the object; for simple objects, it may be their center.
|
|
||||||
|
|
||||||
Objects have mouse sensitivity. They can be clicked, dragged and
|
|
||||||
double-clicked. The behavior may actually determined by the pile
|
|
||||||
they are in.
|
|
||||||
|
|
||||||
All instance attributes are public since the derived class may
|
|
||||||
need them.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, canvas, x=0, y=0, fill='red', text='object'):
|
|
||||||
self.canvas = canvas
|
|
||||||
self.x = x
|
|
||||||
self.y = y
|
|
||||||
self.pile = None
|
|
||||||
self.group = Group(self.canvas)
|
|
||||||
self.createitems(fill, text)
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return str(self.group)
|
|
||||||
|
|
||||||
def createitems(self, fill, text):
|
|
||||||
self.__oval = self.canvas.create_oval(self.x - 20, self.y - 10,
|
|
||||||
self.x + 20, self.y + 20, fill=fill, width=3)
|
|
||||||
self.group.addtag_withtag(self.__oval)
|
|
||||||
self.__text = self.canvas.create_text(self.x, self.y, text=text)
|
|
||||||
self.group.addtag_withtag(self.__text)
|
|
||||||
|
|
||||||
def moveby(self, dx, dy):
|
|
||||||
if dx == dy == 0:
|
|
||||||
return
|
|
||||||
self.group.move(dx, dy)
|
|
||||||
self.x = self.x + dx
|
|
||||||
self.y = self.y + dy
|
|
||||||
|
|
||||||
def moveto(self, x, y):
|
|
||||||
self.moveby(x - self.x, y - self.y)
|
|
||||||
|
|
||||||
def transfer(self, pile):
|
|
||||||
if self.pile:
|
|
||||||
self.pile.delete(self)
|
|
||||||
self.pile = None
|
|
||||||
self.pile = pile
|
|
||||||
if self.pile:
|
|
||||||
self.pile.add(self)
|
|
||||||
|
|
||||||
def tkraise(self):
|
|
||||||
self.group.tkraise()
|
|
||||||
|
|
||||||
|
|
||||||
class Bottom(Object):
|
|
||||||
"""An object to serve as the bottom of a pile."""
|
|
||||||
|
|
||||||
def createitems(self, *args):
|
|
||||||
self.__oval = self.canvas.create_oval(self.x - 20, self.y - 10,
|
|
||||||
self.x + 20, self.y + 10, fill='gray', outline='')
|
|
||||||
self.group.addtag_withtag(self.__oval)
|
|
||||||
|
|
||||||
|
|
||||||
class Pile:
|
|
||||||
"""A group of graphical objects."""
|
|
||||||
|
|
||||||
def __init__(self, canvas, x, y, tag=None):
|
|
||||||
self.canvas = canvas
|
|
||||||
self.x = x
|
|
||||||
self.y = y
|
|
||||||
self.objects = []
|
|
||||||
self.bottom = Bottom(self.canvas, self.x, self.y)
|
|
||||||
self.group = Group(self.canvas, tag=tag)
|
|
||||||
self.group.addtag_withtag(self.bottom.group)
|
|
||||||
self.bindhandlers()
|
|
||||||
|
|
||||||
def bindhandlers(self):
|
|
||||||
self.group.bind('<1>', self.clickhandler)
|
|
||||||
self.group.bind('<Double-1>', self.doubleclickhandler)
|
|
||||||
|
|
||||||
def add(self, object):
|
|
||||||
self.objects.append(object)
|
|
||||||
self.group.addtag_withtag(object.group)
|
|
||||||
self.position(object)
|
|
||||||
|
|
||||||
def delete(self, object):
|
|
||||||
object.group.dtag(self.group)
|
|
||||||
self.objects.remove(object)
|
|
||||||
|
|
||||||
def position(self, object):
|
|
||||||
object.tkraise()
|
|
||||||
i = self.objects.index(object)
|
|
||||||
object.moveto(self.x + i*4, self.y + i*8)
|
|
||||||
|
|
||||||
def clickhandler(self, event):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def doubleclickhandler(self, event):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class MovingPile(Pile):
|
|
||||||
|
|
||||||
def bindhandlers(self):
|
|
||||||
Pile.bindhandlers(self)
|
|
||||||
self.group.bind('<B1-Motion>', self.motionhandler)
|
|
||||||
self.group.bind('<ButtonRelease-1>', self.releasehandler)
|
|
||||||
|
|
||||||
movethis = None
|
|
||||||
|
|
||||||
def clickhandler(self, event):
|
|
||||||
tags = self.canvas.gettags('current')
|
|
||||||
for i in range(len(self.objects)):
|
|
||||||
o = self.objects[i]
|
|
||||||
if o.group.tag in tags:
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
self.movethis = None
|
|
||||||
return
|
|
||||||
self.movethis = self.objects[i:]
|
|
||||||
for o in self.movethis:
|
|
||||||
o.tkraise()
|
|
||||||
self.lastx = event.x
|
|
||||||
self.lasty = event.y
|
|
||||||
|
|
||||||
doubleclickhandler = clickhandler
|
|
||||||
|
|
||||||
def motionhandler(self, event):
|
|
||||||
if not self.movethis:
|
|
||||||
return
|
|
||||||
dx = event.x - self.lastx
|
|
||||||
dy = event.y - self.lasty
|
|
||||||
self.lastx = event.x
|
|
||||||
self.lasty = event.y
|
|
||||||
for o in self.movethis:
|
|
||||||
o.moveby(dx, dy)
|
|
||||||
|
|
||||||
def releasehandler(self, event):
|
|
||||||
objects = self.movethis
|
|
||||||
if not objects:
|
|
||||||
return
|
|
||||||
self.movethis = None
|
|
||||||
self.finishmove(objects)
|
|
||||||
|
|
||||||
def finishmove(self, objects):
|
|
||||||
for o in objects:
|
|
||||||
self.position(o)
|
|
||||||
|
|
||||||
|
|
||||||
class Pile1(MovingPile):
|
|
||||||
|
|
||||||
x = 50
|
|
||||||
y = 50
|
|
||||||
tag = 'p1'
|
|
||||||
|
|
||||||
def __init__(self, demo):
|
|
||||||
self.demo = demo
|
|
||||||
MovingPile.__init__(self, self.demo.canvas, self.x, self.y, self.tag)
|
|
||||||
|
|
||||||
def doubleclickhandler(self, event):
|
|
||||||
try:
|
|
||||||
o = self.objects[-1]
|
|
||||||
except IndexError:
|
|
||||||
return
|
|
||||||
o.transfer(self.other())
|
|
||||||
MovingPile.doubleclickhandler(self, event)
|
|
||||||
|
|
||||||
def other(self):
|
|
||||||
return self.demo.p2
|
|
||||||
|
|
||||||
def finishmove(self, objects):
|
|
||||||
o = objects[0]
|
|
||||||
p = self.other()
|
|
||||||
x, y = o.x, o.y
|
|
||||||
if (x-p.x)**2 + (y-p.y)**2 < (x-self.x)**2 + (y-self.y)**2:
|
|
||||||
for o in objects:
|
|
||||||
o.transfer(p)
|
|
||||||
else:
|
|
||||||
MovingPile.finishmove(self, objects)
|
|
||||||
|
|
||||||
class Pile2(Pile1):
|
|
||||||
|
|
||||||
x = 150
|
|
||||||
y = 50
|
|
||||||
tag = 'p2'
|
|
||||||
|
|
||||||
def other(self):
|
|
||||||
return self.demo.p1
|
|
||||||
|
|
||||||
|
|
||||||
class Demo:
|
|
||||||
|
|
||||||
def __init__(self, master):
|
|
||||||
self.master = master
|
|
||||||
self.canvas = Canvas(master,
|
|
||||||
width=200, height=200,
|
|
||||||
background='yellow',
|
|
||||||
relief=SUNKEN, borderwidth=2)
|
|
||||||
self.canvas.pack(expand=1, fill=BOTH)
|
|
||||||
self.p1 = Pile1(self)
|
|
||||||
self.p2 = Pile2(self)
|
|
||||||
o1 = Object(self.canvas, fill='red', text='o1')
|
|
||||||
o2 = Object(self.canvas, fill='green', text='o2')
|
|
||||||
o3 = Object(self.canvas, fill='light blue', text='o3')
|
|
||||||
o1.transfer(self.p1)
|
|
||||||
o2.transfer(self.p1)
|
|
||||||
o3.transfer(self.p2)
|
|
||||||
|
|
||||||
|
|
||||||
# Main function, run when invoked as a stand-alone Python program.
|
|
||||||
|
|
||||||
def main():
|
|
||||||
root = Tk()
|
|
||||||
demo = Demo(root)
|
|
||||||
root.protocol('WM_DELETE_WINDOW', root.quit)
|
|
||||||
root.mainloop()
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main()
|
|
|
@ -1,108 +0,0 @@
|
||||||
#! /usr/bin/env python3
|
|
||||||
|
|
||||||
# A Python function that generates dialog boxes with a text message,
|
|
||||||
# optional bitmap, and any number of buttons.
|
|
||||||
# Cf. Ousterhout, Tcl and the Tk Toolkit, Figs. 27.2-3, pp. 269-270.
|
|
||||||
|
|
||||||
from tkinter import *
|
|
||||||
import sys
|
|
||||||
|
|
||||||
|
|
||||||
def dialog(master, title, text, bitmap, default, *args):
|
|
||||||
|
|
||||||
# 1. Create the top-level window and divide it into top
|
|
||||||
# and bottom parts.
|
|
||||||
|
|
||||||
w = Toplevel(master, class_='Dialog')
|
|
||||||
w.title(title)
|
|
||||||
w.iconname('Dialog')
|
|
||||||
|
|
||||||
top = Frame(w, relief=RAISED, borderwidth=1)
|
|
||||||
top.pack(side=TOP, fill=BOTH)
|
|
||||||
bot = Frame(w, relief=RAISED, borderwidth=1)
|
|
||||||
bot.pack(side=BOTTOM, fill=BOTH)
|
|
||||||
|
|
||||||
# 2. Fill the top part with the bitmap and message.
|
|
||||||
|
|
||||||
msg = Message(top, width='3i', text=text)
|
|
||||||
msg.pack(side=RIGHT, expand=1, fill=BOTH, padx='3m', pady='3m')
|
|
||||||
if bitmap:
|
|
||||||
bm = Label(top, bitmap=bitmap)
|
|
||||||
bm.pack(side=LEFT, padx='3m', pady='3m')
|
|
||||||
|
|
||||||
# 3. Create a row of buttons at the bottom of the dialog.
|
|
||||||
|
|
||||||
var = IntVar()
|
|
||||||
buttons = []
|
|
||||||
i = 0
|
|
||||||
for but in args:
|
|
||||||
b = Button(bot, text=but, command=lambda v=var,i=i: v.set(i))
|
|
||||||
buttons.append(b)
|
|
||||||
if i == default:
|
|
||||||
bd = Frame(bot, relief=SUNKEN, borderwidth=1)
|
|
||||||
bd.pack(side=LEFT, expand=1, padx='3m', pady='2m')
|
|
||||||
b.lift()
|
|
||||||
b.pack (in_=bd, side=LEFT,
|
|
||||||
padx='2m', pady='2m', ipadx='2m', ipady='1m')
|
|
||||||
else:
|
|
||||||
b.pack (side=LEFT, expand=1,
|
|
||||||
padx='3m', pady='3m', ipadx='2m', ipady='1m')
|
|
||||||
i = i+1
|
|
||||||
|
|
||||||
# 4. Set up a binding for <Return>, if there's a default,
|
|
||||||
# set a grab, and claim the focus too.
|
|
||||||
|
|
||||||
if default >= 0:
|
|
||||||
w.bind('<Return>',
|
|
||||||
lambda e, b=buttons[default], v=var, i=default:
|
|
||||||
(b.flash(),
|
|
||||||
v.set(i)))
|
|
||||||
|
|
||||||
oldFocus = w.focus_get()
|
|
||||||
w.grab_set()
|
|
||||||
w.focus_set()
|
|
||||||
|
|
||||||
# 5. Wait for the user to respond, then restore the focus
|
|
||||||
# and return the index of the selected button.
|
|
||||||
|
|
||||||
w.waitvar(var)
|
|
||||||
w.destroy()
|
|
||||||
if oldFocus: oldFocus.focus_set()
|
|
||||||
return var.get()
|
|
||||||
|
|
||||||
# The rest is the test program.
|
|
||||||
|
|
||||||
def go():
|
|
||||||
i = dialog(mainWidget,
|
|
||||||
'Not Responding',
|
|
||||||
"The file server isn't responding right now; "
|
|
||||||
"I'll keep trying.",
|
|
||||||
'',
|
|
||||||
-1,
|
|
||||||
'OK')
|
|
||||||
print('pressed button', i)
|
|
||||||
i = dialog(mainWidget,
|
|
||||||
'File Modified',
|
|
||||||
'File "tcl.h" has been modified since '
|
|
||||||
'the last time it was saved. '
|
|
||||||
'Do you want to save it before exiting the application?',
|
|
||||||
'warning',
|
|
||||||
0,
|
|
||||||
'Save File',
|
|
||||||
'Discard Changes',
|
|
||||||
'Return To Editor')
|
|
||||||
print('pressed button', i)
|
|
||||||
|
|
||||||
def test():
|
|
||||||
import sys
|
|
||||||
global mainWidget
|
|
||||||
mainWidget = Frame()
|
|
||||||
Pack.config(mainWidget)
|
|
||||||
start = Button(mainWidget, text='Press Here To Start', command=go)
|
|
||||||
start.pack()
|
|
||||||
endit = Button(mainWidget, text="Exit", command=sys.exit)
|
|
||||||
endit.pack(fill=BOTH)
|
|
||||||
mainWidget.mainloop()
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
test()
|
|
|
@ -1,91 +0,0 @@
|
||||||
#! /usr/bin/env python3
|
|
||||||
|
|
||||||
# Simulate "electrons" migrating across the screen.
|
|
||||||
# An optional bitmap file in can be in the background.
|
|
||||||
#
|
|
||||||
# Usage: electrons [n [bitmapfile]]
|
|
||||||
#
|
|
||||||
# n is the number of electrons to animate; default is 30.
|
|
||||||
#
|
|
||||||
# The bitmap file can be any X11 bitmap file (look in
|
|
||||||
# /usr/include/X11/bitmaps for samples); it is displayed as the
|
|
||||||
# background of the animation. Default is no bitmap.
|
|
||||||
|
|
||||||
from tkinter import *
|
|
||||||
import random
|
|
||||||
|
|
||||||
|
|
||||||
# The graphical interface
|
|
||||||
class Electrons:
|
|
||||||
|
|
||||||
# Create our objects
|
|
||||||
def __init__(self, n, bitmap = None):
|
|
||||||
self.n = n
|
|
||||||
self.tk = tk = Tk()
|
|
||||||
self.canvas = c = Canvas(tk)
|
|
||||||
c.pack()
|
|
||||||
width, height = tk.getint(c['width']), tk.getint(c['height'])
|
|
||||||
|
|
||||||
# Add background bitmap
|
|
||||||
if bitmap:
|
|
||||||
self.bitmap = c.create_bitmap(width/2, height/2,
|
|
||||||
bitmap=bitmap,
|
|
||||||
foreground='blue')
|
|
||||||
|
|
||||||
self.pieces = []
|
|
||||||
x1, y1, x2, y2 = 10,70,14,74
|
|
||||||
for i in range(n):
|
|
||||||
p = c.create_oval(x1, y1, x2, y2, fill='red')
|
|
||||||
self.pieces.append(p)
|
|
||||||
y1, y2 = y1 +2, y2 + 2
|
|
||||||
self.tk.update()
|
|
||||||
|
|
||||||
def random_move(self, n):
|
|
||||||
c = self.canvas
|
|
||||||
for p in self.pieces:
|
|
||||||
x = random.choice(range(-2,4))
|
|
||||||
y = random.choice(range(-3,4))
|
|
||||||
c.move(p, x, y)
|
|
||||||
self.tk.update()
|
|
||||||
|
|
||||||
# Run -- allow 500 movemens
|
|
||||||
def run(self):
|
|
||||||
try:
|
|
||||||
for i in range(500):
|
|
||||||
self.random_move(self.n)
|
|
||||||
except TclError:
|
|
||||||
try:
|
|
||||||
self.tk.destroy()
|
|
||||||
except TclError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
# Main program
|
|
||||||
def main():
|
|
||||||
import sys
|
|
||||||
|
|
||||||
# First argument is number of electrons, default 30
|
|
||||||
if sys.argv[1:]:
|
|
||||||
n = int(sys.argv[1])
|
|
||||||
else:
|
|
||||||
n = 30
|
|
||||||
|
|
||||||
# Second argument is bitmap file, default none
|
|
||||||
if sys.argv[2:]:
|
|
||||||
bitmap = sys.argv[2]
|
|
||||||
# Reverse meaning of leading '@' compared to Tk
|
|
||||||
if bitmap[0] == '@': bitmap = bitmap[1:]
|
|
||||||
else: bitmap = '@' + bitmap
|
|
||||||
else:
|
|
||||||
bitmap = None
|
|
||||||
|
|
||||||
# Create the graphical objects...
|
|
||||||
h = Electrons(n, bitmap)
|
|
||||||
|
|
||||||
# ...and run!
|
|
||||||
h.run()
|
|
||||||
|
|
||||||
|
|
||||||
# Call main when run as script
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main()
|
|
|
@ -1,17 +0,0 @@
|
||||||
# Display hello, world in a button; clicking it quits the program
|
|
||||||
|
|
||||||
import sys
|
|
||||||
from tkinter import *
|
|
||||||
|
|
||||||
def main():
|
|
||||||
root = Tk()
|
|
||||||
button = Button(root)
|
|
||||||
button['text'] = 'Hello, world'
|
|
||||||
button['command'] = quit_callback # See below
|
|
||||||
button.pack()
|
|
||||||
root.mainloop()
|
|
||||||
|
|
||||||
def quit_callback():
|
|
||||||
sys.exit(0)
|
|
||||||
|
|
||||||
main()
|
|
|
@ -1,23 +0,0 @@
|
||||||
"""Draw on top of an image"""
|
|
||||||
|
|
||||||
from tkinter import *
|
|
||||||
import sys
|
|
||||||
|
|
||||||
def main():
|
|
||||||
filename = sys.argv[1]
|
|
||||||
root = Tk()
|
|
||||||
img = PhotoImage(file=filename)
|
|
||||||
w, h = img.width(), img.height()
|
|
||||||
canv = Canvas(root, width=w, height=h)
|
|
||||||
canv.create_image(0, 0, anchor=NW, image=img)
|
|
||||||
canv.pack()
|
|
||||||
canv.bind('<Button-1>', blob)
|
|
||||||
root.mainloop()
|
|
||||||
|
|
||||||
def blob(event):
|
|
||||||
x, y = event.x, event.y
|
|
||||||
canv = event.widget
|
|
||||||
r = 5
|
|
||||||
canv.create_oval(x-r, y-r, x+r, y+r, fill='red', outline="")
|
|
||||||
|
|
||||||
main()
|
|
|
@ -1,12 +0,0 @@
|
||||||
from tkinter import *
|
|
||||||
import sys
|
|
||||||
|
|
||||||
def main():
|
|
||||||
filename = sys.argv[1]
|
|
||||||
root = Tk()
|
|
||||||
img = PhotoImage(file=filename)
|
|
||||||
label = Label(root, image=img)
|
|
||||||
label.pack()
|
|
||||||
root.mainloop()
|
|
||||||
|
|
||||||
main()
|
|
|
@ -1,96 +0,0 @@
|
||||||
#! /usr/bin/env python3
|
|
||||||
# Tkinter interface to Linux `kill' command.
|
|
||||||
|
|
||||||
from tkinter import *
|
|
||||||
import subprocess
|
|
||||||
import os
|
|
||||||
|
|
||||||
class BarButton(Menubutton):
|
|
||||||
def __init__(self, master=None, **cnf):
|
|
||||||
Menubutton.__init__(self, master, **cnf)
|
|
||||||
self.pack(side=LEFT)
|
|
||||||
self.menu = Menu(self, name='menu')
|
|
||||||
self['menu'] = self.menu
|
|
||||||
|
|
||||||
class Kill(Frame):
|
|
||||||
# List of (name, option, pid_column)
|
|
||||||
format_list = [('Default', '', 0),
|
|
||||||
('Long', '-l', 2),
|
|
||||||
('User', '-u', 1),
|
|
||||||
('Jobs', '-j', 1),
|
|
||||||
('Signal', '-s', 1),
|
|
||||||
('Memory', '-m', 0),
|
|
||||||
('VM', '-v', 0),
|
|
||||||
('Hex', '-X', 0)]
|
|
||||||
def kill(self, selected):
|
|
||||||
c = self.format_list[self.format.get()][2]
|
|
||||||
pid = selected.split()[c]
|
|
||||||
os.system('kill -9 ' + pid)
|
|
||||||
self.do_update()
|
|
||||||
def do_update(self):
|
|
||||||
name, option, column = self.format_list[self.format.get()]
|
|
||||||
s = subprocess.getoutput('ps -w ' + option)
|
|
||||||
list = s.split('\n')
|
|
||||||
self.header.set(list[0])
|
|
||||||
del list[0]
|
|
||||||
y = self.frame.vscroll.get()[0]
|
|
||||||
self.frame.list.delete(0, AtEnd())
|
|
||||||
for line in list:
|
|
||||||
self.frame.list.insert(0, line)
|
|
||||||
self.frame.list.yview(int(y))
|
|
||||||
def do_motion(self, e):
|
|
||||||
e.widget.select_clear(0, END)
|
|
||||||
e.widget.select_set(e.widget.nearest(e.y))
|
|
||||||
def do_leave(self, e):
|
|
||||||
e.widget.select_clear(0, END)
|
|
||||||
def do_1(self, e):
|
|
||||||
self.kill(e.widget.get(e.widget.nearest(e.y)))
|
|
||||||
def __init__(self, master=None, **cnf):
|
|
||||||
Frame.__init__(self, master, cnf)
|
|
||||||
self.pack(expand=1, fill=BOTH)
|
|
||||||
self.bar = Frame(self, name='bar', relief=RAISED,
|
|
||||||
borderwidth=2)
|
|
||||||
self.bar.pack(fill=X)
|
|
||||||
self.bar.file = BarButton(self.bar, text='File')
|
|
||||||
self.bar.file.menu.add_command(
|
|
||||||
label='Quit', command=self.quit)
|
|
||||||
self.bar.view = BarButton(self.bar, text='View')
|
|
||||||
self.format = IntVar(self)
|
|
||||||
self.format.set(2)
|
|
||||||
for num in range(len(self.format_list)):
|
|
||||||
self.bar.view.menu.add_radiobutton(
|
|
||||||
label=self.format_list[num][0],
|
|
||||||
command=self.do_update,
|
|
||||||
variable=self.format,
|
|
||||||
value=num)
|
|
||||||
#self.bar.view.menu.add_separator()
|
|
||||||
#XXX ...
|
|
||||||
self.bar.tk_menuBar(self.bar.file, self.bar.view)
|
|
||||||
self.frame = Frame(self, relief=RAISED, borderwidth=2)
|
|
||||||
self.frame.pack(expand=1, fill=BOTH)
|
|
||||||
self.header = StringVar(self)
|
|
||||||
self.frame.label = Label(self.frame, relief=FLAT, anchor=NW,
|
|
||||||
borderwidth=0,
|
|
||||||
textvariable=self.header)
|
|
||||||
self.frame.label.pack(fill=X)
|
|
||||||
self.frame.vscroll = Scrollbar(self.frame, orient=VERTICAL)
|
|
||||||
self.frame.list = Listbox(self.frame, relief=SUNKEN,
|
|
||||||
selectbackground='#eed5b7',
|
|
||||||
selectborderwidth=0,
|
|
||||||
yscroll=self.frame.vscroll.set)
|
|
||||||
self.frame.vscroll['command'] = self.frame.list.yview
|
|
||||||
self.frame.vscroll.pack(side=RIGHT, fill=Y)
|
|
||||||
self.frame.list.pack(expand=1, fill=BOTH)
|
|
||||||
self.update = Button(self, text="Update",
|
|
||||||
command=self.do_update)
|
|
||||||
self.update.pack(expand=1, fill=X)
|
|
||||||
self.frame.list.bind('<Motion>', self.do_motion)
|
|
||||||
self.frame.list.bind('<Leave>', self.do_leave)
|
|
||||||
self.frame.list.bind('<1>', self.do_1)
|
|
||||||
self.do_update()
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
kill = Kill(None, borderwidth=5)
|
|
||||||
kill.winfo_toplevel().title('Tkinter Process Killer')
|
|
||||||
kill.winfo_toplevel().minsize(1, 1)
|
|
||||||
kill.mainloop()
|
|
|
@ -1,34 +0,0 @@
|
||||||
# List a remote app's widget tree (names and classes only)
|
|
||||||
|
|
||||||
import sys
|
|
||||||
|
|
||||||
from tkinter import *
|
|
||||||
|
|
||||||
def listtree(master, app):
|
|
||||||
list = Listbox(master, name='list')
|
|
||||||
list.pack(expand=1, fill=BOTH)
|
|
||||||
listnodes(list, app, '.', 0)
|
|
||||||
return list
|
|
||||||
|
|
||||||
def listnodes(list, app, widget, level):
|
|
||||||
klass = list.send(app, 'winfo', 'class', widget)
|
|
||||||
list.insert(END, '%s (%s)' % (widget, klass))
|
|
||||||
children = list.tk.splitlist(
|
|
||||||
list.send(app, 'winfo', 'children', widget))
|
|
||||||
for c in children:
|
|
||||||
listnodes(list, app, c, level+1)
|
|
||||||
|
|
||||||
def main():
|
|
||||||
if not sys.argv[1:]:
|
|
||||||
sys.stderr.write('Usage: listtree appname\n')
|
|
||||||
sys.exit(2)
|
|
||||||
app = sys.argv[1]
|
|
||||||
tk = Tk()
|
|
||||||
tk.minsize(1, 1)
|
|
||||||
f = Frame(tk, name='f')
|
|
||||||
f.pack(expand=1, fill=BOTH)
|
|
||||||
list = listtree(f, app)
|
|
||||||
tk.mainloop()
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main()
|
|
|
@ -1,215 +0,0 @@
|
||||||
# Widget to display a man page
|
|
||||||
|
|
||||||
import os
|
|
||||||
import re
|
|
||||||
import sys
|
|
||||||
|
|
||||||
from tkinter import *
|
|
||||||
from tkinter.font import Font
|
|
||||||
from tkinter.scrolledtext import ScrolledText
|
|
||||||
|
|
||||||
# XXX Recognizing footers is system dependent
|
|
||||||
# (This one works for IRIX 5.2 and Solaris 2.2)
|
|
||||||
footerprog = re.compile(
|
|
||||||
'^ Page [1-9][0-9]*[ \t]+\|^.*Last change:.*[1-9][0-9]*\n')
|
|
||||||
emptyprog = re.compile('^[ \t]*\n')
|
|
||||||
ulprog = re.compile('^[ \t]*[Xv!_][Xv!_ \t]*\n')
|
|
||||||
|
|
||||||
|
|
||||||
class EditableManPage(ScrolledText):
|
|
||||||
"""Basic Man Page class -- does not disable editing."""
|
|
||||||
|
|
||||||
def __init__(self, master=None, **cnf):
|
|
||||||
ScrolledText.__init__(self, master, **cnf)
|
|
||||||
|
|
||||||
bold = Font(font=self['font']).copy()
|
|
||||||
bold.config(weight='bold')
|
|
||||||
italic = Font(font=self['font']).copy()
|
|
||||||
italic.config(slant='italic')
|
|
||||||
|
|
||||||
# Define tags for formatting styles
|
|
||||||
self.tag_config('X', underline=1)
|
|
||||||
self.tag_config('!', font=bold)
|
|
||||||
self.tag_config('_', font=italic)
|
|
||||||
|
|
||||||
# Set state to idle
|
|
||||||
self.fp = None
|
|
||||||
self.lineno = 0
|
|
||||||
|
|
||||||
def busy(self):
|
|
||||||
"""Test whether we are busy parsing a file."""
|
|
||||||
return self.fp != None
|
|
||||||
|
|
||||||
def kill(self):
|
|
||||||
"""Ensure we're not busy."""
|
|
||||||
if self.busy():
|
|
||||||
self._endparser()
|
|
||||||
|
|
||||||
def asyncparsefile(self, fp):
|
|
||||||
"""Parse a file, in the background."""
|
|
||||||
self._startparser(fp)
|
|
||||||
self.tk.createfilehandler(fp, READABLE,
|
|
||||||
self._filehandler)
|
|
||||||
|
|
||||||
parsefile = asyncparsefile # Alias
|
|
||||||
|
|
||||||
def _filehandler(self, fp, mask):
|
|
||||||
"""I/O handler used by background parsing."""
|
|
||||||
nextline = self.fp.readline()
|
|
||||||
if not nextline:
|
|
||||||
self._endparser()
|
|
||||||
return
|
|
||||||
self._parseline(nextline)
|
|
||||||
|
|
||||||
def syncparsefile(self, fp):
|
|
||||||
"""Parse a file, now (cannot be aborted)."""
|
|
||||||
self._startparser(fp)
|
|
||||||
while True:
|
|
||||||
nextline = fp.readline()
|
|
||||||
if not nextline:
|
|
||||||
break
|
|
||||||
self._parseline(nextline)
|
|
||||||
self._endparser()
|
|
||||||
|
|
||||||
def _startparser(self, fp):
|
|
||||||
"""Initialize parsing from a particular file -- must not be busy."""
|
|
||||||
if self.busy():
|
|
||||||
raise RuntimeError('startparser: still busy')
|
|
||||||
fp.fileno() # Test for file-ness
|
|
||||||
self.fp = fp
|
|
||||||
self.lineno = 0
|
|
||||||
self.ok = 0
|
|
||||||
self.empty = 0
|
|
||||||
self.buffer = None
|
|
||||||
savestate = self['state']
|
|
||||||
self['state'] = NORMAL
|
|
||||||
self.delete('1.0', END)
|
|
||||||
self['state'] = savestate
|
|
||||||
|
|
||||||
def _endparser(self):
|
|
||||||
"""End parsing -- must be busy, need not be at EOF."""
|
|
||||||
if not self.busy():
|
|
||||||
raise RuntimeError('endparser: not busy')
|
|
||||||
if self.buffer:
|
|
||||||
self._parseline('')
|
|
||||||
try:
|
|
||||||
self.tk.deletefilehandler(self.fp)
|
|
||||||
except TclError:
|
|
||||||
pass
|
|
||||||
self.fp.close()
|
|
||||||
self.fp = None
|
|
||||||
del self.ok, self.empty, self.buffer
|
|
||||||
|
|
||||||
def _parseline(self, nextline):
|
|
||||||
"""Parse a single line."""
|
|
||||||
if not self.buffer:
|
|
||||||
# Save this line -- we need one line read-ahead
|
|
||||||
self.buffer = nextline
|
|
||||||
return
|
|
||||||
if emptyprog.match(self.buffer):
|
|
||||||
# Buffered line was empty -- set a flag
|
|
||||||
self.empty = 1
|
|
||||||
self.buffer = nextline
|
|
||||||
return
|
|
||||||
textline = self.buffer
|
|
||||||
if ulprog.match(nextline):
|
|
||||||
# Next line is properties for buffered line
|
|
||||||
propline = nextline
|
|
||||||
self.buffer = None
|
|
||||||
else:
|
|
||||||
# Next line is read-ahead
|
|
||||||
propline = None
|
|
||||||
self.buffer = nextline
|
|
||||||
if not self.ok:
|
|
||||||
# First non blank line after footer must be header
|
|
||||||
# -- skip that too
|
|
||||||
self.ok = 1
|
|
||||||
self.empty = 0
|
|
||||||
return
|
|
||||||
if footerprog.match(textline):
|
|
||||||
# Footer -- start skipping until next non-blank line
|
|
||||||
self.ok = 0
|
|
||||||
self.empty = 0
|
|
||||||
return
|
|
||||||
savestate = self['state']
|
|
||||||
self['state'] = NORMAL
|
|
||||||
if TkVersion >= 4.0:
|
|
||||||
self.mark_set('insert', 'end-1c')
|
|
||||||
else:
|
|
||||||
self.mark_set('insert', END)
|
|
||||||
if self.empty:
|
|
||||||
# One or more previous lines were empty
|
|
||||||
# -- insert one blank line in the text
|
|
||||||
self._insert_prop('\n')
|
|
||||||
self.lineno = self.lineno + 1
|
|
||||||
self.empty = 0
|
|
||||||
if not propline:
|
|
||||||
# No properties
|
|
||||||
self._insert_prop(textline)
|
|
||||||
else:
|
|
||||||
# Search for properties
|
|
||||||
p = ''
|
|
||||||
j = 0
|
|
||||||
for i in range(min(len(propline), len(textline))):
|
|
||||||
if propline[i] != p:
|
|
||||||
if j < i:
|
|
||||||
self._insert_prop(textline[j:i], p)
|
|
||||||
j = i
|
|
||||||
p = propline[i]
|
|
||||||
self._insert_prop(textline[j:])
|
|
||||||
self.lineno = self.lineno + 1
|
|
||||||
self['state'] = savestate
|
|
||||||
|
|
||||||
def _insert_prop(self, str, prop = ' '):
|
|
||||||
"""Insert a string at the end, with at most one property (tag)."""
|
|
||||||
here = self.index(AtInsert())
|
|
||||||
self.insert(AtInsert(), str)
|
|
||||||
if TkVersion <= 4.0:
|
|
||||||
tags = self.tag_names(here)
|
|
||||||
for tag in tags:
|
|
||||||
self.tag_remove(tag, here, AtInsert())
|
|
||||||
if prop != ' ':
|
|
||||||
self.tag_add(prop, here, AtInsert())
|
|
||||||
|
|
||||||
|
|
||||||
class ReadonlyManPage(EditableManPage):
|
|
||||||
"""Readonly Man Page class -- disables editing, otherwise the same."""
|
|
||||||
|
|
||||||
def __init__(self, master=None, **cnf):
|
|
||||||
cnf['state'] = DISABLED
|
|
||||||
EditableManPage.__init__(self, master, **cnf)
|
|
||||||
|
|
||||||
# Alias
|
|
||||||
ManPage = ReadonlyManPage
|
|
||||||
|
|
||||||
# usage: ManPage [manpage]; or ManPage [-f] file
|
|
||||||
# -f means that the file is nroff -man output run through ul -i
|
|
||||||
def main():
|
|
||||||
# XXX This directory may be different on your system
|
|
||||||
MANDIR = ''
|
|
||||||
DEFAULTPAGE = 'Tcl'
|
|
||||||
formatted = 0
|
|
||||||
if sys.argv[1:] and sys.argv[1] == '-f':
|
|
||||||
formatted = 1
|
|
||||||
del sys.argv[1]
|
|
||||||
if sys.argv[1:]:
|
|
||||||
name = sys.argv[1]
|
|
||||||
else:
|
|
||||||
name = DEFAULTPAGE
|
|
||||||
if not formatted:
|
|
||||||
if name[-2:-1] != '.':
|
|
||||||
name = name + '.n'
|
|
||||||
name = os.path.join(MANDIR, name)
|
|
||||||
root = Tk()
|
|
||||||
root.minsize(1, 1)
|
|
||||||
manpage = ManPage(root, relief=SUNKEN, borderwidth=2)
|
|
||||||
manpage.pack(expand=1, fill=BOTH)
|
|
||||||
if formatted:
|
|
||||||
fp = open(name, 'r')
|
|
||||||
else:
|
|
||||||
fp = os.popen('nroff -man -c %s | ul -i' % name, 'r')
|
|
||||||
manpage.parsefile(fp)
|
|
||||||
root.mainloop()
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main()
|
|
|
@ -1,286 +0,0 @@
|
||||||
#! /usr/bin/env python3
|
|
||||||
|
|
||||||
# Scan MH folder, display results in window
|
|
||||||
|
|
||||||
import os
|
|
||||||
import re
|
|
||||||
import sys
|
|
||||||
import getopt
|
|
||||||
import mailbox
|
|
||||||
from tkinter import *
|
|
||||||
|
|
||||||
from dialog import dialog
|
|
||||||
|
|
||||||
MBOXPATH = os.environ['HOME'] + '/Mail'
|
|
||||||
|
|
||||||
def main():
|
|
||||||
global root, tk, top, mid, bot
|
|
||||||
global folderbox, foldermenu, scanbox, scanmenu, viewer
|
|
||||||
global folder, seq
|
|
||||||
global mh, mhf
|
|
||||||
|
|
||||||
# Parse command line options
|
|
||||||
|
|
||||||
folder = 'inbox'
|
|
||||||
seq = 'all'
|
|
||||||
try:
|
|
||||||
opts, args = getopt.getopt(sys.argv[1:], '')
|
|
||||||
except getopt.error as msg:
|
|
||||||
print(msg)
|
|
||||||
sys.exit(2)
|
|
||||||
for arg in args:
|
|
||||||
if arg[:1] == '+':
|
|
||||||
folder = arg[1:]
|
|
||||||
else:
|
|
||||||
seq = arg
|
|
||||||
|
|
||||||
# Initialize MH
|
|
||||||
|
|
||||||
mh = mailbox.MH(MBOXPATH)
|
|
||||||
mhf = mh.get_folder(folder)
|
|
||||||
|
|
||||||
# Build widget hierarchy
|
|
||||||
|
|
||||||
root = Tk()
|
|
||||||
tk = root.tk
|
|
||||||
|
|
||||||
top = Frame(root)
|
|
||||||
top.pack({'expand': 1, 'fill': 'both'})
|
|
||||||
|
|
||||||
# Build right part: folder list
|
|
||||||
|
|
||||||
right = Frame(top)
|
|
||||||
right.pack({'fill': 'y', 'side': 'right'})
|
|
||||||
|
|
||||||
folderbar = Scrollbar(right, {'relief': 'sunken', 'bd': 2})
|
|
||||||
folderbar.pack({'fill': 'y', 'side': 'right'})
|
|
||||||
|
|
||||||
folderbox = Listbox(right, {'exportselection': 0})
|
|
||||||
folderbox.pack({'expand': 1, 'fill': 'both', 'side': 'left'})
|
|
||||||
|
|
||||||
foldermenu = Menu(root)
|
|
||||||
foldermenu.add('command',
|
|
||||||
{'label': 'Open Folder',
|
|
||||||
'command': open_folder})
|
|
||||||
foldermenu.add('separator')
|
|
||||||
foldermenu.add('command',
|
|
||||||
{'label': 'Quit',
|
|
||||||
'command': 'exit'})
|
|
||||||
foldermenu.bind('<ButtonRelease-3>', folder_unpost)
|
|
||||||
|
|
||||||
folderbox['yscrollcommand'] = (folderbar, 'set')
|
|
||||||
folderbar['command'] = (folderbox, 'yview')
|
|
||||||
folderbox.bind('<Double-1>', open_folder, 1)
|
|
||||||
folderbox.bind('<3>', folder_post)
|
|
||||||
|
|
||||||
# Build left part: scan list
|
|
||||||
|
|
||||||
left = Frame(top)
|
|
||||||
left.pack({'expand': 1, 'fill': 'both', 'side': 'left'})
|
|
||||||
|
|
||||||
scanbar = Scrollbar(left, {'relief': 'sunken', 'bd': 2})
|
|
||||||
scanbar.pack({'fill': 'y', 'side': 'right'})
|
|
||||||
|
|
||||||
scanbox = Listbox(left, {'font': 'fixed'})
|
|
||||||
scanbox.pack({'expand': 1, 'fill': 'both', 'side': 'left'})
|
|
||||||
|
|
||||||
scanmenu = Menu(root)
|
|
||||||
scanmenu.add('command',
|
|
||||||
{'label': 'Open Message',
|
|
||||||
'command': open_message})
|
|
||||||
scanmenu.add('command',
|
|
||||||
{'label': 'Remove Message',
|
|
||||||
'command': remove_message})
|
|
||||||
scanmenu.add('command',
|
|
||||||
{'label': 'Refile Message',
|
|
||||||
'command': refile_message})
|
|
||||||
scanmenu.add('separator')
|
|
||||||
scanmenu.add('command',
|
|
||||||
{'label': 'Quit',
|
|
||||||
'command': 'exit'})
|
|
||||||
scanmenu.bind('<ButtonRelease-3>', scan_unpost)
|
|
||||||
|
|
||||||
scanbox['yscrollcommand'] = (scanbar, 'set')
|
|
||||||
scanbar['command'] = (scanbox, 'yview')
|
|
||||||
scanbox.bind('<Double-1>', open_message)
|
|
||||||
scanbox.bind('<3>', scan_post)
|
|
||||||
|
|
||||||
# Separator between middle and bottom part
|
|
||||||
|
|
||||||
rule2 = Frame(root, {'bg': 'black'})
|
|
||||||
rule2.pack({'fill': 'x'})
|
|
||||||
|
|
||||||
# Build bottom part: current message
|
|
||||||
|
|
||||||
bot = Frame(root)
|
|
||||||
bot.pack({'expand': 1, 'fill': 'both'})
|
|
||||||
#
|
|
||||||
viewer = None
|
|
||||||
|
|
||||||
# Window manager commands
|
|
||||||
|
|
||||||
root.minsize(800, 1) # Make window resizable
|
|
||||||
|
|
||||||
# Fill folderbox with text
|
|
||||||
|
|
||||||
setfolders()
|
|
||||||
|
|
||||||
# Fill scanbox with text
|
|
||||||
|
|
||||||
rescan()
|
|
||||||
|
|
||||||
# Enter mainloop
|
|
||||||
|
|
||||||
root.mainloop()
|
|
||||||
|
|
||||||
def folder_post(e):
|
|
||||||
x, y = e.x_root, e.y_root
|
|
||||||
foldermenu.post(x - 10, y - 10)
|
|
||||||
foldermenu.grab_set()
|
|
||||||
|
|
||||||
def folder_unpost(e):
|
|
||||||
tk.call('update', 'idletasks')
|
|
||||||
foldermenu.grab_release()
|
|
||||||
foldermenu.unpost()
|
|
||||||
foldermenu.invoke('active')
|
|
||||||
|
|
||||||
def scan_post(e):
|
|
||||||
x, y = e.x_root, e.y_root
|
|
||||||
scanmenu.post(x - 10, y - 10)
|
|
||||||
scanmenu.grab_set()
|
|
||||||
|
|
||||||
def scan_unpost(e):
|
|
||||||
tk.call('update', 'idletasks')
|
|
||||||
scanmenu.grab_release()
|
|
||||||
scanmenu.unpost()
|
|
||||||
scanmenu.invoke('active')
|
|
||||||
|
|
||||||
scanparser = re.compile('^ *([0-9]+)')
|
|
||||||
|
|
||||||
def open_folder(e=None):
|
|
||||||
global folder, mhf
|
|
||||||
sel = folderbox.curselection()
|
|
||||||
if len(sel) != 1:
|
|
||||||
if len(sel) > 1:
|
|
||||||
msg = "Please open one folder at a time"
|
|
||||||
else:
|
|
||||||
msg = "Please select a folder to open"
|
|
||||||
dialog(root, "Can't Open Folder", msg, "", 0, "OK")
|
|
||||||
return
|
|
||||||
i = sel[0]
|
|
||||||
folder = folderbox.get(i)
|
|
||||||
mhf = mh.get_folder(folder)
|
|
||||||
rescan()
|
|
||||||
|
|
||||||
def open_message(e=None):
|
|
||||||
global viewer
|
|
||||||
sel = scanbox.curselection()
|
|
||||||
if len(sel) != 1:
|
|
||||||
if len(sel) > 1:
|
|
||||||
msg = "Please open one message at a time"
|
|
||||||
else:
|
|
||||||
msg = "Please select a message to open"
|
|
||||||
dialog(root, "Can't Open Message", msg, "", 0, "OK")
|
|
||||||
return
|
|
||||||
cursor = scanbox['cursor']
|
|
||||||
scanbox['cursor'] = 'watch'
|
|
||||||
tk.call('update', 'idletasks')
|
|
||||||
i = sel[0]
|
|
||||||
line = scanbox.get(i)
|
|
||||||
m = scanparser.match(line)
|
|
||||||
if m:
|
|
||||||
num = int(m.group(1))
|
|
||||||
m = mhf.get_message(num)
|
|
||||||
if viewer: viewer.destroy()
|
|
||||||
from mimeviewer import MimeViewer
|
|
||||||
viewer = MimeViewer(bot, '+%s/%d' % (folder, num), m)
|
|
||||||
viewer.pack()
|
|
||||||
viewer.show()
|
|
||||||
scanbox['cursor'] = cursor
|
|
||||||
|
|
||||||
def interestingheader(header):
|
|
||||||
return header != 'received'
|
|
||||||
|
|
||||||
def remove_message(e=None):
|
|
||||||
itop = scanbox.nearest(0)
|
|
||||||
sel = scanbox.curselection()
|
|
||||||
if not sel:
|
|
||||||
dialog(root, "No Message To Remove",
|
|
||||||
"Please select a message to remove", "", 0, "OK")
|
|
||||||
return
|
|
||||||
todo = []
|
|
||||||
for i in sel:
|
|
||||||
line = scanbox.get(i)
|
|
||||||
m = scanparser.match(line)
|
|
||||||
if m:
|
|
||||||
toremove = int(m.group(1))
|
|
||||||
todo.append(toremove)
|
|
||||||
mhf.remove(toremove)
|
|
||||||
rescan()
|
|
||||||
fixfocus(min(todo), itop)
|
|
||||||
|
|
||||||
lastrefile = ''
|
|
||||||
tofolder = None
|
|
||||||
def refile_message(e=None):
|
|
||||||
global lastrefile, tofolder
|
|
||||||
itop = scanbox.nearest(0)
|
|
||||||
sel = scanbox.curselection()
|
|
||||||
if not sel:
|
|
||||||
dialog(root, "No Message To Refile",
|
|
||||||
"Please select a message to refile", "", 0, "OK")
|
|
||||||
return
|
|
||||||
foldersel = folderbox.curselection()
|
|
||||||
if len(foldersel) != 1:
|
|
||||||
if not foldersel:
|
|
||||||
msg = "Please select a folder to refile to"
|
|
||||||
else:
|
|
||||||
msg = "Please select exactly one folder to refile to"
|
|
||||||
dialog(root, "No Folder To Refile", msg, "", 0, "OK")
|
|
||||||
return
|
|
||||||
refileto = folderbox.get(foldersel[0])
|
|
||||||
todo = []
|
|
||||||
for i in sel:
|
|
||||||
line = scanbox.get(i)
|
|
||||||
m = scanparser.match(line)
|
|
||||||
if m:
|
|
||||||
todo.append(int(m.group(1)))
|
|
||||||
if lastrefile != refileto or not tofolder:
|
|
||||||
lastrefile = refileto
|
|
||||||
tofolder = None
|
|
||||||
tofolder = mh.get_folder(lastrefile)
|
|
||||||
mhf.refilemessages(todo, tofolder)
|
|
||||||
rescan()
|
|
||||||
fixfocus(min(todo), itop)
|
|
||||||
|
|
||||||
def fixfocus(near, itop):
|
|
||||||
n = scanbox.size()
|
|
||||||
for i in range(n):
|
|
||||||
line = scanbox.get(repr(i))
|
|
||||||
m = scanparser.match(line)
|
|
||||||
if m:
|
|
||||||
num = int(m.group(1))
|
|
||||||
if num >= near:
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
i = 'end'
|
|
||||||
scanbox.yview(itop)
|
|
||||||
|
|
||||||
def setfolders():
|
|
||||||
folderbox.delete(0, 'end')
|
|
||||||
for fn in mh.list_folders():
|
|
||||||
folderbox.insert('end', fn)
|
|
||||||
|
|
||||||
def rescan():
|
|
||||||
global viewer
|
|
||||||
if viewer:
|
|
||||||
viewer.destroy()
|
|
||||||
viewer = None
|
|
||||||
scanbox.delete(0, 'end')
|
|
||||||
for line in scanfolder(folder, seq):
|
|
||||||
scanbox.insert('end', line)
|
|
||||||
|
|
||||||
def scanfolder(folder = 'inbox', sequence = 'all'):
|
|
||||||
return [line[:-1] for line in
|
|
||||||
os.popen('scan +%s %s' % (folder, sequence), 'r').readlines()]
|
|
||||||
|
|
||||||
main()
|
|
|
@ -1,159 +0,0 @@
|
||||||
#! /usr/bin/env python3
|
|
||||||
|
|
||||||
# View a single MIME multipart message.
|
|
||||||
# Display each part as a box.
|
|
||||||
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
import getopt
|
|
||||||
import mailbox
|
|
||||||
from tkinter import *
|
|
||||||
from tkinter.scrolledtext import ScrolledText
|
|
||||||
|
|
||||||
MBOXPATH = os.environ['HOME'] + '/Mail'
|
|
||||||
|
|
||||||
class Error(Exception):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def getcurrent(self):
|
|
||||||
"""Return the current message. Raise Error when there is none."""
|
|
||||||
seqs = self.get_sequences()
|
|
||||||
try:
|
|
||||||
return max(seqs['cur'])
|
|
||||||
except (ValueError, KeyError):
|
|
||||||
raise Error("no cur message")
|
|
||||||
|
|
||||||
|
|
||||||
class MimeViewer:
|
|
||||||
def __init__(self, parent, title, msg):
|
|
||||||
self.title = title
|
|
||||||
self.msg = msg
|
|
||||||
self.frame = Frame(parent, {'relief': 'raised', 'bd': 2})
|
|
||||||
self.frame.packing = {'expand': 0, 'fill': 'both'}
|
|
||||||
self.button = Checkbutton(self.frame,
|
|
||||||
{'text': title,
|
|
||||||
'command': self.toggle})
|
|
||||||
self.button.pack({'anchor': 'w'})
|
|
||||||
headertext = []
|
|
||||||
for item in msg.items():
|
|
||||||
headertext.append("%s: %s" % item)
|
|
||||||
headertext = '\n'.join(headertext)
|
|
||||||
height = countlines(headertext, 4)
|
|
||||||
if height:
|
|
||||||
self.htext = ScrolledText(self.frame,
|
|
||||||
{'height': height,
|
|
||||||
'width': 80,
|
|
||||||
'wrap': 'none',
|
|
||||||
'relief': 'raised',
|
|
||||||
'bd': 2})
|
|
||||||
self.htext.packing = {'expand': 1, 'fill': 'both',
|
|
||||||
'after': self.button}
|
|
||||||
self.htext.insert('end', headertext)
|
|
||||||
else:
|
|
||||||
self.htext = Frame(self.frame,
|
|
||||||
{'relief': 'raised', 'bd': 2})
|
|
||||||
self.htext.packing = {'side': 'top',
|
|
||||||
'ipady': 2,
|
|
||||||
'fill': 'x',
|
|
||||||
'after': self.button}
|
|
||||||
body = msg.get_payload()
|
|
||||||
if type(body) == str:
|
|
||||||
self.pad = None
|
|
||||||
height = countlines(body, 10)
|
|
||||||
if height:
|
|
||||||
self.btext = ScrolledText(self.frame,
|
|
||||||
{'height': height,
|
|
||||||
'width': 80,
|
|
||||||
'wrap': 'none',
|
|
||||||
'relief': 'raised',
|
|
||||||
'bd': 2})
|
|
||||||
self.btext.packing = {'expand': 1,
|
|
||||||
'fill': 'both'}
|
|
||||||
self.btext.insert('end', body)
|
|
||||||
else:
|
|
||||||
self.btext = None
|
|
||||||
self.parts = None
|
|
||||||
else:
|
|
||||||
self.pad = Frame(self.frame,
|
|
||||||
{'relief': 'flat', 'bd': 2})
|
|
||||||
self.pad.packing = {'side': 'left', 'ipadx': 10,
|
|
||||||
'fill': 'y', 'after': self.htext}
|
|
||||||
self.parts = []
|
|
||||||
for i in range(len(body)):
|
|
||||||
p = MimeViewer(self.frame,
|
|
||||||
'%s.%d' % (title, i+1),
|
|
||||||
body[i])
|
|
||||||
self.parts.append(p)
|
|
||||||
self.btext = None
|
|
||||||
self.collapsed = 1
|
|
||||||
def pack(self):
|
|
||||||
self.frame.pack(self.frame.packing)
|
|
||||||
def destroy(self):
|
|
||||||
self.frame.destroy()
|
|
||||||
def show(self):
|
|
||||||
if self.collapsed:
|
|
||||||
self.button.invoke()
|
|
||||||
def toggle(self):
|
|
||||||
if self.collapsed:
|
|
||||||
self.explode()
|
|
||||||
else:
|
|
||||||
self.collapse()
|
|
||||||
def collapse(self):
|
|
||||||
self.collapsed = 1
|
|
||||||
for comp in self.htext, self.btext, self.pad:
|
|
||||||
if comp:
|
|
||||||
comp.forget()
|
|
||||||
if self.parts:
|
|
||||||
for part in self.parts:
|
|
||||||
part.frame.forget()
|
|
||||||
self.frame.pack({'expand': 0})
|
|
||||||
def explode(self):
|
|
||||||
self.collapsed = 0
|
|
||||||
for comp in self.htext, self.btext, self.pad:
|
|
||||||
if comp: comp.pack(comp.packing)
|
|
||||||
if self.parts:
|
|
||||||
for part in self.parts:
|
|
||||||
part.pack()
|
|
||||||
self.frame.pack({'expand': 1})
|
|
||||||
|
|
||||||
def countlines(str, limit):
|
|
||||||
i = 0
|
|
||||||
n = 0
|
|
||||||
while n < limit:
|
|
||||||
i = str.find('\n', i)
|
|
||||||
if i < 0: break
|
|
||||||
n = n+1
|
|
||||||
i = i+1
|
|
||||||
return n
|
|
||||||
|
|
||||||
def main():
|
|
||||||
opts, args = getopt.getopt(sys.argv[1:], '')
|
|
||||||
for o, a in opts:
|
|
||||||
pass
|
|
||||||
message = None
|
|
||||||
folder = 'inbox'
|
|
||||||
for arg in args:
|
|
||||||
if arg[:1] == '+':
|
|
||||||
folder = arg[1:]
|
|
||||||
else:
|
|
||||||
message = int(arg)
|
|
||||||
|
|
||||||
mh = mailbox.MH(MBOXPATH)
|
|
||||||
f = mh.get_folder(folder)
|
|
||||||
if message is None:
|
|
||||||
message = getcurrent(f)
|
|
||||||
m = mailbox.MHMessage(f.get(message))
|
|
||||||
|
|
||||||
root = Tk()
|
|
||||||
tk = root.tk
|
|
||||||
|
|
||||||
top = MimeViewer(root, '+%s/%d' % (folder, message), m)
|
|
||||||
top.pack()
|
|
||||||
top.show()
|
|
||||||
|
|
||||||
root.minsize(1, 1)
|
|
||||||
|
|
||||||
tk.mainloop()
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main()
|
|
|
@ -1,47 +0,0 @@
|
||||||
#! /usr/bin/env python3
|
|
||||||
|
|
||||||
"""Play with the new Tk 8.0 toplevel menu option."""
|
|
||||||
|
|
||||||
from tkinter import *
|
|
||||||
|
|
||||||
class App:
|
|
||||||
|
|
||||||
def __init__(self, master):
|
|
||||||
self.master = master
|
|
||||||
|
|
||||||
self.menubar = Menu(self.master)
|
|
||||||
|
|
||||||
self.filemenu = Menu(self.menubar)
|
|
||||||
|
|
||||||
self.filemenu.add_command(label="New")
|
|
||||||
self.filemenu.add_command(label="Open...")
|
|
||||||
self.filemenu.add_command(label="Close")
|
|
||||||
self.filemenu.add_separator()
|
|
||||||
self.filemenu.add_command(label="Quit", command=self.master.quit)
|
|
||||||
|
|
||||||
self.editmenu = Menu(self.menubar)
|
|
||||||
|
|
||||||
self.editmenu.add_command(label="Cut")
|
|
||||||
self.editmenu.add_command(label="Copy")
|
|
||||||
self.editmenu.add_command(label="Paste")
|
|
||||||
|
|
||||||
self.helpmenu = Menu(self.menubar, name='help')
|
|
||||||
|
|
||||||
self.helpmenu.add_command(label="About...")
|
|
||||||
|
|
||||||
self.menubar.add_cascade(label="File", menu=self.filemenu)
|
|
||||||
self.menubar.add_cascade(label="Edit", menu=self.editmenu)
|
|
||||||
self.menubar.add_cascade(label="Help", menu=self.helpmenu)
|
|
||||||
|
|
||||||
self.top = Toplevel(menu=self.menubar)
|
|
||||||
|
|
||||||
# Rest of app goes here...
|
|
||||||
|
|
||||||
def main():
|
|
||||||
root = Tk()
|
|
||||||
root.withdraw()
|
|
||||||
app = App(root)
|
|
||||||
root.mainloop()
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main()
|
|
|
@ -1,27 +0,0 @@
|
||||||
# option menu sample (Fredrik Lundh, September 1997)
|
|
||||||
|
|
||||||
from tkinter import *
|
|
||||||
|
|
||||||
root = Tk()
|
|
||||||
|
|
||||||
#
|
|
||||||
# standard usage
|
|
||||||
|
|
||||||
var1 = StringVar()
|
|
||||||
var1.set("One") # default selection
|
|
||||||
|
|
||||||
menu1 = OptionMenu(root, var1, "One", "Two", "Three")
|
|
||||||
menu1.pack()
|
|
||||||
|
|
||||||
#
|
|
||||||
# initialize from a sequence
|
|
||||||
|
|
||||||
CHOICES = "Aah", "Bee", "Cee", "Dee", "Eff"
|
|
||||||
|
|
||||||
var2 = StringVar()
|
|
||||||
var2.set(CHOICES[0])
|
|
||||||
|
|
||||||
menu2 = OptionMenu(root, var2, *CHOICES)
|
|
||||||
menu2.pack()
|
|
||||||
|
|
||||||
root.mainloop()
|
|
|
@ -1,60 +0,0 @@
|
||||||
""""Paint program by Dave Michell.
|
|
||||||
|
|
||||||
Subject: tkinter "paint" example
|
|
||||||
From: Dave Mitchell <davem@magnet.com>
|
|
||||||
To: python-list@cwi.nl
|
|
||||||
Date: Fri, 23 Jan 1998 12:18:05 -0500 (EST)
|
|
||||||
|
|
||||||
Not too long ago (last week maybe?) someone posted a request
|
|
||||||
for an example of a paint program using Tkinter. Try as I might
|
|
||||||
I can't seem to find it in the archive, so i'll just post mine
|
|
||||||
here and hope that the person who requested it sees this!
|
|
||||||
|
|
||||||
All this does is put up a canvas and draw a smooth black line
|
|
||||||
whenever you have the mouse button down, but hopefully it will
|
|
||||||
be enough to start with.. It would be easy enough to add some
|
|
||||||
options like other shapes or colors...
|
|
||||||
|
|
||||||
yours,
|
|
||||||
dave mitchell
|
|
||||||
davem@magnet.com
|
|
||||||
"""
|
|
||||||
|
|
||||||
from tkinter import *
|
|
||||||
|
|
||||||
"""paint.py: not exactly a paint program.. just a smooth line drawing demo."""
|
|
||||||
|
|
||||||
b1 = "up"
|
|
||||||
xold, yold = None, None
|
|
||||||
|
|
||||||
def main():
|
|
||||||
root = Tk()
|
|
||||||
drawing_area = Canvas(root)
|
|
||||||
drawing_area.pack()
|
|
||||||
drawing_area.bind("<Motion>", motion)
|
|
||||||
drawing_area.bind("<ButtonPress-1>", b1down)
|
|
||||||
drawing_area.bind("<ButtonRelease-1>", b1up)
|
|
||||||
root.mainloop()
|
|
||||||
|
|
||||||
def b1down(event):
|
|
||||||
global b1
|
|
||||||
b1 = "down" # you only want to draw when the button is down
|
|
||||||
# because "Motion" events happen -all the time-
|
|
||||||
|
|
||||||
def b1up(event):
|
|
||||||
global b1, xold, yold
|
|
||||||
b1 = "up"
|
|
||||||
xold = None # reset the line when you let go of the button
|
|
||||||
yold = None
|
|
||||||
|
|
||||||
def motion(event):
|
|
||||||
if b1 == "down":
|
|
||||||
global xold, yold
|
|
||||||
if xold is not None and yold is not None:
|
|
||||||
event.widget.create_line(xold,yold,event.x,event.y,smooth=TRUE)
|
|
||||||
# here's where you draw it. smooth. neat.
|
|
||||||
xold = event.x
|
|
||||||
yold = event.y
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
main()
|
|
|
@ -1,159 +0,0 @@
|
||||||
#! /usr/bin/env python3
|
|
||||||
|
|
||||||
# A Python program implementing rmt, an application for remotely
|
|
||||||
# controlling other Tk applications.
|
|
||||||
# Cf. Ousterhout, Tcl and the Tk Toolkit, Figs. 27.5-8, pp. 273-276.
|
|
||||||
|
|
||||||
# Note that because of forward references in the original, we
|
|
||||||
# sometimes delay bindings until after the corresponding procedure is
|
|
||||||
# defined. We also introduce names for some unnamed code blocks in
|
|
||||||
# the original because of restrictions on lambda forms in Python.
|
|
||||||
|
|
||||||
# XXX This should be written in a more Python-like style!!!
|
|
||||||
|
|
||||||
from tkinter import *
|
|
||||||
import sys
|
|
||||||
|
|
||||||
# 1. Create basic application structure: menu bar on top of
|
|
||||||
# text widget, scrollbar on right.
|
|
||||||
|
|
||||||
root = Tk()
|
|
||||||
tk = root.tk
|
|
||||||
mBar = Frame(root, relief=RAISED, borderwidth=2)
|
|
||||||
mBar.pack(fill=X)
|
|
||||||
|
|
||||||
f = Frame(root)
|
|
||||||
f.pack(expand=1, fill=BOTH)
|
|
||||||
s = Scrollbar(f, relief=FLAT)
|
|
||||||
s.pack(side=RIGHT, fill=Y)
|
|
||||||
t = Text(f, relief=RAISED, borderwidth=2, yscrollcommand=s.set, setgrid=1)
|
|
||||||
t.pack(side=LEFT, fill=BOTH, expand=1)
|
|
||||||
t.tag_config('bold')
|
|
||||||
s['command'] = t.yview
|
|
||||||
|
|
||||||
root.title('Tk Remote Controller')
|
|
||||||
root.iconname('Tk Remote')
|
|
||||||
|
|
||||||
# 2. Create menu button and menus.
|
|
||||||
|
|
||||||
file = Menubutton(mBar, text='File', underline=0)
|
|
||||||
file.pack(side=LEFT)
|
|
||||||
file_m = Menu(file)
|
|
||||||
file['menu'] = file_m
|
|
||||||
file_m_apps = Menu(file_m, tearoff=0)
|
|
||||||
file_m.add_cascade(label='Select Application', underline=0,
|
|
||||||
menu=file_m_apps)
|
|
||||||
file_m.add_command(label='Quit', underline=0, command=sys.exit)
|
|
||||||
|
|
||||||
# 3. Create bindings for text widget to allow commands to be
|
|
||||||
# entered and information to be selected. New characters
|
|
||||||
# can only be added at the end of the text (can't ever move
|
|
||||||
# insertion point).
|
|
||||||
|
|
||||||
def single1(e):
|
|
||||||
x = e.x
|
|
||||||
y = e.y
|
|
||||||
t.setvar('tk_priv(selectMode)', 'char')
|
|
||||||
t.mark_set('anchor', At(x, y))
|
|
||||||
# Should focus W
|
|
||||||
t.bind('<1>', single1)
|
|
||||||
|
|
||||||
def double1(e):
|
|
||||||
x = e.x
|
|
||||||
y = e.y
|
|
||||||
t.setvar('tk_priv(selectMode)', 'word')
|
|
||||||
t.tk_textSelectTo(At(x, y))
|
|
||||||
t.bind('<Double-1>', double1)
|
|
||||||
|
|
||||||
def triple1(e):
|
|
||||||
x = e.x
|
|
||||||
y = e.y
|
|
||||||
t.setvar('tk_priv(selectMode)', 'line')
|
|
||||||
t.tk_textSelectTo(At(x, y))
|
|
||||||
t.bind('<Triple-1>', triple1)
|
|
||||||
|
|
||||||
def returnkey(e):
|
|
||||||
t.insert(AtInsert(), '\n')
|
|
||||||
invoke()
|
|
||||||
t.bind('<Return>', returnkey)
|
|
||||||
|
|
||||||
def controlv(e):
|
|
||||||
t.insert(AtInsert(), t.selection_get())
|
|
||||||
t.yview_pickplace(AtInsert())
|
|
||||||
if t.index(AtInsert())[-2:] == '.0':
|
|
||||||
invoke()
|
|
||||||
t.bind('<Control-v>', controlv)
|
|
||||||
|
|
||||||
# 4. Procedure to backspace over one character, as long as
|
|
||||||
# the character isn't part of the prompt.
|
|
||||||
|
|
||||||
def backspace(e):
|
|
||||||
if t.index('promptEnd') != t.index('insert - 1 char'):
|
|
||||||
t.delete('insert - 1 char', AtInsert())
|
|
||||||
t.yview_pickplace(AtInsert())
|
|
||||||
t.bind('<BackSpace>', backspace)
|
|
||||||
t.bind('<Control-h>', backspace)
|
|
||||||
t.bind('<Delete>', backspace)
|
|
||||||
|
|
||||||
|
|
||||||
# 5. Procedure that's invoked when return is typed: if
|
|
||||||
# there's not yet a complete command (e.g. braces are open)
|
|
||||||
# then do nothing. Otherwise, execute command (locally or
|
|
||||||
# remotely), output the result or error message, and issue
|
|
||||||
# a new prompt.
|
|
||||||
|
|
||||||
def invoke():
|
|
||||||
cmd = t.get('promptEnd + 1 char', AtInsert())
|
|
||||||
if t.getboolean(tk.call('info', 'complete', cmd)): # XXX
|
|
||||||
if app == root.winfo_name():
|
|
||||||
msg = tk.call('eval', cmd) # XXX
|
|
||||||
else:
|
|
||||||
msg = t.send(app, cmd)
|
|
||||||
if msg:
|
|
||||||
t.insert(AtInsert(), msg + '\n')
|
|
||||||
prompt()
|
|
||||||
t.yview_pickplace(AtInsert())
|
|
||||||
|
|
||||||
def prompt():
|
|
||||||
t.insert(AtInsert(), app + ': ')
|
|
||||||
t.mark_set('promptEnd', 'insert - 1 char')
|
|
||||||
t.tag_add('bold', 'insert linestart', 'promptEnd')
|
|
||||||
|
|
||||||
# 6. Procedure to select a new application. Also changes
|
|
||||||
# the prompt on the current command line to reflect the new
|
|
||||||
# name.
|
|
||||||
|
|
||||||
def newApp(appName):
|
|
||||||
global app
|
|
||||||
app = appName
|
|
||||||
t.delete('promptEnd linestart', 'promptEnd')
|
|
||||||
t.insert('promptEnd', appName + ':')
|
|
||||||
t.tag_add('bold', 'promptEnd linestart', 'promptEnd')
|
|
||||||
|
|
||||||
def fillAppsMenu():
|
|
||||||
file_m_apps.add('command')
|
|
||||||
file_m_apps.delete(0, 'last')
|
|
||||||
names = root.winfo_interps()
|
|
||||||
names = list(names) # convert tuple to list
|
|
||||||
names.sort()
|
|
||||||
for name in names:
|
|
||||||
try:
|
|
||||||
root.send(name, 'winfo name .')
|
|
||||||
except TclError:
|
|
||||||
# Inoperative window -- ignore it
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
file_m_apps.add_command(
|
|
||||||
label=name,
|
|
||||||
command=lambda name=name: newApp(name))
|
|
||||||
|
|
||||||
file_m_apps['postcommand'] = fillAppsMenu
|
|
||||||
mBar.tk_menuBar(file)
|
|
||||||
|
|
||||||
# 7. Miscellaneous initialization.
|
|
||||||
|
|
||||||
app = root.winfo_name()
|
|
||||||
prompt()
|
|
||||||
t.focus()
|
|
||||||
|
|
||||||
root.mainloop()
|
|
|
@ -1,146 +0,0 @@
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
from tkinter import *
|
|
||||||
from tkinter.scrolledtext import ScrolledText
|
|
||||||
from tkinter.dialog import Dialog
|
|
||||||
import signal
|
|
||||||
|
|
||||||
BUFSIZE = 512
|
|
||||||
|
|
||||||
class ShellWindow(ScrolledText):
|
|
||||||
|
|
||||||
def __init__(self, master=None, shell=None, **cnf):
|
|
||||||
if not shell:
|
|
||||||
try:
|
|
||||||
shell = os.environ['SHELL']
|
|
||||||
except KeyError:
|
|
||||||
shell = '/bin/sh'
|
|
||||||
shell = shell + ' -i'
|
|
||||||
args = shell.split()
|
|
||||||
shell = args[0]
|
|
||||||
|
|
||||||
ScrolledText.__init__(self, master, **cnf)
|
|
||||||
self.pos = '1.0'
|
|
||||||
self.bind('<Return>', self.inputhandler)
|
|
||||||
self.bind('<Control-c>', self.sigint)
|
|
||||||
self.bind('<Control-t>', self.sigterm)
|
|
||||||
self.bind('<Control-k>', self.sigkill)
|
|
||||||
self.bind('<Control-d>', self.sendeof)
|
|
||||||
|
|
||||||
self.pid, self.fromchild, self.tochild = spawn(shell, args)
|
|
||||||
self.tk.createfilehandler(self.fromchild, READABLE,
|
|
||||||
self.outputhandler)
|
|
||||||
|
|
||||||
def outputhandler(self, file, mask):
|
|
||||||
data = os.read(file, BUFSIZE).decode()
|
|
||||||
if not data:
|
|
||||||
self.tk.deletefilehandler(file)
|
|
||||||
pid, sts = os.waitpid(self.pid, 0)
|
|
||||||
print('pid', pid, 'status', sts)
|
|
||||||
self.pid = None
|
|
||||||
detail = sts>>8
|
|
||||||
cause = sts & 0xff
|
|
||||||
if cause == 0:
|
|
||||||
msg = "exit status %d" % detail
|
|
||||||
else:
|
|
||||||
msg = "killed by signal %d" % (cause & 0x7f)
|
|
||||||
if cause & 0x80:
|
|
||||||
msg = msg + " -- core dumped"
|
|
||||||
Dialog(self.master,
|
|
||||||
text=msg,
|
|
||||||
title="Exit status",
|
|
||||||
bitmap='warning',
|
|
||||||
default=0,
|
|
||||||
strings=('OK',))
|
|
||||||
return
|
|
||||||
self.insert(END, data)
|
|
||||||
self.pos = self.index("end - 1 char")
|
|
||||||
self.yview_pickplace(END)
|
|
||||||
|
|
||||||
def inputhandler(self, *args):
|
|
||||||
if not self.pid:
|
|
||||||
self.no_process()
|
|
||||||
return "break"
|
|
||||||
self.insert(END, "\n")
|
|
||||||
line = self.get(self.pos, "end - 1 char")
|
|
||||||
self.pos = self.index(END)
|
|
||||||
os.write(self.tochild, line.encode())
|
|
||||||
return "break"
|
|
||||||
|
|
||||||
def sendeof(self, *args):
|
|
||||||
if not self.pid:
|
|
||||||
self.no_process()
|
|
||||||
return "break"
|
|
||||||
os.close(self.tochild)
|
|
||||||
return "break"
|
|
||||||
|
|
||||||
def sendsig(self, sig):
|
|
||||||
if not self.pid:
|
|
||||||
self.no_process()
|
|
||||||
return "break"
|
|
||||||
os.kill(self.pid, sig)
|
|
||||||
return "break"
|
|
||||||
|
|
||||||
def sigint(self, *args):
|
|
||||||
return self.sendsig(signal.SIGINT)
|
|
||||||
|
|
||||||
def sigquit(self, *args):
|
|
||||||
return self.sendsig(signal.SIGQUIT)
|
|
||||||
|
|
||||||
def sigterm(self, *args):
|
|
||||||
return self.sendsig(signal.SIGTERM)
|
|
||||||
|
|
||||||
def sigkill(self, *args):
|
|
||||||
return self.sendsig(signal.SIGKILL)
|
|
||||||
|
|
||||||
def no_process(self):
|
|
||||||
Dialog(self.master,
|
|
||||||
text="No active process",
|
|
||||||
title="No process",
|
|
||||||
bitmap='error',
|
|
||||||
default=0,
|
|
||||||
strings=('OK',))
|
|
||||||
|
|
||||||
MAXFD = 100 # Max number of file descriptors (os.getdtablesize()???)
|
|
||||||
|
|
||||||
def spawn(prog, args):
|
|
||||||
p2cread, p2cwrite = os.pipe()
|
|
||||||
c2pread, c2pwrite = os.pipe()
|
|
||||||
pid = os.fork()
|
|
||||||
if pid == 0:
|
|
||||||
# Child
|
|
||||||
for i in 0, 1, 2:
|
|
||||||
try:
|
|
||||||
os.close(i)
|
|
||||||
except os.error:
|
|
||||||
pass
|
|
||||||
if os.dup(p2cread) != 0:
|
|
||||||
sys.stderr.write('popen2: bad read dup\n')
|
|
||||||
if os.dup(c2pwrite) != 1:
|
|
||||||
sys.stderr.write('popen2: bad write dup\n')
|
|
||||||
if os.dup(c2pwrite) != 2:
|
|
||||||
sys.stderr.write('popen2: bad write dup\n')
|
|
||||||
os.closerange(3, MAXFD)
|
|
||||||
try:
|
|
||||||
os.execvp(prog, args)
|
|
||||||
finally:
|
|
||||||
sys.stderr.write('execvp failed\n')
|
|
||||||
os._exit(1)
|
|
||||||
os.close(p2cread)
|
|
||||||
os.close(c2pwrite)
|
|
||||||
return pid, c2pread, p2cwrite
|
|
||||||
|
|
||||||
def test():
|
|
||||||
shell = ' '.join(sys.argv[1: ])
|
|
||||||
root = Tk()
|
|
||||||
root.minsize(1, 1)
|
|
||||||
if shell:
|
|
||||||
w = ShellWindow(root, shell=shell)
|
|
||||||
else:
|
|
||||||
w = ShellWindow(root)
|
|
||||||
w.pack(expand=1, fill=BOTH)
|
|
||||||
w.focus_set()
|
|
||||||
w.tk.mainloop()
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
test()
|
|
|
@ -1,626 +0,0 @@
|
||||||
#! /usr/bin/env python3
|
|
||||||
|
|
||||||
"""Solitaire game, much like the one that comes with MS Windows.
|
|
||||||
|
|
||||||
Limitations:
|
|
||||||
|
|
||||||
- No cute graphical images for the playing cards faces or backs.
|
|
||||||
- No scoring or timer.
|
|
||||||
- No undo.
|
|
||||||
- No option to turn 3 cards at a time.
|
|
||||||
- No keyboard shortcuts.
|
|
||||||
- Less fancy animation when you win.
|
|
||||||
- The determination of which stack you drag to is more relaxed.
|
|
||||||
|
|
||||||
Apology:
|
|
||||||
|
|
||||||
I'm not much of a card player, so my terminology in these comments may
|
|
||||||
at times be a little unusual. If you have suggestions, please let me
|
|
||||||
know!
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
# Imports
|
|
||||||
|
|
||||||
import random
|
|
||||||
|
|
||||||
from tkinter import *
|
|
||||||
from canvasevents import Group
|
|
||||||
|
|
||||||
|
|
||||||
# Constants determining the size and lay-out of cards and stacks. We
|
|
||||||
# work in a "grid" where each card/stack is surrounded by MARGIN
|
|
||||||
# pixels of space on each side, so adjacent stacks are separated by
|
|
||||||
# 2*MARGIN pixels. OFFSET is the offset used for displaying the
|
|
||||||
# face down cards in the row stacks.
|
|
||||||
|
|
||||||
CARDWIDTH = 100
|
|
||||||
CARDHEIGHT = 150
|
|
||||||
MARGIN = 10
|
|
||||||
XSPACING = CARDWIDTH + 2*MARGIN
|
|
||||||
YSPACING = CARDHEIGHT + 4*MARGIN
|
|
||||||
OFFSET = 5
|
|
||||||
|
|
||||||
# The background color, green to look like a playing table. The
|
|
||||||
# standard green is way too bright, and dark green is way to dark, so
|
|
||||||
# we use something in between. (There are a few more colors that
|
|
||||||
# could be customized, but they are less controversial.)
|
|
||||||
|
|
||||||
BACKGROUND = '#070'
|
|
||||||
|
|
||||||
|
|
||||||
# Suits and colors. The values of the symbolic suit names are the
|
|
||||||
# strings used to display them (you change these and VALNAMES to
|
|
||||||
# internationalize the game). The COLOR dictionary maps suit names to
|
|
||||||
# colors (red and black) which must be Tk color names. The keys() of
|
|
||||||
# the COLOR dictionary conveniently provides us with a list of all
|
|
||||||
# suits (in arbitrary order).
|
|
||||||
|
|
||||||
HEARTS = 'Heart'
|
|
||||||
DIAMONDS = 'Diamond'
|
|
||||||
CLUBS = 'Club'
|
|
||||||
SPADES = 'Spade'
|
|
||||||
|
|
||||||
RED = 'red'
|
|
||||||
BLACK = 'black'
|
|
||||||
|
|
||||||
COLOR = {}
|
|
||||||
for s in (HEARTS, DIAMONDS):
|
|
||||||
COLOR[s] = RED
|
|
||||||
for s in (CLUBS, SPADES):
|
|
||||||
COLOR[s] = BLACK
|
|
||||||
|
|
||||||
ALLSUITS = list(COLOR.keys())
|
|
||||||
NSUITS = len(ALLSUITS)
|
|
||||||
|
|
||||||
|
|
||||||
# Card values are 1-13. We also define symbolic names for the picture
|
|
||||||
# cards. ALLVALUES is a list of all card values.
|
|
||||||
|
|
||||||
ACE = 1
|
|
||||||
JACK = 11
|
|
||||||
QUEEN = 12
|
|
||||||
KING = 13
|
|
||||||
ALLVALUES = range(1, 14) # (one more than the highest value)
|
|
||||||
NVALUES = len(ALLVALUES)
|
|
||||||
|
|
||||||
|
|
||||||
# VALNAMES is a list that maps a card value to string. It contains a
|
|
||||||
# dummy element at index 0 so it can be indexed directly with the card
|
|
||||||
# value.
|
|
||||||
|
|
||||||
VALNAMES = ["", "A"] + list(map(str, range(2, 11))) + ["J", "Q", "K"]
|
|
||||||
|
|
||||||
|
|
||||||
# Solitaire constants. The only one I can think of is the number of
|
|
||||||
# row stacks.
|
|
||||||
|
|
||||||
NROWS = 7
|
|
||||||
|
|
||||||
|
|
||||||
# The rest of the program consists of class definitions. These are
|
|
||||||
# further described in their documentation strings.
|
|
||||||
|
|
||||||
|
|
||||||
class Card:
|
|
||||||
|
|
||||||
"""A playing card.
|
|
||||||
|
|
||||||
A card doesn't record to which stack it belongs; only the stack
|
|
||||||
records this (it turns out that we always know this from the
|
|
||||||
context, and this saves a ``double update'' with potential for
|
|
||||||
inconsistencies).
|
|
||||||
|
|
||||||
Public methods:
|
|
||||||
|
|
||||||
moveto(x, y) -- move the card to an absolute position
|
|
||||||
moveby(dx, dy) -- move the card by a relative offset
|
|
||||||
tkraise() -- raise the card to the top of its stack
|
|
||||||
showface(), showback() -- turn the card face up or down & raise it
|
|
||||||
|
|
||||||
Public read-only instance variables:
|
|
||||||
|
|
||||||
suit, value, color -- the card's suit, value and color
|
|
||||||
face_shown -- true when the card is shown face up, else false
|
|
||||||
|
|
||||||
Semi-public read-only instance variables (XXX should be made
|
|
||||||
private):
|
|
||||||
|
|
||||||
group -- the Canvas.Group representing the card
|
|
||||||
x, y -- the position of the card's top left corner
|
|
||||||
|
|
||||||
Private instance variables:
|
|
||||||
|
|
||||||
__back, __rect, __text -- the canvas items making up the card
|
|
||||||
|
|
||||||
(To show the card face up, the text item is placed in front of
|
|
||||||
rect and the back is placed behind it. To show it face down, this
|
|
||||||
is reversed. The card is created face down.)
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, suit, value, canvas):
|
|
||||||
"""Card constructor.
|
|
||||||
|
|
||||||
Arguments are the card's suit and value, and the canvas widget.
|
|
||||||
|
|
||||||
The card is created at position (0, 0), with its face down
|
|
||||||
(adding it to a stack will position it according to that
|
|
||||||
stack's rules).
|
|
||||||
|
|
||||||
"""
|
|
||||||
self.suit = suit
|
|
||||||
self.value = value
|
|
||||||
self.color = COLOR[suit]
|
|
||||||
self.face_shown = 0
|
|
||||||
|
|
||||||
self.x = self.y = 0
|
|
||||||
self.canvas = canvas
|
|
||||||
self.group = Group(canvas)
|
|
||||||
|
|
||||||
text = "%s %s" % (VALNAMES[value], suit)
|
|
||||||
self.__text = canvas.create_text(CARDWIDTH // 2, 0, anchor=N,
|
|
||||||
fill=self.color, text=text)
|
|
||||||
self.group.addtag_withtag(self.__text)
|
|
||||||
|
|
||||||
self.__rect = canvas.create_rectangle(0, 0, CARDWIDTH, CARDHEIGHT,
|
|
||||||
outline='black', fill='white')
|
|
||||||
self.group.addtag_withtag(self.__rect)
|
|
||||||
|
|
||||||
self.__back = canvas.create_rectangle(MARGIN, MARGIN,
|
|
||||||
CARDWIDTH - MARGIN,
|
|
||||||
CARDHEIGHT - MARGIN,
|
|
||||||
outline='black', fill='blue')
|
|
||||||
self.group.addtag_withtag(self.__back)
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
"""Return a string for debug print statements."""
|
|
||||||
return "Card(%r, %r)" % (self.suit, self.value)
|
|
||||||
|
|
||||||
def moveto(self, x, y):
|
|
||||||
"""Move the card to absolute position (x, y)."""
|
|
||||||
self.moveby(x - self.x, y - self.y)
|
|
||||||
|
|
||||||
def moveby(self, dx, dy):
|
|
||||||
"""Move the card by (dx, dy)."""
|
|
||||||
self.x = self.x + dx
|
|
||||||
self.y = self.y + dy
|
|
||||||
self.group.move(dx, dy)
|
|
||||||
|
|
||||||
def tkraise(self):
|
|
||||||
"""Raise the card above all other objects in its canvas."""
|
|
||||||
self.group.tkraise()
|
|
||||||
|
|
||||||
def showface(self):
|
|
||||||
"""Turn the card's face up."""
|
|
||||||
self.tkraise()
|
|
||||||
self.canvas.tag_raise(self.__rect)
|
|
||||||
self.canvas.tag_raise(self.__text)
|
|
||||||
self.face_shown = 1
|
|
||||||
|
|
||||||
def showback(self):
|
|
||||||
"""Turn the card's face down."""
|
|
||||||
self.tkraise()
|
|
||||||
self.canvas.tag_raise(self.__rect)
|
|
||||||
self.canvas.tag_raise(self.__back)
|
|
||||||
self.face_shown = 0
|
|
||||||
|
|
||||||
|
|
||||||
class Stack:
|
|
||||||
|
|
||||||
"""A generic stack of cards.
|
|
||||||
|
|
||||||
This is used as a base class for all other stacks (e.g. the deck,
|
|
||||||
the suit stacks, and the row stacks).
|
|
||||||
|
|
||||||
Public methods:
|
|
||||||
|
|
||||||
add(card) -- add a card to the stack
|
|
||||||
delete(card) -- delete a card from the stack
|
|
||||||
showtop() -- show the top card (if any) face up
|
|
||||||
deal() -- delete and return the top card, or None if empty
|
|
||||||
|
|
||||||
Method that subclasses may override:
|
|
||||||
|
|
||||||
position(card) -- move the card to its proper (x, y) position
|
|
||||||
|
|
||||||
The default position() method places all cards at the stack's
|
|
||||||
own (x, y) position.
|
|
||||||
|
|
||||||
userclickhandler(), userdoubleclickhandler() -- called to do
|
|
||||||
subclass specific things on single and double clicks
|
|
||||||
|
|
||||||
The default user (single) click handler shows the top card
|
|
||||||
face up. The default user double click handler calls the user
|
|
||||||
single click handler.
|
|
||||||
|
|
||||||
usermovehandler(cards) -- called to complete a subpile move
|
|
||||||
|
|
||||||
The default user move handler moves all moved cards back to
|
|
||||||
their original position (by calling the position() method).
|
|
||||||
|
|
||||||
Private methods:
|
|
||||||
|
|
||||||
clickhandler(event), doubleclickhandler(event),
|
|
||||||
motionhandler(event), releasehandler(event) -- event handlers
|
|
||||||
|
|
||||||
The default event handlers turn the top card of the stack with
|
|
||||||
its face up on a (single or double) click, and also support
|
|
||||||
moving a subpile around.
|
|
||||||
|
|
||||||
startmoving(event) -- begin a move operation
|
|
||||||
finishmoving() -- finish a move operation
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, x, y, game=None):
|
|
||||||
"""Stack constructor.
|
|
||||||
|
|
||||||
Arguments are the stack's nominal x and y position (the top
|
|
||||||
left corner of the first card placed in the stack), and the
|
|
||||||
game object (which is used to get the canvas; subclasses use
|
|
||||||
the game object to find other stacks).
|
|
||||||
|
|
||||||
"""
|
|
||||||
self.x = x
|
|
||||||
self.y = y
|
|
||||||
self.game = game
|
|
||||||
self.cards = []
|
|
||||||
self.group = Group(self.game.canvas)
|
|
||||||
self.group.bind('<1>', self.clickhandler)
|
|
||||||
self.group.bind('<Double-1>', self.doubleclickhandler)
|
|
||||||
self.group.bind('<B1-Motion>', self.motionhandler)
|
|
||||||
self.group.bind('<ButtonRelease-1>', self.releasehandler)
|
|
||||||
self.makebottom()
|
|
||||||
|
|
||||||
def makebottom(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
"""Return a string for debug print statements."""
|
|
||||||
return "%s(%d, %d)" % (self.__class__.__name__, self.x, self.y)
|
|
||||||
|
|
||||||
# Public methods
|
|
||||||
|
|
||||||
def add(self, card):
|
|
||||||
self.cards.append(card)
|
|
||||||
card.tkraise()
|
|
||||||
self.position(card)
|
|
||||||
self.group.addtag_withtag(card.group)
|
|
||||||
|
|
||||||
def delete(self, card):
|
|
||||||
self.cards.remove(card)
|
|
||||||
card.group.dtag(self.group)
|
|
||||||
|
|
||||||
def showtop(self):
|
|
||||||
if self.cards:
|
|
||||||
self.cards[-1].showface()
|
|
||||||
|
|
||||||
def deal(self):
|
|
||||||
if not self.cards:
|
|
||||||
return None
|
|
||||||
card = self.cards[-1]
|
|
||||||
self.delete(card)
|
|
||||||
return card
|
|
||||||
|
|
||||||
# Subclass overridable methods
|
|
||||||
|
|
||||||
def position(self, card):
|
|
||||||
card.moveto(self.x, self.y)
|
|
||||||
|
|
||||||
def userclickhandler(self):
|
|
||||||
self.showtop()
|
|
||||||
|
|
||||||
def userdoubleclickhandler(self):
|
|
||||||
self.userclickhandler()
|
|
||||||
|
|
||||||
def usermovehandler(self, cards):
|
|
||||||
for card in cards:
|
|
||||||
self.position(card)
|
|
||||||
|
|
||||||
# Event handlers
|
|
||||||
|
|
||||||
def clickhandler(self, event):
|
|
||||||
self.finishmoving() # In case we lost an event
|
|
||||||
self.userclickhandler()
|
|
||||||
self.startmoving(event)
|
|
||||||
|
|
||||||
def motionhandler(self, event):
|
|
||||||
self.keepmoving(event)
|
|
||||||
|
|
||||||
def releasehandler(self, event):
|
|
||||||
self.keepmoving(event)
|
|
||||||
self.finishmoving()
|
|
||||||
|
|
||||||
def doubleclickhandler(self, event):
|
|
||||||
self.finishmoving() # In case we lost an event
|
|
||||||
self.userdoubleclickhandler()
|
|
||||||
self.startmoving(event)
|
|
||||||
|
|
||||||
# Move internals
|
|
||||||
|
|
||||||
moving = None
|
|
||||||
|
|
||||||
def startmoving(self, event):
|
|
||||||
self.moving = None
|
|
||||||
tags = self.game.canvas.gettags('current')
|
|
||||||
for i in range(len(self.cards)):
|
|
||||||
card = self.cards[i]
|
|
||||||
if card.group.tag in tags:
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
return
|
|
||||||
if not card.face_shown:
|
|
||||||
return
|
|
||||||
self.moving = self.cards[i:]
|
|
||||||
self.lastx = event.x
|
|
||||||
self.lasty = event.y
|
|
||||||
for card in self.moving:
|
|
||||||
card.tkraise()
|
|
||||||
|
|
||||||
def keepmoving(self, event):
|
|
||||||
if not self.moving:
|
|
||||||
return
|
|
||||||
dx = event.x - self.lastx
|
|
||||||
dy = event.y - self.lasty
|
|
||||||
self.lastx = event.x
|
|
||||||
self.lasty = event.y
|
|
||||||
if dx or dy:
|
|
||||||
for card in self.moving:
|
|
||||||
card.moveby(dx, dy)
|
|
||||||
|
|
||||||
def finishmoving(self):
|
|
||||||
cards = self.moving
|
|
||||||
self.moving = None
|
|
||||||
if cards:
|
|
||||||
self.usermovehandler(cards)
|
|
||||||
|
|
||||||
|
|
||||||
class Deck(Stack):
|
|
||||||
|
|
||||||
"""The deck is a stack with support for shuffling.
|
|
||||||
|
|
||||||
New methods:
|
|
||||||
|
|
||||||
fill() -- create the playing cards
|
|
||||||
shuffle() -- shuffle the playing cards
|
|
||||||
|
|
||||||
A single click moves the top card to the game's open deck and
|
|
||||||
moves it face up; if we're out of cards, it moves the open deck
|
|
||||||
back to the deck.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
def makebottom(self):
|
|
||||||
bottom = self.game.canvas.create_rectangle(self.x, self.y,
|
|
||||||
self.x + CARDWIDTH, self.y + CARDHEIGHT, outline='black',
|
|
||||||
fill=BACKGROUND)
|
|
||||||
self.group.addtag_withtag(bottom)
|
|
||||||
|
|
||||||
def fill(self):
|
|
||||||
for suit in ALLSUITS:
|
|
||||||
for value in ALLVALUES:
|
|
||||||
self.add(Card(suit, value, self.game.canvas))
|
|
||||||
|
|
||||||
def shuffle(self):
|
|
||||||
n = len(self.cards)
|
|
||||||
newcards = []
|
|
||||||
for i in randperm(n):
|
|
||||||
newcards.append(self.cards[i])
|
|
||||||
self.cards = newcards
|
|
||||||
|
|
||||||
def userclickhandler(self):
|
|
||||||
opendeck = self.game.opendeck
|
|
||||||
card = self.deal()
|
|
||||||
if not card:
|
|
||||||
while 1:
|
|
||||||
card = opendeck.deal()
|
|
||||||
if not card:
|
|
||||||
break
|
|
||||||
self.add(card)
|
|
||||||
card.showback()
|
|
||||||
else:
|
|
||||||
self.game.opendeck.add(card)
|
|
||||||
card.showface()
|
|
||||||
|
|
||||||
|
|
||||||
def randperm(n):
|
|
||||||
"""Function returning a random permutation of range(n)."""
|
|
||||||
r = list(range(n))
|
|
||||||
x = []
|
|
||||||
while r:
|
|
||||||
i = random.choice(r)
|
|
||||||
x.append(i)
|
|
||||||
r.remove(i)
|
|
||||||
return x
|
|
||||||
|
|
||||||
|
|
||||||
class OpenStack(Stack):
|
|
||||||
|
|
||||||
def acceptable(self, cards):
|
|
||||||
return 0
|
|
||||||
|
|
||||||
def usermovehandler(self, cards):
|
|
||||||
card = cards[0]
|
|
||||||
stack = self.game.closeststack(card)
|
|
||||||
if not stack or stack is self or not stack.acceptable(cards):
|
|
||||||
Stack.usermovehandler(self, cards)
|
|
||||||
else:
|
|
||||||
for card in cards:
|
|
||||||
self.delete(card)
|
|
||||||
stack.add(card)
|
|
||||||
self.game.wincheck()
|
|
||||||
|
|
||||||
def userdoubleclickhandler(self):
|
|
||||||
if not self.cards:
|
|
||||||
return
|
|
||||||
card = self.cards[-1]
|
|
||||||
if not card.face_shown:
|
|
||||||
self.userclickhandler()
|
|
||||||
return
|
|
||||||
for s in self.game.suits:
|
|
||||||
if s.acceptable([card]):
|
|
||||||
self.delete(card)
|
|
||||||
s.add(card)
|
|
||||||
self.game.wincheck()
|
|
||||||
break
|
|
||||||
|
|
||||||
|
|
||||||
class SuitStack(OpenStack):
|
|
||||||
|
|
||||||
def makebottom(self):
|
|
||||||
bottom = self.game.canvas.create_rectangle(self.x, self.y,
|
|
||||||
self.x + CARDWIDTH, self.y + CARDHEIGHT, outline='black', fill='')
|
|
||||||
|
|
||||||
def userclickhandler(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def userdoubleclickhandler(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def acceptable(self, cards):
|
|
||||||
if len(cards) != 1:
|
|
||||||
return 0
|
|
||||||
card = cards[0]
|
|
||||||
if not self.cards:
|
|
||||||
return card.value == ACE
|
|
||||||
topcard = self.cards[-1]
|
|
||||||
return card.suit == topcard.suit and card.value == topcard.value + 1
|
|
||||||
|
|
||||||
|
|
||||||
class RowStack(OpenStack):
|
|
||||||
|
|
||||||
def acceptable(self, cards):
|
|
||||||
card = cards[0]
|
|
||||||
if not self.cards:
|
|
||||||
return card.value == KING
|
|
||||||
topcard = self.cards[-1]
|
|
||||||
if not topcard.face_shown:
|
|
||||||
return 0
|
|
||||||
return card.color != topcard.color and card.value == topcard.value - 1
|
|
||||||
|
|
||||||
def position(self, card):
|
|
||||||
y = self.y
|
|
||||||
for c in self.cards:
|
|
||||||
if c == card:
|
|
||||||
break
|
|
||||||
if c.face_shown:
|
|
||||||
y = y + 2*MARGIN
|
|
||||||
else:
|
|
||||||
y = y + OFFSET
|
|
||||||
card.moveto(self.x, y)
|
|
||||||
|
|
||||||
|
|
||||||
class Solitaire:
|
|
||||||
|
|
||||||
def __init__(self, master):
|
|
||||||
self.master = master
|
|
||||||
|
|
||||||
self.canvas = Canvas(self.master,
|
|
||||||
background=BACKGROUND,
|
|
||||||
highlightthickness=0,
|
|
||||||
width=NROWS*XSPACING,
|
|
||||||
height=3*YSPACING + 20 + MARGIN)
|
|
||||||
self.canvas.pack(fill=BOTH, expand=TRUE)
|
|
||||||
|
|
||||||
self.dealbutton = Button(self.canvas,
|
|
||||||
text="Deal",
|
|
||||||
highlightthickness=0,
|
|
||||||
background=BACKGROUND,
|
|
||||||
activebackground="green",
|
|
||||||
command=self.deal)
|
|
||||||
self.canvas.create_window(MARGIN, 3 * YSPACING + 20,
|
|
||||||
window=self.dealbutton, anchor=SW)
|
|
||||||
|
|
||||||
x = MARGIN
|
|
||||||
y = MARGIN
|
|
||||||
|
|
||||||
self.deck = Deck(x, y, self)
|
|
||||||
|
|
||||||
x = x + XSPACING
|
|
||||||
self.opendeck = OpenStack(x, y, self)
|
|
||||||
|
|
||||||
x = x + XSPACING
|
|
||||||
self.suits = []
|
|
||||||
for i in range(NSUITS):
|
|
||||||
x = x + XSPACING
|
|
||||||
self.suits.append(SuitStack(x, y, self))
|
|
||||||
|
|
||||||
x = MARGIN
|
|
||||||
y = y + YSPACING
|
|
||||||
|
|
||||||
self.rows = []
|
|
||||||
for i in range(NROWS):
|
|
||||||
self.rows.append(RowStack(x, y, self))
|
|
||||||
x = x + XSPACING
|
|
||||||
|
|
||||||
self.openstacks = [self.opendeck] + self.suits + self.rows
|
|
||||||
|
|
||||||
self.deck.fill()
|
|
||||||
self.deal()
|
|
||||||
|
|
||||||
def wincheck(self):
|
|
||||||
for s in self.suits:
|
|
||||||
if len(s.cards) != NVALUES:
|
|
||||||
return
|
|
||||||
self.win()
|
|
||||||
self.deal()
|
|
||||||
|
|
||||||
def win(self):
|
|
||||||
"""Stupid animation when you win."""
|
|
||||||
cards = []
|
|
||||||
for s in self.openstacks:
|
|
||||||
cards = cards + s.cards
|
|
||||||
while cards:
|
|
||||||
card = random.choice(cards)
|
|
||||||
cards.remove(card)
|
|
||||||
self.animatedmoveto(card, self.deck)
|
|
||||||
|
|
||||||
def animatedmoveto(self, card, dest):
|
|
||||||
for i in range(10, 0, -1):
|
|
||||||
dx, dy = (dest.x-card.x)//i, (dest.y-card.y)//i
|
|
||||||
card.moveby(dx, dy)
|
|
||||||
self.master.update_idletasks()
|
|
||||||
|
|
||||||
def closeststack(self, card):
|
|
||||||
closest = None
|
|
||||||
cdist = 999999999
|
|
||||||
# Since we only compare distances,
|
|
||||||
# we don't bother to take the square root.
|
|
||||||
for stack in self.openstacks:
|
|
||||||
dist = (stack.x - card.x)**2 + (stack.y - card.y)**2
|
|
||||||
if dist < cdist:
|
|
||||||
closest = stack
|
|
||||||
cdist = dist
|
|
||||||
return closest
|
|
||||||
|
|
||||||
def deal(self):
|
|
||||||
self.reset()
|
|
||||||
self.deck.shuffle()
|
|
||||||
for i in range(NROWS):
|
|
||||||
for r in self.rows[i:]:
|
|
||||||
card = self.deck.deal()
|
|
||||||
r.add(card)
|
|
||||||
for r in self.rows:
|
|
||||||
r.showtop()
|
|
||||||
|
|
||||||
def reset(self):
|
|
||||||
for stack in self.openstacks:
|
|
||||||
while 1:
|
|
||||||
card = stack.deal()
|
|
||||||
if not card:
|
|
||||||
break
|
|
||||||
self.deck.add(card)
|
|
||||||
card.showback()
|
|
||||||
|
|
||||||
|
|
||||||
# Main function, run when invoked as a stand-alone Python program.
|
|
||||||
|
|
||||||
def main():
|
|
||||||
root = Tk()
|
|
||||||
game = Solitaire(root)
|
|
||||||
root.protocol('WM_DELETE_WINDOW', root.quit)
|
|
||||||
root.mainloop()
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main()
|
|
|
@ -1,124 +0,0 @@
|
||||||
#! /usr/bin/env python3
|
|
||||||
|
|
||||||
# Tkinter interface to SYSV `ps' and `kill' commands.
|
|
||||||
|
|
||||||
from tkinter import *
|
|
||||||
|
|
||||||
if TkVersion < 4.0:
|
|
||||||
raise ImportError("This version of svkill requires Tk 4.0 or later")
|
|
||||||
|
|
||||||
import subprocess
|
|
||||||
import os
|
|
||||||
|
|
||||||
user = os.environ['LOGNAME']
|
|
||||||
|
|
||||||
class BarButton(Menubutton):
|
|
||||||
def __init__(self, master=None, **cnf):
|
|
||||||
Menubutton.__init__(self, master, **cnf)
|
|
||||||
self.pack(side=LEFT)
|
|
||||||
self.menu = Menu(self, name='menu')
|
|
||||||
self['menu'] = self.menu
|
|
||||||
|
|
||||||
class Kill(Frame):
|
|
||||||
# List of (name, option, pid_column)
|
|
||||||
view_list = [
|
|
||||||
('Default', ''),
|
|
||||||
('Every (-e)', '-e'),
|
|
||||||
('Non process group leaders (-d)', '-d'),
|
|
||||||
('Non leaders with tty (-a)', '-a'),
|
|
||||||
('For this user (-u %s)' % user, '-u %s' % user),
|
|
||||||
]
|
|
||||||
format_list = [
|
|
||||||
('Default', '', 0),
|
|
||||||
('Long (-l)', '-l', 3),
|
|
||||||
('Full (-f)', '-f', 1),
|
|
||||||
('Full Long (-f -l)', '-l -f', 3),
|
|
||||||
('Session and group ID (-j)', '-j', 0),
|
|
||||||
('Scheduler properties (-c)', '-c', 0),
|
|
||||||
]
|
|
||||||
def kill(self, selected):
|
|
||||||
c = self.format_list[self.format.get()][2]
|
|
||||||
pid = selected.split()[c]
|
|
||||||
os.system('kill -9 ' + pid)
|
|
||||||
self.do_update()
|
|
||||||
def do_update(self):
|
|
||||||
format = self.format_list[self.format.get()][1]
|
|
||||||
view = self.view_list[self.view.get()][1]
|
|
||||||
s = subprocess.getoutput('ps %s %s' % (view, format))
|
|
||||||
list = s.split('\n')
|
|
||||||
self.header.set(list[0] + ' ')
|
|
||||||
del list[0]
|
|
||||||
self.frame.list.delete(0, AtEnd())
|
|
||||||
for line in list:
|
|
||||||
self.frame.list.insert(0, line)
|
|
||||||
def do_motion(self, e):
|
|
||||||
e.widget.select_clear('0', 'end')
|
|
||||||
e.widget.select_set(e.widget.nearest(e.y))
|
|
||||||
def do_leave(self, e):
|
|
||||||
e.widget.select_clear('0', 'end')
|
|
||||||
def do_1(self, e):
|
|
||||||
self.kill(e.widget.get(e.widget.nearest(e.y)))
|
|
||||||
def __init__(self, master=None, **cnf):
|
|
||||||
Frame.__init__(self, master, **cnf)
|
|
||||||
self.pack(expand=1, fill=BOTH)
|
|
||||||
self.bar = Frame(self, name='bar', relief=RAISED,
|
|
||||||
borderwidth=2)
|
|
||||||
self.bar.pack(fill=X)
|
|
||||||
self.bar.file = BarButton(self.bar, text='File')
|
|
||||||
self.bar.file.menu.add_command(
|
|
||||||
label='Quit', command=self.quit)
|
|
||||||
self.bar.view = BarButton(self.bar, text='View')
|
|
||||||
self.bar.format = BarButton(self.bar, text='Format')
|
|
||||||
self.view = IntVar(self)
|
|
||||||
self.view.set(0)
|
|
||||||
self.format = IntVar(self)
|
|
||||||
self.format.set(0)
|
|
||||||
for num in range(len(self.view_list)):
|
|
||||||
label, option = self.view_list[num]
|
|
||||||
self.bar.view.menu.add_radiobutton(
|
|
||||||
label=label,
|
|
||||||
command=self.do_update,
|
|
||||||
variable=self.view,
|
|
||||||
value=num)
|
|
||||||
for num in range(len(self.format_list)):
|
|
||||||
label, option, col = self.format_list[num]
|
|
||||||
self.bar.format.menu.add_radiobutton(
|
|
||||||
label=label,
|
|
||||||
command=self.do_update,
|
|
||||||
variable=self.format,
|
|
||||||
value=num)
|
|
||||||
self.bar.tk_menuBar(self.bar.file,
|
|
||||||
self.bar.view,
|
|
||||||
self.bar.format)
|
|
||||||
self.frame = Frame(self, relief=RAISED, borderwidth=2)
|
|
||||||
self.frame.pack(expand=1, fill=BOTH)
|
|
||||||
self.header = StringVar(self)
|
|
||||||
self.frame.label = Label(
|
|
||||||
self.frame, relief=FLAT, anchor=NW, borderwidth=0,
|
|
||||||
textvariable=self.header)
|
|
||||||
self.frame.label.pack(fill=Y, anchor=W)
|
|
||||||
self.frame.vscroll = Scrollbar(self.frame, orient=VERTICAL)
|
|
||||||
self.frame.list = Listbox(
|
|
||||||
self.frame,
|
|
||||||
relief=SUNKEN,
|
|
||||||
width=40, height=10,
|
|
||||||
selectbackground='#eed5b7',
|
|
||||||
selectborderwidth=0,
|
|
||||||
selectmode=BROWSE,
|
|
||||||
yscroll=self.frame.vscroll.set)
|
|
||||||
self.frame.vscroll['command'] = self.frame.list.yview
|
|
||||||
self.frame.vscroll.pack(side=RIGHT, fill=Y)
|
|
||||||
self.frame.list.pack(expand=1, fill=BOTH)
|
|
||||||
self.update = Button(self, text='Update',
|
|
||||||
command=self.do_update)
|
|
||||||
self.update.pack(fill=X)
|
|
||||||
self.frame.list.bind('<Motion>', self.do_motion)
|
|
||||||
self.frame.list.bind('<Leave>', self.do_leave)
|
|
||||||
self.frame.list.bind('<1>', self.do_1)
|
|
||||||
self.do_update()
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
kill = Kill(None, borderwidth=5)
|
|
||||||
kill.winfo_toplevel().title('Tkinter Process Killer (SYSV)')
|
|
||||||
kill.winfo_toplevel().minsize(1, 1)
|
|
||||||
kill.mainloop()
|
|
|
@ -1,55 +0,0 @@
|
||||||
# Show how to do switchable panels.
|
|
||||||
|
|
||||||
from tkinter import *
|
|
||||||
|
|
||||||
class App:
|
|
||||||
|
|
||||||
def __init__(self, top=None, master=None):
|
|
||||||
if top is None:
|
|
||||||
if master is None:
|
|
||||||
top = Tk()
|
|
||||||
else:
|
|
||||||
top = Toplevel(master)
|
|
||||||
self.top = top
|
|
||||||
self.buttonframe = Frame(top)
|
|
||||||
self.buttonframe.pack()
|
|
||||||
self.panelframe = Frame(top, borderwidth=2, relief=GROOVE)
|
|
||||||
self.panelframe.pack(expand=1, fill=BOTH)
|
|
||||||
self.panels = {}
|
|
||||||
self.curpanel = None
|
|
||||||
|
|
||||||
def addpanel(self, name, klass):
|
|
||||||
button = Button(self.buttonframe, text=name,
|
|
||||||
command=lambda self=self, name=name: self.show(name))
|
|
||||||
button.pack(side=LEFT)
|
|
||||||
frame = Frame(self.panelframe)
|
|
||||||
instance = klass(frame)
|
|
||||||
self.panels[name] = (button, frame, instance)
|
|
||||||
if self.curpanel is None:
|
|
||||||
self.show(name)
|
|
||||||
|
|
||||||
def show(self, name):
|
|
||||||
(button, frame, instance) = self.panels[name]
|
|
||||||
if self.curpanel:
|
|
||||||
self.curpanel.pack_forget()
|
|
||||||
self.curpanel = frame
|
|
||||||
frame.pack(expand=1, fill="both")
|
|
||||||
|
|
||||||
class LabelPanel:
|
|
||||||
def __init__(self, frame):
|
|
||||||
self.label = Label(frame, text="Hello world")
|
|
||||||
self.label.pack()
|
|
||||||
|
|
||||||
class ButtonPanel:
|
|
||||||
def __init__(self, frame):
|
|
||||||
self.button = Button(frame, text="Press me")
|
|
||||||
self.button.pack()
|
|
||||||
|
|
||||||
def main():
|
|
||||||
app = App()
|
|
||||||
app.addpanel("label", LabelPanel)
|
|
||||||
app.addpanel("button", ButtonPanel)
|
|
||||||
app.top.mainloop()
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main()
|
|
|
@ -1,267 +0,0 @@
|
||||||
#! /usr/bin/env python3
|
|
||||||
|
|
||||||
# Tk man page browser -- currently only shows the Tcl/Tk man pages
|
|
||||||
|
|
||||||
import os
|
|
||||||
import re
|
|
||||||
import sys
|
|
||||||
from tkinter import *
|
|
||||||
|
|
||||||
from manpage import ManPage
|
|
||||||
|
|
||||||
MANNDIRLIST = ['/usr/local/man/mann', '/usr/share/man/mann']
|
|
||||||
MAN3DIRLIST = ['/usr/local/man/man3', '/usr/share/man/man3']
|
|
||||||
|
|
||||||
foundmanndir = 0
|
|
||||||
for dir in MANNDIRLIST:
|
|
||||||
if os.path.exists(dir):
|
|
||||||
MANNDIR = dir
|
|
||||||
foundmanndir = 1
|
|
||||||
|
|
||||||
foundman3dir = 0
|
|
||||||
for dir in MAN3DIRLIST:
|
|
||||||
if os.path.exists(dir):
|
|
||||||
MAN3DIR = dir
|
|
||||||
foundman3dir = 1
|
|
||||||
|
|
||||||
if not foundmanndir or not foundman3dir:
|
|
||||||
sys.stderr.write('\n')
|
|
||||||
if not foundmanndir:
|
|
||||||
msg = """\
|
|
||||||
Failed to find mann directory.
|
|
||||||
Please add the correct entry to the MANNDIRLIST
|
|
||||||
at the top of %s script.""" % \
|
|
||||||
sys.argv[0]
|
|
||||||
sys.stderr.write("%s\n\n" % msg)
|
|
||||||
if not foundman3dir:
|
|
||||||
msg = """\
|
|
||||||
Failed to find man3 directory.
|
|
||||||
Please add the correct entry to the MAN3DIRLIST
|
|
||||||
at the top of %s script.""" % \
|
|
||||||
sys.argv[0]
|
|
||||||
sys.stderr.write("%s\n\n" % msg)
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
del foundmanndir
|
|
||||||
del foundman3dir
|
|
||||||
|
|
||||||
def listmanpages(mandir):
|
|
||||||
files = os.listdir(mandir)
|
|
||||||
names = []
|
|
||||||
for file in files:
|
|
||||||
if file[-2:-1] == '.' and (file[-1] in 'ln123456789'):
|
|
||||||
names.append(file[:-2])
|
|
||||||
names.sort()
|
|
||||||
return names
|
|
||||||
|
|
||||||
class SelectionBox:
|
|
||||||
|
|
||||||
def __init__(self, master=None):
|
|
||||||
self.choices = []
|
|
||||||
|
|
||||||
self.frame = Frame(master, name="frame")
|
|
||||||
self.frame.pack(expand=1, fill=BOTH)
|
|
||||||
self.master = self.frame.master
|
|
||||||
self.subframe = Frame(self.frame, name="subframe")
|
|
||||||
self.subframe.pack(expand=0, fill=BOTH)
|
|
||||||
self.leftsubframe = Frame(self.subframe, name='leftsubframe')
|
|
||||||
self.leftsubframe.pack(side=LEFT, expand=1, fill=BOTH)
|
|
||||||
self.rightsubframe = Frame(self.subframe, name='rightsubframe')
|
|
||||||
self.rightsubframe.pack(side=RIGHT, expand=1, fill=BOTH)
|
|
||||||
self.chaptervar = StringVar(master)
|
|
||||||
self.chapter = Menubutton(self.rightsubframe, name='chapter',
|
|
||||||
text='Directory', relief=RAISED,
|
|
||||||
borderwidth=2)
|
|
||||||
self.chapter.pack(side=TOP)
|
|
||||||
self.chaptermenu = Menu(self.chapter, name='chaptermenu')
|
|
||||||
self.chaptermenu.add_radiobutton(label='C functions',
|
|
||||||
value=MAN3DIR,
|
|
||||||
variable=self.chaptervar,
|
|
||||||
command=self.newchapter)
|
|
||||||
self.chaptermenu.add_radiobutton(label='Tcl/Tk functions',
|
|
||||||
value=MANNDIR,
|
|
||||||
variable=self.chaptervar,
|
|
||||||
command=self.newchapter)
|
|
||||||
self.chapter['menu'] = self.chaptermenu
|
|
||||||
self.listbox = Listbox(self.rightsubframe, name='listbox',
|
|
||||||
relief=SUNKEN, borderwidth=2,
|
|
||||||
width=20, height=5)
|
|
||||||
self.listbox.pack(expand=1, fill=BOTH)
|
|
||||||
self.l1 = Button(self.leftsubframe, name='l1',
|
|
||||||
text='Display manual page named:',
|
|
||||||
command=self.entry_cb)
|
|
||||||
self.l1.pack(side=TOP)
|
|
||||||
self.entry = Entry(self.leftsubframe, name='entry',
|
|
||||||
relief=SUNKEN, borderwidth=2,
|
|
||||||
width=20)
|
|
||||||
self.entry.pack(expand=0, fill=X)
|
|
||||||
self.l2frame = Frame(self.leftsubframe, name='l2frame')
|
|
||||||
self.l2frame.pack(expand=0, fill=NONE)
|
|
||||||
self.l2 = Button(self.l2frame, name='l2',
|
|
||||||
text='Search regexp:',
|
|
||||||
command=self.search_cb)
|
|
||||||
self.l2.pack(side=LEFT)
|
|
||||||
self.casevar = BooleanVar()
|
|
||||||
self.casesense = Checkbutton(self.l2frame, name='casesense',
|
|
||||||
text='Case sensitive',
|
|
||||||
variable=self.casevar,
|
|
||||||
relief=FLAT)
|
|
||||||
self.casesense.pack(side=LEFT)
|
|
||||||
self.search = Entry(self.leftsubframe, name='search',
|
|
||||||
relief=SUNKEN, borderwidth=2,
|
|
||||||
width=20)
|
|
||||||
self.search.pack(expand=0, fill=X)
|
|
||||||
self.title = Label(self.leftsubframe, name='title',
|
|
||||||
text='(none)')
|
|
||||||
self.title.pack(side=BOTTOM)
|
|
||||||
self.text = ManPage(self.frame, name='text',
|
|
||||||
relief=SUNKEN, borderwidth=2,
|
|
||||||
wrap=NONE, width=72,
|
|
||||||
selectbackground='pink')
|
|
||||||
self.text.pack(expand=1, fill=BOTH)
|
|
||||||
|
|
||||||
self.entry.bind('<Return>', self.entry_cb)
|
|
||||||
self.search.bind('<Return>', self.search_cb)
|
|
||||||
self.listbox.bind('<Double-1>', self.listbox_cb)
|
|
||||||
|
|
||||||
self.entry.bind('<Tab>', self.entry_tab)
|
|
||||||
self.search.bind('<Tab>', self.search_tab)
|
|
||||||
self.text.bind('<Tab>', self.text_tab)
|
|
||||||
|
|
||||||
self.entry.focus_set()
|
|
||||||
|
|
||||||
self.chaptervar.set(MANNDIR)
|
|
||||||
self.newchapter()
|
|
||||||
|
|
||||||
def newchapter(self):
|
|
||||||
mandir = self.chaptervar.get()
|
|
||||||
self.choices = []
|
|
||||||
self.addlist(listmanpages(mandir))
|
|
||||||
|
|
||||||
def addchoice(self, choice):
|
|
||||||
if choice not in self.choices:
|
|
||||||
self.choices.append(choice)
|
|
||||||
self.choices.sort()
|
|
||||||
self.update()
|
|
||||||
|
|
||||||
def addlist(self, list):
|
|
||||||
self.choices[len(self.choices):] = list
|
|
||||||
self.choices.sort()
|
|
||||||
self.update()
|
|
||||||
|
|
||||||
def entry_cb(self, *e):
|
|
||||||
self.update()
|
|
||||||
|
|
||||||
def listbox_cb(self, e):
|
|
||||||
selection = self.listbox.curselection()
|
|
||||||
if selection and len(selection) == 1:
|
|
||||||
name = self.listbox.get(selection[0])
|
|
||||||
self.show_page(name)
|
|
||||||
|
|
||||||
def search_cb(self, *e):
|
|
||||||
self.search_string(self.search.get())
|
|
||||||
|
|
||||||
def entry_tab(self, e):
|
|
||||||
self.search.focus_set()
|
|
||||||
|
|
||||||
def search_tab(self, e):
|
|
||||||
self.entry.focus_set()
|
|
||||||
|
|
||||||
def text_tab(self, e):
|
|
||||||
self.entry.focus_set()
|
|
||||||
|
|
||||||
def updatelist(self):
|
|
||||||
key = self.entry.get()
|
|
||||||
ok = list(filter(lambda name, key=key, n=len(key): name[:n]==key,
|
|
||||||
self.choices))
|
|
||||||
if not ok:
|
|
||||||
self.frame.bell()
|
|
||||||
self.listbox.delete(0, AtEnd())
|
|
||||||
exactmatch = 0
|
|
||||||
for item in ok:
|
|
||||||
if item == key: exactmatch = 1
|
|
||||||
self.listbox.insert(AtEnd(), item)
|
|
||||||
if exactmatch:
|
|
||||||
return key
|
|
||||||
n = self.listbox.size()
|
|
||||||
if n == 1:
|
|
||||||
return self.listbox.get(0)
|
|
||||||
# Else return None, meaning not a unique selection
|
|
||||||
|
|
||||||
def update(self):
|
|
||||||
name = self.updatelist()
|
|
||||||
if name:
|
|
||||||
self.show_page(name)
|
|
||||||
self.entry.delete(0, AtEnd())
|
|
||||||
self.updatelist()
|
|
||||||
|
|
||||||
def show_page(self, name):
|
|
||||||
file = '%s/%s.?' % (self.chaptervar.get(), name)
|
|
||||||
fp = os.popen('nroff -man -c %s | ul -i' % file, 'r')
|
|
||||||
self.text.kill()
|
|
||||||
self.title['text'] = name
|
|
||||||
self.text.parsefile(fp)
|
|
||||||
|
|
||||||
def search_string(self, search):
|
|
||||||
if not search:
|
|
||||||
self.frame.bell()
|
|
||||||
print('Empty search string')
|
|
||||||
return
|
|
||||||
if not self.casevar.get():
|
|
||||||
map = re.IGNORECASE
|
|
||||||
else:
|
|
||||||
map = None
|
|
||||||
try:
|
|
||||||
if map:
|
|
||||||
prog = re.compile(search, map)
|
|
||||||
else:
|
|
||||||
prog = re.compile(search)
|
|
||||||
except re.error as msg:
|
|
||||||
self.frame.bell()
|
|
||||||
print('Regex error:', msg)
|
|
||||||
return
|
|
||||||
here = self.text.index(AtInsert())
|
|
||||||
lineno = int(here[:here.find('.')])
|
|
||||||
end = self.text.index(AtEnd())
|
|
||||||
endlineno = int(end[:end.find('.')])
|
|
||||||
wraplineno = lineno
|
|
||||||
found = 0
|
|
||||||
while 1:
|
|
||||||
lineno = lineno + 1
|
|
||||||
if lineno > endlineno:
|
|
||||||
if wraplineno <= 0:
|
|
||||||
break
|
|
||||||
endlineno = wraplineno
|
|
||||||
lineno = 0
|
|
||||||
wraplineno = 0
|
|
||||||
line = self.text.get('%d.0 linestart' % lineno,
|
|
||||||
'%d.0 lineend' % lineno)
|
|
||||||
i = prog.search(line)
|
|
||||||
if i:
|
|
||||||
found = 1
|
|
||||||
n = max(1, len(i.group(0)))
|
|
||||||
try:
|
|
||||||
self.text.tag_remove('sel',
|
|
||||||
AtSelFirst(),
|
|
||||||
AtSelLast())
|
|
||||||
except TclError:
|
|
||||||
pass
|
|
||||||
self.text.tag_add('sel',
|
|
||||||
'%d.%d' % (lineno, i.start()),
|
|
||||||
'%d.%d' % (lineno, i.start()+n))
|
|
||||||
self.text.mark_set(AtInsert(),
|
|
||||||
'%d.%d' % (lineno, i.start()))
|
|
||||||
self.text.yview_pickplace(AtInsert())
|
|
||||||
break
|
|
||||||
if not found:
|
|
||||||
self.frame.bell()
|
|
||||||
|
|
||||||
def main():
|
|
||||||
root = Tk()
|
|
||||||
sb = SelectionBox(root)
|
|
||||||
if sys.argv[1:]:
|
|
||||||
sb.show_page(sys.argv[1])
|
|
||||||
root.minsize(1, 1)
|
|
||||||
root.mainloop()
|
|
||||||
|
|
||||||
main()
|
|
|
@ -1,34 +0,0 @@
|
||||||
# This is about all it requires to write a wish shell in Python!
|
|
||||||
|
|
||||||
import _tkinter
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
|
|
||||||
tk = _tkinter.create(os.environ['DISPLAY'], 'wish', 'Tk', 1, 1)
|
|
||||||
tk.call('update')
|
|
||||||
|
|
||||||
cmd = ''
|
|
||||||
|
|
||||||
while True:
|
|
||||||
if cmd:
|
|
||||||
prompt = ''
|
|
||||||
else:
|
|
||||||
prompt = '% '
|
|
||||||
try:
|
|
||||||
sys.stdout.write(prompt)
|
|
||||||
sys.stdout.flush()
|
|
||||||
line = sys.stdin.readline()
|
|
||||||
if not line:
|
|
||||||
break
|
|
||||||
except EOFError:
|
|
||||||
break
|
|
||||||
cmd += line
|
|
||||||
if tk.getboolean(tk.call('info', 'complete', cmd)):
|
|
||||||
tk.record(line)
|
|
||||||
try:
|
|
||||||
result = tk.call('eval', cmd)
|
|
||||||
except _tkinter.TclError as msg:
|
|
||||||
print('TclError:', msg)
|
|
||||||
else:
|
|
||||||
if result: print(result)
|
|
||||||
cmd = ''
|
|
|
@ -1,27 +0,0 @@
|
||||||
from tkinter import *
|
|
||||||
|
|
||||||
# note that there is no explicit call to start Tk.
|
|
||||||
# Tkinter is smart enough to start the system if it's not already going.
|
|
||||||
|
|
||||||
class Test(Frame):
|
|
||||||
def printit(self):
|
|
||||||
print("hi")
|
|
||||||
|
|
||||||
def createWidgets(self):
|
|
||||||
self.QUIT = Button(self, text='QUIT', foreground='red',
|
|
||||||
command=self.quit)
|
|
||||||
|
|
||||||
self.QUIT.pack(side=LEFT, fill=BOTH)
|
|
||||||
|
|
||||||
# a hello button
|
|
||||||
self.hi_there = Button(self, text='Hello',
|
|
||||||
command=self.printit)
|
|
||||||
self.hi_there.pack(side=LEFT)
|
|
||||||
|
|
||||||
def __init__(self, master=None):
|
|
||||||
Frame.__init__(self, master)
|
|
||||||
Pack.config(self)
|
|
||||||
self.createWidgets()
|
|
||||||
|
|
||||||
test = Test()
|
|
||||||
test.mainloop()
|
|
|
@ -1,30 +0,0 @@
|
||||||
This directory contains some ad-hoc examples of Tkinter widget
|
|
||||||
creation. The files named
|
|
||||||
|
|
||||||
*-simple.py
|
|
||||||
|
|
||||||
are the ones to start with if you're looking for a bare-bones usage of
|
|
||||||
a widget. The other files are meant to show common usage patters that
|
|
||||||
are a tad more involved.
|
|
||||||
|
|
||||||
If you have a suggestion for an example program, please send mail to
|
|
||||||
|
|
||||||
conway@virginia.edu
|
|
||||||
|
|
||||||
and I'll include it.
|
|
||||||
|
|
||||||
|
|
||||||
matt
|
|
||||||
|
|
||||||
TODO
|
|
||||||
-------
|
|
||||||
The X selection
|
|
||||||
Dialog Boxes
|
|
||||||
More canvas examples
|
|
||||||
Message widgets
|
|
||||||
Text Editors
|
|
||||||
Scrollbars
|
|
||||||
Listboxes
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,35 +0,0 @@
|
||||||
from tkinter import *
|
|
||||||
|
|
||||||
# This program shows how to use the "after" function to make animation.
|
|
||||||
|
|
||||||
class Test(Frame):
|
|
||||||
def printit(self):
|
|
||||||
print("hi")
|
|
||||||
|
|
||||||
def createWidgets(self):
|
|
||||||
self.QUIT = Button(self, text='QUIT', foreground='red',
|
|
||||||
command=self.quit)
|
|
||||||
self.QUIT.pack(side=LEFT, fill=BOTH)
|
|
||||||
|
|
||||||
self.draw = Canvas(self, width="5i", height="5i")
|
|
||||||
|
|
||||||
# all of these work..
|
|
||||||
self.draw.create_rectangle(0, 0, 10, 10, tags="thing", fill="blue")
|
|
||||||
self.draw.pack(side=LEFT)
|
|
||||||
|
|
||||||
def moveThing(self, *args):
|
|
||||||
# move 1/10 of an inch every 1/10 sec (1" per second, smoothly)
|
|
||||||
self.draw.move("thing", "0.01i", "0.01i")
|
|
||||||
self.after(10, self.moveThing)
|
|
||||||
|
|
||||||
|
|
||||||
def __init__(self, master=None):
|
|
||||||
Frame.__init__(self, master)
|
|
||||||
Pack.config(self)
|
|
||||||
self.createWidgets()
|
|
||||||
self.after(10, self.moveThing)
|
|
||||||
|
|
||||||
|
|
||||||
test = Test()
|
|
||||||
|
|
||||||
test.mainloop()
|
|
|
@ -1,44 +0,0 @@
|
||||||
from tkinter import *
|
|
||||||
|
|
||||||
# this is the same as simple-demo-1.py, but uses
|
|
||||||
# subclassing.
|
|
||||||
# note that there is no explicit call to start Tk.
|
|
||||||
# Tkinter is smart enough to start the system if it's not already going.
|
|
||||||
|
|
||||||
|
|
||||||
class Test(Frame):
|
|
||||||
def printit(self):
|
|
||||||
print("hi")
|
|
||||||
|
|
||||||
def createWidgets(self):
|
|
||||||
self.QUIT = Button(self, text='QUIT', foreground='red',
|
|
||||||
command=self.quit)
|
|
||||||
self.QUIT.pack(side=BOTTOM, fill=BOTH)
|
|
||||||
|
|
||||||
self.draw = Canvas(self, width="5i", height="5i")
|
|
||||||
|
|
||||||
self.speed = Scale(self, orient=HORIZONTAL, from_=-100, to=100)
|
|
||||||
|
|
||||||
self.speed.pack(side=BOTTOM, fill=X)
|
|
||||||
|
|
||||||
# all of these work..
|
|
||||||
self.draw.create_rectangle(0, 0, 10, 10, tags="thing", fill="blue")
|
|
||||||
self.draw.pack(side=LEFT)
|
|
||||||
|
|
||||||
def moveThing(self, *args):
|
|
||||||
velocity = self.speed.get()
|
|
||||||
str = float(velocity) / 1000.0
|
|
||||||
str = "%ri" % (str,)
|
|
||||||
self.draw.move("thing", str, str)
|
|
||||||
self.after(10, self.moveThing)
|
|
||||||
|
|
||||||
def __init__(self, master=None):
|
|
||||||
Frame.__init__(self, master)
|
|
||||||
Pack.config(self)
|
|
||||||
self.createWidgets()
|
|
||||||
self.after(10, self.moveThing)
|
|
||||||
|
|
||||||
|
|
||||||
test = Test()
|
|
||||||
|
|
||||||
test.mainloop()
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue