summaryrefslogtreecommitdiffstats
path: root/Lib/stdwin/WindowParent.py
blob: cdec10b28314cf47d416dcc0ed8ee0cbe32c3b04 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
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
# A 'WindowParent' is the only module that uses real stdwin functionality.
# It is the root of the tree.
# It should have exactly one child when realized.
#
# There is also an alternative interface to "mainloop" here.

import stdwin
from stdwinevents import *
import mainloop

from TransParent import ManageOneChild

Error = 'WindowParent.Error'	# Exception

class WindowParent(ManageOneChild):
	#
	def create(self, title, size):
		self.title = title
		self.size = size		# (width, height)
		self._reset()
		self.close_hook = WindowParent.delayed_destroy
		return self
	#
	def _reset(self):
		self.child = None
		self.win = None
		self.itimer = 0
		self.do_mouse = 0
		self.do_keybd = 0
		self.do_timer = 0
		self.do_altdraw = 0
		self.pending_destroy = 0
		self.close_hook = None
		self.menu_hook = None
	#
	def destroy(self):
		mainloop.unregister(self.win)
		if self.child: self.child.destroy()
		self._reset()
	#
	def delayed_destroy(self):
		# This interface to be used by 'Close' buttons etc.;
		# destroying a window from within a button hook
		# is not a good idea...
		self.pending_destroy = 1
	#
	def close_trigger(self):
		if self.close_hook: self.close_hook(self)
	#
	def menu_trigger(self, menu, item):
		if self.menu_hook:
			self.menu_hook(self, menu, item)
	#
	def need_mouse(self, child): self.do_mouse = 1
	def no_mouse(self, child): self.do_mouse = 0
	#
	def need_keybd(self, child):
		self.do_keybd = 1
		self.child.activate()
	def no_keybd(self, child):
		self.do_keybd = 0
		self.child.deactivate()
	#
	def need_timer(self, child): self.do_timer = 1
	def no_timer(self, child): self.do_timer = 0
	#
	def need_altdraw(self, child): self.do_altdraw = 1
	def no_altdraw(self, child): self.do_altdraw = 0
	#
	def realize(self):
		if self.win:
			raise Error, 'realize(): called twice'
		if not self.child:
			raise Error, 'realize(): no child'
		# Compute suggested size
		self.size = self.child.getminsize(self.beginmeasuring(), \
						  self.size)
		save_defsize = stdwin.getdefwinsize()
		scrwidth, scrheight = stdwin.getscrsize()
		width, height = self.size
		if width > scrwidth:
			width = scrwidth * 2/3
		if height > scrheight:
			height = scrheight * 2/3
		stdwin.setdefwinsize(width, height)
		self.hbar, self.vbar = stdwin.getdefscrollbars()
		self.win = stdwin.open(self.title)
		stdwin.setdefwinsize(save_defsize)
		self.win.setdocsize(self.size)
		if self.itimer:
			self.win.settimer(self.itimer)
		width, height = self.win.getwinsize()
		if self.hbar:
			width = self.size[0]
		if self.vbar:
			height = self.size[1]
		self.child.setbounds(((0, 0), (width, height)))
		self.child.realize()
		self.win.dispatch = self.dispatch
		mainloop.register(self.win)
	#
	def fixup(self):
		# XXX This could share code with realize() above
		self.size = self.child.getminsize(self.beginmeasuring(), \
					          self.win.getwinsize())
		self.win.setdocsize(self.size)
		width, height = self.win.getwinsize()
		if self.hbar:
			width = self.size[0]
		if self.vbar:
			height = self.size[1]
		self.child.setbounds(((0, 0), (width, height)))
		# Force a redraw of the entire window:
		self.win.change((0, 0), self.size)
	#
	def beginmeasuring(self):
		# Return something with which a child can measure text
		if self.win:
			return self.win.begindrawing()
		else:
			return stdwin
	#
	def begindrawing(self):
		if self.win:
			return self.win.begindrawing()
		else:
			raise Error, 'begindrawing(): not realized yet'
	#
	def getwindow(self):
		if self.win:
			return self.win
		else:
			raise Error, 'getwindow(): not realized yet'
	#
	def change(self, area):
		if self.win:
			self.win.change(area)
	#
	def scroll(self, area, vector):
		if self.win:
			self.win.scroll(area, vector)
	#
	def settimer(self, itimer):
		if self.win:
			self.win.settimer(itimer)
		else:
			self.itimer = itimer
	#
	# Only call dispatch once we are realized
	#
	def dispatch(self, (type, win, detail)):
		if type == WE_DRAW:
			d = self.win.begindrawing()
			self.child.draw(d, detail)
			del d
			if self.do_altdraw: self.child.altdraw(detail)
		elif type == WE_MOUSE_DOWN:
			if self.do_mouse: self.child.mouse_down(detail)
		elif type == WE_MOUSE_MOVE:
			if self.do_mouse: self.child.mouse_move(detail)
		elif type == WE_MOUSE_UP:
			if self.do_mouse: self.child.mouse_up(detail)
		elif type in (WE_CHAR, WE_COMMAND):
			if self.do_keybd: self.child.keybd(type, detail)
		elif type == WE_TIMER:
			if self.do_timer: self.child.timer()
		elif type == WE_SIZE:
			self.fixup()
		elif type == WE_CLOSE:
			self.close_trigger()
		elif type == WE_MENU:
			self.menu_trigger(detail)
		if self.pending_destroy:
			self.destroy()
	#

def MainLoop():
	mainloop.mainloop()

def Dispatch(event):
	mainloop.dispatch(event)

# Interface used by WindowSched:

def CountWindows():
	return mainloop.countwindows()

def AnyWindow():
	return mainloop.anywindow()