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

📄 widget.py

📁 Urwid is a Python library for making text console applications. It has many features including fluid
💻 PY
📖 第 1 页 / 共 5 页
字号:
				if self.state is not True:			self.set_state(True)		else:			return key		def mouse_event(self, (maxcol,), event, button, x, y, focus):		"""Set state to True on button 1 press."""		if button != 1 or not is_mouse_press(event):			return False		if self.state is not True:			self.set_state(True)		return True			class Button(WidgetWrap):	button_left = Text("<")	button_right = Text(">")	def selectable(self):		return True		def __init__(self, label, on_press=None, user_data=None):		"""		label -- markup for button label		on_press -- callback function for button "press"		           on_press( button object, user_data=None)                user_data -- additional param for on_press callback,		           ommited if None for compatibility reasons		"""		self.__super.__init__(None) # self.w set by set_label below					self.set_label( label )		self.on_press = on_press		self.user_data = user_data		def set_label(self, label):		self.label = label		self.w = Columns([			('fixed', 1, self.button_left),			Text( label ),			('fixed', 1, self.button_right)],			dividechars=1)		self._invalidate()		def get_label(self):		return self.label		def render(self, (maxcol,), focus=False):		"""Display button. Show a cursor when in focus."""		canv = self.__super.render((maxcol,), focus=focus)		canv = CompositeCanvas(canv)		if focus and maxcol >2:			canv.cursor = (2,0)		return canv	def get_cursor_coords(self, (maxcol,)):		"""Return the location of the cursor."""		if maxcol >2:			return (2,0)		return None	def keypress(self, (maxcol,), key):		"""Call on_press on spage or enter."""		if key not in (' ','enter'):			return key		if self.on_press:			if self.user_data is None:				self.on_press(self)			else:				self.on_press(self, self.user_data)	def mouse_event(self, (maxcol,), event, button, x, y, focus):		"""Call on_press on button 1 press."""		if button != 1 or not is_mouse_press(event):			return False					if self.on_press:			self.on_press( self )			return True		return False	class GridFlow(FlowWidget):	def selectable(self): 		"""Return True if the cell in focus is selectable."""		return self.focus_cell and self.focus_cell.selectable()			def __init__(self, cells, cell_width, h_sep, v_sep, align):		"""		cells -- list of flow widgets to display		cell_width -- column width for each cell		h_sep -- blank columns between each cell horizontally		v_sep -- blank rows between cells vertically (if more than		         one row is required to display all the cells)		align -- horizontal alignment of cells, see "align" parameter		         of Padding widget for available options		"""		self.__super.__init__()		self.cells = cells		self.cell_width = cell_width		self.h_sep = h_sep		self.v_sep = v_sep		self.align = align		self.focus_cell = None		if cells:			self.focus_cell = cells[0]		self._cache_maxcol = None	def set_focus(self, cell):		"""Set the cell in focus.  				cell -- widget or integer index into self.cells"""		if type(cell) == type(0):			assert cell>=0 and cell<len(self.cells)			self.focus_cell = self.cells[cell]		else:			assert cell in self.cells			self.focus_cell = cell		self._cache_maxcol = None		self._invalidate()			def get_display_widget(self, (maxcol,)):		"""		Arrange the cells into columns (and possibly a pile) for 		display, input or to calculate rows. 		"""		# use cache if possible		if self._cache_maxcol == maxcol:			return self._cache_display_widget		self._cache_maxcol = maxcol		self._cache_display_widget = self.generate_display_widget(			(maxcol,))		return self._cache_display_widget	def generate_display_widget(self, (maxcol,)):		"""		Actually generate display widget (ignoring cache)		"""		d = Divider()		if len(self.cells) == 0: # how dull			return d				if self.v_sep > 1:			# increase size of divider			d.top = self.v_sep-1				# cells per row		bpr = (maxcol+self.h_sep) / (self.cell_width+self.h_sep)				if bpr == 0: # too narrow, pile them on top of eachother			l = [self.cells[0]]			f = 0			for b in self.cells[1:]:				if b is self.focus_cell:					f = len(l)				if self.v_sep:					l.append(d)				l.append(b)			return Pile(l, f)				if bpr >= len(self.cells): # all fit on one row			k = len(self.cells)			f = self.cells.index(self.focus_cell)			cols = Columns(self.cells, self.h_sep, f)			rwidth = (self.cell_width+self.h_sep)*k - self.h_sep			row = Padding(cols, self.align, rwidth)			return row				out = []		s = 0		f = 0		while s < len(self.cells):			if out and self.v_sep:				out.append(d)			k = min( len(self.cells), s+bpr )			cells = self.cells[s:k]			if self.focus_cell in cells:				f = len(out)				fcol = cells.index(self.focus_cell)				cols = Columns(cells, self.h_sep, fcol)			else:				cols = Columns(cells, self.h_sep)			rwidth = (self.cell_width+self.h_sep)*(k-s)-self.h_sep			row = Padding(cols, self.align, rwidth)			out.append(row)			s += bpr		return Pile(out, f)			def _set_focus_from_display_widget(self, w):		"""Set the focus to the item in focus in the display widget."""		if isinstance(w, Padding):			# unwrap padding			w = w.w		w = w.get_focus()		if w in self.cells:			self.set_focus(w)			return		if isinstance(w, Padding):			# unwrap padding			w = w.w		w = w.get_focus()		#assert w == self.cells[0], `w, self.cells`		self.set_focus(w)	def keypress(self, (maxcol,), key):		"""		Pass keypress to display widget for handling.  		Capture	focus changes."""				d = self.get_display_widget((maxcol,))		if not d.selectable():			return key		key = d.keypress( (maxcol,), key)		if key is None:			self._set_focus_from_display_widget(d)		return key	def rows(self, (maxcol,), focus=False):		"""Return rows used by this widget."""		d = self.get_display_widget((maxcol,))		return d.rows((maxcol,), focus=focus)		def render(self, (maxcol,), focus=False ):		"""Use display widget to render."""		d = self.get_display_widget((maxcol,))		return d.render((maxcol,), focus)	def get_cursor_coords(self, (maxcol,)):		"""Get cursor from display widget."""		d = self.get_display_widget((maxcol,))		if not d.selectable():			return None		return d.get_cursor_coords((maxcol,))		def move_cursor_to_coords(self, (maxcol,), col, row ):		"""Set the widget in focus based on the col + row."""		d = self.get_display_widget((maxcol,))		if not d.selectable():			# happy is the default			return True				r =  d.move_cursor_to_coords((maxcol,), col, row)		if not r:			return False				self._set_focus_from_display_widget(d)		self._invalidate()		return True		def mouse_event(self, (maxcol,), event, button, col, row, focus):		"""Send mouse event to contained widget."""		d = self.get_display_widget((maxcol,))				r = d.mouse_event( (maxcol,), event, button, col, row, focus )		if not r:			return False				self._set_focus_from_display_widget(d)		self._invalidate()		return True				def get_pref_col(self, (maxcol,)):		"""Return pref col from display widget."""		d = self.get_display_widget((maxcol,))		if not d.selectable():			return None		return d.get_pref_col((maxcol,))	class PaddingError(Exception):	passclass Padding(Widget):	def __init__(self, w, align, width, min_width=None):		"""		w -- a box, flow or fixed widget to pad on the left and/or right		align -- one of:		    'left', 'center', 'right'		    ('fixed left', columns)		    ('fixed right', columns)		    ('relative', percentage 0=left 100=right)		width -- one of:		    number of columns wide 		    ('fixed right', columns)  Only if align is 'fixed left'		    ('fixed left', columns)  Only if align is 'fixed right'		    ('relative', percentage of total width)		    None   to enable clipping mode		min_width -- the minimum number of columns for w or None					Padding widgets will try to satisfy width argument first by		reducing the align amount when necessary.  If width still 		cannot be satisfied it will also be reduced.		Clipping Mode:		In clipping mode w is treated as a fixed widget and this 		widget expects to be treated as a flow widget.  w will		be clipped to fit within the space given.  For example,		if align is 'left' then w may be clipped on the right.		"""		self.__super.__init__()		at,aa,wt,wa=decompose_align_width(align, width, PaddingError)				self.w = w		self.align_type, self.align_amount = at, aa		self.width_type, self.width_amount = wt, wa		self.min_width = min_width			def render(self, size, focus=False):			left, right = self.padding_values(size, focus)				maxcol = size[0]		maxcol -= left+right		if self.width_type is None:			canv = self.w.render((), focus)		else:			canv = self.w.render((maxcol,)+size[1:], focus)		if canv.cols() == 0:			canv = SolidCanvas(' ', size[0], canv.rows())			canv = CompositeCanvas(canv)			canv.set_depends([self.w])			return canv		canv = CompositeCanvas(canv)		canv.set_depends([self.w])		if left != 0 or right != 0:			canv.pad_trim_left_right(left, right)		return canv	def padding_values(self, size, focus):		"""Return the number of columns to pad on the left and right.				Override this method to define custom padding behaviour."""		maxcol = size[0]		if self.width_type is None:			width, ignore = self.w.pack(focus=focus)			return calculate_padding(self.align_type,				self.align_amount, 'fixed', width, 				None, maxcol, clip=True )		return calculate_padding( self.align_type, self.align_amount,			self.width_type, self.width_amount,			self.min_width, maxcol )	def selectable(self):		"""Return the selectable value of self.w."""		return self.w.selectable()	def rows(self, (maxcol,), focus=False ):		"""Return the rows needed for self.w."""		if self.width_type is None:			ignore, height = self.w.pack(focus)			return height		left, right = self.padding_values((maxcol,), focus)		return self.w.rows( (maxcol-left-right,), focus=focus )		def keypress(self, size, key):		"""Pass keypress to self.w."""		maxcol = size[0]		left, right = self.padding_values(size, True)		maxvals = (maxcol-left-right,)+size[1:] 		return self.w.keypress(maxvals, key)	def get_cursor_coords(self,size):		"""Return the (x,y) coordinates of cursor within self.w."""		if not hasattr(self.w,'get_cursor_coords'):			return None		left, right = self.padding_values(size, True)		maxcol = size[0]		maxvals = (maxcol-left-right,)+size[1:] 		coords = self.w.get_cursor_coords(maxvals)		if coords is None: 			return None		x, y = coords		return x+left, y	def move_cursor_to_coords(self, size, x, y):		"""Set the cursor position with (x,y) coordinates of self.w.		Returns True if move succeeded, False otherwise.		"""		if not hasattr(self.w,'move_cursor_to_coords'):			return True		left, right = self.padding_values(size, True)		maxcol = size[0]		maxvals = (maxcol-left-right,)+size[1:] 		if type(x)==type(0):			if x < left: 				x = left			elif x >= maxcol-right: 				x = maxcol-right-1			x -= left		return self.w.move_cursor_to_coords(maxvals, x, y)		def mouse_event(self, size, event, button, x, y, focus):		"""Send mouse event if position is within self.w."""		if not hasattr(self.w,'mouse_event'):			return False		left, right = self.padding_values(size, focus)		maxcol = size[0]		if x < left or x >= maxcol-right: 			return False		maxvals = (maxcol-left-right,)+size[1:] 		return self.w.mouse_event(maxvals, event, button, x-left, y,			focus)			def get_pref_col(self, size):		"""Return the preferred column from self.w, or None."""		if not hasattr(self.w,'get_pref_col'):			return None		left, right = self.padding_values(size, True)		maxcol = size[0]		maxvals = (maxcol-left-right,)+size[1:] 		x = self.w.get_pref_col(maxvals)		if type(x) == type(0):			return x+left		return x		class FillerError(Exception):	passclass Filler(BoxWidget):	def __init__(self, body, valign="middle", height=None, min_height=None):		"""		body -- a flow widget or box widget to be filled around		valign -- one of:		    'top', 'middle', 'bottom'		    ('fixed top', rows)		    ('fixed bottom', rows)		    ('relative', percentage 0=top 100=bottom)		height -- one of:		    None if body is a flow widget		    number of rows high 		    ('fixed bottom', rows)  Only if valign is 'fixed top'		    ('fixed top', rows)  Only if valign is 'fixed bottom'		    ('relative', percentage of total height)		min_height -- one of:		    None if no minimum or if body is a flow widget		    minimum number of rows for the widget when height not fixed				If body is a flow widget then height and min_height must be set		to None.				Filler widgets will try to satisfy height argument first by		reducing the valign amount when necessary.  If height still 		cannot be satisfied it will also be reduced.		"""		self.__super.__init__()		vt,va,ht,ha=decompose_valign_height(valign,height,FillerError)				self._body = body		self.valign_type, self.valign_amount = vt, va		self.height_type, self.height_amount = ht, ha		if self.height_type not in ('fixed', None):			self.min_height = min_height		else:			self.min_height = None		def get_body(self):		return self._body	def set_body(self, body):

⌨️ 快捷键说明

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