forked from brentnewey/Sokoban
/
inputbox.py
150 lines (131 loc) · 5.11 KB
/
inputbox.py
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
""" inputbox.by by Brent Newey
Create a box on the screen that accepts keyboard input, and returns
the typed string.
"""
from string import maketrans
from time import sleep
from sys import argv, exit
from pygame import font, event, draw, display, KEYDOWN, KEYUP, QUIT, MOUSEBUTTONDOWN
import pygame.key
from pygame.locals import K_BACKSPACE, K_RETURN, K_ESCAPE, K_END
BOXW = 200
BOXH = 20
BORDERW = 2
BOXC = (0, 0, 0)
BORDERC = (255, 255, 255)
TEXTC = (255, 255, 255)
FONTFILE = None
FONTSIZE = 18
FONTSPACE = 2
def blitfont(screen, text, xy, fontobj, textc):
return screen.blit(fontobj.render(text, 1, textc), xy)
def textbox(screen, orect, irect, fontupleft, fontobj, text,
borderc=BORDERC, boxc=BOXC, textc=TEXTC):
draw.rect(screen, borderc, orect)
draw.rect(screen, boxc, irect)
tw = 0
if text:
textlines = text.split('\n')
th = 0
for t in textlines:
tupleft = (fontupleft[0], fontupleft[1] + th)
fontrect = blitfont(screen, t, tupleft, fontobj, textc)
tw = max(tw, fontrect.w)
th += fontrect.h + 2
display.update(orect)
return tw
def defaultbox(screen, orect, text):
irect = (tuple(i + BORDERW for i in orect[0]),
tuple(b - 2 * BORDERW for b in orect[1]))
fontupleft = tuple(i + 2 for i in irect[0])
font.init()
fontobj = font.Font(FONTFILE, FONTSIZE)
textbox(screen, orect, irect, fontupleft, fontobj, text,
borderc=BORDERC, boxc=BOXC, textc=TEXTC)
class InputBox():
"InputBox class - __init__ handles all custom variables."
def __init__(self, screen, boxw=BOXW, boxh=BOXH, borderw=BORDERW,
boxc=BOXC, borderc=BORDERC, textc=TEXTC, fontfile=FONTFILE,
fontsize=FONTSIZE, fontspace=FONTSPACE, transtable=None,
cb=None, cbargs=None):
self.__dict__.update(locals())
self.inupleft = ((screen.get_width() - boxw) / 2,
(screen.get_height() - boxh) / 2)
self.outupleft = tuple(i - borderw for i in self.inupleft)
self.fontupleft = tuple(i + boxh / 10 for i in self.inupleft)
self.irect = (self.inupleft, (boxw, boxh))
self.orect = (self.outupleft,
tuple(b + 2 * borderw for b in (boxw, boxh)))
font.init()
self.fontobj = font.Font(fontfile, fontsize)
pygame.key.set_repeat(250, 50)
def blitfont(self, text, xy):
"Blit text at the given xy coordinates."
return blitfont(self.screen, text, xy, self.fontobj, self.textc)
def box(self, text):
"Print a box in the middle of the screen."
return textbox(self.screen, self.orect, self.irect, self.fontupleft,
self.fontobj, text, self.borderc, self.boxc, self.textc)
def message(self, qw, text):
"Display entered text."
frect = ((self.irect[0][0] + qw, self.irect[0][1]),
(self.irect[1][0] - qw, self.irect[1][1]))
draw.rect(self.screen, self.boxc, frect)
if text:
self.blitfont(text, (self.fontupleft[0] + qw, self.fontupleft[1]))
display.update(self.irect)
def ask(self, question, text=''):
"ask(question, text) -> answer"
qw = self.box('%s: ' % question)
lasttext = None
while 1:
if self.cb and self.cbargs:
self.cb(*self.cbargs)
sleep(0.01)
if lasttext != text:
self.message(qw, text)
lasttext = text
events = event.get((KEYDOWN, QUIT))
if not events:
continue
if QUIT in [e.type for e in events]:
return e
elif events[0].key == K_BACKSPACE:
text = text[:-1]
elif events[0].key in (K_ESCAPE, K_END):
return None
elif events[0].key == K_RETURN:
return text
elif 31 < events[0].key < 127:
key = events[0].unicode.encode('ascii')
text += (key.translate(self.transtable) if
self.transtable else key)
def show(self, text):
self.box(text)
while 1:
if self.cb and self.cbargs:
self.cb(*self.cbargs)
sleep(0.01)
events = event.get((KEYDOWN, MOUSEBUTTONDOWN, QUIT))
if not events:
event.clear()
continue
if QUIT in [e.type for e in events]:
return e
else:
sleep(0.1)
return
if __name__ == '__main__':
screen = display.set_mode((320,240))
if len(argv) > 1 and argv[1] == 'show':
InputBox(screen, boxw=170).show('You are the Messiah of Earth')
if len(argv) > 1 and argv[1] == 'multiline':
inbox = InputBox(screen, boxw=120, boxh=35)
inbox.show('You are the\nMessiah of Earth')
if len(argv) > 1 and argv[1] == 'box':
defaultbox(screen, ((5, 5), (40, 20)), 'Help')
sleep(5)
if len(argv) == 1:
intext = InputBox(screen).ask('Yo dawg')
if type(intext) is str:
print "'%s' was entered" % intext