# Demo of using just windows, without documents and views.

# Also demo of a GUI thread, pretty much direct from the MFC C++ sample MTMDI.

import win32ui
import win32con
import win32api
import timer

from pywin.mfc import window, docview, thread


WM_USER_PREPARE_TO_CLOSE = win32con.WM_USER + 32

# font is a dictionary in which the following elements matter:
# (the best matching font to supplied parameters is returned)
#   name		string name of the font as known by Windows
#   size		point size of font in logical units
#   weight		weight of font (win32con.FW_NORMAL, win32con.FW_BOLD)
#   italic		boolean; true if set to anything but None
#   underline	boolean; true if set to anything but None

# This window is a child window of a frame.  It is not the frame window itself.
class FontWindow(window.Wnd):
	def __init__(self,  text = 'Python Rules!'):
		window.Wnd.__init__(self)
		self.text = text
		self.index = 0
		self.incr = 1
		self.width = self.height = 0
		self.ChangeAttributes()
		# set up message handlers
		
	def Create(self, title, style, rect, parent):
		classStyle = win32con.CS_HREDRAW | win32con.CS_VREDRAW
		className = win32ui.RegisterWndClass(classStyle, 0, win32con.COLOR_WINDOW+1, 0)
		self._obj_ = win32ui.CreateWnd()
		self._obj_.AttachObject(self)
		self._obj_.CreateWindow(className, title, style, rect, parent, win32ui.AFX_IDW_PANE_FIRST)
		self.HookMessage (self.OnSize, win32con.WM_SIZE)
		self.HookMessage (self.OnPrepareToClose, WM_USER_PREPARE_TO_CLOSE)
		self.HookMessage (self.OnDestroy, win32con.WM_DESTROY)
		self.timerid = timer.set_timer (100, self.OnTimer)
		self.InvalidateRect()

	def OnDestroy (self, msg):
		timer.kill_timer(self.timerid)

	def OnTimer(self, id, timeVal):
		self.index = self.index + self.incr
		if self.index > len(self.text):
			self.incr = -1
			self.index = len(self.text)
		elif self.index < 0:
			self.incr = 1
			self.index = 0
		self.InvalidateRect()

	def OnPaint (self):
#		print "Paint message from thread", win32api.GetCurrentThreadId()
		dc, paintStruct = self.BeginPaint()
		self.OnPrepareDC(dc, None)
		
		if (self.width == 0 and self.height == 0):
			left, top, right, bottom = self.GetClientRect()
			self.width = right - left
			self.height = bottom - top
		x, y = self.width / 2, self.height / 2
		dc.TextOut (x, y, self.text[:self.index])
		self.EndPaint(paintStruct)

	def ChangeAttributes(self):
		font_spec = {'name':'Arial', 'height':42}
		self.font = win32ui.CreateFont (font_spec)
		
	def OnPrepareToClose(self, params):
		self.DestroyWindow()

	def OnSize (self, params):
		lParam = params[3]
		self.width = win32api.LOWORD(lParam)
		self.height = win32api.HIWORD(lParam)

	def OnPrepareDC (self, dc, printinfo):
		# Set up the DC for forthcoming OnDraw call
		dc.SetTextColor (win32api.RGB(0,0,255))
		dc.SetBkColor (win32api.GetSysColor (win32con.COLOR_WINDOW))
		dc.SelectObject (self.font)
		dc.SetTextAlign (win32con.TA_CENTER | win32con.TA_BASELINE)

class FontFrame(window.MDIChildWnd):
	def __init__(self):
		pass # Dont call base class doc/view version...
	def Create(self, title, rect = None, parent = None):
		style = win32con.WS_CHILD | win32con.WS_VISIBLE | win32con.WS_OVERLAPPEDWINDOW
		self._obj_ = win32ui.CreateMDIChild()
		self._obj_.AttachObject(self)
		self._obj_.CreateWindow(None, title, style, rect, parent)
		rect = self.GetClientRect()
		rect = (0,0,rect[2]-rect[0], rect[3]-rect[1])
		self.child = FontWindow("Not threaded")
		self.child.Create("FontDemo", win32con.WS_CHILD | win32con.WS_VISIBLE, rect, self)


class TestThread(thread.WinThread):
	def __init__(self, parentWindow):
		self.parentWindow = parentWindow
		self.child = None
		thread.WinThread.__init__(self)
	def InitInstance(self):
		rect = self.parentWindow.GetClientRect()
		rect = (0,0,rect[2]-rect[0], rect[3]-rect[1])
		self.child = FontWindow()
		self.child.Create("FontDemo", win32con.WS_CHILD | win32con.WS_VISIBLE, rect, self.parentWindow)
		self.SetMainFrame(self.child)
		return thread.WinThread.InitInstance(self)

	def ExitInstance(self):
		return 0

class ThreadedFontFrame(window.MDIChildWnd):
	def __init__(self):
		pass # Dont call base class doc/view version...
		self.thread = None
	def Create(self, title, rect = None, parent = None):
		style = win32con.WS_CHILD | win32con.WS_VISIBLE | win32con.WS_OVERLAPPEDWINDOW
		self._obj_ = win32ui.CreateMDIChild()
		self._obj_.CreateWindow(None, title, style, rect, parent)
		self._obj_.HookMessage(self.OnDestroy, win32con.WM_DESTROY)
		self._obj_.HookMessage (self.OnSize, win32con.WM_SIZE)
		
		self.thread = TestThread(self)
		self.thread.CreateThread()
		
	def OnSize(self, msg):
		pass

	def OnDestroy(self, msg):
		win32ui.OutputDebugString("OnDestroy\n")
		if self.thread and self.thread.child:
			child = self.thread.child
			child.SendMessage(WM_USER_PREPARE_TO_CLOSE, 0, 0)
			win32ui.OutputDebugString("Destroyed\n")

	
def Demo():
	f = FontFrame()
	f.Create("Font Demo")

def ThreadedDemo():
	rect = win32ui.GetMainFrame().GetMDIClient().GetClientRect()
	rect = rect[0], rect[3]*3/4, rect[2]/4, rect[3]
	incr = rect[2]
	for i in range(4):
		if i==0:
			f = FontFrame()
			title = "Not threaded"
		else:
			f = ThreadedFontFrame()
			title = "Threaded GUI Demo"
		f.Create(title, rect)
		rect = rect[0] + incr, rect[1], rect[2]+incr, rect[3]
	# Givem a chance to start
	win32api.Sleep(100)
	win32ui.PumpWaitingMessages()

if __name__=='__main__':
	import demoutils
	if demoutils.NeedGoodGUI():
		ThreadedDemo()
#		Demo()
