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 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.9"
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 = 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._x0 / scale
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._x0 + self._x1) / 2) / scale
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._x1 / scale
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._y1 / scale
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._y0 + self._y1) / 2) / scale
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._y0 / scale
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 = 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
  )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: salabim
3
- Version: 25.0.9.post4
3
+ Version: 25.0.10
4
4
  Summary: salabim - discrete event simulation in Python
5
5
  Author-email: Ruud van der Ham <rt.van.der.ham@gmail.com>
6
6
  Project-URL: Homepage, https://salabim.org
@@ -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,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.3.1)
2
+ Generator: setuptools (80.9.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -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,,