(py-indent-right, py-outdent-left): new commands, bound to C-c C-r and
[python/dscho.git] / Demo / sgi / gl / glstdwin / glstdwin.py
blob22285548cf187bce0d6c565e6d32d3210c35e061
1 # GL STDWIN
3 # See stdwingl for a convenient hack to use this instead of built-in stdwin
4 # without modifying your application, except for one line in the main file.
6 # Intrinsic differences with built-in stdwin (hard or impossible to fix):
7 # - Need to call w.close() to close a window !!!
8 # - Need to call m.close() to remove a menu !!!
9 # - Doesn't enforce the existence of at most one drawing object
10 # - No textedit package
11 # - No X11 selections
13 # Not yet implemented:
14 # - shade drawing
15 # - elliptical arc drawing (need to play with transformation)
16 # - more than one mouse button
17 # - scroll bars (need to redo viewport handling to get this)
18 # - partial redraws
19 # - dialog boxes
20 # - timer events
21 # - cursors
23 # Extra features:
24 # - color (for now, you need to know the colormap index)
27 import gl
28 import fm
29 from GL import *
30 from DEVICE import *
31 from stdwinevents import *
34 # Customizable constants
36 DEF_FONT = 'Times-Roman' # Default font
37 DEF_SIZE = 12 # Default font size (points)
38 MASK = 20 # Viewport minus scrmask
41 # A structure to hold global variables
43 class Struct: pass
44 G = Struct()
46 G.queue = [] # Pending STDWIN events
47 G.drawqueue = [] # Windows that need WE_REDRAW
48 G.windowmap = {} # Map window id to window object
49 G.windowmap['0'] = None # For convenience
50 G.focus = None # Input focus
51 G.fg = BLACK # Foreground color
52 G.bg = WHITE # Background color
53 G.def_size = 0, 0 # Default window size
54 G.def_pos = 0, 0 # Default window position
56 G.size = DEF_SIZE
57 G.font = fm.findfont(DEF_FONT).scalefont(G.size)
60 # Initialize GL
62 gl.foreground()
63 gl.noport()
64 dummygid = gl.winopen('')
66 # Ask for all sorts of events
68 # Both REDRAW (= resize and/or redraw!) and INPUTCHANGE are implicitly queued
69 #qdevice(REDRAW)
70 #qdevice(INPUTCHANGE)
72 # Keyboard
73 gl.qdevice(KEYBD)
74 gl.qdevice(LEFTARROWKEY)
75 gl.qdevice(RIGHTARROWKEY)
76 gl.qdevice(UPARROWKEY)
77 gl.qdevice(DOWNARROWKEY)
78 gl.qdevice(LEFTALTKEY)
79 gl.qdevice(RIGHTALTKEY)
81 # Mouse
82 gl.qdevice(LEFTMOUSE)
83 #gl.qdevice(MIDDLEMOUSE)
84 gl.qdevice(RIGHTMOUSE) # Menu button
85 # NB MOUSEX, MOUSEY events are queued on button down
87 # Window close requests
88 gl.qdevice(WINQUIT)
89 gl.qdevice(WINSHUT)
91 # These aren't needed
92 #gl.qdevice(TIMER0)
93 #gl.qdevice(WINFREEZE)
94 #gl.qdevice(WINTHAW)
95 #gl.qdevice(REDRAWICONIC)
98 # STDWIN: create a new window
100 def open(title):
101 h, v = G.def_pos
102 width, height = G.def_size
103 if h > 0 or v > 0:
104 # Choose arbitrary defaults
105 if h < 0: h = 10
106 if v < 0: v = 30
107 if width <= 0: width = 400
108 if height <= 0: height = 300
109 gl.prefposition(h, h+width, 1024-v, 1024-v-height)
110 elif width > 0 or height > 0:
111 if width <= 0: width = 400
112 if height <= 0: height = 300
113 gl.prefsize(width, height)
114 from glstdwwin import WindowObject
115 win = WindowObject()._init(title)
116 G.windowmap[`win._gid`] = win
117 return win
120 # STDWIN: set default initial window position (0 means use default)
122 def setdefwinpos(h, v):
123 G.def_pos = h, v
126 # STDWIN: set default window size (0 means use default)
128 def setdefwinsize(width, height):
129 G.def_size = width, height
132 # STDWIN: beep or ring the bell
134 def fleep():
135 gl.ringbell()
138 # STDWIN: set default foreground color
140 def setfgcolor(color):
141 G.fg = color
144 # STDWIN: set default background color
146 def setbgcolor(color):
147 G.bg = color
150 # STDWIN: get default foreground color
152 def getfgcolor():
153 return G.fgcolor
156 # STDWIN: get default background color
158 def getbgcolor():
159 return G.bgcolor
162 # Table mapping characters to key codes
164 key2code = key = {}
165 key['A'] = AKEY
166 key['B'] = BKEY
167 key['C'] = CKEY
168 key['D'] = DKEY
169 key['E'] = EKEY
170 key['F'] = FKEY
171 key['G'] = GKEY
172 key['H'] = HKEY
173 key['I'] = IKEY
174 key['J'] = JKEY
175 key['K'] = KKEY
176 key['L'] = LKEY
177 key['M'] = MKEY
178 key['N'] = NKEY
179 key['O'] = OKEY
180 key['P'] = PKEY
181 key['Q'] = QKEY
182 key['R'] = RKEY
183 key['S'] = SKEY
184 key['T'] = TKEY
185 key['U'] = UKEY
186 key['V'] = VKEY
187 key['W'] = WKEY
188 key['X'] = XKEY
189 key['Y'] = YKEY
190 key['Z'] = ZKEY
191 key['0'] = ZEROKEY
192 key['1'] = ONEKEY
193 key['2'] = TWOKEY
194 key['3'] = THREEKEY
195 key['4'] = FOURKEY
196 key['5'] = FIVEKEY
197 key['6'] = SIXKEY
198 key['7'] = SEVENKEY
199 key['8'] = EIGHTKEY
200 key['9'] = NINEKEY
201 del key
203 code2key = {}
204 codelist = []
205 for key in key2code.keys():
206 code = key2code[key]
207 code2key[`code`] = key
208 codelist.append(code)
209 del key
212 # STDWIN: wait for the next event
214 commands = {}
215 commands['\r'] = WC_RETURN
216 commands['\b'] = WC_BACKSPACE
217 commands['\t'] = WC_TAB
219 def getevent():
220 while 1:
222 # Get next event from the processed queue, if any
224 if G.queue:
225 event = G.queue[0]
226 del G.queue[0]
227 #print 'getevent from queue -->', event
228 return event
230 # Get next event from the draw queue, if any,
231 # but only if there is nothing in the system queue.
233 if G.drawqueue and not gl.qtest():
234 win = G.drawqueue[0]
235 del G.drawqueue[0]
236 gl.winset(win._gid)
237 gl.color(win._bg)
238 gl.clear()
239 event = WE_DRAW, win, win._area
240 #print 'getevent from drawqueue -->', event
241 return event
243 # Get next event from system queue, blocking if necessary
244 # until one is available.
245 # Some cases immediately return the event, others do nothing
246 # or append one or more events to the processed queue.
248 dev, val = gl.qread()
250 if dev == REDRAW:
251 win = G.windowmap[`val`]
252 old_area = win._area
253 win._fixviewport()
254 win._needredraw()
255 if old_area <> win._area:
256 #print 'getevent --> WE_SIZE'
257 return WE_SIZE, win, None
258 elif dev == KEYBD:
259 if val == 3:
260 raise KeyboardInterrupt # Control-C in window
261 character = chr(val)
262 if commands.has_key(character):
263 return WE_COMMAND, G.focus, commands[character]
264 return WE_CHAR, G.focus, character
265 elif dev == LEFTARROWKEY:
266 if val:
267 return WE_COMMAND, G.focus, WC_LEFT
268 elif dev == RIGHTARROWKEY:
269 if val:
270 return WE_COMMAND, G.focus, WC_RIGHT
271 elif dev == UPARROWKEY:
272 if val:
273 return WE_COMMAND, G.focus, WC_UP
274 elif dev == DOWNARROWKEY:
275 if val:
276 return WE_COMMAND, G.focus, WC_DOWN
277 elif dev in (LEFTALTKEY, RIGHTALTKEY):
278 if val:
279 for code in codelist:
280 gl.qdevice(code)
281 else:
282 for code in codelist:
283 gl.unqdevice(code)
284 elif dev in codelist:
285 if val:
286 event = G.focus._doshortcut(code2key[`dev`])
287 if event:
288 return event
289 elif dev == LEFTMOUSE:
290 G.mousex = gl.getvaluator(MOUSEX)
291 G.mousey = gl.getvaluator(MOUSEY)
292 if val:
293 type = WE_MOUSE_DOWN
294 gl.qdevice(MOUSEX)
295 gl.qdevice(MOUSEY)
296 else:
297 type = WE_MOUSE_UP
298 gl.unqdevice(MOUSEX)
299 gl.unqdevice(MOUSEY)
300 return _mouseevent(type)
301 elif dev == MOUSEX:
302 G.mousex = val
303 return _mouseevent(WE_MOUSE_MOVE)
304 elif dev == MOUSEY:
305 G.mousey = val
306 return _mouseevent(WE_MOUSE_MOVE)
307 elif dev == RIGHTMOUSE: # Menu button press/release
308 if val: # Press
309 event = G.focus._domenu()
310 if event:
311 return event
312 elif dev == INPUTCHANGE:
313 if G.focus:
314 G.queue.append(WE_DEACTIVATE, G.focus, None)
315 G.focus = G.windowmap[`val`]
316 if G.focus:
317 G.queue.append(WE_ACTIVATE, G.focus, None)
318 elif dev in (WINSHUT, WINQUIT):
319 return WE_CLOSE, G.windowmap[`val`], None
320 else:
321 print '*** qread() --> dev:', dev, 'val:', val
323 # Helper routine to construct a mouse (up, move or down) event
325 def _mouseevent(type):
326 gl.winset(G.focus._gid)
327 orgx, orgy = gl.getorigin()
328 sizex, sizey = gl.getsize()
329 x = G.mousex - orgx
330 y = G.mousey - orgy
331 return type, G.focus, ((x, sizey-y), 1, 0, 0)
336 # STDWIN: text measuring functions
338 def baseline():
339 (printermatched, fixed_width, xorig, yorig, xsize, ysize, \
340 height, nglyphs) = G.font.getfontinfo()
341 return height - yorig
343 def lineheight():
344 (printermatched, fixed_width, xorig, yorig, xsize, ysize, \
345 height, nglyphs) = G.font.getfontinfo()
346 return height
348 def textbreak(string, width):
349 # XXX Slooooow!
350 n = len(string)
351 nwidth = textwidth(string[:n])
352 while nwidth > width:
353 n = n-1
354 nwidth = textwidth(string[:n])
355 return n
357 def textwidth(string):
358 return G.font.getstrwidth(string)
361 # STDWIN: set default font and size
363 def setfont(fontname):
364 G.font = fm.findfont(fontname).scalefont(G.size)
366 def setsize(size):
367 ratio = float(size) / float(G.size)
368 G.size = size
369 G.font = G.font.scalefont(ratio)
372 # Utility functions
374 # Exclusive-or of two BYTES
376 def xor(x, y):
377 a = bits(x)
378 b = bits(y)
379 c = [0, 0, 0, 0, 0, 0, 0, 0]
380 for i in range(8):
381 c[i] = (a[i] + b[i]) % 2
382 return stib(c)
384 # Return the bits of a byte as a list of 8 integers
386 def bits(x):
387 b = [0, 0, 0, 0, 0, 0, 0, 0]
388 for i in range(8):
389 x, b[i] = divmod(x, 2)
390 return b
392 # Convert a list of 8 integers (0|1) to a byte
394 def stib(b):
395 x = 0
396 shift = 1
397 for i in range(8):
398 x = x + b[i]*shift
399 shift = shift*2
400 return x