framework-lib 0.1.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- framework_lib/__init__.py +0 -0
- framework_lib/data.py +156 -0
- framework_lib/framework.py +139 -0
- framework_lib/models.py +1470 -0
- framework_lib/program.py +126 -0
- framework_lib/setup.py +12 -0
- framework_lib-0.1.2.dist-info/METADATA +54 -0
- framework_lib-0.1.2.dist-info/RECORD +11 -0
- framework_lib-0.1.2.dist-info/WHEEL +5 -0
- framework_lib-0.1.2.dist-info/licenses/LICENSE +0 -0
- framework_lib-0.1.2.dist-info/top_level.txt +1 -0
framework_lib/models.py
ADDED
|
@@ -0,0 +1,1470 @@
|
|
|
1
|
+
"""
|
|
2
|
+
DOCUMENTATION for models.py:
|
|
3
|
+
|
|
4
|
+
========================
|
|
5
|
+
|
|
6
|
+
GENERAL INFORMATION:
|
|
7
|
+
|
|
8
|
+
- ErrorForm is used for raising errors without crashes and to be friendly
|
|
9
|
+
|
|
10
|
+
- SpaceField, InputField, RedirectField, TextField: fields for your own models
|
|
11
|
+
|
|
12
|
+
- ErrorHelper is used for automatical type error checks
|
|
13
|
+
|
|
14
|
+
- ListErrorHelper is used for automatical list length checks
|
|
15
|
+
|
|
16
|
+
- check is used for checking user errors related to InputField
|
|
17
|
+
|
|
18
|
+
- Embedding is used for storing data about multiple fields and managing them
|
|
19
|
+
|
|
20
|
+
- CanvasEmbedding is an embedding that is used for Tkinter
|
|
21
|
+
|
|
22
|
+
- ImageField is used for displaying images with Tkinter
|
|
23
|
+
|
|
24
|
+
- TextFieldAdv is used for displaying text with Tkinter
|
|
25
|
+
|
|
26
|
+
- ButtonField is used for displaying button with Tkinter
|
|
27
|
+
|
|
28
|
+
- InputForm is used for displaying input with Tkinter
|
|
29
|
+
|
|
30
|
+
- BackgroundForm is used for displaying tiled images(e.g. backgrounds) with Tkinter
|
|
31
|
+
|
|
32
|
+
- GeometryField is used for displaying geometric shapes with Tkinter
|
|
33
|
+
|
|
34
|
+
- InteractiveUserErrorForm is used for displaying user errors with Tkinter
|
|
35
|
+
|
|
36
|
+
- Container is used for containing multiple Tkinter fields/forms and positioning them
|
|
37
|
+
|
|
38
|
+
- PygameEmbedding is an embedding that is used for Pygame
|
|
39
|
+
|
|
40
|
+
- ImageSprite is used for displaying sprites from images in Pygame
|
|
41
|
+
|
|
42
|
+
- ButtonPressField is used for commanding program what to do on specific key press events
|
|
43
|
+
|
|
44
|
+
- ButtonFieldAdv is used for displaying buttons in Pygame
|
|
45
|
+
|
|
46
|
+
- TextFieldExp is used for displaying text in Pygame
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
========================
|
|
50
|
+
|
|
51
|
+
VALUE INFORMATION:
|
|
52
|
+
|
|
53
|
+
- page must be STR unless Redirect field where it must be class with self.name and self.call()
|
|
54
|
+
|
|
55
|
+
- InputField's argument "type" supports only int, bool, str, float
|
|
56
|
+
|
|
57
|
+
========================
|
|
58
|
+
|
|
59
|
+
ERROR INFORMATION:
|
|
60
|
+
|
|
61
|
+
- 1xx: Framework/developer fault - PREFIX
|
|
62
|
+
|
|
63
|
+
- 2xx: User fault - PREFIX
|
|
64
|
+
|
|
65
|
+
- 3xx: Developer fault - PREFIX
|
|
66
|
+
|
|
67
|
+
- 4xx: Warning - PREFIX
|
|
68
|
+
|
|
69
|
+
- 100 INTERNAL ERROR:
|
|
70
|
+
Used by framework, raises when something within framework does not work.
|
|
71
|
+
|
|
72
|
+
- 101 REDIRECT ERROR:
|
|
73
|
+
Used by framework, raises when page isn't valid(page in development, developer should setup VALID_PAGES to not raise this error).
|
|
74
|
+
|
|
75
|
+
- 102 DATABASE ERROR:
|
|
76
|
+
Used by framework (look in data.py), raises when database key does not exist or database is not found.
|
|
77
|
+
|
|
78
|
+
- 103 NON-EXISTENT ERROR:
|
|
79
|
+
Used by framework to indicate that something within framework does not exist
|
|
80
|
+
|
|
81
|
+
- 104 IMAGE ERROR:
|
|
82
|
+
Used by framework (look in data.py), raises when something is wrong with image
|
|
83
|
+
|
|
84
|
+
- 105 INSTANCE ERROR:
|
|
85
|
+
Used by framework, raises when an instance is invalid
|
|
86
|
+
|
|
87
|
+
- 106 CALLABILITY ERROR:
|
|
88
|
+
Used by framework, raises when an object has incorrect callability(can be called while shouldn't or can't be called while should)
|
|
89
|
+
|
|
90
|
+
- 107 ARGUMENT ERROR:
|
|
91
|
+
Used by framework when an object has incorrect signature
|
|
92
|
+
|
|
93
|
+
- 108 SOUND ERROR:
|
|
94
|
+
Used by framework, raises when something is wrong with sound
|
|
95
|
+
|
|
96
|
+
- 200 INPUT ERROR:
|
|
97
|
+
Used by framework AND by developer to show user they have entered incorrect input
|
|
98
|
+
|
|
99
|
+
- 201 ACCESS ERROR:
|
|
100
|
+
Used by developer to show user that they have tried to access something without respective permission(when creating pages)
|
|
101
|
+
|
|
102
|
+
- 300 PAGE ERROR:
|
|
103
|
+
Used by framework when page is non-existent, doesn't have name or .call() with ctx.
|
|
104
|
+
|
|
105
|
+
- 301 PROGRAM ERROR:
|
|
106
|
+
Used by framework(look in program.py) when program is non existent, doesn't have name, etc
|
|
107
|
+
|
|
108
|
+
- 302 HISTORY ERROR:
|
|
109
|
+
Used by framework(look in program.py) when developer tries to access a history page which is unreachable
|
|
110
|
+
|
|
111
|
+
- 303 CANVAS ERROR:
|
|
112
|
+
Used by framework when developer tries to do something illegal with CanvasEmbedding
|
|
113
|
+
|
|
114
|
+
- 304 GAME ERROR:
|
|
115
|
+
Used by framework(look in program.py) when developer tries to do something illegal with Game
|
|
116
|
+
|
|
117
|
+
- 400 EXIT WARNING:
|
|
118
|
+
Used by framework(look in program.py) when developer or user tries to force-quit the program
|
|
119
|
+
"""
|
|
120
|
+
|
|
121
|
+
"""CODE"""
|
|
122
|
+
from inspect import signature as s
|
|
123
|
+
from math import floor, ceil
|
|
124
|
+
from tkinter import *
|
|
125
|
+
from time import sleep
|
|
126
|
+
import os
|
|
127
|
+
os.environ["PYGAME_HIDE_SUPPORT_PROMPT"] = "hide"
|
|
128
|
+
import pygame
|
|
129
|
+
import pygame.font
|
|
130
|
+
import sys
|
|
131
|
+
class ErrorForm:
|
|
132
|
+
def __init__(self, text, occurrence, type="200 INPUT ERROR"):
|
|
133
|
+
self.t=text
|
|
134
|
+
self.o=occurrence
|
|
135
|
+
self.ty=type
|
|
136
|
+
self.w=""
|
|
137
|
+
if "warning" not in self.ty.lower():
|
|
138
|
+
self.w=f"An error occurred on page {self.o}: "
|
|
139
|
+
def call(self):
|
|
140
|
+
SpaceField("=", 40, "ERRS").call()
|
|
141
|
+
TextField(self.ty, "ERRS", fancy=True, fancytotal=40).call()
|
|
142
|
+
TextField(f"{self.w}{self.t}", "ERRS",delim=0).call()
|
|
143
|
+
SpaceField("=", 40, "ERRS").call()
|
|
144
|
+
|
|
145
|
+
class SpaceField:
|
|
146
|
+
def __init__(self, sym, amo, page):
|
|
147
|
+
self.s=sym
|
|
148
|
+
self.a=amo
|
|
149
|
+
asr=["page", "symbol", "amount"]
|
|
150
|
+
args=[page, sym, amo]
|
|
151
|
+
types=[str, str, int]
|
|
152
|
+
self.c=ErrorHelper(asr, args, types)
|
|
153
|
+
|
|
154
|
+
def __str__(self):
|
|
155
|
+
return self.s*self.a
|
|
156
|
+
|
|
157
|
+
def call(self):
|
|
158
|
+
if self.c:
|
|
159
|
+
return 1
|
|
160
|
+
else:
|
|
161
|
+
print(self)
|
|
162
|
+
return 0
|
|
163
|
+
|
|
164
|
+
def ErrorHelper(argstrrep, args, types, ignore=False):
|
|
165
|
+
caller=True
|
|
166
|
+
if type(argstrrep) is not list:
|
|
167
|
+
ErrorForm(f"Invalid type for ErrorHelper argument 'argument string representation': {type(argstrrep).__name__}", "ERRHELP", type="100 INTERNAL ERROR").call()
|
|
168
|
+
caller=False
|
|
169
|
+
elif type(args) is not list:
|
|
170
|
+
ErrorForm(f"Invalid type for ErrorHelper argument 'arguments': {type(args).__name__}", "ERRHELP", type="100 INTERNAL ERROR").call()
|
|
171
|
+
caller=False
|
|
172
|
+
elif type(types) is not list:
|
|
173
|
+
ErrorForm(f"Invalid type for ErrorHelper argument 'types': {type(types).__name__}", "ERRHELP", type="100 INTERNAL ERROR").call()
|
|
174
|
+
caller=False
|
|
175
|
+
elif type(ignore) is not bool:
|
|
176
|
+
ErrorForm(f"Invalid type for ErrorHelper argument 'ignore': {type(ignore).__name__}", "ERRHELP", type="100 INTERNAL ERROR").call()
|
|
177
|
+
caller=False
|
|
178
|
+
if caller:
|
|
179
|
+
for x in range(0, len(argstrrep)):
|
|
180
|
+
if argstrrep[x]=="page" or ignore:
|
|
181
|
+
pfp="UNDEFINED"
|
|
182
|
+
else:
|
|
183
|
+
pfp=args[argstrrep.index("page")]
|
|
184
|
+
if type(types[x]) is list:
|
|
185
|
+
if args[x] not in types[x]:
|
|
186
|
+
ErrorForm(f"Invalid type for argument '{argstrrep[x]}': {type(args[x]).__name__} not in {types[x]}", f"{pfp}", type="100 INTERNAL ERROR").call()
|
|
187
|
+
caller=False
|
|
188
|
+
break
|
|
189
|
+
elif not isinstance(args[x],types[x]):
|
|
190
|
+
ErrorForm(f"Invalid type for argument '{argstrrep[x]}': {type(args[x]).__name__}", f"{pfp}", type="100 INTERNAL ERROR").call()
|
|
191
|
+
caller=False
|
|
192
|
+
break
|
|
193
|
+
return not caller
|
|
194
|
+
|
|
195
|
+
def ListErrorHelper(lists):
|
|
196
|
+
caller=True
|
|
197
|
+
for x in range(len(lists)):
|
|
198
|
+
if type(lists[x]) is not list:
|
|
199
|
+
ErrorForm(f"Invalid type for ListErrorHelper argument 'lists[{x}]': {type(lists).__name__}", "ERRHELP", type="100 INTERNAL ERROR").call()
|
|
200
|
+
caller=False
|
|
201
|
+
if caller:
|
|
202
|
+
lens=[]
|
|
203
|
+
for x in range(0, len(lists)):
|
|
204
|
+
lens.append(len(lists[x]))
|
|
205
|
+
prev=lens[0]
|
|
206
|
+
for x in range(1, len(lens)):
|
|
207
|
+
if prev==lens[x]:
|
|
208
|
+
prev=lens[x]
|
|
209
|
+
else:
|
|
210
|
+
ErrorForm(f"Invalid length for list 'lists[{x}]': {lens[x]}", "ERRHELP", type="100 INTERNAL ERROR").call()
|
|
211
|
+
caller=False
|
|
212
|
+
break
|
|
213
|
+
return not caller
|
|
214
|
+
|
|
215
|
+
class TextField:
|
|
216
|
+
def __init__(self, text, page, modifs=[], delim=0, fancy=False, fancytotal=40, sign="="):
|
|
217
|
+
self.d=delim
|
|
218
|
+
self.t=text
|
|
219
|
+
self.m=modifs
|
|
220
|
+
self.f=fancy
|
|
221
|
+
self.ft=fancytotal
|
|
222
|
+
asr=["page", "modifiers", "delimiter", "fancy", "fancytotal"]
|
|
223
|
+
args=[page, modifs, delim, fancy, fancytotal]
|
|
224
|
+
types=[str, list, int, bool, int]
|
|
225
|
+
caller=ErrorHelper(asr, args, types)
|
|
226
|
+
if self.ft<len(self.t) and not caller and self.f:
|
|
227
|
+
ErrorForm(f"Invalid amount for argument 'fancytotal': {self.ft} is less than length of text", page, type="100 INTERNAL ERROR").call()
|
|
228
|
+
caller=True
|
|
229
|
+
self.s=sign
|
|
230
|
+
self.p=page
|
|
231
|
+
self.c=caller
|
|
232
|
+
|
|
233
|
+
def __str__(self):
|
|
234
|
+
if self.c:
|
|
235
|
+
return "ERR"
|
|
236
|
+
out=""
|
|
237
|
+
txt=self.t
|
|
238
|
+
if self.f:
|
|
239
|
+
oka=self.s*floor((self.ft-len(self.t))/2)
|
|
240
|
+
else:
|
|
241
|
+
oka=self.s*self.d
|
|
242
|
+
out+=oka
|
|
243
|
+
e=True
|
|
244
|
+
for mod in self.m:
|
|
245
|
+
if mod.lower()=="up":
|
|
246
|
+
txt=txt.upper()
|
|
247
|
+
elif mod.lower()=="lo":
|
|
248
|
+
txt=txt.lower()
|
|
249
|
+
else:
|
|
250
|
+
ErrorForm(f"Unknown modifier {mod}", page, type="100 INTERNAL ERROR").call()
|
|
251
|
+
e=False
|
|
252
|
+
break
|
|
253
|
+
if e:
|
|
254
|
+
out+=txt
|
|
255
|
+
if self.f:
|
|
256
|
+
oka=self.s*ceil((self.ft-len(self.t))/2)
|
|
257
|
+
else:
|
|
258
|
+
oka=self.s*self.d
|
|
259
|
+
out+=oka
|
|
260
|
+
return out
|
|
261
|
+
else:
|
|
262
|
+
self.c=True
|
|
263
|
+
return "ERR"
|
|
264
|
+
|
|
265
|
+
def call(self):
|
|
266
|
+
val=self.__str__()
|
|
267
|
+
if self.c:
|
|
268
|
+
return 1
|
|
269
|
+
else:
|
|
270
|
+
print(val)
|
|
271
|
+
return 0
|
|
272
|
+
|
|
273
|
+
class InputField:
|
|
274
|
+
def __init__(self, prompt, name, page, req=True, inp_type=str, minimum=0, maximum=100, discretes=None):
|
|
275
|
+
self.TYPES=[str, float, int, bool]
|
|
276
|
+
self.p=page
|
|
277
|
+
self.pr=prompt
|
|
278
|
+
self.r=req
|
|
279
|
+
self.n=name
|
|
280
|
+
self.m=minimum
|
|
281
|
+
self.ma=maximum
|
|
282
|
+
self.t=inp_type
|
|
283
|
+
self.d=discretes
|
|
284
|
+
val=[]
|
|
285
|
+
if discretes:
|
|
286
|
+
val=discretes
|
|
287
|
+
asr=["page", "prompt", "required", "minimum","maximum", "discrete values"]
|
|
288
|
+
args=[self.p, self.pr, self.r, self.m, self.ma, val]
|
|
289
|
+
types=[str, str, bool, int, int, list]
|
|
290
|
+
self.c=ErrorHelper(asr, args, types)
|
|
291
|
+
if not self.c and inp_type not in self.TYPES:
|
|
292
|
+
ErrorForm(f"Type {inp_type} cannot be parsed", self.p, type="100 INTERNAL ERROR").call()
|
|
293
|
+
self.c=True
|
|
294
|
+
def call(self):
|
|
295
|
+
if self.c:
|
|
296
|
+
return "ERR"
|
|
297
|
+
res=""
|
|
298
|
+
if self.r:
|
|
299
|
+
bad=True
|
|
300
|
+
while res=="" or res==None or bad:
|
|
301
|
+
print(self.pr+"(field required):")
|
|
302
|
+
val=input()
|
|
303
|
+
if val=="" or val==None:
|
|
304
|
+
ErrorForm(f"Field {self.n} is required", self.p).call()
|
|
305
|
+
else:
|
|
306
|
+
res, bad=check(val, self.t, self.p, self.m, self.ma, self.d)
|
|
307
|
+
else:
|
|
308
|
+
bad=True
|
|
309
|
+
while bad:
|
|
310
|
+
print(self.pr+":")
|
|
311
|
+
val=input()
|
|
312
|
+
res, bad=check(val, self.t, self.p, self.m, self.ma, self.d)
|
|
313
|
+
return res
|
|
314
|
+
|
|
315
|
+
def check(val, req, page, mini, maxi, dis, adv=False, cne=None, canvas=None, element=None):
|
|
316
|
+
res=val
|
|
317
|
+
bad=False
|
|
318
|
+
rk=False
|
|
319
|
+
rk2=False
|
|
320
|
+
def s(req, page, cne, canvas, element):
|
|
321
|
+
if not adv:
|
|
322
|
+
ErrorForm(f"Wrong type: '{req}' type required", page).call()
|
|
323
|
+
else:
|
|
324
|
+
InteractiveUserErrorForm(cne, canvas, element, f"Wrong type: '{req}' type required", page).call()
|
|
325
|
+
return True
|
|
326
|
+
def k(mini, page, cne, canvas, element):
|
|
327
|
+
if not adv:
|
|
328
|
+
ErrorForm(f"Minimum limit is {mini}. Your input is not sufficiently large", page).call()
|
|
329
|
+
else:
|
|
330
|
+
InteractiveUserErrorForm(cne, canvas, element, f"Minimum limit is {mini}. Your input is not sufficiently large", page).call()
|
|
331
|
+
def u(maxi, page, cne, canvas, element):
|
|
332
|
+
if not adv:
|
|
333
|
+
ErrorForm(f"Maximum limit is {maxi}. Your input is too large", page).call()
|
|
334
|
+
else:
|
|
335
|
+
InteractiveUserErrorForm(cne, canvas, element, f"Maximum limit is {maxi}. Your input is too large", page).call()
|
|
336
|
+
if req==bool:
|
|
337
|
+
try:
|
|
338
|
+
if val.lower()=="true" or val=="1":
|
|
339
|
+
res=True
|
|
340
|
+
elif val.lower()=="false" or val=="0":
|
|
341
|
+
res=False
|
|
342
|
+
else:
|
|
343
|
+
raise ValueError()
|
|
344
|
+
except:
|
|
345
|
+
bad=s("bool", page, cne, canvas, element)
|
|
346
|
+
elif req==int:
|
|
347
|
+
try:
|
|
348
|
+
res=int(val)
|
|
349
|
+
if res<mini:
|
|
350
|
+
rk=True
|
|
351
|
+
elif res>maxi:
|
|
352
|
+
rk2=True
|
|
353
|
+
except:
|
|
354
|
+
bad=s("int", page, cne, canvas, element)
|
|
355
|
+
elif req==str:
|
|
356
|
+
try:
|
|
357
|
+
res=str(val)
|
|
358
|
+
if len(res)<mini:
|
|
359
|
+
rk=True
|
|
360
|
+
elif len(res)>maxi:
|
|
361
|
+
rk2=True
|
|
362
|
+
except:
|
|
363
|
+
bad=s("str", page, cne, canvas, element)
|
|
364
|
+
elif req==float:
|
|
365
|
+
try:
|
|
366
|
+
res=float(val)
|
|
367
|
+
if res<mini:
|
|
368
|
+
rk=True
|
|
369
|
+
elif res>maxi:
|
|
370
|
+
rk2=True
|
|
371
|
+
except:
|
|
372
|
+
bad=s("float", page, cne, canvas, element)
|
|
373
|
+
if rk:
|
|
374
|
+
k(mini, page, cne, canvas, element)
|
|
375
|
+
bad=True
|
|
376
|
+
elif rk2:
|
|
377
|
+
u(maxi, page, cne, canvas, element)
|
|
378
|
+
bad=True
|
|
379
|
+
if dis and (req!=bool):
|
|
380
|
+
if res not in dis and not bad:
|
|
381
|
+
distxt="Possible input values are: "
|
|
382
|
+
for di in dis:
|
|
383
|
+
distxt+=f"'{di}', "
|
|
384
|
+
distxt+=". You did not input one of them."
|
|
385
|
+
ErrorForm(distxt, page).call()
|
|
386
|
+
bad=True
|
|
387
|
+
return res, bad
|
|
388
|
+
|
|
389
|
+
class RedirectField:
|
|
390
|
+
def __init__(self, target, page, program, ctx={}):
|
|
391
|
+
self.pr=program
|
|
392
|
+
try:
|
|
393
|
+
self.t=target()
|
|
394
|
+
self.tc=target
|
|
395
|
+
self.p=page()
|
|
396
|
+
except:
|
|
397
|
+
ErrorForm("Target or starter page class for redirect isn't a class","UNDEFINED", type="300 PAGE ERROR").call()
|
|
398
|
+
self.c=True
|
|
399
|
+
return
|
|
400
|
+
self.ct=ctx
|
|
401
|
+
err=False
|
|
402
|
+
if not self.pr:
|
|
403
|
+
ErrorForm("Program isn't defined", "UNDEFINED", type="301 PROGRAM ERROR").call()
|
|
404
|
+
self.c=True
|
|
405
|
+
return
|
|
406
|
+
else:
|
|
407
|
+
try:
|
|
408
|
+
if program.vpgs!=[]:
|
|
409
|
+
VALID_PAGES=program.vpgs
|
|
410
|
+
else:
|
|
411
|
+
raise ValueError()
|
|
412
|
+
except:
|
|
413
|
+
ErrorForm("Program doesn't have any valid pages", "UNDEFINED", type="301 PROGRAM ERROR").call()
|
|
414
|
+
self.c=True
|
|
415
|
+
return
|
|
416
|
+
if not self.p:
|
|
417
|
+
ErrorForm("Starter page of redirect does not exist", "UNDEFINED", type="300 PAGE ERROR").call()
|
|
418
|
+
err=True
|
|
419
|
+
else:
|
|
420
|
+
try:
|
|
421
|
+
if type(self.p.name)==str:
|
|
422
|
+
pass
|
|
423
|
+
else:
|
|
424
|
+
raise ValueError()
|
|
425
|
+
except:
|
|
426
|
+
ErrorForm("Starter page of redirect has an invalid name/type", "UNDEFINED", type="300 PAGE ERROR").call()
|
|
427
|
+
err=True
|
|
428
|
+
if not err and (self.p.name not in VALID_PAGES):
|
|
429
|
+
ErrorForm(f"Page {self.p.name} is not a valid page for a redirect starter", self.p.name, type="101 REDIRECT ERROR").call()
|
|
430
|
+
err=True
|
|
431
|
+
elif not self.t:
|
|
432
|
+
ErrorForm("Target page of redirect does not exist", self.p.name, type="300 PAGE ERROR").call()
|
|
433
|
+
err=True
|
|
434
|
+
else:
|
|
435
|
+
try:
|
|
436
|
+
if type(self.t.name)==str:
|
|
437
|
+
pass
|
|
438
|
+
else:
|
|
439
|
+
raise ValueError()
|
|
440
|
+
except:
|
|
441
|
+
ErrorForm("Target page of redirect has an invalid name/type or it does not exist", self.p.name, type="300 PAGE ERROR").call()
|
|
442
|
+
err=True
|
|
443
|
+
if not err and (self.t.name not in VALID_PAGES):
|
|
444
|
+
ErrorForm(f"Page {self.t.name} is not a valid page for a redirect target", self.p.name, type="101 REDIRECT ERROR").call()
|
|
445
|
+
err=True
|
|
446
|
+
if not err:
|
|
447
|
+
try:
|
|
448
|
+
si=s(self.t.call)
|
|
449
|
+
args=list(si.parameters)
|
|
450
|
+
if "ctx" not in args:
|
|
451
|
+
err=True
|
|
452
|
+
ErrorForm(f"Target page does not conform to standards: a page must have a context argument 'ctx' in target.call", self.p.name, type="300 PAGE ERROR").call()
|
|
453
|
+
except:
|
|
454
|
+
err=True
|
|
455
|
+
ErrorForm(f"Target page does not conform to standards: target.call function not found", self.p.name, type="300 PAGE ERROR").call()
|
|
456
|
+
|
|
457
|
+
if not err:
|
|
458
|
+
self.c=ErrorHelper(["page", "context"], [self.p.name, self.ct], [str, dict])
|
|
459
|
+
else:
|
|
460
|
+
self.c=False
|
|
461
|
+
self.c=self.c or err
|
|
462
|
+
def call(self):
|
|
463
|
+
global control
|
|
464
|
+
global page_class
|
|
465
|
+
global page_ctx
|
|
466
|
+
if self.c:
|
|
467
|
+
return 1
|
|
468
|
+
else:
|
|
469
|
+
self.pr.control=self.t.name
|
|
470
|
+
self.pr.page_class=self.tc
|
|
471
|
+
self.pr.page_ctx=self.ct
|
|
472
|
+
return 0
|
|
473
|
+
|
|
474
|
+
class DummyPage:
|
|
475
|
+
name="dummy"
|
|
476
|
+
def call(self, ctx={}):
|
|
477
|
+
pass
|
|
478
|
+
|
|
479
|
+
class Embedding:
|
|
480
|
+
def __init__(self,page, grouped={}):
|
|
481
|
+
self.pg=page
|
|
482
|
+
self.gr=grouped
|
|
483
|
+
asr=["page","grouped data"]
|
|
484
|
+
args=[page, grouped]
|
|
485
|
+
types=[str, dict]
|
|
486
|
+
self.c=ErrorHelper(asr,args,types)
|
|
487
|
+
|
|
488
|
+
class CanvasEmbedding:
|
|
489
|
+
def __init__(self, page, name, width, height, program, resizex=0, resizey=0, thick=0, highlight_thick=0):
|
|
490
|
+
asr=["page", "name", "width", "height", "resizable - x-axis", "resizable - y-axis", "border thickness", "border highlight thickness"]
|
|
491
|
+
args=[page, name, width, height, resizex, resizey, thick, highlight_thick]
|
|
492
|
+
types=[str, str, int, int, int, int, int, int]
|
|
493
|
+
self.c=ErrorHelper(asr,args,types)
|
|
494
|
+
self.wins=[]
|
|
495
|
+
self.cnvs=[]
|
|
496
|
+
if not self.c:
|
|
497
|
+
self.embed=Embedding(page, {"page": page, "name":name, "program": program, "width":width, "height": height, "rx":resizex, "ry":resizey, "thick":thick, "hlt":highlight_thick})
|
|
498
|
+
def NewWindow(self):
|
|
499
|
+
if self.c:
|
|
500
|
+
return 1
|
|
501
|
+
gr=self.embed.gr
|
|
502
|
+
self.tk = Tk()
|
|
503
|
+
self.tk.title(gr["name"])
|
|
504
|
+
self.tk.resizable(gr["rx"], gr["ry"])
|
|
505
|
+
self.tk.wm_attributes("-topmost",1)
|
|
506
|
+
self.wins.append(self.tk)
|
|
507
|
+
return 0
|
|
508
|
+
|
|
509
|
+
def NewCanvas(self, window):
|
|
510
|
+
if self.c:
|
|
511
|
+
return 1
|
|
512
|
+
if self.wins==[]:
|
|
513
|
+
ErrorForm("Canvas Embedding did not find any valid windows. Please create a window by using NewWindow.", self.embed.gr["page"], type="103 NON-EXISTENT ERROR").call()
|
|
514
|
+
return 1
|
|
515
|
+
if ErrorHelper(["page", "window"], [self.embed.gr["page"], window], [str,int]):
|
|
516
|
+
return 1
|
|
517
|
+
if window>len(self.wins)-1 or window<0:
|
|
518
|
+
ErrorForm(f"Canvas Embedding did not find the window in question(Window #{window}). Please select another window ID.", self.embed.gr["page"], type="103 NON-EXISTENT ERROR").call()
|
|
519
|
+
return 1
|
|
520
|
+
self.cnv=Canvas(self.wins[window], width=self.embed.gr["width"], height=self.embed.gr["height"], bd=self.embed.gr["thick"], highlightthickness=self.embed.gr["hlt"])
|
|
521
|
+
self.cnvs.append({"tk":self.wins[window], "cnv":self.cnv})
|
|
522
|
+
self.cnv.pack()
|
|
523
|
+
return 0
|
|
524
|
+
|
|
525
|
+
def call(self):
|
|
526
|
+
if self.c:
|
|
527
|
+
return 1
|
|
528
|
+
if self.tk:
|
|
529
|
+
self.tk.update_idletasks()
|
|
530
|
+
self.tk.update()
|
|
531
|
+
return 0
|
|
532
|
+
else:
|
|
533
|
+
ErrorForm("Canvas Embedding did not find any valid windows. Please create a window by using NewWindow.", self.embed.gr["page"], type="103 NON-EXISTENT ERROR").call()
|
|
534
|
+
return 1
|
|
535
|
+
|
|
536
|
+
|
|
537
|
+
class ButtonField:
|
|
538
|
+
def __init__(self, canvas_embed, cmd, name, canvas, background="None", foreground="None", anchor="nw", x=150, y=100):
|
|
539
|
+
self.c=False
|
|
540
|
+
if not isinstance(canvas_embed, CanvasEmbedding):
|
|
541
|
+
ErrorForm("Wrong Embedding", "UNKNOWN", "304 CANVAS ERROR").call()
|
|
542
|
+
self.c=True
|
|
543
|
+
else:
|
|
544
|
+
self.cne=canvas_embed
|
|
545
|
+
if not self.c:
|
|
546
|
+
asr=["page", "button name", "button background color", "button foreground color", "canvas number", "button window position x", "button window position y", "button window anchor"]
|
|
547
|
+
args=[self.cne.embed.gr["page"], name, background, foreground, canvas, x, y, anchor]
|
|
548
|
+
types=[str, str, str, str, int, int, int, ["nw", "sw", "w", "n", "s", "e","ne", "se", "center"]]
|
|
549
|
+
self.c=self.c or ErrorHelper(asr, args, types)
|
|
550
|
+
if not self.c and len(self.cne.cnvs)==0:
|
|
551
|
+
ErrorForm("Canvas Embedding did not find any valid canvases.", self.cne.embed.gr["page"], type="103 NON-EXISTENT ERROR").call()
|
|
552
|
+
self.c=True
|
|
553
|
+
if not self.c and canvas>len(self.cne.cnvs)-1 or canvas<0:
|
|
554
|
+
ErrorForm(f"Canvas Embedding did not find the canvas in question(Canvas #{canvas})", self.cne.embed.gr["page"], type="103 NON-EXISTENT ERROR").call()
|
|
555
|
+
self.c=True
|
|
556
|
+
if not self.c:
|
|
557
|
+
self.x=x
|
|
558
|
+
self.y=y
|
|
559
|
+
self.w=0
|
|
560
|
+
self.embed=Embedding(self.cne.embed.gr["page"],{"canvas":canvas, "background":background, "foreground":foreground, "name":name, "command":cmd, "anchor":anchor, "x":x,"y":y,"w":0,"container":None, "special":False,"window":None})
|
|
561
|
+
def call(self, redraw=False, ignored=False):
|
|
562
|
+
if self.c:
|
|
563
|
+
return 1
|
|
564
|
+
if redraw and self.embed.gr["window"]:
|
|
565
|
+
self.cne.cnvs[self.embed.gr["canvas"]]["cnv"].delete(self.embed.gr["window"])
|
|
566
|
+
if ignored:
|
|
567
|
+
return 0
|
|
568
|
+
if self.embed.gr["background"]=="None" and self.embed.gr["foreground"]=="None":
|
|
569
|
+
self.btn=Button(self.cne.cnvs[self.embed.gr["canvas"]]["tk"], text=self.embed.gr["name"], command=self.embed.gr["command"])
|
|
570
|
+
elif self.embed.gr["background"]=="None":
|
|
571
|
+
self.btn=Button(self.cne.cnvs[self.embed.gr["canvas"]]["tk"], text=self.embed.gr["name"], command=self.embed.gr["command"], fg=self.embed.gr["foreground"])
|
|
572
|
+
elif self.embed.gr["foreground"]=="None":
|
|
573
|
+
self.btn=Button(self.cne.cnvs[self.embed.gr["canvas"]]["tk"], text=self.embed.gr["name"], command=self.embed.gr["command"], bg=self.embed.gr["background"])
|
|
574
|
+
else:
|
|
575
|
+
self.btn=Button(self.cne.cnvs[self.embed.gr["canvas"]]["tk"], text=self.embed.gr["name"], command=self.embed.gr["command"], bg=self.embed.gr["background"], fg=self.embed.gr["foreground"])
|
|
576
|
+
self.embed.gr["window"]=self.cne.cnvs[self.embed.gr["canvas"]]["cnv"].create_window(self.x, self.y, window=self.btn, anchor=self.embed.gr["anchor"])
|
|
577
|
+
self.cne.call()
|
|
578
|
+
return 0
|
|
579
|
+
|
|
580
|
+
class ChoiceForm:
|
|
581
|
+
def __init__(self, canvas_embed, choicenames, choicecmds, canvas, backgrounds=[], foregrounds=[], anchor="nw", x=150, y=100, distance=30):
|
|
582
|
+
self.cne=canvas_embed
|
|
583
|
+
self.ca=canvas
|
|
584
|
+
self.d=distance
|
|
585
|
+
self.bg=backgrounds
|
|
586
|
+
self.fg=foregrounds
|
|
587
|
+
self.nm=choicenames
|
|
588
|
+
self.cmd=choicecmds
|
|
589
|
+
self.an=anchor
|
|
590
|
+
self.w=0
|
|
591
|
+
self.x=x
|
|
592
|
+
self.y=y
|
|
593
|
+
if backgrounds==[]:
|
|
594
|
+
self.bg=["None"]*len(choicenames)
|
|
595
|
+
if foregrounds==[]:
|
|
596
|
+
self.fg=["None"]*len(choicenames)
|
|
597
|
+
self.c=ErrorHelper(["distance from choice to choice"], [distance], [int], ignore=True)
|
|
598
|
+
self.c=self.c or ListErrorHelper([choicenames, choicecmds, self.bg, self.fg])
|
|
599
|
+
self.cont=None
|
|
600
|
+
self.special=False
|
|
601
|
+
self.wind=None
|
|
602
|
+
|
|
603
|
+
def call(self, redraw=False, ignored=False):
|
|
604
|
+
if self.c:
|
|
605
|
+
return 1
|
|
606
|
+
for x in range(len(self.bg)):
|
|
607
|
+
ButtonField(self.cne, self.cmd[x], self.nm[x], self.ca, self.bg[x], self.fg[x], self.an, self.x+x*self.d, self.y).call(redraw=redraw, ignored=ignored)
|
|
608
|
+
return 0
|
|
609
|
+
|
|
610
|
+
class TextFieldAdv:
|
|
611
|
+
def __init__(self, canvas_embed, text, canvas, x, y, font_color="black", font_type="Times", font_size=15, anchor="nw"):
|
|
612
|
+
self.c=False
|
|
613
|
+
if not isinstance(canvas_embed, CanvasEmbedding):
|
|
614
|
+
ErrorForm("Wrong Embedding", "UNKNOWN", "304 CANVAS ERROR").call()
|
|
615
|
+
self.c=True
|
|
616
|
+
else:
|
|
617
|
+
self.cne=canvas_embed
|
|
618
|
+
if not self.c:
|
|
619
|
+
asr=["page", "font size", "font color", "text", "canvas number", "text window position x", "text window position y", "anchor"]
|
|
620
|
+
args=[self.cne.embed.gr["page"], font_size, font_color, text, canvas, x, y, anchor]
|
|
621
|
+
types=[str, int, str, str, int, int, int, ["nw", "sw", "w", "n", "s", "e","ne", "se", "center"]]
|
|
622
|
+
self.c=self.c or ErrorHelper(asr, args, types)
|
|
623
|
+
if not self.c and len(self.cne.cnvs)==0:
|
|
624
|
+
ErrorForm("Canvas Embedding did not find any valid canvases.", self.cne.embed.gr["page"], type="103 NON-EXISTENT ERROR").call()
|
|
625
|
+
self.c=True
|
|
626
|
+
if not self.c and canvas>len(self.cne.cnvs)-1 or canvas<0:
|
|
627
|
+
ErrorForm(f"Canvas Embedding did not find the canvas in question(Canvas #{canvas})", self.cne.embed.gr["page"], type="103 NON-EXISTENT ERROR").call()
|
|
628
|
+
self.c=True
|
|
629
|
+
if not self.c:
|
|
630
|
+
self.fs=font_size
|
|
631
|
+
self.fc=font_color
|
|
632
|
+
self.tx=text
|
|
633
|
+
self.ca=canvas
|
|
634
|
+
self.x=x
|
|
635
|
+
self.y=y
|
|
636
|
+
self.ft=font_type
|
|
637
|
+
self.an=anchor
|
|
638
|
+
self.w=(font_size/3)*len(text)
|
|
639
|
+
self.cont=None
|
|
640
|
+
self.special=False
|
|
641
|
+
self.wind=None
|
|
642
|
+
self.iuef=None
|
|
643
|
+
def call(self, redraw=False, ignored=False):
|
|
644
|
+
if self.c:
|
|
645
|
+
return 1
|
|
646
|
+
if redraw and self.wind:
|
|
647
|
+
self.cne.cnvs[self.ca]["cnv"].delete(self.wind)
|
|
648
|
+
if ignored:
|
|
649
|
+
return 0
|
|
650
|
+
self.wind=self.cne.cnvs[self.ca]["cnv"].create_text(self.x, self.y, text=self.tx, font=(self.ft, self.fs), fill=self.fc, anchor=self.an)
|
|
651
|
+
self.cne.call()
|
|
652
|
+
return self.wind
|
|
653
|
+
|
|
654
|
+
class ImageField:
|
|
655
|
+
def __init__(self, canvas_embed, x, y, canvas, img="./uploads/example.png", anchor="nw"):
|
|
656
|
+
self.c=False
|
|
657
|
+
if not isinstance(canvas_embed, CanvasEmbedding):
|
|
658
|
+
ErrorForm("Wrong Embedding", "UNKNOWN", "304 CANVAS ERROR").call()
|
|
659
|
+
self.c=True
|
|
660
|
+
else:
|
|
661
|
+
self.cne=canvas_embed
|
|
662
|
+
if not self.c:
|
|
663
|
+
asr=["page", "image x coordinate", "image y coordinate", "canvas number", "anchor"]
|
|
664
|
+
args=[self.cne.embed.gr["page"], x, y, canvas, anchor]
|
|
665
|
+
types=[str, int, int, int, ["nw", "sw", "w", "n", "s", "e","ne", "se", "center"]]
|
|
666
|
+
if not isinstance(img, PhotoImage):
|
|
667
|
+
asr.append("image path")
|
|
668
|
+
args.append(img)
|
|
669
|
+
types.append(str)
|
|
670
|
+
flag=True
|
|
671
|
+
self.c=self.c or ErrorHelper(asr, args, types)
|
|
672
|
+
if not self.c and len(self.cne.cnvs)==0:
|
|
673
|
+
ErrorForm("Canvas Embedding did not find any valid canvases.", self.cne.embed.gr["page"], type="103 NON-EXISTENT ERROR").call()
|
|
674
|
+
self.c=True
|
|
675
|
+
if not self.c and canvas>len(self.cne.cnvs)-1 or canvas<0:
|
|
676
|
+
ErrorForm(f"Canvas Embedding did not find the canvas in question(Canvas #{canvas})", self.cne.embed.gr["page"], type="103 NON-EXISTENT ERROR").call()
|
|
677
|
+
self.c=True
|
|
678
|
+
if not self.c:
|
|
679
|
+
self.x=x
|
|
680
|
+
self.y=y
|
|
681
|
+
self.ca=canvas
|
|
682
|
+
self.img=img
|
|
683
|
+
self.an=anchor
|
|
684
|
+
if not isinstance(self.img, PhotoImage):
|
|
685
|
+
self.imgf=PhotoImage(file=self.img)
|
|
686
|
+
else:
|
|
687
|
+
self.imgf=self.img
|
|
688
|
+
self.w=self.imgf.width()
|
|
689
|
+
self.cont=None
|
|
690
|
+
self.special=False
|
|
691
|
+
self.wind=None
|
|
692
|
+
|
|
693
|
+
def call(self, redraw=False, ignored=False):
|
|
694
|
+
if self.c:
|
|
695
|
+
return 1
|
|
696
|
+
if redraw and self.wind:
|
|
697
|
+
self.cne.cnvs[self.ca]["cnv"].delete(self.wind)
|
|
698
|
+
if ignored:
|
|
699
|
+
return 0
|
|
700
|
+
self.wind=self.cne.cnvs[self.ca]["cnv"].create_image(self.x, self.y, image=self.imgf, anchor=self.an)
|
|
701
|
+
self.cne.call()
|
|
702
|
+
return self
|
|
703
|
+
|
|
704
|
+
def updimg(self, image):
|
|
705
|
+
asr=["page"]
|
|
706
|
+
args=[self.cne.embed.gr["page"]]
|
|
707
|
+
types=[str]
|
|
708
|
+
if not isinstance(image, PhotoImage):
|
|
709
|
+
asr.append("image path")
|
|
710
|
+
args.append(image)
|
|
711
|
+
types.append(str)
|
|
712
|
+
if ErrorHelper(asr, args, types):
|
|
713
|
+
return 1
|
|
714
|
+
if not isinstance(image, PhotoImage):
|
|
715
|
+
self.imgf=PhotoImage(file=image)
|
|
716
|
+
else:
|
|
717
|
+
self.imgf=image
|
|
718
|
+
self.w=self.imgf.width()
|
|
719
|
+
return 0
|
|
720
|
+
|
|
721
|
+
class BackgroundForm:
|
|
722
|
+
def __init__(self, canvas_embed, beginx, beginy, copyx, copyy, canvas, img="./uploads/example.png", anchor="nw"):
|
|
723
|
+
self.c=False
|
|
724
|
+
flag=False
|
|
725
|
+
if not isinstance(canvas_embed, CanvasEmbedding):
|
|
726
|
+
ErrorForm("Wrong Embedding", "UNKNOWN", "304 CANVAS ERROR").call()
|
|
727
|
+
self.c=True
|
|
728
|
+
else:
|
|
729
|
+
self.cne=canvas_embed
|
|
730
|
+
if not self.c:
|
|
731
|
+
asr=["page", "begin x coordinate", "begin y coordinate", "times to copy on x axis", "times to copy on y axis", "canvas number", "anchor"]
|
|
732
|
+
args=[self.cne.embed.gr["page"], beginx, beginy, copyx, copyy, canvas, anchor]
|
|
733
|
+
types=[str, int, int, int, int, int,["nw", "sw", "w", "n", "s", "e","ne", "se", "center"]]
|
|
734
|
+
if not isinstance(img, PhotoImage):
|
|
735
|
+
asr.append("image path")
|
|
736
|
+
args.append(img)
|
|
737
|
+
types.append(str)
|
|
738
|
+
flag=True
|
|
739
|
+
self.c=self.c or ErrorHelper(asr, args, types)
|
|
740
|
+
if not self.c and len(self.cne.cnvs)==0:
|
|
741
|
+
ErrorForm("Canvas Embedding did not find any valid canvases.", self.cne.embed.gr["page"], type="103 NON-EXISTENT ERROR").call()
|
|
742
|
+
self.c=True
|
|
743
|
+
if not self.c and canvas>len(self.cne.cnvs)-1 or canvas<0:
|
|
744
|
+
ErrorForm(f"Canvas Embedding did not find the canvas in question(Canvas #{canvas})", self.cne.embed.gr["page"], type="103 NON-EXISTENT ERROR").call()
|
|
745
|
+
self.c=True
|
|
746
|
+
if not self.c:
|
|
747
|
+
self.bx=beginx
|
|
748
|
+
self.by=beginy
|
|
749
|
+
self.cx=copyx
|
|
750
|
+
self.cy=copyy
|
|
751
|
+
self.ca=canvas
|
|
752
|
+
self.img=img
|
|
753
|
+
self.tiles=[]
|
|
754
|
+
self.an=anchor
|
|
755
|
+
if flag:
|
|
756
|
+
self.imgf=PhotoImage(file=self.img)
|
|
757
|
+
else:
|
|
758
|
+
self.imgf=self.img
|
|
759
|
+
self.wi = self.imgf.width()
|
|
760
|
+
self.w=self.wi*self.cx
|
|
761
|
+
self.cont=None
|
|
762
|
+
self.special=False
|
|
763
|
+
self.wind=None
|
|
764
|
+
def call(self, redraw=False, ignored=False):
|
|
765
|
+
if self.c:
|
|
766
|
+
return 1
|
|
767
|
+
if redraw:
|
|
768
|
+
self.tiles=[]
|
|
769
|
+
h = self.imgf.height()
|
|
770
|
+
for x in range(self.cx):
|
|
771
|
+
self.tiles.append([])
|
|
772
|
+
for y in range(self.cy):
|
|
773
|
+
self.tiles[x].append(ImageField(self.cne, self.bx+x*self.wi, self.by+y*h,self.ca, self.imgf,self.an).call(redraw=redraw, ignored=ignored))
|
|
774
|
+
return 0
|
|
775
|
+
|
|
776
|
+
class GeometryField:
|
|
777
|
+
def __init__(self, canvas_embed, xs, ys, canvas, extent=180, bd=1, outline="black", fill="", typea="arc"):
|
|
778
|
+
self.c=False
|
|
779
|
+
if not isinstance(canvas_embed, CanvasEmbedding):
|
|
780
|
+
ErrorForm("Wrong Embedding", "UNKNOWN", "304 CANVAS ERROR").call()
|
|
781
|
+
self.c=True
|
|
782
|
+
else:
|
|
783
|
+
self.cne=canvas_embed
|
|
784
|
+
if not self.c:
|
|
785
|
+
asr=["page", "x coordinates", "y coordinates", "extent", "outline", "fill", "border width","type"]
|
|
786
|
+
args=[self.cne.embed.gr["page"], xs, ys, extent, outline, fill, bd, typea]
|
|
787
|
+
types=[str, list, list, int, str, str, int, ["arc", "polygon"]]
|
|
788
|
+
self.c=self.c or ErrorHelper(asr, args, types)
|
|
789
|
+
if not self.c and len(self.cne.cnvs)==0:
|
|
790
|
+
ErrorForm("Canvas Embedding did not find any valid canvases.", self.cne.embed.gr["page"], type="103 NON-EXISTENT ERROR").call()
|
|
791
|
+
self.c=True
|
|
792
|
+
if not self.c and canvas>len(self.cne.cnvs)-1 or canvas<0:
|
|
793
|
+
ErrorForm(f"Canvas Embedding did not find the canvas in question(Canvas #{canvas})", self.cne.embed.gr["page"], type="103 NON-EXISTENT ERROR").call()
|
|
794
|
+
self.c=True
|
|
795
|
+
if not self.c and len(xs)!=len(ys):
|
|
796
|
+
ErrorForm(f"Lengths of lists don't match", self.cne.embed.gr["page"], type="100 INTERNAL ERROR").call()
|
|
797
|
+
self.c=True
|
|
798
|
+
if not self.c and len(xs)<2:
|
|
799
|
+
ErrorForm(f"Lengths of lists aren't large enough", self.cne.embed.gr["page"], type="100 INTERNAL ERROR").call()
|
|
800
|
+
self.c=True
|
|
801
|
+
if not self.c:
|
|
802
|
+
self.xs=xs
|
|
803
|
+
self.ys=ys
|
|
804
|
+
self.ca=canvas
|
|
805
|
+
self.ex=extent
|
|
806
|
+
self.ol=outline
|
|
807
|
+
self.fl=fill
|
|
808
|
+
self.ty=typea
|
|
809
|
+
self.cont=None
|
|
810
|
+
self.special=False
|
|
811
|
+
self.wind=None
|
|
812
|
+
self.bdw=bd
|
|
813
|
+
def call(self, redraw=False,ignored=False):
|
|
814
|
+
if self.c:
|
|
815
|
+
return 1
|
|
816
|
+
if redraw and self.wind:
|
|
817
|
+
self.cne.cnvs[self.ca]["cnv"].delete(self.wind)
|
|
818
|
+
if ignored:
|
|
819
|
+
return 0
|
|
820
|
+
if self.ty=="arc":
|
|
821
|
+
self.wind=self.cne.cnvs[self.ca]["cnv"].create_arc(self.xs[0], self.ys[0], self.xs[1], self.ys[1], extent=self.ex, style=ARC, width=self.bdw, fill=self.fl, outline=self.ol)
|
|
822
|
+
elif self.ty=="polygon":
|
|
823
|
+
res=[]
|
|
824
|
+
for x in range(len(self.xs)):
|
|
825
|
+
res.append(self.xs[x])
|
|
826
|
+
res.append(self.ys[x])
|
|
827
|
+
self.wind=self.cne.cnvs[self.ca]["cnv"].create_polygon(*res, fill=self.fl, width=self.bdw, outline=self.ol)
|
|
828
|
+
self.cne.call()
|
|
829
|
+
return 0
|
|
830
|
+
|
|
831
|
+
class InteractiveUserErrorForm:
|
|
832
|
+
def __init__(self, cne, canvas, element, text,occurrence, type="200 INPUT ERROR"):
|
|
833
|
+
self.t=text
|
|
834
|
+
self.o=occurrence
|
|
835
|
+
self.ty=type
|
|
836
|
+
self.e=element
|
|
837
|
+
self.cne=cne
|
|
838
|
+
self.ca=canvas
|
|
839
|
+
self.cont=None
|
|
840
|
+
self.special=False
|
|
841
|
+
self.wind=None
|
|
842
|
+
def call(self, redraw=False, ignored=False):
|
|
843
|
+
if redraw and self.wind:
|
|
844
|
+
self.cne.cnvs[self.ca]["cnv"].delete(self.wind)
|
|
845
|
+
if ignored:
|
|
846
|
+
self.e.special=False
|
|
847
|
+
self.e.cont.call()
|
|
848
|
+
return 0
|
|
849
|
+
self.e.y+=20
|
|
850
|
+
if self.e.cont:
|
|
851
|
+
ignore, ypos=self.e.cont.get_pos(self.e)
|
|
852
|
+
xpos=self.e.cont.x
|
|
853
|
+
self.e.special=True
|
|
854
|
+
else:
|
|
855
|
+
xpos, ypos=self.e.x, self.e.y-20
|
|
856
|
+
self.wind=TextFieldAdv(self.cne, f"{self.ty}: {self.t}", self.ca, xpos, ypos, font_color="red", font_size=10).call(redraw=redraw)
|
|
857
|
+
self.e.cont.call()
|
|
858
|
+
self.e.iuef=self
|
|
859
|
+
return 0
|
|
860
|
+
|
|
861
|
+
class InputForm:
|
|
862
|
+
def __init__(self, canvas_embed, width, x, y, canvas, prompt, anchor="nw", type_req=str, minimum=0, maximum=100, discretes=[]):
|
|
863
|
+
required=type_req
|
|
864
|
+
self.c=False
|
|
865
|
+
if not isinstance(canvas_embed, CanvasEmbedding):
|
|
866
|
+
ErrorForm("Wrong Embedding", "UNKNOWN", "304 CANVAS ERROR").call()
|
|
867
|
+
self.c=True
|
|
868
|
+
else:
|
|
869
|
+
self.cne=canvas_embed
|
|
870
|
+
if not self.c:
|
|
871
|
+
asr=["page", "x coordinate", "y coordinate", "width", "canvas number", "anchor", "field required", "minimum value", "maximum value", "discrete values"]
|
|
872
|
+
args=[self.cne.embed.gr["page"], x, y, width, canvas, anchor, required, minimum, maximum, discretes]
|
|
873
|
+
types=[str, int, int, int, int, ["nw", "sw", "w", "ne", "e", "se", "center"], [str, int, bool, float], int, int, list]
|
|
874
|
+
self.c=self.c or ErrorHelper(asr, args, types)
|
|
875
|
+
if not self.c and len(self.cne.cnvs)==0:
|
|
876
|
+
ErrorForm("Canvas Embedding did not find any valid canvases.", self.cne.embed.gr["page"], type="103 NON-EXISTENT ERROR").call()
|
|
877
|
+
self.c=True
|
|
878
|
+
if not self.c and canvas>len(self.cne.cnvs)-1 or canvas<0:
|
|
879
|
+
ErrorForm(f"Canvas Embedding did not find the canvas in question(Canvas #{canvas})", self.cne.embed.gr["page"], type="103 NON-EXISTENT ERROR").call()
|
|
880
|
+
self.c=True
|
|
881
|
+
if not self.c:
|
|
882
|
+
if not isinstance(prompt, TextFieldAdv):
|
|
883
|
+
ErrorForm("Wrong Prompt Field: Field is not TextFieldAdv", self.cne.embed.gr["page"], type="105 INSTANCE ERROR").call()
|
|
884
|
+
self.c=True
|
|
885
|
+
if not self.c:
|
|
886
|
+
self.x=x
|
|
887
|
+
self.y=y
|
|
888
|
+
self.p=prompt
|
|
889
|
+
self.w=max(self.p.w, width)
|
|
890
|
+
self.wi=width
|
|
891
|
+
self.ca=canvas
|
|
892
|
+
self.an=anchor
|
|
893
|
+
self.r=required
|
|
894
|
+
self.mi=minimum
|
|
895
|
+
self.ma=maximum
|
|
896
|
+
self.d=discretes
|
|
897
|
+
self.cont=None
|
|
898
|
+
self.special=False
|
|
899
|
+
self.wind=None
|
|
900
|
+
self.ch_b=False
|
|
901
|
+
self.iuef=None
|
|
902
|
+
def call(self, redraw=False, ignored=False):
|
|
903
|
+
if self.c:
|
|
904
|
+
return 1
|
|
905
|
+
if redraw and self.wind:
|
|
906
|
+
self.cne.cnvs[self.ca]["cnv"].delete(self.wind)
|
|
907
|
+
if ignored:
|
|
908
|
+
return 0
|
|
909
|
+
x=self.p.x
|
|
910
|
+
y=self.p.y
|
|
911
|
+
self.p.x=self.x
|
|
912
|
+
self.p.y=self.y
|
|
913
|
+
self.p.call(redraw=redraw)
|
|
914
|
+
self.p.x=x
|
|
915
|
+
self.p.y=y
|
|
916
|
+
self.e=Entry(self.cne.tk, width=self.wi)
|
|
917
|
+
self.wind=self.cne.cnvs[self.ca]["cnv"].create_window(self.x, self.y+self.p.fs+10, window=self.e, anchor=self.an)
|
|
918
|
+
self.cne.call()
|
|
919
|
+
return 0
|
|
920
|
+
def get(self):
|
|
921
|
+
if self.c:
|
|
922
|
+
return "ERR"
|
|
923
|
+
ch=check(self.e.get(), self.r, self.cne.embed.gr["page"], self.mi, self.ma, self.d, adv=True, cne=self.cne, canvas=self.ca, element=self)
|
|
924
|
+
if ch[1]==False and self.ch_b:
|
|
925
|
+
self.iuef.call(redraw=True,ignored=True)
|
|
926
|
+
if not self.ch_b and ch[1]==True:
|
|
927
|
+
self.ch_b=True
|
|
928
|
+
return ch
|
|
929
|
+
|
|
930
|
+
class Container:
|
|
931
|
+
def __init__(self, canvas_embed, beginx, beginy, endx, canvas, fields=[], height=40, pos="center"):
|
|
932
|
+
instances=[TextFieldAdv, ImageField, ButtonField, InputForm, GeometryField, ChoiceForm, self.__class__]
|
|
933
|
+
self.c=False
|
|
934
|
+
if not isinstance(canvas_embed, CanvasEmbedding):
|
|
935
|
+
ErrorForm("Wrong Embedding", "UNKNOWN", "304 CANVAS ERROR").call()
|
|
936
|
+
self.c=True
|
|
937
|
+
else:
|
|
938
|
+
self.cne=canvas_embed
|
|
939
|
+
if not self.c:
|
|
940
|
+
asr=["page", "begin x coordinate", "begin y coordinate", "canvas number", "fields list", "height of one field", "end x coordinate", "position in container"]
|
|
941
|
+
args=[self.cne.embed.gr["page"], beginx, beginy, canvas, fields, height, endx, pos]
|
|
942
|
+
types=[str, int, int, int, list, int, int, ["begin", "end", "center"]]
|
|
943
|
+
self.c=self.c or ErrorHelper(asr, args, types)
|
|
944
|
+
if not self.c and len(self.cne.cnvs)==0:
|
|
945
|
+
ErrorForm("Canvas Embedding did not find any valid canvases.", self.cne.embed.gr["page"], type="103 NON-EXISTENT ERROR").call()
|
|
946
|
+
self.c=True
|
|
947
|
+
if not self.c and canvas>len(self.cne.cnvs)-1 or canvas<0:
|
|
948
|
+
ErrorForm(f"Canvas Embedding did not find the canvas in question(Canvas #{canvas})", self.cne.embed.gr["page"], type="103 NON-EXISTENT ERROR").call()
|
|
949
|
+
self.c=True
|
|
950
|
+
if not self.c:
|
|
951
|
+
for field in fields:
|
|
952
|
+
back=False
|
|
953
|
+
for instance in instances:
|
|
954
|
+
if isinstance(field, instance):
|
|
955
|
+
back=True
|
|
956
|
+
break
|
|
957
|
+
if not back:
|
|
958
|
+
self.c=True
|
|
959
|
+
ErrorForm("Non-valid instance detected", self.cne.embed.gr["page"], type="105 INSTANCE ERROR").call()
|
|
960
|
+
break
|
|
961
|
+
if not self.c:
|
|
962
|
+
self.x=beginx
|
|
963
|
+
self.y=beginy
|
|
964
|
+
self.ca=canvas
|
|
965
|
+
self.fs=fields
|
|
966
|
+
self.h=height
|
|
967
|
+
self.po=pos
|
|
968
|
+
self.ex=endx
|
|
969
|
+
self.w=self.ex-self.x
|
|
970
|
+
for el in fields:
|
|
971
|
+
el.cont=self
|
|
972
|
+
el.special=False
|
|
973
|
+
|
|
974
|
+
def call(self, ignored=False):
|
|
975
|
+
if self.c:
|
|
976
|
+
return 1
|
|
977
|
+
for fld in range(len(self.fs)):
|
|
978
|
+
xp=self.fs[fld].x
|
|
979
|
+
if self.po=="begin":
|
|
980
|
+
self.fs[fld].x=self.x
|
|
981
|
+
elif self.po=="center":
|
|
982
|
+
self.fs[fld].x=int(max(self.x, self.x+self.w/2-self.fs[fld].w/2))
|
|
983
|
+
elif self.po=="end":
|
|
984
|
+
self.fs[fld].x=int(self.ex-self.fs[fld].w)
|
|
985
|
+
yp=self.fs[fld].y
|
|
986
|
+
self.fs[fld].y=self.y+fld*self.h
|
|
987
|
+
if self.fs[fld].special:
|
|
988
|
+
self.fs[fld].y+=20
|
|
989
|
+
self.fs[fld].call(redraw=True, ignored=ignored)
|
|
990
|
+
self.fs[fld].y=yp
|
|
991
|
+
self.fs[fld].x=xp
|
|
992
|
+
return 0
|
|
993
|
+
|
|
994
|
+
def get_pos(self, fld2):
|
|
995
|
+
for fld in range(len(self.fs)):
|
|
996
|
+
if self.fs[fld] == fld2:
|
|
997
|
+
if self.po=="begin":
|
|
998
|
+
xx=self.x
|
|
999
|
+
elif self.po=="center":
|
|
1000
|
+
xx=int(max(self.x, self.x+self.w/2-self.fs[fld].w/2))
|
|
1001
|
+
elif self.po=="end":
|
|
1002
|
+
xx=int(self.ex-self.fs[fld].w)
|
|
1003
|
+
return xx, self.y+fld*self.h
|
|
1004
|
+
|
|
1005
|
+
def DummyCmd():
|
|
1006
|
+
pass
|
|
1007
|
+
def DummyCmdArgs(*args):
|
|
1008
|
+
pass
|
|
1009
|
+
class PygameEmbedding:
|
|
1010
|
+
def __init__(self, width, height, name,page, color=(230,230,230)):
|
|
1011
|
+
asr=["page", "width", "height", "red", "green", "blue", "name"]
|
|
1012
|
+
args=[page, width, height, color[0], color[1], color[2], name]
|
|
1013
|
+
types=[str, int, int, int, int, int, str]
|
|
1014
|
+
self.c=ErrorHelper(asr, args, types)
|
|
1015
|
+
self.sprites=[]
|
|
1016
|
+
self.kys=[]
|
|
1017
|
+
if not self.c:
|
|
1018
|
+
pygame.init()
|
|
1019
|
+
self.color=color
|
|
1020
|
+
self.center=(width/2,height/2)
|
|
1021
|
+
self.screen = pygame.display.set_mode((width, height))
|
|
1022
|
+
self.width, self.height=width, height
|
|
1023
|
+
pygame.display.set_caption(name)
|
|
1024
|
+
self.page=page
|
|
1025
|
+
self.rect=self.screen.get_rect()
|
|
1026
|
+
self.exit=False
|
|
1027
|
+
self.setup()
|
|
1028
|
+
def link(self,sprite):
|
|
1029
|
+
if self.c:
|
|
1030
|
+
return 1
|
|
1031
|
+
if ErrorHelper(["page","sprite"], [self.page,sprite], [str,ImageSprite]):
|
|
1032
|
+
return 1
|
|
1033
|
+
elif sprite.c:
|
|
1034
|
+
return 1
|
|
1035
|
+
self.sprites.append(sprite)
|
|
1036
|
+
return 0
|
|
1037
|
+
|
|
1038
|
+
def linkbtn(self,sprite):
|
|
1039
|
+
if self.c:
|
|
1040
|
+
return 1
|
|
1041
|
+
if ErrorHelper(["page","sprite"], [self.page,sprite], [str,ButtonFieldAdv]):
|
|
1042
|
+
return 1
|
|
1043
|
+
elif sprite.c:
|
|
1044
|
+
return 1
|
|
1045
|
+
self.sprites.append(sprite)
|
|
1046
|
+
return 0
|
|
1047
|
+
|
|
1048
|
+
def linkkey(self,keypress):
|
|
1049
|
+
if self.c:
|
|
1050
|
+
return 1
|
|
1051
|
+
elif ErrorHelper(["page","key press field"], [self.page,keypress], [str,ButtonPressField]):
|
|
1052
|
+
return 1
|
|
1053
|
+
elif keypress.c:
|
|
1054
|
+
return 1
|
|
1055
|
+
self.kys.append(keypress)
|
|
1056
|
+
return 0
|
|
1057
|
+
|
|
1058
|
+
def register_keys(self,*btns):
|
|
1059
|
+
for btn in btns:
|
|
1060
|
+
self.linkkey(btn)
|
|
1061
|
+
return 0
|
|
1062
|
+
|
|
1063
|
+
def setup(self,exec_before_flip=DummyCmd, ticks=DummyCmd, before_imgs=DummyCmd, custom_event_checker=DummyCmdArgs):
|
|
1064
|
+
if self.c:
|
|
1065
|
+
return 1
|
|
1066
|
+
if not callable(exec_before_flip):
|
|
1067
|
+
ErrorForm("Non-callable object recieved, exec_before_flip should be a callable", self.page, "106 CALLABILITY ERROR").call()
|
|
1068
|
+
return 1
|
|
1069
|
+
si=s(exec_before_flip)
|
|
1070
|
+
args=list(si.parameters)
|
|
1071
|
+
if len(args)!=0:
|
|
1072
|
+
ErrorForm(f"exec_before_flip does not conform to standards: should accept no arguments", self.page, type="107 ARGUMENT ERROR").call()
|
|
1073
|
+
return 1
|
|
1074
|
+
|
|
1075
|
+
if not callable(ticks):
|
|
1076
|
+
ErrorForm("Non-callable object recieved, clock ticks function should be a callable", self.page, "106 CALLABILITY ERROR").call()
|
|
1077
|
+
return 1
|
|
1078
|
+
si=s(ticks)
|
|
1079
|
+
args=list(si.parameters)
|
|
1080
|
+
if len(args)!=0:
|
|
1081
|
+
ErrorForm(f"clock ticks function does not conform to standards: should accept no arguments", self.page, type="107 ARGUMENT ERROR").call()
|
|
1082
|
+
return 1
|
|
1083
|
+
|
|
1084
|
+
if not callable(before_imgs):
|
|
1085
|
+
ErrorForm("Non-callable object recieved, before drawing images function should be a callable", self.page, "106 CALLABILITY ERROR").call()
|
|
1086
|
+
return 1
|
|
1087
|
+
si=s(before_imgs)
|
|
1088
|
+
args=list(si.parameters)
|
|
1089
|
+
if len(args)!=0:
|
|
1090
|
+
ErrorForm(f"before drawing images function does not conform to standards: should accept no arguments", self.page, type="107 ARGUMENT ERROR").call()
|
|
1091
|
+
return 1
|
|
1092
|
+
|
|
1093
|
+
if not callable(custom_event_checker):
|
|
1094
|
+
ErrorForm("Non-callable object recieved, custom event checking function should be a callable", self.page, "106 CALLABILITY ERROR").call()
|
|
1095
|
+
return 1
|
|
1096
|
+
si=s(custom_event_checker)
|
|
1097
|
+
args=list(si.parameters)
|
|
1098
|
+
if len(args)!=1:
|
|
1099
|
+
ErrorForm(f"custom event checking function does not conform to standards: should accept event argument", self.page, type="107 ARGUMENT ERROR").call()
|
|
1100
|
+
return 1
|
|
1101
|
+
|
|
1102
|
+
self.ebf=exec_before_flip
|
|
1103
|
+
self.tks=ticks
|
|
1104
|
+
self.bim=before_imgs
|
|
1105
|
+
self.cec=custom_event_checker
|
|
1106
|
+
|
|
1107
|
+
def call(self):
|
|
1108
|
+
if self.c:
|
|
1109
|
+
return 1
|
|
1110
|
+
|
|
1111
|
+
self.mouse=pygame.mouse.get_pos()
|
|
1112
|
+
|
|
1113
|
+
self.tks()
|
|
1114
|
+
for event in pygame.event.get():
|
|
1115
|
+
if event.type==pygame.QUIT:
|
|
1116
|
+
self.exit=True
|
|
1117
|
+
elif event.type==pygame.KEYUP:
|
|
1118
|
+
for fld in self.kys:
|
|
1119
|
+
if event.key==fld.key and not fld.cont:
|
|
1120
|
+
fld.cmdr()
|
|
1121
|
+
elif event.type==pygame.KEYDOWN:
|
|
1122
|
+
for fld in self.kys:
|
|
1123
|
+
if event.key==fld.key and not fld.cont:
|
|
1124
|
+
fld.cmd()
|
|
1125
|
+
self.cec(event)
|
|
1126
|
+
keys=pygame.key.get_pressed()
|
|
1127
|
+
for fld in self.kys:
|
|
1128
|
+
if fld.cont and keys[fld.key]:
|
|
1129
|
+
fld.cmd()
|
|
1130
|
+
self.screen.fill(self.color)
|
|
1131
|
+
self.bim()
|
|
1132
|
+
for sprite in self.sprites:
|
|
1133
|
+
sprite.upd()
|
|
1134
|
+
sprite.call()
|
|
1135
|
+
self.ebf()
|
|
1136
|
+
pygame.display.flip()
|
|
1137
|
+
return 0
|
|
1138
|
+
|
|
1139
|
+
class ImageSprite:
|
|
1140
|
+
def __init__(self,embed,center, imgpath):
|
|
1141
|
+
self.c=ErrorHelper(["page", "path to image", "Pygame embedding", "center x", "center y"],["Sprite loader", imgpath,embed,center[0], center[1]],[str,str, PygameEmbedding, int,int])
|
|
1142
|
+
if not self.c:
|
|
1143
|
+
if "/" in imgpath:
|
|
1144
|
+
actpath=imgpath
|
|
1145
|
+
else:
|
|
1146
|
+
actpath=f"uploads/{imgpath}"
|
|
1147
|
+
try:
|
|
1148
|
+
self.img=pygame.image.load(actpath)
|
|
1149
|
+
except:
|
|
1150
|
+
self.c=True
|
|
1151
|
+
ErrorForm(f"Image {imgpath} was not found or had a wrong extension", "Sprite loader", "104 IMAGE ERROR").call()
|
|
1152
|
+
if embed.c:
|
|
1153
|
+
ErrorForm(f"Invalid CanvasEmbedding object: Object had an error", "Sprite loader","105 INSTANCE ERROR").call()
|
|
1154
|
+
self.c=self.c or embed.c
|
|
1155
|
+
|
|
1156
|
+
if not self.c:
|
|
1157
|
+
self.screen=embed.screen
|
|
1158
|
+
self.srect=embed.rect
|
|
1159
|
+
self.rect=self.img.get_rect()
|
|
1160
|
+
self.rect.center=center
|
|
1161
|
+
self.embed=embed
|
|
1162
|
+
self.moving=[False,False,False,False]
|
|
1163
|
+
self.pix=[0,0,0,0]
|
|
1164
|
+
self.x=float(self.rect.x)
|
|
1165
|
+
self.y=float(self.rect.y)
|
|
1166
|
+
|
|
1167
|
+
def call(self):
|
|
1168
|
+
if self.c:
|
|
1169
|
+
return 1
|
|
1170
|
+
self.screen.blit(self.img,self.rect)
|
|
1171
|
+
return 0
|
|
1172
|
+
|
|
1173
|
+
def toggle_move(self, pix,dire="left"):
|
|
1174
|
+
if self.c:
|
|
1175
|
+
return 1
|
|
1176
|
+
elif ErrorHelper(["page", "direction", "pixels"], [self.embed.page,dire,pix],[str, ["left", "right", "up", "down"], float]):
|
|
1177
|
+
return 1
|
|
1178
|
+
if dire=="left":
|
|
1179
|
+
self.moving[0]=not self.moving[0]
|
|
1180
|
+
self.pix[0]=pix
|
|
1181
|
+
elif dire=="right":
|
|
1182
|
+
self.moving[1]=not self.moving[1]
|
|
1183
|
+
self.pix[1]=pix
|
|
1184
|
+
elif dire=="up":
|
|
1185
|
+
self.moving[2]=not self.moving[2]
|
|
1186
|
+
self.pix[2]=pix
|
|
1187
|
+
elif dire=="down":
|
|
1188
|
+
self.moving[3]=not self.moving[3]
|
|
1189
|
+
self.pix[3]=pix
|
|
1190
|
+
return 0
|
|
1191
|
+
def upd(self):
|
|
1192
|
+
if self.c:
|
|
1193
|
+
return 1
|
|
1194
|
+
if self.moving[0] and self.rect.left>0:
|
|
1195
|
+
self.x-=self.pix[0]
|
|
1196
|
+
if self.moving[1] and self.rect.right<self.srect.right:
|
|
1197
|
+
self.x+=self.pix[1]
|
|
1198
|
+
if self.moving[2] and self.rect.top>0:
|
|
1199
|
+
self.y-=self.pix[2]
|
|
1200
|
+
if self.moving[3] and self.rect.bottom<self.srect.bottom:
|
|
1201
|
+
self.y+=self.pix[3]
|
|
1202
|
+
self.rect.x=self.x
|
|
1203
|
+
self.rect.y=self.y
|
|
1204
|
+
if self.rect.top<0:
|
|
1205
|
+
self.rect.top=0
|
|
1206
|
+
self.y=self.rect.y
|
|
1207
|
+
if self.rect.bottom>self.srect.bottom:
|
|
1208
|
+
self.rect.bottom=self.srect.bottom
|
|
1209
|
+
self.y=self.rect.y
|
|
1210
|
+
if self.rect.right>self.srect.right:
|
|
1211
|
+
self.rect.right=self.srect.right
|
|
1212
|
+
self.x=self.rect.x
|
|
1213
|
+
if self.rect.left<0:
|
|
1214
|
+
self.rect.left=0
|
|
1215
|
+
self.x=self.rect.x
|
|
1216
|
+
return 0
|
|
1217
|
+
|
|
1218
|
+
class ButtonPressField:
|
|
1219
|
+
def __init__(self, key, cmd,cmdr=DummyCmd, continuous=True):
|
|
1220
|
+
self.c=False
|
|
1221
|
+
if pygame.key.name(key)=="unknown key":
|
|
1222
|
+
self.c=True
|
|
1223
|
+
if not self.c:
|
|
1224
|
+
self.key=key
|
|
1225
|
+
self.cmd=cmd
|
|
1226
|
+
self.cmdr=cmdr
|
|
1227
|
+
self.cont=continuous
|
|
1228
|
+
|
|
1229
|
+
class ButtonFieldAdv:
|
|
1230
|
+
def __init__(self, embed, text, width, height, begin_x, begin_y,on_click,color=(150,150,200), text_color=(255,255,255), fonttype=None, fontsize=48, begin_state=0):
|
|
1231
|
+
if fonttype==None:
|
|
1232
|
+
fonttype=""
|
|
1233
|
+
self.c=ErrorHelper(["page", "Pygame embedding", "text","width","height","red button color", "green button color","blue button color","red text color","green text color","blue text color","font type","font size", "begin x coordinate", "begin y coordinate","begin state"],["Button loader", embed,text,width,height,color[0],color[1],color[2],text_color[0],text_color[1],text_color[2], fonttype,fontsize, begin_x,begin_y,begin_state],[str, PygameEmbedding,str,int,int,int,int,int,int,int,int,str,int,int,int, [0,1,2]])
|
|
1234
|
+
if not callable(on_click):
|
|
1235
|
+
ErrorForm("Non-callable object recieved, on_click should be a callable", self.page, "106 CALLABILITY ERROR").call()
|
|
1236
|
+
self.c=True
|
|
1237
|
+
if not self.c:
|
|
1238
|
+
if fonttype=="":
|
|
1239
|
+
fonttype=None
|
|
1240
|
+
self.ft=fonttype
|
|
1241
|
+
self.embed=embed
|
|
1242
|
+
self.color=color
|
|
1243
|
+
self.width=width
|
|
1244
|
+
self.height=height
|
|
1245
|
+
self.tc=text_color
|
|
1246
|
+
self.font=pygame.font.SysFont(fonttype,fontsize)
|
|
1247
|
+
self.screen=embed.screen
|
|
1248
|
+
self.srect=embed.rect
|
|
1249
|
+
self.text=text
|
|
1250
|
+
self.rect=pygame.Rect(0,0,self.width,self.height)
|
|
1251
|
+
self.rect.topleft=(begin_x, begin_y)
|
|
1252
|
+
self.oc=on_click
|
|
1253
|
+
self.state=begin_state
|
|
1254
|
+
self.pressed=False
|
|
1255
|
+
self._prep_msg(text)
|
|
1256
|
+
|
|
1257
|
+
def _prep_msg(self,msg):
|
|
1258
|
+
self.mimg=self.font.render(msg, True, self.tc, self.color)
|
|
1259
|
+
self.mimgrect = self.mimg.get_rect()
|
|
1260
|
+
self.mimgrect.center=self.rect.center
|
|
1261
|
+
return 0
|
|
1262
|
+
|
|
1263
|
+
def change_text(self,nxt):
|
|
1264
|
+
self.c=ErrorHelper(["page","new text"], ["Pygame Button Text Changer", nxt], [str,str])
|
|
1265
|
+
if self.c:
|
|
1266
|
+
return 1
|
|
1267
|
+
self._prep_msg(nxt)
|
|
1268
|
+
self.text=nxt
|
|
1269
|
+
|
|
1270
|
+
def call(self):
|
|
1271
|
+
if self.c:
|
|
1272
|
+
return 1
|
|
1273
|
+
if self.state!=2:
|
|
1274
|
+
self.screen.fill(self.color,self.rect)
|
|
1275
|
+
self.screen.blit(self.mimg, self.mimgrect)
|
|
1276
|
+
return 0
|
|
1277
|
+
|
|
1278
|
+
def upd(self):
|
|
1279
|
+
if self.c:
|
|
1280
|
+
return 1
|
|
1281
|
+
if self.rect.collidepoint(self.embed.mouse) and self.state==0 and pygame.mouse.get_pressed()[0] and not self.pressed:
|
|
1282
|
+
self.pressed=True
|
|
1283
|
+
return 2
|
|
1284
|
+
if self.rect.collidepoint(self.embed.mouse) and self.state==0 and not pygame.mouse.get_pressed()[0] and self.pressed:
|
|
1285
|
+
self.pressed=False
|
|
1286
|
+
self.oc()
|
|
1287
|
+
return 0
|
|
1288
|
+
|
|
1289
|
+
def disable(self):
|
|
1290
|
+
self.state=1
|
|
1291
|
+
|
|
1292
|
+
def enable(self):
|
|
1293
|
+
self.state=0
|
|
1294
|
+
|
|
1295
|
+
def off(self):
|
|
1296
|
+
self.state=2
|
|
1297
|
+
|
|
1298
|
+
class TextFieldExp:
|
|
1299
|
+
def __init__(self, embed, text, begin_x, begin_y,color=(230,230,230), text_color=(255,255,255), fonttype=None, fontsize=48, begin_state=0, nobg=0):
|
|
1300
|
+
if fonttype==None:
|
|
1301
|
+
fonttype=""
|
|
1302
|
+
self.c=ErrorHelper(["page", "Pygame embedding", "text","red outside color", "green outside color","blue outside color","red text color","green text color","blue text color","font type","font size", "begin x coordinate", "begin y coordinate","begin state", "no background"],["Text loader", embed,text,color[0],color[1],color[2],text_color[0],text_color[1],text_color[2], fonttype,fontsize, begin_x,begin_y,begin_state, nobg],[str, PygameEmbedding,str,int,int,int,int,int,int,str,int,int,int, [0,1], [0,1]])
|
|
1303
|
+
if not self.c:
|
|
1304
|
+
if fonttype=="":
|
|
1305
|
+
fonttype=None
|
|
1306
|
+
self.ft=fonttype
|
|
1307
|
+
self.embed=embed
|
|
1308
|
+
self.color=color
|
|
1309
|
+
self.tc=text_color
|
|
1310
|
+
self.font=pygame.font.SysFont(fonttype,fontsize)
|
|
1311
|
+
self.screen=embed.screen
|
|
1312
|
+
self.srect=embed.rect
|
|
1313
|
+
self.text=text
|
|
1314
|
+
self.tl=(begin_x,begin_y)
|
|
1315
|
+
self.state=begin_state
|
|
1316
|
+
self.nobg=nobg
|
|
1317
|
+
self._prep_msg(text)
|
|
1318
|
+
|
|
1319
|
+
def _prep_msg(self,msg):
|
|
1320
|
+
if self.nobg:
|
|
1321
|
+
self.mimg=self.font.render(msg, True, self.tc)
|
|
1322
|
+
else:
|
|
1323
|
+
self.mimg=self.font.render(msg, True, self.tc, self.color)
|
|
1324
|
+
self.mimgrect = self.mimg.get_rect()
|
|
1325
|
+
self.mimgrect.topleft=self.tl
|
|
1326
|
+
return 0
|
|
1327
|
+
|
|
1328
|
+
def change_text(self,nxt):
|
|
1329
|
+
self.c=ErrorHelper(["page","new text"], ["Pygame Text Changer", nxt], [str,str])
|
|
1330
|
+
if self.c:
|
|
1331
|
+
return 1
|
|
1332
|
+
self.text=nxt
|
|
1333
|
+
self._prep_msg(nxt)
|
|
1334
|
+
|
|
1335
|
+
def call(self):
|
|
1336
|
+
if self.c:
|
|
1337
|
+
return 1
|
|
1338
|
+
if self.state==0:
|
|
1339
|
+
self.screen.blit(self.mimg, self.mimgrect)
|
|
1340
|
+
return 0
|
|
1341
|
+
|
|
1342
|
+
def on(self):
|
|
1343
|
+
self.state=0
|
|
1344
|
+
|
|
1345
|
+
def off(self):
|
|
1346
|
+
self.state=1
|
|
1347
|
+
|
|
1348
|
+
class Music:
|
|
1349
|
+
def __init__(self, embed, filepath, type="sound", permanent=0, volume=0.5):
|
|
1350
|
+
self.c=ErrorHelper(["page", "pygame embedding", "music type", "permanent music", "path to file", "volume"], ["Music loader and player", embed, type, permanent,filepath, volume], [str, PygameEmbedding, ["music", "sound"], [0,1],str, float])
|
|
1351
|
+
if not self.c:
|
|
1352
|
+
if "/" in filepath:
|
|
1353
|
+
actpath=filepath
|
|
1354
|
+
else:
|
|
1355
|
+
actpath=f"uploads/{filepath}"
|
|
1356
|
+
try:
|
|
1357
|
+
if type=="music":
|
|
1358
|
+
snd=pygame.mixer.music.load(actpath)
|
|
1359
|
+
elif type=="sound":
|
|
1360
|
+
snd=pygame.mixer.Sound(actpath)
|
|
1361
|
+
except:
|
|
1362
|
+
self.c=True
|
|
1363
|
+
ErrorForm(f"Sound {filepath} was not found or had a wrong extension", "Sound loader", "108 SOUND ERROR").call()
|
|
1364
|
+
if not self.c:
|
|
1365
|
+
self.type=type
|
|
1366
|
+
self.sound=snd
|
|
1367
|
+
self.permanent=permanent
|
|
1368
|
+
self.volume=volume
|
|
1369
|
+
|
|
1370
|
+
def call(self):
|
|
1371
|
+
if self.c:
|
|
1372
|
+
return 1
|
|
1373
|
+
if self.type=="music":
|
|
1374
|
+
pygame.mixer.music.set_volume(self.volume)
|
|
1375
|
+
if self.permanent:
|
|
1376
|
+
pygame.mixer.music.play(-1)
|
|
1377
|
+
else:
|
|
1378
|
+
pygame.mixer.music.play()
|
|
1379
|
+
else:
|
|
1380
|
+
self.sound.set_volume(self.volume)
|
|
1381
|
+
self.sound.play()
|
|
1382
|
+
|
|
1383
|
+
return 0
|
|
1384
|
+
|
|
1385
|
+
def newvolume(self, volume):
|
|
1386
|
+
self.c=self.c or ErrorHelper(["page", "volume"], ["Sound changer", volume], [str, float])
|
|
1387
|
+
if self.c:
|
|
1388
|
+
return 1
|
|
1389
|
+
self.volume=volume
|
|
1390
|
+
if self.type=="music":
|
|
1391
|
+
pygame.mixer.music.set_volume(volume)
|
|
1392
|
+
else:
|
|
1393
|
+
self.sound.set_volume(self.volume)
|
|
1394
|
+
class Slider:
|
|
1395
|
+
def __init__(self, embed, pos, size, limit, slidercolor, rectcolor, initialpercentage=0):
|
|
1396
|
+
self.c=ErrorHelper(["page", "pygame embedding", "position", "x coordinate", "y coordinate", "size", "limit", "slider color", "slider color red", "slider color green", "slider color blue", "rect color", "rect color red", "rect color green", "rect color blue", "initial percentage"],["Slider loader", embed, pos, pos[0],pos[1], size, limit, slidercolor, slidercolor[0], slidercolor[1], slidercolor[2], rectcolor, rectcolor[0], rectcolor[1], rectcolor[2], initialpercentage],[str, PygameEmbedding, tuple, int, int, int, int, tuple, int, int, int, tuple, int, int, int, float])
|
|
1397
|
+
if not self.c:
|
|
1398
|
+
self.track=pygame.Rect(pos, (limit-pos[0]+size, size+4))
|
|
1399
|
+
self.slidecirclepos=(self.track.midleft[0]+size/2, self.track.midleft[1])
|
|
1400
|
+
self.slidecircleradius=size/2
|
|
1401
|
+
self.held=False
|
|
1402
|
+
self.embed=embed
|
|
1403
|
+
self.slider_color=slidercolor
|
|
1404
|
+
self.rect_color=rectcolor
|
|
1405
|
+
self.size=size
|
|
1406
|
+
self.limit=(self.track.midleft[0]+size/2, self.track.midright[0]-size/2)
|
|
1407
|
+
self.slidecirclepos=(min(max(self.limit[0]+initialpercentage*(self.limit[1]-self.limit[0]), self.limit[0]), self.limit[1]), self.slidecirclepos[1])
|
|
1408
|
+
|
|
1409
|
+
def call(self):
|
|
1410
|
+
if self.c:
|
|
1411
|
+
return 2
|
|
1412
|
+
mouse=self.embed.mouse
|
|
1413
|
+
if self.held:
|
|
1414
|
+
self.slidecirclepos=(min(max(mouse[0], self.limit[0]), self.limit[1]), self.slidecirclepos[1])
|
|
1415
|
+
pygame.draw.rect(self.embed.screen, self.rect_color, self.track, border_radius=int(2+self.size/2))
|
|
1416
|
+
pygame.draw.circle(self.embed.screen, self.slider_color, self.slidecirclepos, self.slidecircleradius)
|
|
1417
|
+
if pygame.mouse.get_pressed()[0] and (mouse[0]-self.slidecirclepos[0])**2+(mouse[1]-self.slidecirclepos[1])**2<=self.slidecircleradius**2:
|
|
1418
|
+
self.held=True
|
|
1419
|
+
else:
|
|
1420
|
+
self.held=False
|
|
1421
|
+
return (self.slidecirclepos[0]-self.limit[0])/(self.limit[1]-self.limit[0])
|
|
1422
|
+
|
|
1423
|
+
class PygameObjectGroup:
|
|
1424
|
+
AVAILABLE_TYPES=[ImageSprite, ButtonFieldAdv, TextFieldExp, Music, Slider]
|
|
1425
|
+
def __init__(self, embed, togroup):
|
|
1426
|
+
self.c=ErrorHelper(["page", "pygame embedding"], ["Pygame group creator", embed], [str, PygameEmbedding])
|
|
1427
|
+
if not self.c:
|
|
1428
|
+
self.grouped=[]
|
|
1429
|
+
for obj in togroup:
|
|
1430
|
+
calc=0
|
|
1431
|
+
for type_ in self.AVAILABLE_TYPES:
|
|
1432
|
+
if not isinstance(obj, type_):
|
|
1433
|
+
calc+=1
|
|
1434
|
+
if calc==len(self.AVAILABLE_TYPES):
|
|
1435
|
+
ErrorForm(f"Invalid type for subargument of argument togroup: Can't group object of type {(obj).__class__} into a group", "100 INTERNAL ERROR").call()
|
|
1436
|
+
elif obj.c:
|
|
1437
|
+
ErrorForm(f"Invalid state for subargument of argument togroup: Can't group errored object {obj} of type {(obj).__class__} into a group", "100 INTERNAL ERROR").call()
|
|
1438
|
+
else:
|
|
1439
|
+
self.grouped.append(obj)
|
|
1440
|
+
def off_all(self):
|
|
1441
|
+
for obj in self.grouped:
|
|
1442
|
+
objclass=(obj).__class__
|
|
1443
|
+
if objclass==TextFieldExp or objclass==ButtonFieldAdv:
|
|
1444
|
+
obj.off()
|
|
1445
|
+
elif objclass==Music:
|
|
1446
|
+
obj.newvolume(0.0)
|
|
1447
|
+
|
|
1448
|
+
def on_all(self):
|
|
1449
|
+
for obj in self.grouped:
|
|
1450
|
+
objclass=(obj).__class__
|
|
1451
|
+
if objclass==TextFieldExp:
|
|
1452
|
+
obj.on()
|
|
1453
|
+
elif objclass==ButtonFieldAdv:
|
|
1454
|
+
obj.enable()
|
|
1455
|
+
elif objclass==Music:
|
|
1456
|
+
obj.newvolume(1.0)
|
|
1457
|
+
|
|
1458
|
+
def disable_all(self):
|
|
1459
|
+
for obj in self.grouped:
|
|
1460
|
+
objclass=(obj).__class__
|
|
1461
|
+
if objclass==ButtonFieldAdv:
|
|
1462
|
+
obj.disable()
|
|
1463
|
+
|
|
1464
|
+
def call(self):
|
|
1465
|
+
values=[]
|
|
1466
|
+
for obj in self.grouped:
|
|
1467
|
+
values.append(obj.call())
|
|
1468
|
+
return values
|
|
1469
|
+
|
|
1470
|
+
|