about summary refs log tree commit diff stats
path: root/html/030container.cc.html
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2017-07-09 14:25:48 -0700
committerKartik K. Agaram <vc@akkartik.com>2017-07-09 14:25:48 -0700
commit6573fe1f1aa6d87c027d10429ded7e0162e52902 (patch)
treeddd110af3e987e49bb60ba05c16833c92d6d8901 /html/030container.cc.html
parent6ff9413c5dc624df6a33d7680a6667c27cd9352e (diff)
downloadmu-6573fe1f1aa6d87c027d10429ded7e0162e52902.tar.gz
3965 - get rid of the teardown() function
Instead of setup() and teardown() we'll just use a reset() function from
now on, which will bring the machine back to a good state before each
test or run, and also before exit (to avoid memory leaks).
Diffstat (limited to 'html/030container.cc.html')
0 files changed, 0 insertions, 0 deletions
href='#n116'>116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217
# Copyright (C) 2009, 2010  Roman Zimbelmann <romanz@lavabit.com>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

import os
import socket
import sys
import curses
import _curses

from .displayable import DisplayableContainer
from ranger.container.keymap import CommandArgs
from .mouse_event import MouseEvent

TERMINALS_WITH_TITLE = ("xterm", "xterm-256color", "rxvt",
		"rxvt-256color", "rxvt-unicode", "aterm", "Eterm",
		"screen", "screen-256color")

class UI(DisplayableContainer):
	is_set_up = False
	mousemask = curses.ALL_MOUSE_EVENTS | curses.REPORT_MOUSE_POSITION
	load_mode = False
	def __init__(self, keymap=None, env=None, fm=None):
		self._draw_title = os.environ["TERM"] in TERMINALS_WITH_TITLE
		os.environ['ESCDELAY'] = '25'   # don't know a cleaner way

		if env is not None:
			self.env = env
		if fm is not None:
			self.fm = fm

		if keymap is None:
			self.keymap = self.settings.keys.browser_keys()
		else:
			self.keymap = keymap
		self.win = curses.initscr()
		self.env.keybuffer.assign(self.keymap, self.settings.keys.directions)
		self.env.keybuffer.clear()

		DisplayableContainer.__init__(self, None)

	def initialize(self):
		"""initialize curses, then call setup (at the first time) and resize."""
		self.win.leaveok(0)
		self.win.keypad(1)
		self.load_mode = False

		curses.cbreak()
		curses.noecho()
		curses.halfdelay(20)
		try:
			curses.curs_set(int(bool(self.settings.show_cursor)))
		except:
			pass
		curses.start_color()
		curses.use_default_colors()

		curses.mousemask(self.mousemask)
		curses.mouseinterval(0)

		## this line solves this problem:
		## If an action, following a mouse click, includes the
		## suspension and re-initializion of the ui (e.g. running a
		## file by clicking on its preview) and the next key is another
		## mouse click, the bstate of this mouse event will be invalid.
		## (atm, invalid bstates are recognized as scroll-down)
		curses.ungetmouse(0,0,0,0,0)

		if not self.is_set_up:
			self.is_set_up = True
			self.setup()
		self.update_size()

	def suspend(self):
		"""Turn off curses"""
		# from ranger import log
		# log("suspending ui!")
		self.win.keypad(0)
		curses.nocbreak()
		curses.echo()
		try:
			curses.curs_set(1)
		except:
			pass
		curses.mousemask(0)
		curses.endwin()

	def set_load_mode(self, boolean):
		boolean = bool(boolean)
		if boolean != self.load_mode:
			self.load_mode = boolean

			if boolean:
				# don't wait for key presses in the load mode
				curses.cbreak()
				self.win.nodelay(1)
			else:
				self.win.nodelay(0)
				curses.halfdelay(20)

	def destroy(self):
		"""Destroy all widgets and turn off curses"""
		DisplayableContainer.destroy(self)
		self.suspend()

	def handle_mouse(self):
		"""Handles mouse input"""
		try:
			event = MouseEvent(curses.getmouse())
		except _curses.error:
			return

		# from ranger import log
		# log('{0:0>28b} ({0})'.format(event.bstate))
		# log('y: {0}  x: {1}'.format(event.y, event.x))

		DisplayableContainer.click(self, event)

	def handle_key(self, key):
		"""Handles key input"""

		if hasattr(self, 'hint'):
			self.hint()

		self.env.key_append(key)

		if DisplayableContainer.press(self, key):
			return

		kbuf = self.env.keybuffer
		cmd = kbuf.command

		self.fm.hide_bookmarks()

		if kbuf.failure:
			kbuf.clear()
			return
		elif not cmd:
			return

		self.env.cmd = cmd

		if cmd.function:
			try:
				cmd.function(CommandArgs.from_widget(self))
			except Exception as error:
				self.fm.notify(error)
			if kbuf.done:
				kbuf.clear()
		else:
			kbuf.clear()

	def get_next_key(self):
		"""Waits for key input and returns the pressed key"""
		key = self.win.getch()
		if key is not -1:
			if self.settings.flushinput:
				curses.flushinp()
		return key

	def setup(self):
		"""
		Called after an initialize() call.
		Override this!
		"""

	def redraw(self):
		"""Redraw all widgets"""
		self.poke()
		self.draw()
		self.finalize()

	def redraw_window(self):
		"""Redraw the window. This only calls self.win.redrawwin()."""
		self.win.erase()
		self.win.redrawwin()
		self.win.refresh()
		self.win.redrawwin()
		self.need_redraw = True

	def update_size(self):
		"""
		Update self.env.termsize.
		Extend this method to resize all widgets!
		"""
		self.env.termsize = self.win.getmaxyx()

	def draw(self):
		"""Erase the window, then draw all objects in the container"""
		self.win.touchwin()
		DisplayableContainer.draw(self)
		if self._draw_title and self.settings.update_title:
			cwd = self.fm.env.cwd.path
			if cwd.startswith(self.env.home_path):
				cwd = '~' + cwd[len(self.env.home_path):]
			if self.settings.shorten_title:
				split = cwd.rsplit(os.sep, self.settings.shorten_title)
				if os.sep in split[0]:
					cwd = os.sep.join(split[1:])
			sys.stdout.write("\033]2;ranger:" + cwd + "\007")
		self.win.refresh()

	def finalize(self):
		"""Finalize every object in container and refresh the window"""
		DisplayableContainer.finalize(self)
		self.win.refresh()