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
13 # Not yet implemented:
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)
24 # - color (for now, you need to know the colormap index)
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
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
57 G
.font
= fm
.findfont(DEF_FONT
).scalefont(G
.size
)
64 dummygid
= gl
.winopen('')
66 # Ask for all sorts of events
68 # Both REDRAW (= resize and/or redraw!) and INPUTCHANGE are implicitly queued
74 gl
.qdevice(LEFTARROWKEY
)
75 gl
.qdevice(RIGHTARROWKEY
)
76 gl
.qdevice(UPARROWKEY
)
77 gl
.qdevice(DOWNARROWKEY
)
78 gl
.qdevice(LEFTALTKEY
)
79 gl
.qdevice(RIGHTALTKEY
)
83 #gl.qdevice(MIDDLEMOUSE)
84 gl
.qdevice(RIGHTMOUSE
) # Menu button
85 # NB MOUSEX, MOUSEY events are queued on button down
87 # Window close requests
93 #gl.qdevice(WINFREEZE)
95 #gl.qdevice(REDRAWICONIC)
98 # STDWIN: create a new window
102 width
, height
= G
.def_size
104 # Choose arbitrary defaults
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
120 # STDWIN: set default initial window position (0 means use default)
122 def setdefwinpos(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
138 # STDWIN: set default foreground color
140 def setfgcolor(color
):
144 # STDWIN: set default background color
146 def setbgcolor(color
):
150 # STDWIN: get default foreground color
156 # STDWIN: get default background color
162 # Table mapping characters to key codes
205 for key
in key2code
.keys():
207 code2key
[`code`
] = key
208 codelist
.append(code
)
212 # STDWIN: wait for the next event
215 commands
['\r'] = WC_RETURN
216 commands
['\b'] = WC_BACKSPACE
217 commands
['\t'] = WC_TAB
222 # Get next event from the processed queue, if any
227 #print 'getevent from queue -->', 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():
239 event
= WE_DRAW
, win
, win
._area
240 #print 'getevent from drawqueue -->', 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()
251 win
= G
.windowmap
[`val`
]
255 if old_area
<> win
._area
:
256 #print 'getevent --> WE_SIZE'
257 return WE_SIZE
, win
, None
260 raise KeyboardInterrupt # Control-C in window
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
:
267 return WE_COMMAND
, G
.focus
, WC_LEFT
268 elif dev
== RIGHTARROWKEY
:
270 return WE_COMMAND
, G
.focus
, WC_RIGHT
271 elif dev
== UPARROWKEY
:
273 return WE_COMMAND
, G
.focus
, WC_UP
274 elif dev
== DOWNARROWKEY
:
276 return WE_COMMAND
, G
.focus
, WC_DOWN
277 elif dev
in (LEFTALTKEY
, RIGHTALTKEY
):
279 for code
in codelist
:
282 for code
in codelist
:
284 elif dev
in codelist
:
286 event
= G
.focus
._doshortcut
(code2key
[`dev`
])
289 elif dev
== LEFTMOUSE
:
290 G
.mousex
= gl
.getvaluator(MOUSEX
)
291 G
.mousey
= gl
.getvaluator(MOUSEY
)
300 return _mouseevent(type)
303 return _mouseevent(WE_MOUSE_MOVE
)
306 return _mouseevent(WE_MOUSE_MOVE
)
307 elif dev
== RIGHTMOUSE
: # Menu button press/release
309 event
= G
.focus
._domenu
()
312 elif dev
== INPUTCHANGE
:
314 G
.queue
.append(WE_DEACTIVATE
, G
.focus
, None)
315 G
.focus
= G
.windowmap
[`val`
]
317 G
.queue
.append(WE_ACTIVATE
, G
.focus
, None)
318 elif dev
in (WINSHUT
, WINQUIT
):
319 return WE_CLOSE
, G
.windowmap
[`val`
], None
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()
331 return type, G
.focus
, ((x
, sizey
-y
), 1, 0, 0)
336 # STDWIN: text measuring functions
339 (printermatched
, fixed_width
, xorig
, yorig
, xsize
, ysize
, \
340 height
, nglyphs
) = G
.font
.getfontinfo()
341 return height
- yorig
344 (printermatched
, fixed_width
, xorig
, yorig
, xsize
, ysize
, \
345 height
, nglyphs
) = G
.font
.getfontinfo()
348 def textbreak(string
, width
):
351 nwidth
= textwidth(string
[:n
])
352 while nwidth
> width
:
354 nwidth
= textwidth(string
[: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
)
367 ratio
= float(size
) / float(G
.size
)
369 G
.font
= G
.font
.scalefont(ratio
)
374 # Exclusive-or of two BYTES
379 c
= [0, 0, 0, 0, 0, 0, 0, 0]
381 c
[i
] = (a
[i
] + b
[i
]) % 2
384 # Return the bits of a byte as a list of 8 integers
387 b
= [0, 0, 0, 0, 0, 0, 0, 0]
389 x
, b
[i
] = divmod(x
, 2)
392 # Convert a list of 8 integers (0|1) to a byte