📄 glstdwin.py
字号:
# GL STDWIN## See stdwingl for a convenient hack to use this instead of built-in stdwin# without modifying your application, except for one line in the main file.## Intrinsic differences with built-in stdwin (hard or impossible to fix):# - Need to call w.close() to close a window !!!# - Need to call m.close() to remove a menu !!!# - Doesn't enforce the existence of at most one drawing object# - No textedit package# - No X11 selections## Not yet implemented:# - shade drawing# - elliptical arc drawing (need to play with transformation)# - more than one mouse button# - scroll bars (need to redo viewport handling to get this)# - partial redraws# - dialog boxes# - timer events# - cursors## Extra features:# - color (for now, you need to know the colormap index)import glimport fmfrom GL import *from DEVICE import *from stdwinevents import *# Customizable constants#DEF_FONT = 'Times-Roman' # Default fontDEF_SIZE = 12 # Default font size (points)MASK = 20 # Viewport minus scrmask# A structure to hold global variables#class Struct: passG = Struct()#G.queue = [] # Pending STDWIN eventsG.drawqueue = [] # Windows that need WE_REDRAWG.windowmap = {} # Map window id to window objectG.windowmap['0'] = None # For convenienceG.focus = None # Input focusG.fg = BLACK # Foreground colorG.bg = WHITE # Background colorG.def_size = 0, 0 # Default window sizeG.def_pos = 0, 0 # Default window position#G.size = DEF_SIZEG.font = fm.findfont(DEF_FONT).scalefont(G.size)# Initialize GL#gl.foreground()gl.noport()dummygid = gl.winopen('')# Ask for all sorts of events## Both REDRAW (= resize and/or redraw!) and INPUTCHANGE are implicitly queued#qdevice(REDRAW)#qdevice(INPUTCHANGE)## Keyboardgl.qdevice(KEYBD)gl.qdevice(LEFTARROWKEY)gl.qdevice(RIGHTARROWKEY)gl.qdevice(UPARROWKEY)gl.qdevice(DOWNARROWKEY)gl.qdevice(LEFTALTKEY)gl.qdevice(RIGHTALTKEY)## Mousegl.qdevice(LEFTMOUSE)#gl.qdevice(MIDDLEMOUSE)gl.qdevice(RIGHTMOUSE) # Menu button# NB MOUSEX, MOUSEY events are queued on button down## Window close requestsgl.qdevice(WINQUIT)gl.qdevice(WINSHUT)## These aren't needed#gl.qdevice(TIMER0)#gl.qdevice(WINFREEZE)#gl.qdevice(WINTHAW)#gl.qdevice(REDRAWICONIC)# STDWIN: create a new window#def open(title): h, v = G.def_pos width, height = G.def_size if h > 0 or v > 0: # Choose arbitrary defaults if h < 0: h = 10 if v < 0: v = 30 if width <= 0: width = 400 if height <= 0: height = 300 gl.prefposition(h, h+width, 1024-v, 1024-v-height) elif width > 0 or height > 0: if width <= 0: width = 400 if height <= 0: height = 300 gl.prefsize(width, height) from glstdwwin import WindowObject win = WindowObject()._init(title) G.windowmap[`win._gid`] = win return win# STDWIN: set default initial window position (0 means use default)#def setdefwinpos(h, v): G.def_pos = h, v# STDWIN: set default window size (0 means use default)#def setdefwinsize(width, height): G.def_size = width, height# STDWIN: beep or ring the bell#def fleep(): gl.ringbell()# STDWIN: set default foreground color#def setfgcolor(color): G.fg = color# STDWIN: set default background color#def setbgcolor(color): G.bg = color# STDWIN: get default foreground color#def getfgcolor(): return G.fgcolor# STDWIN: get default background color#def getbgcolor(): return G.bgcolor# Table mapping characters to key codes#key2code = key = {}key['A'] = AKEYkey['B'] = BKEYkey['C'] = CKEYkey['D'] = DKEYkey['E'] = EKEYkey['F'] = FKEYkey['G'] = GKEYkey['H'] = HKEYkey['I'] = IKEYkey['J'] = JKEYkey['K'] = KKEYkey['L'] = LKEYkey['M'] = MKEYkey['N'] = NKEYkey['O'] = OKEYkey['P'] = PKEYkey['Q'] = QKEYkey['R'] = RKEYkey['S'] = SKEYkey['T'] = TKEYkey['U'] = UKEYkey['V'] = VKEYkey['W'] = WKEYkey['X'] = XKEYkey['Y'] = YKEYkey['Z'] = ZKEYkey['0'] = ZEROKEYkey['1'] = ONEKEYkey['2'] = TWOKEYkey['3'] = THREEKEYkey['4'] = FOURKEYkey['5'] = FIVEKEYkey['6'] = SIXKEYkey['7'] = SEVENKEYkey['8'] = EIGHTKEYkey['9'] = NINEKEYdel key#code2key = {}codelist = []for key in key2code.keys(): code = key2code[key] code2key[`code`] = key codelist.append(code)del key# STDWIN: wait for the next event#commands = {}commands['\r'] = WC_RETURNcommands['\b'] = WC_BACKSPACEcommands['\t'] = WC_TAB#def getevent(): while 1: # # Get next event from the processed queue, if any # if G.queue: event = G.queue[0] del G.queue[0] #print 'getevent from queue -->', event return event # # Get next event from the draw queue, if any, # but only if there is nothing in the system queue. # if G.drawqueue and not gl.qtest(): win = G.drawqueue[0] del G.drawqueue[0] gl.winset(win._gid) gl.color(win._bg) gl.clear() event = WE_DRAW, win, win._area #print 'getevent from drawqueue -->', event return event # # Get next event from system queue, blocking if necessary # until one is available. # Some cases immediately return the event, others do nothing # or append one or more events to the processed queue. # dev, val = gl.qread() # if dev == REDRAW: win = G.windowmap[`val`] old_area = win._area win._fixviewport() win._needredraw() if old_area <> win._area: #print 'getevent --> WE_SIZE' return WE_SIZE, win, None elif dev == KEYBD: if val == 3: raise KeyboardInterrupt # Control-C in window character = chr(val) if commands.has_key(character): return WE_COMMAND, G.focus, commands[character] return WE_CHAR, G.focus, character elif dev == LEFTARROWKEY: if val: return WE_COMMAND, G.focus, WC_LEFT elif dev == RIGHTARROWKEY: if val: return WE_COMMAND, G.focus, WC_RIGHT elif dev == UPARROWKEY: if val: return WE_COMMAND, G.focus, WC_UP elif dev == DOWNARROWKEY: if val: return WE_COMMAND, G.focus, WC_DOWN elif dev in (LEFTALTKEY, RIGHTALTKEY): if val: for code in codelist: gl.qdevice(code) else: for code in codelist: gl.unqdevice(code) elif dev in codelist: if val: event = G.focus._doshortcut(code2key[`dev`]) if event: return event elif dev == LEFTMOUSE: G.mousex = gl.getvaluator(MOUSEX) G.mousey = gl.getvaluator(MOUSEY) if val: type = WE_MOUSE_DOWN gl.qdevice(MOUSEX) gl.qdevice(MOUSEY) else: type = WE_MOUSE_UP gl.unqdevice(MOUSEX) gl.unqdevice(MOUSEY) return _mouseevent(type) elif dev == MOUSEX: G.mousex = val return _mouseevent(WE_MOUSE_MOVE) elif dev == MOUSEY: G.mousey = val return _mouseevent(WE_MOUSE_MOVE) elif dev == RIGHTMOUSE: # Menu button press/release if val: # Press event = G.focus._domenu() if event: return event elif dev == INPUTCHANGE: if G.focus: G.queue.append(WE_DEACTIVATE, G.focus, None) G.focus = G.windowmap[`val`] if G.focus: G.queue.append(WE_ACTIVATE, G.focus, None) elif dev in (WINSHUT, WINQUIT): return WE_CLOSE, G.windowmap[`val`], None else: print '*** qread() --> dev:', dev, 'val:', val# Helper routine to construct a mouse (up, move or down) event#def _mouseevent(type): gl.winset(G.focus._gid) orgx, orgy = gl.getorigin() sizex, sizey = gl.getsize() x = G.mousex - orgx y = G.mousey - orgy return type, G.focus, ((x, sizey-y), 1, 0, 0)# STDWIN: text measuring functionsdef baseline(): (printermatched, fixed_width, xorig, yorig, xsize, ysize, \ height, nglyphs) = G.font.getfontinfo() return height - yorigdef lineheight(): (printermatched, fixed_width, xorig, yorig, xsize, ysize, \ height, nglyphs) = G.font.getfontinfo() return heightdef textbreak(string, width): # XXX Slooooow! n = len(string) nwidth = textwidth(string[:n]) while nwidth > width: n = n-1 nwidth = textwidth(string[:n]) return ndef textwidth(string): return G.font.getstrwidth(string)# STDWIN: set default font and sizedef setfont(fontname): G.font = fm.findfont(fontname).scalefont(G.size)def setsize(size): ratio = float(size) / float(G.size) G.size = size G.font = G.font.scalefont(ratio)# Utility functions# Exclusive-or of two BYTES#def xor(x, y): a = bits(x) b = bits(y) c = [0, 0, 0, 0, 0, 0, 0, 0] for i in range(8): c[i] = (a[i] + b[i]) % 2 return stib(c)# Return the bits of a byte as a list of 8 integers#def bits(x): b = [0, 0, 0, 0, 0, 0, 0, 0] for i in range(8): x, b[i] = divmod(x, 2) return b# Convert a list of 8 integers (0|1) to a byte#def stib(b): x = 0 shift = 1 for i in range(8): x = x + b[i]*shift shift = shift*2 return x
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -