salabim 25.0.9.post4__py3-none-any.whl → 25.0.10__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.
- salabim/salabim.py +109 -22
- {salabim-25.0.9.post4.dist-info → salabim-25.0.10.dist-info}/METADATA +1 -1
- salabim-25.0.10.dist-info/RECORD +10 -0
- {salabim-25.0.9.post4.dist-info → salabim-25.0.10.dist-info}/WHEEL +1 -1
- salabim-25.0.9.post4.dist-info/RECORD +0 -10
- {salabim-25.0.9.post4.dist-info → salabim-25.0.10.dist-info}/top_level.txt +0 -0
salabim/salabim.py
CHANGED
@@ -7,7 +7,7 @@
|
|
7
7
|
#
|
8
8
|
# see www.salabim.org for more information, the documentation and license information
|
9
9
|
|
10
|
-
__version__ = "25.0.
|
10
|
+
__version__ = "25.0.10"
|
11
11
|
import heapq
|
12
12
|
import random
|
13
13
|
import time
|
@@ -43,7 +43,6 @@ import base64
|
|
43
43
|
import zipfile
|
44
44
|
from pathlib import Path
|
45
45
|
|
46
|
-
|
47
46
|
from typing import Any, Union, Iterable, Tuple, List, Callable, TextIO, Dict, Set, Type, Hashable, Optional
|
48
47
|
|
49
48
|
dataframe = None # to please PyLance
|
@@ -52,6 +51,7 @@ ColorType = Union[str, Iterable[float]]
|
|
52
51
|
|
53
52
|
Pythonista = sys.platform == "ios"
|
54
53
|
Windows = sys.platform.startswith("win")
|
54
|
+
MacOS = platform.system == "Darwin"
|
55
55
|
PyPy = platform.python_implementation() == "PyPy"
|
56
56
|
Chromebook = "penguin" in platform.uname()
|
57
57
|
Xlwings = "xlwings" in sys.modules
|
@@ -110,6 +110,7 @@ def a_log(*args):
|
|
110
110
|
|
111
111
|
class g: ...
|
112
112
|
|
113
|
+
|
113
114
|
if Pythonista:
|
114
115
|
try:
|
115
116
|
import scene # type: ignore
|
@@ -3662,14 +3663,6 @@ class AnimateMonitor(DynamicClass):
|
|
3662
3663
|
if False, animation monitor is not shown, shown otherwise
|
3663
3664
|
(default True)
|
3664
3665
|
|
3665
|
-
screen_coordinates : bool
|
3666
|
-
use screen_coordinates
|
3667
|
-
|
3668
|
-
if False, the scale parameters are use for positioning and scaling
|
3669
|
-
objects.
|
3670
|
-
|
3671
|
-
if True (default), screen_coordinates will be used.
|
3672
|
-
|
3673
3666
|
Note
|
3674
3667
|
----
|
3675
3668
|
All measures are in screen coordinates
|
@@ -3716,7 +3709,6 @@ class AnimateMonitor(DynamicClass):
|
|
3716
3709
|
layer: Union[float, Callable] = 0,
|
3717
3710
|
visible: Union[bool, Callable] = True,
|
3718
3711
|
keep: Union[bool, Callable] = True,
|
3719
|
-
screen_coordinates: bool = True,
|
3720
3712
|
arg: Any = None,
|
3721
3713
|
):
|
3722
3714
|
super().__init__()
|
@@ -3775,7 +3767,7 @@ class AnimateMonitor(DynamicClass):
|
|
3775
3767
|
self._monitor = monitor
|
3776
3768
|
self.as_level = monitor._level
|
3777
3769
|
self.over3d = over3d
|
3778
|
-
self.screen_coordinates =
|
3770
|
+
self.screen_coordinates = True
|
3779
3771
|
self.register_dynamic_attributes(
|
3780
3772
|
"linecolor linewidth fillcolor bordercolor borderlinewidth titlecolor nowcolor titlefont titlefontsize title "
|
3781
3773
|
"x y offsetx offsety angle vertical_offset parent vertical_scale horizontal_scale width height "
|
@@ -7234,7 +7226,7 @@ by adding at the end:
|
|
7234
7226
|
"""
|
7235
7227
|
size_x = 50
|
7236
7228
|
size_y = 50
|
7237
|
-
ao0 = AnimateRectangle(text=str(self.sequence_number()), textcolor="bg", spec=(-20, -20, 20, 20), linewidth=0, fillcolor="fg")
|
7229
|
+
ao0 = AnimateRectangle(text=str(self.sequence_number()), textcolor="bg", spec=(-20, -20, 20, 20), linewidth=0, fillcolor="fg", screen_coordinates=True)
|
7238
7230
|
return (size_x, size_y, ao0)
|
7239
7231
|
|
7240
7232
|
def animation3d_objects(self, id: Any) -> Tuple:
|
@@ -10583,6 +10575,8 @@ class Environment:
|
|
10583
10575
|
self._step_pressed = False
|
10584
10576
|
self.stopped = False
|
10585
10577
|
self._paused = False
|
10578
|
+
self._zoom_factor = 1.1
|
10579
|
+
|
10586
10580
|
self.last_s0 = ""
|
10587
10581
|
if Xlwings:
|
10588
10582
|
if blind_animation is None:
|
@@ -10711,6 +10705,23 @@ class Environment:
|
|
10711
10705
|
"""
|
10712
10706
|
if self._ui:
|
10713
10707
|
self._handle_ui_event()
|
10708
|
+
self._x0_org = self._x0
|
10709
|
+
self._x1_org = self._x1
|
10710
|
+
self._y0_org = self._y0
|
10711
|
+
self._y1_org = self._y1
|
10712
|
+
self._scale_org = self._scale
|
10713
|
+
self._x0 = self._x0z
|
10714
|
+
self._y0 = self._y0z
|
10715
|
+
self._x1 = self._x1z # 0+self._width/self._scale
|
10716
|
+
self._y1 = self._y1z # +self._height/self._scale
|
10717
|
+
self._scale = self._scalez
|
10718
|
+
|
10719
|
+
# midx=self._x0+self._panx*(self._x1-self._x0)
|
10720
|
+
# self._x0, self._x1= midx-(1/self._zoom)*(self._x1-self._x0)/2,midx+(1/self._zoom)*(self._x1-self._x0)/2
|
10721
|
+
|
10722
|
+
# midy=self._y0+self._pany*(self._y1-self._y0)
|
10723
|
+
# self._y0, self._y1 = midy-(1/self._zoom)*(self._y1-self._y0)/2, midy+(1/self._zoom)*(self._y1-self._y0)/2
|
10724
|
+
# self._scale = self._width / (self._x1 - self._x0)
|
10714
10725
|
|
10715
10726
|
def animation_post_tick(self, t: float) -> None:
|
10716
10727
|
"""
|
@@ -10723,7 +10734,11 @@ class Environment:
|
|
10723
10734
|
t : float
|
10724
10735
|
Current (animation) time.
|
10725
10736
|
"""
|
10726
|
-
|
10737
|
+
self._x0 = self._x0_org
|
10738
|
+
self._x1 = self._x1_org
|
10739
|
+
self._y0 = self._y0_org
|
10740
|
+
self._y1 = self._y1_org
|
10741
|
+
self._scale = self._scale
|
10727
10742
|
|
10728
10743
|
def animation_pre_tick_sys(self, t: float) -> None:
|
10729
10744
|
for ao in self.sys_objects.copy(): # copy required as ao's may be removed due to keep
|
@@ -11248,6 +11263,63 @@ class Environment:
|
|
11248
11263
|
def on_closing(self):
|
11249
11264
|
self.an_quit()
|
11250
11265
|
|
11266
|
+
|
11267
|
+
def on_mousewheel(self, event):
|
11268
|
+
x_mouse = self.root.winfo_pointerx() - self.root.winfo_rootx()
|
11269
|
+
y_mouse = self.height() - self.root.winfo_pointery() + self.root.winfo_rooty()
|
11270
|
+
x = (x_mouse / self._scale) + self._x0z
|
11271
|
+
y = (y_mouse / self._scale) + self._y0z
|
11272
|
+
|
11273
|
+
if Windows:
|
11274
|
+
delta = int(event.delta / 120) # normalize to ticks
|
11275
|
+
elif MacOS:
|
11276
|
+
delta = int(event.delta) # already small, usually ±1
|
11277
|
+
else:
|
11278
|
+
delta = 0 # fallback
|
11279
|
+
for _ in range(abs(delta)):
|
11280
|
+
if delta < 0:
|
11281
|
+
zoom_factor = self._zoom_factor
|
11282
|
+
|
11283
|
+
else:
|
11284
|
+
zoom_factor = 1 / self._zoom_factor
|
11285
|
+
|
11286
|
+
# min_zoom = min(
|
11287
|
+
# (self._x0 - x) / (self._x0z - x),
|
11288
|
+
# (self._x0 - x) / (self._x0z - x),
|
11289
|
+
# (self._x1 - x) / (self._x1z - x),
|
11290
|
+
# (self._y0 - y) / (self._y0z - y),
|
11291
|
+
# (self._y1 - y) / (self._y1z - y),
|
11292
|
+
# )
|
11293
|
+
|
11294
|
+
# zoom_factor = min(zoom_factor, min_zoom)
|
11295
|
+
|
11296
|
+
self._scalez /= zoom_factor
|
11297
|
+
self._x0z = x - (x - self._x0z) * zoom_factor
|
11298
|
+
self._y0z = y - (y - self._y0z) * zoom_factor
|
11299
|
+
self._x1z = x - (x - self._x1z) * zoom_factor
|
11300
|
+
self._y1z = y - (y - self._y1z) * zoom_factor
|
11301
|
+
|
11302
|
+
def start_pan(self, event):
|
11303
|
+
g.canvas.config(cursor="fleur") # Change cursor to "move" style
|
11304
|
+
self.lastx = event.x
|
11305
|
+
self.lasty = event.y
|
11306
|
+
self.lastx0 = self._x0z
|
11307
|
+
self.lasty0 = self._y0z
|
11308
|
+
|
11309
|
+
def do_pan(self, event):
|
11310
|
+
dx = -((event.x - self.lastx) / self._scale)
|
11311
|
+
dy = ((event.y - self.lasty) / self._scale)
|
11312
|
+
# self._x0z = max(self._x0,self.lastx0 + dx)
|
11313
|
+
# self._y0z = max(self._y0,self.lasty0 + dy)
|
11314
|
+
self._x0z = self.lastx0 + dx
|
11315
|
+
self._y0z = self.lasty0 + dy
|
11316
|
+
self._x1z = self._x0z + (self._x1 - self._x0)
|
11317
|
+
self._y1z = self._y0z + (self._y1 - self._y0)
|
11318
|
+
|
11319
|
+
|
11320
|
+
def end_pan(self, event):
|
11321
|
+
g.canvas.config(cursor="") # Reset to default
|
11322
|
+
|
11251
11323
|
def animation_parameters(
|
11252
11324
|
self,
|
11253
11325
|
animate: Union[bool, str] = None,
|
@@ -11850,12 +11922,22 @@ class Environment:
|
|
11850
11922
|
self.root.bind("<space>", lambda self: g.animation_env.an_menu_go())
|
11851
11923
|
self.root.bind("s", lambda self: g.animation_env.an_single_step())
|
11852
11924
|
self.root.bind("<Control-c>", lambda self: g.animation_env.an_quit())
|
11925
|
+
self.root.bind("<MouseWheel>", self.on_mousewheel)
|
11926
|
+
self.root.bind("<ButtonPress-1>", self.start_pan)
|
11927
|
+
self.root.bind("<B1-Motion>", self.do_pan)
|
11928
|
+
self.root.bind("<ButtonRelease-1>", self.end_pan)
|
11929
|
+
|
11853
11930
|
|
11854
11931
|
g.canvas = tkinter.Canvas(self.root, width=self._width, height=self._height)
|
11855
11932
|
g.canvas.configure(background=self.colorspec_to_hex("bg", False))
|
11856
11933
|
g.canvas.pack()
|
11857
11934
|
g.canvas_objects = []
|
11858
11935
|
g.canvas_object_overflow_image = None
|
11936
|
+
|
11937
|
+
# g.canvas.move("all", 1, 1)
|
11938
|
+
# g.canvas.update()
|
11939
|
+
# g.canvas.move("all", -1, -1)
|
11940
|
+
# g.canvas.update()
|
11859
11941
|
|
11860
11942
|
self.uninstall_uios() # this causes all ui objects to be (re)installed
|
11861
11943
|
|
@@ -13313,6 +13395,12 @@ class Environment:
|
|
13313
13395
|
raise SimulationStopped
|
13314
13396
|
else:
|
13315
13397
|
self.root.after(0, self.simulate_and_animate_loop)
|
13398
|
+
self._x0z = self._x0
|
13399
|
+
self._y0z = self._y0
|
13400
|
+
self._x1z = self._x1
|
13401
|
+
self._y1z = self._y1
|
13402
|
+
|
13403
|
+
self._scalez = self._scale
|
13316
13404
|
self.root.mainloop()
|
13317
13405
|
if self._animate and self.running:
|
13318
13406
|
if self._video:
|
@@ -13822,19 +13910,19 @@ class Environment:
|
|
13822
13910
|
if screen_coordinates:
|
13823
13911
|
return 0
|
13824
13912
|
else:
|
13825
|
-
return self.
|
13913
|
+
return self._x0_org / scale
|
13826
13914
|
|
13827
13915
|
if xy_anchor in ("n", "c", "center", "s"):
|
13828
13916
|
if screen_coordinates:
|
13829
13917
|
return (width / 2) / scale
|
13830
13918
|
else:
|
13831
|
-
return ((self.
|
13919
|
+
return ((self._x0_org + self._x1_org) / 2) / scale
|
13832
13920
|
|
13833
13921
|
if xy_anchor in ("ne", "e", "se", ""):
|
13834
13922
|
if screen_coordinates:
|
13835
13923
|
return width / scale
|
13836
13924
|
else:
|
13837
|
-
return self.
|
13925
|
+
return self._x1_org / scale
|
13838
13926
|
|
13839
13927
|
raise ValueError("incorrect xy_anchor", xy_anchor)
|
13840
13928
|
|
@@ -13849,19 +13937,19 @@ class Environment:
|
|
13849
13937
|
if screen_coordinates:
|
13850
13938
|
return height / scale
|
13851
13939
|
else:
|
13852
|
-
return self.
|
13940
|
+
return self._y1_org / scale
|
13853
13941
|
|
13854
13942
|
if xy_anchor in ("w", "c", "center", "e"):
|
13855
13943
|
if screen_coordinates:
|
13856
13944
|
return (height / 2) / scale
|
13857
13945
|
else:
|
13858
|
-
return ((self.
|
13946
|
+
return ((self._y0_org + self._y1_org) / 2) / scale
|
13859
13947
|
|
13860
13948
|
if xy_anchor in ("sw", "s", "se", ""):
|
13861
13949
|
if screen_coordinates:
|
13862
13950
|
return 0
|
13863
13951
|
else:
|
13864
|
-
return self.
|
13952
|
+
return self._y0_org / scale
|
13865
13953
|
|
13866
13954
|
raise ValueError("incorrect xy_anchor", xy_anchor)
|
13867
13955
|
|
@@ -18124,7 +18212,6 @@ class AnimateQueue(DynamicClass):
|
|
18124
18212
|
over3d=None,
|
18125
18213
|
keep=True,
|
18126
18214
|
visible=True,
|
18127
|
-
screen_coordinates=True,
|
18128
18215
|
):
|
18129
18216
|
super().__init__()
|
18130
18217
|
_checkisqueue(queue)
|
@@ -18155,7 +18242,7 @@ class AnimateQueue(DynamicClass):
|
|
18155
18242
|
self.keep = keep
|
18156
18243
|
self.over3d = _default_over3d if over3d is None else over3d
|
18157
18244
|
self.trajectory = trajectory
|
18158
|
-
self.screen_coordinates =
|
18245
|
+
self.screen_coordinates = True
|
18159
18246
|
self.register_dynamic_attributes(
|
18160
18247
|
"xy_anchor x y id max_length direction reverse titleoffsetx titleoffsety titlefont titlefontsize titlecolor title layer visible keep trajectory"
|
18161
18248
|
)
|
@@ -0,0 +1,10 @@
|
|
1
|
+
salabim/DejaVuSansMono.ttf,sha256=Z_oIXp5yp1Zaw2y2p3vaxwHhjHpG0MFbmwhxSh4aIEI,335068
|
2
|
+
salabim/LICENSE.txt,sha256=eTPlcDJz4G0096Qv-wfMjm1Wxbd4ilDlsYg5rN4HjWQ,1106
|
3
|
+
salabim/__init__.py,sha256=r7qPLvlmX0dkZDyjuTo8Jo3ex3sD1L4pmK6K5ib9vyw,56
|
4
|
+
salabim/calibri.ttf,sha256=RWpf8Uo31RfvGGNaSt9-2sXSuN87AVE_NFMRsV3LhBk,1330156
|
5
|
+
salabim/mplus-1m-regular.ttf,sha256=EuFHr90BJjuAn_r5MleJFN-WfkeWJ4tf7DweI5zr8tU,289812
|
6
|
+
salabim/salabim.py,sha256=j8z-zIxsbamnr5aghJLzKffv-lzCnXhAkyo3O1nNLGk,1124813
|
7
|
+
salabim-25.0.10.dist-info/METADATA,sha256=0mIkvZXvdvJxlOBnmZta4du6Nf6MhQuiGnfsqgL4iwA,3400
|
8
|
+
salabim-25.0.10.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
9
|
+
salabim-25.0.10.dist-info/top_level.txt,sha256=UE6zVlbi3F6T5ma1a_5TrojMaF21GYKDt9svvm0U4cQ,8
|
10
|
+
salabim-25.0.10.dist-info/RECORD,,
|
@@ -1,10 +0,0 @@
|
|
1
|
-
salabim/DejaVuSansMono.ttf,sha256=Z_oIXp5yp1Zaw2y2p3vaxwHhjHpG0MFbmwhxSh4aIEI,335068
|
2
|
-
salabim/LICENSE.txt,sha256=eTPlcDJz4G0096Qv-wfMjm1Wxbd4ilDlsYg5rN4HjWQ,1106
|
3
|
-
salabim/__init__.py,sha256=r7qPLvlmX0dkZDyjuTo8Jo3ex3sD1L4pmK6K5ib9vyw,56
|
4
|
-
salabim/calibri.ttf,sha256=RWpf8Uo31RfvGGNaSt9-2sXSuN87AVE_NFMRsV3LhBk,1330156
|
5
|
-
salabim/mplus-1m-regular.ttf,sha256=EuFHr90BJjuAn_r5MleJFN-WfkeWJ4tf7DweI5zr8tU,289812
|
6
|
-
salabim/salabim.py,sha256=hL-5b2WhppIVwwldm-O5-pCFOEHRoFt1DhoIhCHf9-w,1121320
|
7
|
-
salabim-25.0.9.post4.dist-info/METADATA,sha256=t2mmahEmxd0puFxYki_G4vcb1k05dVyw9F-IQuNjs2A,3405
|
8
|
-
salabim-25.0.9.post4.dist-info/WHEEL,sha256=0CuiUZ_p9E4cD6NyLD6UG80LBXYyiSYZOKDm5lp32xk,91
|
9
|
-
salabim-25.0.9.post4.dist-info/top_level.txt,sha256=UE6zVlbi3F6T5ma1a_5TrojMaF21GYKDt9svvm0U4cQ,8
|
10
|
-
salabim-25.0.9.post4.dist-info/RECORD,,
|
File without changes
|