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