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