⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 canvas.py

📁 Urwid is a Python library for making text console applications. It has many features including fluid
💻 PY
📖 第 1 页 / 共 3 页
字号:
	"""	def __init__(self):		Canvas.__init__(self, None)	def content(self, trim_left, trim_top, cols, rows, attr):		"""		return (cols, rows) of spaces with def_attr attribute.		"""		line = [(attr, None, " "*cols)]		for i in range(rows):			yield line	def cols(self):		raise NotImplementedError("BlankCanvas doesn't know its own size!")	def rows(self):		raise NotImplementedError("BlankCanvas doesn't know its own size!")		def content_delta(self):		raise NotImplementedError("BlankCanvas doesn't know its own size!")		blank_canvas = BlankCanvas()class SolidCanvas(Canvas):	"""	A canvas filled completely with a single character.	"""	def __init__(self, fill_char, cols, rows):		Canvas.__init__(self)		end, col = calc_text_pos(fill_char, 0, len(fill_char), 1)		assert col == 1, "Invalid fill_char: %r" % fill_char		self._text, cs = apply_target_encoding(fill_char[:end])		self._cs = cs[0][0]		self.size = cols, rows		self.cursor = None		def cols(self):		return self.size[0]		def rows(self):		return self.size[1]	def content(self, trim_left=0, trim_top=0, cols=None, rows=None, 			attr=None):		if cols is None:			cols = self.size[0]		if rows is None:			rows = self.size[1]		line = [(attr, self._cs, self._text*cols)]		for i in range(rows):			yield line	def content_delta(self, other):		"""		Return the differences between other and this canvas.		"""		if other is self:			return [self.cols()]*self.rows()		return self.content()		class CompositeCanvas(Canvas):	"""	class for storing a combination of canvases	"""	def __init__(self, canv=None):		"""		canv -- a Canvas object to wrap this CompositeCanvas around.		if canv is a CompositeCanvas, make a copy of its contents		"""		# a "shard" is a (num_rows, list of cviews) tuple, one for 		# each cview starting in this shard		# a "cview" is a tuple that defines a view of a canvas:		# (trim_left, trim_top, cols, rows, def_attr, canv)		# a "shard tail" is a list of tuples:		# (col_gap, done_rows, content_iter, cview) 				# tuples that define the unfinished cviews that are part of		# shards following the first shard.		Canvas.__init__(self)		if canv is None:			self.shards = []			self.children = []		else:			if hasattr(canv, "shards"):				self.shards = canv.shards			else:				self.shards = [(canv.rows(), [					(0, 0, canv.cols(), canv.rows(), 					None, canv)])]			self.children = [(0, 0, canv, None)]			self.coords.update(canv.coords)			for shortcut in canv.shortcuts:				self.shortcuts[shortcut] = "wrap"	def rows(self):		return sum([r for r,cv in self.shards])	def cols(self):		if not self.shards:			return 0		return sum([cv[2] for cv in self.shards[0][1]])			def content(self):		"""		Return the canvas content as a list of rows where each row		is a list of (attr, cs, text) tuples.		"""		shard_tail = []		for num_rows, cviews in self.shards:			# combine shard and shard tail			sbody = shard_body(cviews, shard_tail)			# output rows			for i in range(num_rows):				yield shard_body_row(sbody)			# prepare next shard tail						shard_tail = shard_body_tail(num_rows, sbody)							def content_delta(self, other):		"""		Return the differences between other and this canvas.		"""		if not hasattr(other, 'shards'):			for row in self.content():				yield row			return		shard_tail = []		for num_rows, cviews in shards_delta(				self.shards, other.shards):			# combine shard and shard tail			sbody = shard_body(cviews, shard_tail)			# output rows			row = []			for i in range(num_rows):				# if whole shard is unchanged, don't keep 				# calling shard_body_row				if len(row) != 1 or type(row[0]) != type(0):					row = shard_body_row(sbody)				yield row			# prepare next shard tail			shard_tail = shard_body_tail(num_rows, sbody)						def trim(self, top, count=None):		"""Trim lines from the top and/or bottom of canvas.		top -- number of lines to remove from top		count -- number of lines to keep, or None for all the rest		"""		assert top >= 0, "invalid trim amount %d!"%top		assert top < self.rows(), "cannot trim %d lines from %d!"%(			top, self.rows())		if self.widget_info:			raise self._finalized_error				if top:			self.shards = shards_trim_top(self.shards, top)		if count == 0:			self.shards = []		elif count is not None:			self.shards = shards_trim_rows(self.shards, count)		self.coords = self.translate_coords(0, -top)			def trim_end(self, end):		"""Trim lines from the bottom of the canvas.				end -- number of lines to remove from the end		"""		assert end > 0, "invalid trim amount %d!"%end		assert end <= self.rows(), "cannot trim %d lines from %d!"%(			end, self.rows())		if self.widget_info:			raise self._finalized_error				self.shards = shards_trim_rows(self.shards, self.rows() - end)				def pad_trim_left_right(self, left, right):		"""		Pad or trim this canvas on the left and right				values > 0 indicate screen columns to pad		values < 0 indicate screen columns to trim		"""		if self.widget_info:			raise self._finalized_error		shards = self.shards		if left < 0 or right < 0:			trim_left = max(0, -left)			cols = self.cols() - trim_left - max(0, -right)			shards = shards_trim_sides(shards, trim_left, cols)		rows = self.rows()		if left > 0 or right > 0:			top_rows, top_cviews = shards[0]			if left > 0:				new_top_cviews = (					[(0,0,left,rows,None,blank_canvas)] +					top_cviews)			else:				new_top_cviews = top_cviews[:] #copy			if right > 0:				new_top_cviews.append(					(0,0,right,rows,None,blank_canvas))			shards = [(top_rows, new_top_cviews)] + shards[1:]		self.coords = self.translate_coords(left, 0)		self.shards = shards	def pad_trim_top_bottom(self, top, bottom):		"""		Pad or trim this canvas on the top and bottom.		"""		if self.widget_info:			raise self._finalized_error		orig_shards = self.shards		if top < 0 or bottom < 0:			trim_top = max(0, -top)			rows = self.rows() - trim_top - max(0, -bottom)			self.trim(trim_top, rows)		cols = self.cols()		if top > 0:			self.shards = [(top,				[(0,0,cols,top,None,blank_canvas)])] + \				self.shards			self.coords = self.translate_coords(0, top)				if bottom > 0:			if orig_shards is self.shards:				self.shards = self.shards[:]			self.shards.append((bottom,				[(0,0,cols,bottom,None,blank_canvas)]))			def overlay(self, other, left, top ):		"""Overlay other onto this canvas."""		if self.widget_info:			raise self._finalized_error				width = other.cols()		height = other.rows()		right = self.cols() - left - width		bottom = self.rows() - top - height				assert right >= 0, "top canvas of overlay not the size expected!" + `other.cols(),left,right,width`		assert bottom >= 0, "top canvas of overlay not the size expected!" + `other.rows(),top,bottom,height`		shards = self.shards		top_shards = []		side_shards = self.shards		bottom_shards = []		if top:			side_shards = shards_trim_top(shards, top)			top_shards = shards_trim_rows(shards, top)		if bottom:			bottom_shards = shards_trim_top(side_shards, height)			side_shards = shards_trim_rows(side_shards, height)		left_shards = []		right_shards = []		if left:			left_shards = [shards_trim_sides(side_shards, 0, left)]		if right:			right_shards = [shards_trim_sides(side_shards, 				left + width, right)]				if not self.rows():			middle_shards = []		elif left or right:			middle_shards = shards_join(left_shards + 				[other.shards] + right_shards)		else:			middle_shards = other.shards		self.shards = top_shards + middle_shards + bottom_shards				self.coords.update(other.translate_coords(left, top))	def fill_attr(self, a):		"""		Apply attribute a to all areas of this canvas with default		attribute currently set to None, leaving other attributes		intact."""		if self.widget_info:			raise self._finalized_error		shards = []		for num_rows, original_cviews in self.shards:			new_cviews = []			for cv in original_cviews:				if cv[4] is None:					new_cviews.append(cv[:4] + (a,) + cv[5:])				else:					new_cviews.append(cv)			shards.append((num_rows, new_cviews))		self.shards = shards	def set_depends(self, widget_list):		"""		Explicitly specify the list of widgets that this canvas		depends on.  If any of these widgets change this canvas		will have to be updated.		"""		if self.widget_info:			raise self._finalized_error		self.depends_on = widget_listdef shard_body_row(sbody):	"""	Return one row, advancing the iterators in sbody.	** MODIFIES sbody by calling next() on its iterators **	"""	row = []	for done_rows, content_iter, cview in sbody:		if content_iter:			row.extend(content_iter.next())		else:			# need to skip this unchanged canvas			if row and type(row[-1]) == type(0):				row[-1] = row[-1] + cview[2]			else:				row.append(cview[2])	return rowdef shard_body_tail(num_rows, sbody):	"""	Return a new shard tail that follows this shard body.	"""	shard_tail = []	col_gap = 0	done_rows = 0	for done_rows, content_iter, cview in sbody:		cols, rows = cview[2:4]		done_rows += num_rows		if done_rows == rows:			col_gap += cols			continue		shard_tail.append((col_gap, done_rows, content_iter, cview))		col_gap = 0	return shard_taildef shards_delta(shards, other_shards):	"""	Yield shards1 with cviews that are the same as shards2 	having canv = None.	"""	other_shards_iter = iter(other_shards)	other_num_rows = other_cviews = None	done = other_done = 0	for num_rows, cviews in shards:		if other_num_rows is None:			other_num_rows, other_cviews = other_shards_iter.next()		while other_done < done:			other_done += other_num_rows			other_num_rows, other_cviews = other_shards_iter.next()		if other_done > done:			yield (num_rows, cviews)			done += num_rows			continue		# top-aligned shards, compare each cview		yield (num_rows, shard_cviews_delta(cviews, other_cviews))		other_done += other_num_rows		other_num_rows = None		done += num_rowsdef shard_cviews_delta(cviews, other_cviews):	"""	"""	other_cviews_iter = iter(other_cviews)	other_cv = None	cols = other_cols = 0	for cv in cviews:		if other_cv is None:			other_cv = other_cviews_iter.next()		while other_cols < cols:			other_cols += other_cv[2]			other_cv = other_cviews_iter.next()		if other_cols > cols:			yield cv			cols += cv[2]			continue

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -