# Text editing widget

# NB: this always assumes fixed bounds.
# For auto-growing TextEdit windows, different code would be needed.

from stdwinevents import *

class TextEdit:
	#
	def create(self, parent, (cols, rows)):
		parent.addchild(self)
		self.parent = parent
		self.cols = cols
		self.rows = rows
		self.text = ''
		# Creation of the editor is done in realize()
		self.editor = None
		self.dh = self.dv = 0
		return self
	#
	def createboxed(self, parent, (cols, rows), (dh, dv)):
		self = self.create(parent, (cols, rows))
		self.dh = max(0, dh)
		self.dv = max(0, dv)
		return self
	#
	def settext(self, text):
		self.editor.settext(text)
	#
	def gettext(self):
		return self.editor.gettext(text)
	#
	# Downcalls from parent to child
	#
	def destroy(self):
		del self.parent
		del self.editor
		del self.window
	#
	def getminsize(self, m, (width, height)):
		width = max(0, width - 2*self.dh)
		height = max(0, height - 2*self.dv)
		if width > 0 and self.editor:
			(left, top), (right, bottom) = self.editor.getrect()
			act_width, act_height = right - left, bottom - top
			if width >= act_width:
				width = width + 2*self.dh
				height = max(height, act_height) + 2*self.dv
				return width, height
		width = max(width, self.cols*m.textwidth('in')/2) + 2*self.dh
		height = max(height, self.rows*m.lineheight()) + 2*self.dv
		return width, height
	#
	def setbounds(self, bounds):
		self.bounds = bounds
		if self.editor:
			(left, top), (right, bottom) = bounds
			left = left + self.dh
			top = top + self.dv
			right = right - self.dh
			bottom = bottom - self.dv
			self.editor.move((left, top), (right, bottom))
			if self.dh and self.dv:
				(left, top), (right, bottom) = bounds
				left = left + 1
				top = top + 1
				right = right - 1
				bottom = bottom - 1
				bounds = (left, top), (right, bottom)
			self.editor.setview(bounds)
	#
	def getbounds(self):
		return self.bounds
	#
	def realize(self):
		self.window = self.parent.getwindow()
		(left, top), (right, bottom) = self.bounds
		left = left + self.dh
		top = top + self.dv
		right = right - self.dh
		bottom = bottom - self.dv
		self.editor = \
			self.window.textcreate((left, top), (right, bottom))
		self.editor.setactive(0)
		bounds = self.bounds
		if self.dh and self.dv:
			(left, top), (right, bottom) = bounds
			left = left + 1
			top = top + 1
			right = right - 1
			bottom = bottom - 1
			bounds = (left, top), (right, bottom)
		self.editor.setview(bounds)
		self.editor.settext(self.text)
		self.parent.need_mouse(self)
		self.parent.need_keybd(self)
		self.parent.need_altdraw(self)
	#
	def draw(self, d, area):
		if self.dh and self.dv:
			d.box(self.bounds)
	#
	def altdraw(self, area):
		self.editor.draw(area)
	#
	# Event downcalls
	#
	def mouse_down(self, detail):
		x = self.editor.event(WE_MOUSE_DOWN, self.window, detail)
	#
	def mouse_move(self, detail):
		x = self.editor.event(WE_MOUSE_MOVE, self.window, detail)
	#
	def mouse_up(self, detail):
		x = self.editor.event(WE_MOUSE_UP, self.window, detail)
	#
	def keybd(self, type, detail):
		x = self.editor.event(type, self.window, detail)
	#
	def activate(self):
		self.editor.setfocus(0, 30000)
		self.editor.setactive(1)
	#
	def deactivate(self):
		self.editor.setactive(0)
	#
