mwxlib 0.96.8__py3-none-any.whl → 0.97.1__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.

Potentially problematic release.


This version of mwxlib might be problematic. Click here for more details.

mwx/bookshelf.py CHANGED
@@ -1,8 +1,8 @@
1
1
  #! python3
2
- from functools import partial
3
2
  import re
4
3
  import wx
5
4
 
5
+ from .utilus import funcall as _F
6
6
  from .framework import CtrlInterface, postcall
7
7
 
8
8
 
@@ -20,7 +20,7 @@ class EditorTreeCtrl(wx.TreeCtrl, CtrlInterface):
20
20
  self.parent = parent
21
21
  self.target = None
22
22
 
23
- self.context = { # DNA<EditorTreeCtrl>
23
+ self.context = { # DNA<EditorBook>
24
24
  None : {
25
25
  'buffer_new' : [ None, self.on_buffer_new ],
26
26
  'buffer_saved' : [ None, ],
@@ -36,34 +36,38 @@ class EditorTreeCtrl(wx.TreeCtrl, CtrlInterface):
36
36
  self.Bind(wx.EVT_TREE_SEL_CHANGED, self.OnSelChanged)
37
37
  self.Bind(wx.EVT_WINDOW_DESTROY, self.OnDestroy)
38
38
 
39
- @self.handler.bind('enter pressed')
40
- def enter(evt):
39
+ def enter():
41
40
  data = self.GetItemData(self.Selection)
42
41
  if data:
43
42
  data.SetFocus()
44
43
 
45
- @self.handler.bind('f5 pressed')
46
- def refresh(evt, clear=False):
44
+ def refresh(clear=False):
47
45
  self.build_tree(clear)
48
- if self.target:
49
- self.target.current_editor.SetFocus()
50
- wx.CallAfter(self.SetFocus)
51
-
52
- self.handler.bind('S-f5 pressed', partial(refresh, clear=1))
46
+ wx.CallAfter(self.SetFocus)
53
47
 
54
- @self.handler.bind('delete pressed')
55
- def delete(evt):
48
+ def delete():
56
49
  data = self.GetItemData(self.Selection)
57
50
  if data:
58
51
  data.parent.kill_buffer(data) # -> focus moves
59
52
  wx.CallAfter(self.SetFocus)
60
53
 
61
- @self.handler.bind('*button* pressed')
62
- @self.handler.bind('*button* released')
63
54
  def dispatch(evt):
64
- """Fork mouse events to the parent."""
55
+ """Fork events to the parent."""
65
56
  self.parent.handler(self.handler.current_event, evt)
66
57
  evt.Skip()
58
+
59
+ self.handler.update({ # DNA<EditorTreeCtrl>
60
+ None : {
61
+ '*button* pressed' : [ None, dispatch ],
62
+ '*button* released' : [ None, dispatch ],
63
+ },
64
+ 0 : {
65
+ 'enter pressed' : (0, _F(enter)),
66
+ 'delete pressed' : (0, _F(delete)),
67
+ 'f5 pressed' : (0, _F(refresh, clear=0)),
68
+ 'S-f5 pressed' : (0, _F(refresh, clear=1)),
69
+ },
70
+ })
67
71
 
68
72
  def OnDestroy(self, evt):
69
73
  if evt.EventObject is self:
@@ -128,19 +132,18 @@ class EditorTreeCtrl(wx.TreeCtrl, CtrlInterface):
128
132
  ## Actions for bookshelf interfaces
129
133
  ## --------------------------------
130
134
 
131
- ## @postcall
132
135
  def on_buffer_new(self, buf):
133
136
  self.build_tree(clear=0)
134
137
 
135
- ## @postcall
136
138
  def on_buffer_deleted(self, buf):
137
139
  self.Delete(buf.__itemId)
138
140
 
141
+ ## Note: [buffer_activated][EVT_SET_FOCUS] > [buffer_new] の順で呼ばれる
142
+ ## buf.__itemId がない場合がある (delete_buffer 直後など)
139
143
  @postcall
140
144
  def on_buffer_selected(self, buf):
141
145
  self.SelectItem(buf.__itemId)
142
146
 
143
- @postcall
144
147
  def on_buffer_filename(self, buf):
145
148
  self.SetItemText(buf.__itemId, buf.caption_prefix + buf.name)
146
149
 
mwx/controls.py CHANGED
@@ -1225,7 +1225,7 @@ class Indicator(wx.Control):
1225
1225
  self.__value = int(v)
1226
1226
  self.Refresh()
1227
1227
 
1228
- def update_design(self, **kwargs):
1228
+ def redesign(self, **kwargs):
1229
1229
  """Update multiple design properties at once.
1230
1230
 
1231
1231
  This method is useful for changing colors, spacing, radius, etc.
mwx/framework.py CHANGED
@@ -1,7 +1,7 @@
1
1
  #! python3
2
2
  """mwxlib framework.
3
3
  """
4
- __version__ = "0.96.8"
4
+ __version__ = "0.97.1"
5
5
  __author__ = "Kazuya O'moto <komoto@jeol.co.jp>"
6
6
 
7
7
  from functools import wraps, partial
@@ -19,7 +19,7 @@ from wx import stc
19
19
  from wx.py import dispatcher
20
20
 
21
21
  from .utilus import funcall as _F
22
- from .utilus import get_rootpath, ignore, warn # noqa
22
+ from .utilus import get_rootpath, ignore, warn
23
23
  from .utilus import FSM, TreeList, apropos, typename, where, mro, pp
24
24
 
25
25
 
@@ -54,16 +54,15 @@ def deb(target=None, loop=True, locals=None, **kwargs):
54
54
  kwargs.setdefault("ensureClose", True)
55
55
 
56
56
  app = wx.GetApp() or wx.App()
57
- try:
58
- frame = ShellFrame(None, target, **kwargs)
59
- frame.Show()
60
- frame.rootshell.SetFocus()
61
- if locals:
62
- frame.rootshell.locals.update(locals)
57
+ frame = ShellFrame(None, target, **kwargs)
58
+ frame.Show()
59
+ frame.rootshell.SetFocus()
60
+ if locals:
61
+ frame.rootshell.locals.update(locals)
62
+ if not loop:
63
63
  return frame
64
- finally:
65
- if loop and not app.GetMainLoop():
66
- app.MainLoop()
64
+ if not app.GetMainLoop():
65
+ return app.MainLoop()
67
66
 
68
67
 
69
68
  def postcall(f):
@@ -159,7 +158,7 @@ _speckeys = {
159
158
 
160
159
  _speckeys_wxkmap = dict((v, k) for k, v in _speckeys.items())
161
160
 
162
- def keyspec(key):
161
+ def getKeyState(key):
163
162
  """Returns state of speckey (cf. wx.GetKeyState)."""
164
163
  try:
165
164
  return wx.GetKeyState(_speckeys_wxkmap[key])
@@ -193,10 +192,9 @@ def hotkey(evt):
193
192
 
194
193
 
195
194
  def regulate_key(key):
196
- return (key.replace("ctrl+", "C-") # modifier keys abbreviation
197
- .replace("alt+", "M-")
198
- .replace("shift+", "S-")
199
- .replace("win+", "win-")
195
+ return (key.replace("ctrl-", "C-") # modifier keys abbreviation
196
+ .replace("alt-", "M-")
197
+ .replace("shift-", "S-")
200
198
  .replace("M-C-", "C-M-") # modifier key regulation C-M-S-
201
199
  .replace("S-M-", "M-S-")
202
200
  .replace("S-C-", "C-S-"))
@@ -310,6 +308,11 @@ class KeyCtrlInterfaceMixin:
310
308
  else:
311
309
  self.handler.update({map: {key: [state, f]}})
312
310
  return action
311
+
312
+ @ignore(UserWarning)
313
+ def undefine_key(self, keymap):
314
+ """Delete [map key (pressed)] context."""
315
+ self.define_key(keymap, None)
313
316
 
314
317
 
315
318
  class CtrlInterface(KeyCtrlInterfaceMixin):
@@ -343,8 +346,8 @@ class CtrlInterface(KeyCtrlInterfaceMixin):
343
346
  self.Bind(wx.EVT_KILL_FOCUS, inactivate)
344
347
 
345
348
  self.Bind(wx.EVT_CHAR_HOOK, self.on_hotkey_press)
346
- self.Bind(wx.EVT_KEY_DOWN, self.on_hotkey_dndrag)
347
- self.Bind(wx.EVT_KEY_UP, self.on_hotkey_release)
349
+ self.Bind(wx.EVT_KEY_DOWN, self.on_hotkey_down)
350
+ self.Bind(wx.EVT_KEY_UP, self.on_hotkey_up)
348
351
 
349
352
  self.Bind(wx.EVT_MOUSEWHEEL, self.on_mousewheel)
350
353
 
@@ -376,20 +379,20 @@ class CtrlInterface(KeyCtrlInterfaceMixin):
376
379
  evt.Skip()
377
380
  return
378
381
  key = hotkey(evt)
379
- self.__key = regulate_key(key + '+')
382
+ self.__key = regulate_key(key + '-')
380
383
  if self.handler('{} pressed'.format(key), evt) is None:
381
384
  evt.Skip()
382
385
 
383
- def on_hotkey_dndrag(self, evt): #<wx._core.KeyEvent>
386
+ def on_hotkey_down(self, evt): #<wx._core.KeyEvent>
384
387
  """Called when a key is pressed while dragging.
385
388
  Specifically called when the mouse is being captured.
386
389
  """
387
390
  if self.__isDragging:
388
391
  self.on_hotkey_press(evt)
389
392
  else:
390
- evt.Skip() # for TextCtrl
393
+ evt.Skip()
391
394
 
392
- def on_hotkey_release(self, evt): #<wx._core.KeyEvent>
395
+ def on_hotkey_up(self, evt): #<wx._core.KeyEvent>
393
396
  """Called when a key is released."""
394
397
  key = hotkey(evt)
395
398
  self.__key = ''
@@ -408,7 +411,7 @@ class CtrlInterface(KeyCtrlInterfaceMixin):
408
411
  if self.handler('{} pressed'.format(evt.key), evt) is None:
409
412
  evt.Skip()
410
413
 
411
- def on_motion(self, evt):
414
+ def on_motion(self, evt): #<wx._core.MouseEvent>
412
415
  """Called on mouse motion events.
413
416
  Trigger event: 'key+[LMR]drag begin/motion/end'
414
417
  """
mwx/graphman.py CHANGED
@@ -214,13 +214,10 @@ class Thread(object):
214
214
  Use ``check`` method where you want to quit.
215
215
  """
216
216
  def _stop():
217
- try:
218
- busy = wx.BusyInfo("One moment please, "
219
- "waiting for threads to die...")
217
+ with wx.BusyInfo("One moment please, "
218
+ "waiting for threads to die..."):
220
219
  self.handler('thread_quit', self)
221
220
  self.worker.join(1)
222
- finally:
223
- del busy
224
221
  if self.running:
225
222
  self.active = 0
226
223
  wx.CallAfter(_stop) # main-thread で終了させる
@@ -685,7 +682,7 @@ class Frame(mwx.Frame):
685
682
  lambda v: self.save_frame(),
686
683
  lambda v: v.Enable(self.__view.frame is not None)),
687
684
 
688
- (wx.ID_SAVEAS, "&Save as TIFFs", "Save buffers as a statck-tiff", Icon('saveall'),
685
+ (wx.ID_SAVEAS, "&Save as TIFFs", "Save buffers as a multi-page tiff", Icon('saveall'),
689
686
  lambda v: self.save_buffers_as_tiffs(),
690
687
  lambda v: v.Enable(self.__view.frame is not None)),
691
688
  (),
@@ -831,6 +828,9 @@ class Frame(mwx.Frame):
831
828
 
832
829
  ## Accepts DnD
833
830
  self.SetDropTarget(MyFileDropLoader(self.graph, self))
831
+
832
+ ## Script editor for plugins (external call)
833
+ self.Editor = "notepad"
834
834
 
835
835
  sync_switch = True
836
836
 
@@ -845,17 +845,6 @@ class Frame(mwx.Frame):
845
845
  b.OnDraw(None)
846
846
  b.canvas.draw_idle()
847
847
 
848
- Editor = "notepad"
849
-
850
- @ignore(ResourceWarning)
851
- def edit(self, fn):
852
- if hasattr(fn, '__file__'):
853
- name, _ = os.path.splitext(fn.__file__)
854
- fn = name + '.py'
855
- cmd = '{} "{}"'.format(self.Editor, fn)
856
- subprocess.Popen(cmd)
857
- self.message(cmd)
858
-
859
848
  def set_title(self, frame):
860
849
  ssn = os.path.basename(self.session_file or '--')
861
850
  ssn, _ = os.path.splitext(ssn)
@@ -906,6 +895,8 @@ class Frame(mwx.Frame):
906
895
  evt.Skip()
907
896
 
908
897
  def Destroy(self):
898
+ ## for name in list(self.plugins):
899
+ ## self.unload_plug(name) # => plug.Destroy
909
900
  self._mgr.UnInit()
910
901
  return mwx.Frame.Destroy(self)
911
902
 
@@ -1302,48 +1293,39 @@ class Frame(mwx.Frame):
1302
1293
 
1303
1294
  def unload_plug(self, name):
1304
1295
  """Unload plugin and detach the pane from UI manager."""
1305
- try:
1306
- plug = self.get_plug(name)
1307
- if not plug:
1308
- return False
1309
-
1310
- name = plug.__module__
1311
- if name not in self.plugins:
1312
- return False
1313
-
1314
- del self.plugins[name]
1315
-
1316
- if plug.__Menu_item:
1317
- menu, sep, tail = plug.menukey.rpartition('/')
1318
- menu = menu or Layer.MENU
1319
- self.menubar[menu].remove(plug.__Menu_item)
1320
- self.menubar.update(menu)
1321
-
1322
- if isinstance(plug.Parent, aui.AuiNotebook):
1323
- nb = plug.Parent
1324
- j = nb.GetPageIndex(plug)
1325
- nb.RemovePage(j) # just remove page
1326
- ## nb.DeletePage(j) # Destroys plug object too.
1327
- else:
1328
- nb = None
1329
- self._mgr.DetachPane(plug)
1330
- self._mgr.Update()
1331
-
1332
- plug.handler('page_closed', plug) # (even if not shown)
1333
- plug.Destroy()
1334
-
1335
- if nb and not nb.PageCount:
1336
- self._mgr.DetachPane(nb) # detach notebook pane
1337
- self._mgr.Update()
1338
- nb.Destroy()
1339
-
1340
- except Exception as e:
1341
- traceback.print_exc()
1342
- wx.CallAfter(wx.MessageBox,
1343
- f"{e}\n\n" + traceback.format_exc(),
1344
- f"Error in unloading {name!r}",
1345
- style=wx.ICON_ERROR)
1346
- return False
1296
+ plug = self.get_plug(name)
1297
+ if not plug:
1298
+ return
1299
+
1300
+ name = plug.__module__
1301
+ if name not in self.plugins:
1302
+ return
1303
+
1304
+ del self.plugins[name]
1305
+
1306
+ if plug.__Menu_item:
1307
+ menu, sep, tail = plug.menukey.rpartition('/')
1308
+ menu = menu or Layer.MENU
1309
+ self.menubar[menu].remove(plug.__Menu_item)
1310
+ self.menubar.update(menu)
1311
+
1312
+ if isinstance(plug.Parent, aui.AuiNotebook):
1313
+ nb = plug.Parent
1314
+ j = nb.GetPageIndex(plug)
1315
+ nb.RemovePage(j) # just remove page
1316
+ ## nb.DeletePage(j) # Destroys plug object too.
1317
+ else:
1318
+ nb = None
1319
+ self._mgr.DetachPane(plug)
1320
+ self._mgr.Update()
1321
+
1322
+ plug.handler('page_closed', plug) # (even if not shown)
1323
+ plug.Destroy()
1324
+
1325
+ if nb and not nb.PageCount:
1326
+ self._mgr.DetachPane(nb) # detach notebook pane
1327
+ self._mgr.Update()
1328
+ nb.Destroy()
1347
1329
 
1348
1330
  def reload_plug(self, name):
1349
1331
  plug = self.get_plug(name)
@@ -1360,11 +1342,16 @@ class Frame(mwx.Frame):
1360
1342
  return self.load_plug(plug.__module__, force=1, session=session)
1361
1343
  return False
1362
1344
 
1345
+ @ignore(ResourceWarning)
1363
1346
  def edit_plug(self, name):
1364
1347
  plug = self.get_plug(name)
1365
1348
  if not plug:
1366
1349
  return
1367
- self.edit(self.plugins[plug.__module__])
1350
+ ## this = inspect.getmodule(plug)
1351
+ this = self.plugins[plug.__module__]
1352
+ cmd = '{} "{}"'.format(self.Editor, this.__file__)
1353
+ subprocess.Popen(cmd)
1354
+ self.message(cmd)
1368
1355
 
1369
1356
  def inspect_plug(self, name):
1370
1357
  """Dive into the process to inspect plugs in the shell.
@@ -1707,14 +1694,14 @@ class Frame(mwx.Frame):
1707
1694
  return None
1708
1695
 
1709
1696
  def save_buffers_as_tiffs(self, path=None, frames=None):
1710
- """Export buffers to a file as a multi-page tiff."""
1697
+ """Save buffers to a file as a multi-page tiff."""
1711
1698
  if not frames:
1712
1699
  frames = self.selected_view.all_frames
1713
1700
  if not frames:
1714
1701
  return None
1715
1702
 
1716
1703
  if not path:
1717
- with wx.FileDialog(self, "Save frames as stack-tiff",
1704
+ with wx.FileDialog(self, "Save buffers as a multi-page tiff",
1718
1705
  defaultFile="Stack-image",
1719
1706
  wildcard="TIF file (*.tif)|*.tif",
1720
1707
  style=wx.FD_SAVE|wx.FD_OVERWRITE_PROMPT) as dlg:
@@ -1724,23 +1711,20 @@ class Frame(mwx.Frame):
1724
1711
  try:
1725
1712
  name = os.path.basename(path)
1726
1713
  self.message("Saving {!r}...".format(name))
1727
- busy = wx.BusyInfo("One moment please, "
1728
- "now saving {!r}...".format(name))
1729
-
1730
- stack = [Image.fromarray(x.buffer.astype(int)) for x in frames]
1731
- stack[0].save(path,
1732
- save_all=True,
1733
- compression="tiff_deflate", # cf. tiff_lzw
1734
- append_images=stack[1:])
1735
-
1714
+ with wx.BusyInfo("One moment please, "
1715
+ "now saving {!r}...".format(name)):
1716
+ stack = [Image.fromarray(x.buffer.astype(int)) for x in frames]
1717
+ stack[0].save(path,
1718
+ save_all=True,
1719
+ compression="tiff_deflate", # cf. tiff_lzw
1720
+ append_images=stack[1:])
1736
1721
  self.message("\b done.")
1722
+ wx.MessageBox("{} files successfully saved into\n{!r}.".format(len(stack), path))
1737
1723
  return True
1738
1724
  except Exception as e:
1739
1725
  self.message("\b failed.")
1740
1726
  wx.MessageBox(str(e), style=wx.ICON_ERROR)
1741
1727
  return False
1742
- finally:
1743
- del busy
1744
1728
 
1745
1729
  ## --------------------------------
1746
1730
  ## load/save session
mwx/matplot2.py CHANGED
@@ -141,8 +141,8 @@ class MatplotPanel(wx.Panel):
141
141
  ## self.canvas.mpl_connect('draw_event', lambda v: self.handler('canvas_drawn', v))
142
142
 
143
143
  self.canvas.Bind(wx.EVT_CHAR_HOOK, self.on_hotkey_press)
144
- self.canvas.Bind(wx.EVT_KEY_DOWN, self.on_hotkey_dndrag)
145
- self.canvas.Bind(wx.EVT_KEY_UP, self.on_hotkey_release)
144
+ self.canvas.Bind(wx.EVT_KEY_DOWN, self.on_hotkey_down)
145
+ self.canvas.Bind(wx.EVT_KEY_UP, self.on_hotkey_up)
146
146
 
147
147
  self.canvas.Bind(wx.EVT_MOUSE_AUX1_DOWN, lambda v: self.handler('Xbutton1 pressed', v))
148
148
  self.canvas.Bind(wx.EVT_MOUSE_AUX2_DOWN, lambda v: self.handler('Xbutton2 pressed', v))
@@ -528,11 +528,11 @@ class MatplotPanel(wx.Panel):
528
528
  def on_hotkey_press(self, evt): #<wx._core.KeyEvent>
529
529
  """Called when a key is pressed."""
530
530
  key = hotkey(evt)
531
- self.__key = regulate_key(key + '+')
531
+ self.__key = regulate_key(key + '-')
532
532
  if self.handler('{} pressed'.format(key), evt) is None:
533
533
  evt.Skip()
534
534
 
535
- def on_hotkey_dndrag(self, evt): #<wx._core.KeyEvent>
535
+ def on_hotkey_down(self, evt): #<wx._core.KeyEvent>
536
536
  """Called when a key is pressed while dragging.
537
537
  Specifically called when the mouse is being captured.
538
538
  """
@@ -541,7 +541,7 @@ class MatplotPanel(wx.Panel):
541
541
  else:
542
542
  evt.Skip()
543
543
 
544
- def on_hotkey_release(self, evt): #<wx._core.KeyEvent>
544
+ def on_hotkey_up(self, evt): #<wx._core.KeyEvent>
545
545
  """Called when a key is released."""
546
546
  key = hotkey(evt)
547
547
  self.__key = ''
mwx/matplot2g.py CHANGED
@@ -228,7 +228,6 @@ class AxesImagePhantom(object):
228
228
 
229
229
  @unit.setter
230
230
  def unit(self, v):
231
- u = self.unit
232
231
  if v is None:
233
232
  v = self.parent.unit
234
233
  self.__localunit = None
@@ -273,7 +272,7 @@ class AxesImagePhantom(object):
273
272
  return self.parent.index(self)
274
273
 
275
274
  def update_buffer(self, buf=None):
276
- """Update buffer and the image."""
275
+ """Update buffer and the image (internal use only)."""
277
276
  if buf is not None:
278
277
  self.__buf = _to_buffer(buf)
279
278
 
@@ -287,7 +286,7 @@ class AxesImagePhantom(object):
287
286
  self.parent.handler('frame_modified', self)
288
287
 
289
288
  def update_extent(self):
290
- """Update logical extent of the image."""
289
+ """Update logical extent of the image (internal use only)."""
291
290
  h, w = self.__buf.shape[:2]
292
291
  ux, uy = self.xy_unit
293
292
  w *= ux/2
@@ -397,7 +396,7 @@ class GraphPlot(MatplotPanel):
397
396
  'pageup pressed' : [ None, self.OnPageUp ],
398
397
  'pagedown pressed' : [ None, self.OnPageDown ],
399
398
  'M-a pressed' : [ None, _F(self.fit_to_canvas) ],
400
- 'C-a pressed' : [ None, _F(self.update_axis) ],
399
+ 'C-a pressed' : [ None, _F(self.fit_to_axes) ],
401
400
  'C-i pressed' : [ None, _F(self.invert_cmap) ],
402
401
  'C-k pressed' : [ None, _F(self.kill_buffer) ],
403
402
  'C-S-k pressed' : [ None, _F(self.kill_buffer_all) ],
@@ -809,7 +808,6 @@ class GraphPlot(MatplotPanel):
809
808
  else:
810
809
  if v == self.__unit: # no effect unless unit changes
811
810
  return
812
- u = self.__unit
813
811
  self.__unit = v
814
812
  for art in self.__Arts:
815
813
  art.update_extent()
@@ -825,8 +823,8 @@ class GraphPlot(MatplotPanel):
825
823
  def kill_buffer_all(self):
826
824
  del self[:]
827
825
 
828
- def update_axis(self):
829
- """Reset display range (xylim's), update home position."""
826
+ def fit_to_axes(self):
827
+ """Reset the view limits to the current frame extent."""
830
828
  if self.frame:
831
829
  self.axes.axis(self.frame.get_extent()) # reset xlim and ylim
832
830
  self.toolbar.update()
@@ -834,7 +832,7 @@ class GraphPlot(MatplotPanel):
834
832
  self.draw()
835
833
 
836
834
  def fit_to_canvas(self):
837
- """fit display range (xylim's) to canvas."""
835
+ """Reset the view limits to the canvas range."""
838
836
  x, y = self.xlim, self.ylim
839
837
  w, h = self.canvas.GetSize()
840
838
  r = h/w
@@ -1116,7 +1114,7 @@ class GraphPlot(MatplotPanel):
1116
1114
  self.select(i - 1)
1117
1115
 
1118
1116
  def OnHomePosition(self, evt):
1119
- self.update_axis()
1117
+ self.fit_to_axes()
1120
1118
 
1121
1119
  def OnEscapeSelection(self, evt):
1122
1120
  xs, ys = self.Selector
mwx/nutshell.py CHANGED
@@ -1749,7 +1749,7 @@ class EditorBook(AuiNotebook, CtrlInterface):
1749
1749
  )
1750
1750
  self.parent = parent #: parent<ShellFrame> is not Parent<AuiNotebook>
1751
1751
  self.Name = name
1752
- self.default_name = "*{}*".format(name.lower())
1752
+ self.default_name = "*{}*".format(name.lower()) # e.g. '*scratch*'
1753
1753
  self.default_buffer = self.create_buffer(self.default_name)
1754
1754
 
1755
1755
  self.Bind(aui.EVT_AUINOTEBOOK_PAGE_CLOSE, self.OnPageClose)
@@ -1,13 +1,15 @@
1
1
  #! python3
2
2
  """FFmpeg wrapper.
3
3
  """
4
+ from functools import partial
4
5
  from subprocess import Popen, PIPE
5
6
  import numpy as np
6
7
  import os
7
8
  import wx
8
9
  import wx.media
9
10
 
10
- from mwx.graphman import Layer, Frame
11
+ from mwx.framework import _F, hotkey
12
+ from mwx.graphman import Layer
11
13
  from mwx.controls import LParam, Icon, Button, TextCtrl
12
14
 
13
15
 
@@ -87,7 +89,6 @@ class Plugin(Layer):
87
89
  )
88
90
  self.mc.ShowPlayerControls()
89
91
  self.mc.Bind(wx.media.EVT_MEDIA_LOADED, self.OnMediaLoaded)
90
- self.mc.Bind(wx.media.EVT_MEDIA_PAUSE, self.OnMediaPause)
91
92
 
92
93
  self.mc.SetDropTarget(MyFileDropLoader(self))
93
94
 
@@ -128,6 +129,27 @@ class Plugin(Layer):
128
129
  ]
129
130
 
130
131
  self.parent.handler.bind("unknown_format", self.load_media)
132
+
133
+ self.handler.update({ # DNA<ffmpeg_viewer>
134
+ 0 : {
135
+ 'play' : (1, ),
136
+ 'space pressed' : (1, _F(self.mc.Play)),
137
+ },
138
+ 1 : {
139
+ 'stop' : (0, ),
140
+ 'pause' : (0, ),
141
+ 'space pressed' : (1, _F(self.mc.Pause)),
142
+ },
143
+ })
144
+
145
+ self.mc.Bind(wx.media.EVT_MEDIA_PAUSE, partial(self.handler, 'pause'))
146
+ self.mc.Bind(wx.media.EVT_MEDIA_PLAY, partial(self.handler, 'play'))
147
+ self.mc.Bind(wx.media.EVT_MEDIA_STOP, partial(self.handler, 'stop'))
148
+
149
+ ## self.mc.Bind(wx.EVT_KEY_DOWN, self.on_hotkey_down)
150
+ ## self.mc.Bind(wx.EVT_KEY_UP, self.on_hotkey_up)
151
+ self.mc.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown)
152
+ self.mc.Bind(wx.EVT_KEY_UP, self.OnKeyUp)
131
153
 
