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

📄 listbox.py

📁 Urwid is a Python library for making text console applications. It has many features including fluid
💻 PY
📖 第 1 页 / 共 3 页
字号:
		trim_top, fill_above = top		trim_bottom, fill_below = bottom		if focus_widget.selectable():			return		if trim_bottom:			fill_below = fill_below[:-1]		new_row_offset = row_offset + focus_rows		for widget, pos, rows in fill_below:			if widget.selectable():				self.body.set_focus(pos)				self.shift_focus((maxcol, maxrow), 					new_row_offset)				return			new_row_offset += rows	def _set_focus_complete(self, (maxcol, maxrow), focus):		"""		Finish setting the position now that we have maxcol & maxrow.		"""		self._invalidate()		if self.set_focus_pending == "first selectable":			return self._set_focus_first_selectable(				(maxcol,maxrow), focus)		if self.set_focus_valign_pending is not None:			return self._set_focus_valign_complete(				(maxcol,maxrow), focus)		coming_from, focus_widget, focus_pos = self.set_focus_pending		self.set_focus_pending = None				# new position		new_focus_widget, position = self.body.get_focus()		if focus_pos == position:			# do nothing			return					# restore old focus temporarily		self.body.set_focus(focus_pos)						middle,top,bottom=self.calculate_visible((maxcol,maxrow),focus)		focus_offset, focus_widget, focus_pos, focus_rows, cursor=middle		trim_top, fill_above = top		trim_bottom, fill_below = bottom				offset = focus_offset		for widget, pos, rows in fill_above:			offset -= rows			if pos == position:				self.change_focus((maxcol, maxrow), pos,					offset, 'below' )				return		offset = focus_offset + focus_rows		for widget, pos, rows in fill_below:			if pos == position:				self.change_focus((maxcol, maxrow), pos,					offset, 'above' )				return			offset += rows		# failed to find widget among visible widgets		self.body.set_focus( position )		widget, position = self.body.get_focus()		rows = widget.rows((maxcol,), focus)		if coming_from=='below':			offset = 0		elif coming_from=='above':			offset = maxrow-rows		else:			offset = (maxrow-rows)/2		self.shift_focus((maxcol, maxrow), offset)		def shift_focus(self, (maxcol,maxrow), offset_inset ):		"""Move the location of the current focus relative to the top.				offset_inset -- either the number of rows between the 		  top of the listbox and the start of the focus widget (+ve		  value) or the number of lines of the focus widget hidden off 		  the top edge of the listbox (-ve value) or 0 if the top edge		  of the focus widget is aligned with the top edge of the		  listbox		"""				if offset_inset >= 0:			if offset_inset >= maxrow:				raise ListBoxError, "Invalid offset_inset: %s, only %s rows in list box"% (`offset_inset`, `maxrow`)			self.offset_rows = offset_inset			self.inset_fraction = (0,1)		else:			target, _ignore = self.body.get_focus()			tgt_rows = target.rows( (maxcol,), focus=1 )			if offset_inset + tgt_rows <= 0:				raise ListBoxError, "Invalid offset_inset: %s, only %s rows in target!" %(`offset_inset`, `tgt_rows`)			self.offset_rows = 0			self.inset_fraction = (-offset_inset,tgt_rows)		self._invalidate()					def update_pref_col_from_focus(self, (maxcol,maxrow) ):		"""Update self.pref_col from the focus widget."""				widget, old_pos = self.body.get_focus()		if widget is None: return		pref_col = None		if hasattr(widget,'get_pref_col'):			pref_col = widget.get_pref_col((maxcol,))		if pref_col is None and hasattr(widget,'get_cursor_coords'):			coords = widget.get_cursor_coords((maxcol,))			if type(coords) == type(()):				pref_col,y = coords		if pref_col is not None: 			self.pref_col = pref_col	def change_focus(self, (maxcol,maxrow), position, 			offset_inset = 0, coming_from = None, 			cursor_coords = None, snap_rows = None ):		"""Change the current focus widget.				position -- a position compatible with self.body.set_focus		offset_inset_rows -- either the number of rows between the 		  top of the listbox and the start of the focus widget (+ve		  value) or the number of lines of the focus widget hidden off 		  the top edge of the listbox (-ve value) or 0 if the top edge		  of the focus widget is aligned with the top edge of the		  listbox (default if unspecified)		coming_from -- eiter 'above', 'below' or unspecified (None)		cursor_coords -- (x, y) tuple indicating the desired		  column and row for the cursor, a (x,) tuple indicating only		  the column for the cursor, or unspecified (None)		snap_rows -- the maximum number of extra rows to scroll		  when trying to "snap" a selectable focus into the view		"""				# update pref_col before change		if cursor_coords:			self.pref_col = cursor_coords[0]		else:			self.update_pref_col_from_focus((maxcol,maxrow))		self.body.set_focus(position)		target, _ignore = self.body.get_focus()		tgt_rows = target.rows( (maxcol,), focus=1 )		if snap_rows is None:			snap_rows = maxrow-1		# "snap" to selectable widgets		align_top = 0		align_bottom = maxrow - tgt_rows				if ( coming_from == 'above' 				and target.selectable()				and offset_inset > align_bottom				and align_bottom >= offset_inset-snap_rows ):			offset_inset = align_bottom					if ( coming_from == 'below' 				and target.selectable() 				and offset_inset < align_top				and align_top <= offset_inset+snap_rows ):			offset_inset = align_top				# convert offset_inset to offset_rows or inset_fraction		if offset_inset >= 0:			self.offset_rows = offset_inset			self.inset_fraction = (0,1)		else:			if offset_inset + tgt_rows <= 0:				raise ListBoxError, "Invalid offset_inset: %s, only %s rows in target!" %(offset_inset, tgt_rows)			self.offset_rows = 0			self.inset_fraction = (-offset_inset,tgt_rows)				if cursor_coords is None:			if coming_from is None: 				return # must either know row or coming_from			cursor_coords = (self.pref_col,)				if not hasattr(target,'move_cursor_to_coords'):			return					attempt_rows = []				if len(cursor_coords) == 1:			# only column (not row) specified			# start from closest edge and move inwards			(pref_col,) = cursor_coords			if coming_from=='above':				attempt_rows = range( 0, tgt_rows )			else:				assert coming_from == 'below', "must specify coming_from ('above' or 'below') if cursor row is not specified"				attempt_rows = range( tgt_rows, -1, -1)		else:			# both column and row specified			# start from preferred row and move back to closest edge			(pref_col, pref_row) = cursor_coords			if pref_row < 0 or pref_row >= tgt_rows:				raise ListBoxError, "cursor_coords row outside valid range for target. pref_row:%s target_rows:%s"%(`pref_row`,`tgt_rows`)			if coming_from=='above':				attempt_rows = range( pref_row, -1, -1 )			elif coming_from=='below':				attempt_rows = range( pref_row, tgt_rows )			else:				attempt_rows = [pref_row]		for row in attempt_rows:			if target.move_cursor_to_coords((maxcol,),pref_col,row):				break		self._invalidate()	def get_focus_offset_inset(self,(maxcol, maxrow)):		"""Return (offset rows, inset rows) for focus widget."""		focus_widget, pos = self.body.get_focus()		focus_rows = focus_widget.rows((maxcol,), True)		offset_rows = self.offset_rows		inset_rows = 0		if offset_rows == 0:			inum, iden = self.inset_fraction			if inum < 0 or iden < 0 or inum >= iden:				raise ListBoxError, "Invalid inset_fraction: %s"%`self.inset_fraction`			inset_rows = focus_rows * inum / iden			assert inset_rows < focus_rows, "urwid inset_fraction error (please report)"		return offset_rows, inset_rows	def make_cursor_visible(self,(maxcol,maxrow)):		"""Shift the focus widget so that its cursor is visible."""				focus_widget, pos = self.body.get_focus()		if focus_widget is None:			return		if not focus_widget.selectable(): 			return		if not hasattr(focus_widget,'get_cursor_coords'): 			return		cursor = focus_widget.get_cursor_coords((maxcol,))		if cursor is None: 			return		cx, cy = cursor		offset_rows, inset_rows = self.get_focus_offset_inset(			(maxcol, maxrow))				if cy < inset_rows:			self.shift_focus( (maxcol,maxrow), - (cy) )			return					if offset_rows - inset_rows + cy >= maxrow:			self.shift_focus( (maxcol,maxrow), maxrow-cy-1 )			return	def keypress(self,(maxcol,maxrow), key):		"""Move selection through the list elements scrolling when 		necessary. 'up' and 'down' are first passed to widget in focus		in case that widget can handle them. 'page up' and 'page down'		are always handled by the ListBox.				Keystrokes handled by this widget are:		 'up'        up one line (or widget)		 'down'      down one line (or widget)		 'page up'   move cursor up one listbox length		 'page down' move cursor down one listbox length		"""		if self.set_focus_pending or self.set_focus_valign_pending:			self._set_focus_complete( (maxcol,maxrow), focus=True )					focus_widget, pos = self.body.get_focus()		if focus_widget is None: # empty listbox, can't do anything			return key					if key not in ['page up','page down']:			if focus_widget.selectable():				key = focus_widget.keypress((maxcol,),key)			if key is None: 				self.make_cursor_visible((maxcol,maxrow))				return				# pass off the heavy lifting		if key == 'up':			return self._keypress_up((maxcol, maxrow))					if key == 'down':			return self._keypress_down((maxcol, maxrow))		if key == 'page up':			return self._keypress_page_up((maxcol, maxrow))					if key == 'page down':			return self._keypress_page_down((maxcol, maxrow))		return key				def _keypress_up( self, (maxcol, maxrow) ):			middle, top, bottom = self.calculate_visible(			(maxcol,maxrow), focus=1 )		if middle is None: return 'up'				focus_row_offset,focus_widget,focus_pos,_ignore,cursor = middle		trim_top, fill_above = top				row_offset = focus_row_offset				# look for selectable widget above		pos = focus_pos		widget = None		for widget, pos, rows in fill_above:			row_offset -= rows			if widget.selectable():				# this one will do				self.change_focus((maxcol,maxrow), pos,					row_offset, 'below')				return				# at this point we must scroll		row_offset += 1		self._invalidate()				if row_offset > 0:			# need to scroll in another candidate widget			widget, pos = self.body.get_prev(pos)			if widget is None:				# cannot scroll any further				return 'up' # keypress not handled			rows = widget.rows((maxcol,), focus=1)			row_offset -= rows			if widget.selectable():				# this one will do				self.change_focus((maxcol,maxrow), pos,					row_offset, 'below')				return				if not focus_widget.selectable() or focus_row_offset+1>=maxrow:			# just take top one if focus is not selectable			# or if focus has moved out of view			if widget is None:				self.shift_focus((maxcol,maxrow), row_offset)				return			self.change_focus((maxcol,maxrow), pos,				row_offset, 'below')			return		# check if cursor will stop scroll from taking effect		if cursor is not None:			x,y = cursor			if y+focus_row_offset+1 >= maxrow:				# cursor position is a problem, 				# choose another focus				if widget is None:					# try harder to get prev widget					widget, pos = self.body.get_prev(pos)					if widget is None:						return # can't do anything					rows = widget.rows((maxcol,),focus=1)					row_offset -= rows								if -row_offset >= rows:					# must scroll further than 1 line					row_offset = - (rows-1)								self.change_focus((maxcol,maxrow),pos,					row_offset, 'below')				return		# if all else fails, just shift the current focus.		self.shift_focus((maxcol,maxrow), focus_row_offset+1)											def _keypress_down( self, (maxcol, maxrow) ):			middle, top, bottom = self.calculate_visible(			(maxcol,maxrow), focus=1 )		if middle is None: return 'down'					focus_row_offset,focus_widget,focus_pos,focus_rows,cursor=middle		trim_bottom, fill_below = bottom				row_offset = focus_row_offset + focus_rows		rows = focus_rows			# look for selectable widget below		pos = focus_pos		widget = None		for widget, pos, rows in fill_below:			if widget.selectable():				# this one will do				self.change_focus((maxcol,maxrow), pos,					row_offset, 'above')				return			row_offset += rows				# at this point we must scroll		row_offset -= 1		self._invalidate()				if row_offset < maxrow:			# need to scroll in another candidate widget			widget, pos = self.body.get_next(pos)			if widget is None:				# cannot scroll any further				return 'down' # keypress not handled			if widget.selectable():				# this one will do				self.change_focus((maxcol,maxrow), pos,					row_offset, 'above')				return			rows = widget.rows((maxcol,))			row_offset += rows				if not focus_widget.selectable() or focus_row_offset+focus_rows-1 <= 0:			# just take bottom one if current is not selectable			# or if focus has moved out of view			if widget is None:				self.shift_focus((maxcol,maxrow), 					row_offset-rows)				return			# FIXME: catch this bug in testcase			#self.change_focus((maxcol,maxrow), pos,			#	row_offset+rows, 'above')			self.change_focus((maxcol,maxrow), pos,				row_offset-rows, 'above')			return		# check if cursor will stop scroll from taking effect		if cursor is not None:			x,y = cursor			if y+focus_row_offset-1 < 0:				# cursor position is a problem,				# choose another focus				if widget is None:					# try harder to get next widget					widget, pos = self.body.get_next(pos)					if widget is None:						return # can't do anything				else:					row_offset -= rows

⌨️ 快捷键说明

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