132
154
  def Destroy(self):
133
155
  try:
@@ -136,15 +158,20 @@ class Plugin(Layer):
136
158
  finally:
137
159
  return Layer.Destroy(self)
138
160
 
161
+ def OnKeyDown(self, evt):
162
+ if self.handler('{} pressed'.format(hotkey(evt)), evt) is None:
163
+ evt.Skip()
164
+
165
+ def OnKeyUp(self, evt):
166
+ if self.handler('{} released'.format(hotkey(evt)), evt) is None:
167
+ evt.Skip()
168
+
139
169
  def OnMediaLoaded(self, evt):
140
170
  self.ss.range = (0, self.video_dur, 0.01)
141
171
  self.to.range = (0, self.video_dur, 0.01)
142
172
  self.Show()
143
173
  evt.Skip()
144
174
 
145
- def OnMediaPause(self, evt):
146
- evt.Skip()
147
-
148
175
  def load_media(self, path=None):
149
176
  if path is None:
150
177
  with wx.FileDialog(self, "Choose a media file",
mwx/plugins/fft_view.py CHANGED
@@ -42,8 +42,8 @@ class Plugin(Layer):
42
42
  self.parent.define_key('C-S-f', self.newifft)
43
43
 
44
44
  def Destroy(self):
45
- self.parent.define_key('C-f', None)
46
- self.parent.define_key('C-S-f', None)
45
+ self.parent.undefine_key('C-f')
46
+ self.parent.undefine_key('C-S-f')
47
47
  return Layer.Destroy(self)
48
48
 
49
49
  def newfft(self):
@@ -67,7 +67,7 @@ class CheckList(wx.ListCtrl, ListCtrlAutoWidthMixin, CtrlInterface):
67
67
  self.InsertItem(j, str(j))
68
68
  self.UpdateInfo(frame) # update all --> 計算が入ると時間がかかる
69
69
 
70
- self.handler.update({
70
+ self.handler.update({ # DNA<frame_listview>
71
71
  0 : {
72
72
  'Lbutton dblclick' : (0, self.OnShowItems), # -> frame_shown
73
73
  'enter pressed' : (0, self.OnShowItems), # -> frame_shown
@@ -84,7 +84,7 @@ class CheckList(wx.ListCtrl, ListCtrlAutoWidthMixin, CtrlInterface):
84
84
  self.Bind(wx.EVT_LIST_COL_CLICK, self.OnSortItems)
85
85
  self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnItemSelected)
86
86
 
87
- self.context = { # bound to the target
87
+ self.context = { # DNA<GraphPlot>
88
88
  None: {
89
89
  'frame_shown' : [ None, self.on_frame_shown ],
90
90
  'frame_hidden' : [ None, self.on_frame_hidden ],
mwx/wxwit.py CHANGED
@@ -7,6 +7,7 @@ import wx
7
7
  import wx.lib.inspection as it
8
8
 
9
9
  from .controls import Icon
10
+ from .utilus import typename
10
11
  from .framework import CtrlInterface, Menu, filling
11
12
 
12
13
 
@@ -176,7 +177,7 @@ class Inspector(it.InspectionTree, CtrlInterface):
176
177
  lambda v: watch(obj),
177
178
  lambda v: v.Enable(obj is not None)),
178
179
 
179
- (1, "&Dive into {!r}".format(obj), Icon('core'),
180
+ (1, "&Dive into {!r}".format(typename(obj)), Icon('core'),
180
181
  lambda v: dive(obj),
181
182
  lambda v: v.Enable(obj is not None)),
182
183
  ])
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: mwxlib
3
- Version: 0.96.8
3
+ Version: 0.97.1
4
4
  Summary: A wrapper of matplotlib and wxPython (phoenix)
5
5
  Home-page: https://github.com/komoto48g/mwxlib
6
6
  Author: Kazuya O'moto
@@ -0,0 +1,28 @@
1
+ mwx/__init__.py,sha256=nN62CGTWjME7Zz2h-jIRB8MxwuErIkHPGrlBzydkF0o,643
2
+ mwx/bookshelf.py,sha256=SiDYw0bMW-dHrPl2eP4ZEoQAn17f9XeEk8_0XbYw9DQ,5319
3
+ mwx/controls.py,sha256=ebF16EOoDWndVdBh_x2TKLZ4WevkH91QkKWyEivfCjY,48373
4
+ mwx/framework.py,sha256=ffCTDK7wMnAct-kaNXK3FoL8Bm0vECPDxXO1ordG2Og,75300
5
+ mwx/graphman.py,sha256=NLklcxzTKklaL_FXpl5qW2apwAb3YuHH_NSr--PlqMQ,70612
6
+ mwx/images.py,sha256=_-Eh3xF7Khu42ivkYp97NXIzSNGbjcidqtWjZQFGtqE,47827
7
+ mwx/matplot2.py,sha256=xCJ_ZzdDEWmzctpPaOrzTnwXyHINP4nfFHweoTZa6ug,32899
8
+ mwx/matplot2g.py,sha256=95J4tyA6VgKrTN7zPPGoo_f24kYAqKB5BOBordExNUg,64443
9
+ mwx/matplot2lg.py,sha256=JRWjWnLJUytbSq6wxs4P0gbVUr3xoLSF6Wwqd5V_pJI,27404
10
+ mwx/mgplt.py,sha256=ITzxA97yDwr_35BUk5OqnyskSuKVDbpf2AQCKY1jHTI,5671
11
+ mwx/nutshell.py,sha256=zrye6tLuGgyCC-Od323o71bauGDKFnO8Zsabs0JMqjs,137383
12
+ mwx/utilus.py,sha256=8GK_2mGY08DVN5_SGWynLKQEJsCKqvqWTDToar1XozM,37333
13
+ mwx/wxmon.py,sha256=f3V24EF7kdMlYF7usLYK9QE5KU6fSu0jVqsvwAiA-Ag,12647
14
+ mwx/wxpdb.py,sha256=lLowkkAgMhPFHAfklD7wZHq0qbSMjRxnBFtSajmVgME,19133
15
+ mwx/wxwil.py,sha256=hhyB1lPrF9ixeObxCOKQv0Theu-B-kpJg_yVU3EGSNg,5406
16
+ mwx/wxwit.py,sha256=ifxMwdIz-QhDEr8vyAztToF8VVSxKNXlq4Ap1awBZvo,7362
17
+ mwx/plugins/__init__.py,sha256=jnJ-Sl9XJ_7BFDslD_r7dsbxsOT57q_IaEriV53XIGY,41
18
+ mwx/plugins/ffmpeg_view.py,sha256=1s7QqIbOpqNrSwbNoc4wQQNo8o1ho5JfXLuseAhgzK4,10441
19
+ mwx/plugins/fft_view.py,sha256=xxTDD-_z4l18u4t2ybPB3xAMIslJmJ0gQlTxEqJUhNI,2782
20
+ mwx/plugins/frame_listview.py,sha256=hbApzZWa9-BmQthu7uZBlBbGbtf4iJ_prO8IhxoGMs8,10421
21
+ mwx/plugins/line_profile.py,sha256=--9NIc3x5EfRB3L59JvD7rzENQHyiYfu7wWJo6AuMkA,820
22
+ mwx/py/__init__.py,sha256=xykgfOytOwNuvXsfkLoumFZSTN-iBsHOjczYXngjmUE,12
23
+ mwx/py/filling.py,sha256=KaHooM32hrGGgqw75Cbt8lAvACwC6RXadob9LGgNnEc,16806
24
+ mwxlib-0.97.1.dist-info/LICENSE,sha256=PGtRKCaTkmUDlBQwpptJAxJtdqxIUtAmdBsaT9nUVkA,1091
25
+ mwxlib-0.97.1.dist-info/METADATA,sha256=2iRI3XivGubsXjavm_XGa1fkwoFx5MjiWFbWnNqhrko,1880
26
+ mwxlib-0.97.1.dist-info/WHEEL,sha256=rWxmBtp7hEUqVLOnTaDOPpR-cZpCDkzhhcBce-Zyd5k,91
27
+ mwxlib-0.97.1.dist-info/top_level.txt,sha256=SI1Mh118AstnUFGPNq5aMNKiAnVNmZk1S9Ij-OwAEpY,4
28
+ mwxlib-0.97.1.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (70.2.0)
2
+ Generator: setuptools (71.0.4)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,28 +0,0 @@
1
- mwx/__init__.py,sha256=nN62CGTWjME7Zz2h-jIRB8MxwuErIkHPGrlBzydkF0o,643
2
- mwx/bookshelf.py,sha256=CjcgtHC33KR5mHp1lW6Bqfndpzr7hC8ICkFihw4kM3g,5134
3
- mwx/controls.py,sha256=s6yJzQyYnjCzcjXa6nbTJncxzpMI0E5zYWPn3-cFy5Q,48378
4
- mwx/framework.py,sha256=WdKCaMnp3S0_PbpAfK2AxfUZgriUMFPAP2I4yGzZoVA,75227
5
- mwx/graphman.py,sha256=DtTnz2fW78eAIWC1QV8nMuSddiIsjb4cSnXb3BkTpdI,71043
6
- mwx/images.py,sha256=_-Eh3xF7Khu42ivkYp97NXIzSNGbjcidqtWjZQFGtqE,47827
7
- mwx/matplot2.py,sha256=NcNOIhOzrzU6smRtCnHZxJenkrHq0R4D7bWp7PF4QVA,32913
8
- mwx/matplot2g.py,sha256=ydqAiM_gw9DwjOOc_akKeVsVKPD8KfXu8KFJx32dlZ0,64453
9
- mwx/matplot2lg.py,sha256=JRWjWnLJUytbSq6wxs4P0gbVUr3xoLSF6Wwqd5V_pJI,27404
10
- mwx/mgplt.py,sha256=ITzxA97yDwr_35BUk5OqnyskSuKVDbpf2AQCKY1jHTI,5671
11
- mwx/nutshell.py,sha256=cdrg3cuF6AVU2OuR3QswSiTWrTsGIVaqrBSMuxJIjdE,137364
12
- mwx/utilus.py,sha256=8GK_2mGY08DVN5_SGWynLKQEJsCKqvqWTDToar1XozM,37333
13
- mwx/wxmon.py,sha256=f3V24EF7kdMlYF7usLYK9QE5KU6fSu0jVqsvwAiA-Ag,12647
14
- mwx/wxpdb.py,sha256=lLowkkAgMhPFHAfklD7wZHq0qbSMjRxnBFtSajmVgME,19133
15
- mwx/wxwil.py,sha256=hhyB1lPrF9ixeObxCOKQv0Theu-B-kpJg_yVU3EGSNg,5406
16
- mwx/wxwit.py,sha256=yU6XeCCWRBP7CLmpphjT072PfXAL30DNaxoChDX2p0I,7322
17
- mwx/plugins/__init__.py,sha256=jnJ-Sl9XJ_7BFDslD_r7dsbxsOT57q_IaEriV53XIGY,41
18
- mwx/plugins/ffmpeg_view.py,sha256=QjNqnvPEd9vCwfATU2BOO75fIOFD5LQ-Wf-BBhvZNZs,9368
19
- mwx/plugins/fft_view.py,sha256=HVptnn1dq-Dg7AzXKJXq1dfKiy38catlrMbJkvyLM98,2790
20
- mwx/plugins/frame_listview.py,sha256=7LDAYbl5NvmD4Ehc690IrTbcRgCALRWeLVVOT9cm9Do,10404
21
- mwx/plugins/line_profile.py,sha256=--9NIc3x5EfRB3L59JvD7rzENQHyiYfu7wWJo6AuMkA,820
22
- mwx/py/__init__.py,sha256=xykgfOytOwNuvXsfkLoumFZSTN-iBsHOjczYXngjmUE,12
23
- mwx/py/filling.py,sha256=KaHooM32hrGGgqw75Cbt8lAvACwC6RXadob9LGgNnEc,16806
24
- mwxlib-0.96.8.dist-info/LICENSE,sha256=PGtRKCaTkmUDlBQwpptJAxJtdqxIUtAmdBsaT9nUVkA,1091
25
- mwxlib-0.96.8.dist-info/METADATA,sha256=eNdwrk8WxGhWphg4UbZrKiMynpJ1_f17-8NpqR2F-j0,1880
26
- mwxlib-0.96.8.dist-info/WHEEL,sha256=y4mX-SOX4fYIkonsAGA5N0Oy-8_gI4FXw5HNI1xqvWg,91
27
- mwxlib-0.96.8.dist-info/top_level.txt,sha256=SI1Mh118AstnUFGPNq5aMNKiAnVNmZk1S9Ij-OwAEpY,4
28
- mwxlib-0.96.8.dist-info/RECORD,,