mwxlib 0.96.7__py3-none-any.whl → 0.97.0__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 +18 -11
- mwx/framework.py +19 -15
- mwx/graphman.py +66 -92
- mwx/matplot2.py +7 -21
- mwx/matplot2g.py +72 -88
- mwx/matplot2lg.py +21 -15
- mwx/nutshell.py +1 -1
- mwx/plugins/ffmpeg_view.py +32 -5
- mwx/plugins/fft_view.py +2 -2
- mwx/plugins/frame_listview.py +2 -2
- mwx/wxwil.py +0 -3
- mwx/wxwit.py +2 -1
- {mwxlib-0.96.7.dist-info → mwxlib-0.97.0.dist-info}/METADATA +1 -1
- mwxlib-0.97.0.dist-info/RECORD +28 -0
- {mwxlib-0.96.7.dist-info → mwxlib-0.97.0.dist-info}/WHEEL +1 -1
- mwxlib-0.96.7.dist-info/RECORD +0 -28
- {mwxlib-0.96.7.dist-info → mwxlib-0.97.0.dist-info}/LICENSE +0 -0
- {mwxlib-0.96.7.dist-info → mwxlib-0.97.0.dist-info}/top_level.txt +0 -0
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<
|
|
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,41 @@ 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
39
|
def enter(evt):
|
|
41
40
|
data = self.GetItemData(self.Selection)
|
|
42
41
|
if data:
|
|
43
42
|
data.SetFocus()
|
|
44
43
|
|
|
45
|
-
@self.handler.bind('f5 pressed')
|
|
46
44
|
def refresh(evt, clear=False):
|
|
47
45
|
self.build_tree(clear)
|
|
48
46
|
if self.target:
|
|
49
47
|
self.target.current_editor.SetFocus()
|
|
50
48
|
wx.CallAfter(self.SetFocus)
|
|
51
49
|
|
|
52
|
-
self.handler.bind('S-f5 pressed', partial(refresh, clear=1))
|
|
53
|
-
|
|
54
|
-
@self.handler.bind('delete pressed')
|
|
55
50
|
def delete(evt):
|
|
56
51
|
data = self.GetItemData(self.Selection)
|
|
57
52
|
if data:
|
|
58
|
-
data.
|
|
53
|
+
if data.mtdelta or data.Text:
|
|
54
|
+
data.parent.kill_buffer(data) # -> focus moves
|
|
59
55
|
wx.CallAfter(self.SetFocus)
|
|
60
56
|
|
|
61
|
-
@self.handler.bind('*button* pressed')
|
|
62
|
-
@self.handler.bind('*button* released')
|
|
63
57
|
def dispatch(evt):
|
|
64
|
-
"""Fork
|
|
58
|
+
"""Fork events to the parent."""
|
|
65
59
|
self.parent.handler(self.handler.current_event, evt)
|
|
66
60
|
evt.Skip()
|
|
61
|
+
|
|
62
|
+
self.handler.update({ # DNA<EditorTreeCtrl>
|
|
63
|
+
None : {
|
|
64
|
+
'*button* pressed' : [ None, dispatch ],
|
|
65
|
+
'*button* released' : [ None, dispatch ],
|
|
66
|
+
},
|
|
67
|
+
0 : {
|
|
68
|
+
'enter pressed' : (0, enter),
|
|
69
|
+
'delete pressed' : (0, delete),
|
|
70
|
+
'f5 pressed' : (0, refresh),
|
|
71
|
+
'S-f5 pressed' : (0, _F(refresh, clear=1)),
|
|
72
|
+
},
|
|
73
|
+
})
|
|
67
74
|
|
|
68
75
|
def OnDestroy(self, evt):
|
|
69
76
|
if evt.EventObject is self:
|
mwx/framework.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#! python3
|
|
2
2
|
"""mwxlib framework.
|
|
3
3
|
"""
|
|
4
|
-
__version__ = "0.
|
|
4
|
+
__version__ = "0.97.0"
|
|
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
|
|
22
|
+
from .utilus import get_rootpath, ignore, warn
|
|
23
23
|
from .utilus import FSM, TreeList, apropos, typename, where, mro, pp
|
|
24
24
|
|
|
25
25
|
|
|
@@ -193,10 +193,9 @@ def hotkey(evt):
|
|
|
193
193
|
|
|
194
194
|
|
|
195
195
|
def regulate_key(key):
|
|
196
|
-
return (key.replace("ctrl
|
|
197
|
-
.replace("alt
|
|
198
|
-
.replace("shift
|
|
199
|
-
.replace("win+", "win-")
|
|
196
|
+
return (key.replace("ctrl-", "C-") # modifier keys abbreviation
|
|
197
|
+
.replace("alt-", "M-")
|
|
198
|
+
.replace("shift-", "S-")
|
|
200
199
|
.replace("M-C-", "C-M-") # modifier key regulation C-M-S-
|
|
201
200
|
.replace("S-M-", "M-S-")
|
|
202
201
|
.replace("S-C-", "C-S-"))
|
|
@@ -310,6 +309,11 @@ class KeyCtrlInterfaceMixin:
|
|
|
310
309
|
else:
|
|
311
310
|
self.handler.update({map: {key: [state, f]}})
|
|
312
311
|
return action
|
|
312
|
+
|
|
313
|
+
@ignore(UserWarning)
|
|
314
|
+
def undefine_key(self, keymap):
|
|
315
|
+
"""Delete [map key (pressed)] context."""
|
|
316
|
+
self.define_key(keymap, None)
|
|
313
317
|
|
|
314
318
|
|
|
315
319
|
class CtrlInterface(KeyCtrlInterfaceMixin):
|
|
@@ -343,8 +347,8 @@ class CtrlInterface(KeyCtrlInterfaceMixin):
|
|
|
343
347
|
self.Bind(wx.EVT_KILL_FOCUS, inactivate)
|
|
344
348
|
|
|
345
349
|
self.Bind(wx.EVT_CHAR_HOOK, self.on_hotkey_press)
|
|
346
|
-
self.Bind(wx.EVT_KEY_DOWN, self.
|
|
347
|
-
self.Bind(wx.EVT_KEY_UP, self.
|
|
350
|
+
self.Bind(wx.EVT_KEY_DOWN, self.on_hotkey_down)
|
|
351
|
+
self.Bind(wx.EVT_KEY_UP, self.on_hotkey_up)
|
|
348
352
|
|
|
349
353
|
self.Bind(wx.EVT_MOUSEWHEEL, self.on_mousewheel)
|
|
350
354
|
|
|
@@ -376,20 +380,20 @@ class CtrlInterface(KeyCtrlInterfaceMixin):
|
|
|
376
380
|
evt.Skip()
|
|
377
381
|
return
|
|
378
382
|
key = hotkey(evt)
|
|
379
|
-
self.__key = regulate_key(key + '
|
|
383
|
+
self.__key = regulate_key(key + '-')
|
|
380
384
|
if self.handler('{} pressed'.format(key), evt) is None:
|
|
381
385
|
evt.Skip()
|
|
382
386
|
|
|
383
|
-
def
|
|
387
|
+
def on_hotkey_down(self, evt): #<wx._core.KeyEvent>
|
|
384
388
|
"""Called when a key is pressed while dragging.
|
|
385
389
|
Specifically called when the mouse is being captured.
|
|
386
390
|
"""
|
|
387
391
|
if self.__isDragging:
|
|
388
392
|
self.on_hotkey_press(evt)
|
|
389
393
|
else:
|
|
390
|
-
evt.Skip()
|
|
394
|
+
evt.Skip()
|
|
391
395
|
|
|
392
|
-
def
|
|
396
|
+
def on_hotkey_up(self, evt): #<wx._core.KeyEvent>
|
|
393
397
|
"""Called when a key is released."""
|
|
394
398
|
key = hotkey(evt)
|
|
395
399
|
self.__key = ''
|
|
@@ -408,7 +412,7 @@ class CtrlInterface(KeyCtrlInterfaceMixin):
|
|
|
408
412
|
if self.handler('{} pressed'.format(evt.key), evt) is None:
|
|
409
413
|
evt.Skip()
|
|
410
414
|
|
|
411
|
-
def on_motion(self, evt):
|
|
415
|
+
def on_motion(self, evt): #<wx._core.MouseEvent>
|
|
412
416
|
"""Called on mouse motion events.
|
|
413
417
|
Trigger event: 'key+[LMR]drag begin/motion/end'
|
|
414
418
|
"""
|
|
@@ -1630,9 +1634,9 @@ class ShellFrame(MiniFrame):
|
|
|
1630
1634
|
if isinstance(obj, wx.Object):
|
|
1631
1635
|
self.monitor.watch(obj)
|
|
1632
1636
|
self.popup_window(self.monitor)
|
|
1633
|
-
|
|
1637
|
+
if hasattr(obj, '__dict__'):
|
|
1634
1638
|
self.linfo.watch(obj.__dict__)
|
|
1635
|
-
self.ginfo.watch(
|
|
1639
|
+
self.ginfo.watch(None)
|
|
1636
1640
|
self.popup_window(self.linfo)
|
|
1637
1641
|
|
|
1638
1642
|
def highlight(self, obj, *args, **kwargs):
|
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
|
-
|
|
218
|
-
|
|
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 で終了させる
|
|
@@ -541,19 +538,6 @@ class Graph(GraphPlot):
|
|
|
541
538
|
if self.infobar.IsShown():
|
|
542
539
|
self.infobar.ShowMessage(frame.annotation)
|
|
543
540
|
|
|
544
|
-
def get_frame_visible(self):
|
|
545
|
-
if self.frame:
|
|
546
|
-
return self.frame.get_visible()
|
|
547
|
-
return False
|
|
548
|
-
|
|
549
|
-
def set_frame_visible(self, v):
|
|
550
|
-
if self.frame:
|
|
551
|
-
if self.frame.get_visible() != v:
|
|
552
|
-
self.frame.set_visible(v)
|
|
553
|
-
return True
|
|
554
|
-
return False
|
|
555
|
-
return None
|
|
556
|
-
|
|
557
541
|
def get_markups_visible(self):
|
|
558
542
|
return self.marked.get_visible()
|
|
559
543
|
|
|
@@ -698,7 +682,7 @@ class Frame(mwx.Frame):
|
|
|
698
682
|
lambda v: self.save_frame(),
|
|
699
683
|
lambda v: v.Enable(self.__view.frame is not None)),
|
|
700
684
|
|
|
701
|
-
(wx.ID_SAVEAS, "&Save as TIFFs", "Save buffers as a
|
|
685
|
+
(wx.ID_SAVEAS, "&Save as TIFFs", "Save buffers as a multi-page tiff", Icon('saveall'),
|
|
702
686
|
lambda v: self.save_buffers_as_tiffs(),
|
|
703
687
|
lambda v: v.Enable(self.__view.frame is not None)),
|
|
704
688
|
(),
|
|
@@ -823,11 +807,13 @@ class Frame(mwx.Frame):
|
|
|
823
807
|
self.Bind(wx.EVT_CLOSE, self.OnClose)
|
|
824
808
|
|
|
825
809
|
def on_move(evt, show):
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
810
|
+
def _display(view, show):
|
|
811
|
+
if view.frame:
|
|
812
|
+
view.frame.set_visible(show)
|
|
813
|
+
if show:
|
|
814
|
+
view.draw()
|
|
815
|
+
_display(self.graph, show)
|
|
816
|
+
_display(self.output, show)
|
|
831
817
|
evt.Skip()
|
|
832
818
|
self.Bind(wx.EVT_MOVE_START, lambda v :on_move(v, show=0))
|
|
833
819
|
self.Bind(wx.EVT_MOVE_END, lambda v :on_move(v, show=1))
|
|
@@ -842,6 +828,9 @@ class Frame(mwx.Frame):
|
|
|
842
828
|
|
|
843
829
|
## Accepts DnD
|
|
844
830
|
self.SetDropTarget(MyFileDropLoader(self.graph, self))
|
|
831
|
+
|
|
832
|
+
## Script editor for plugins (external call)
|
|
833
|
+
self.Editor = "notepad"
|
|
845
834
|
|
|
846
835
|
sync_switch = True
|
|
847
836
|
|
|
@@ -856,17 +845,6 @@ class Frame(mwx.Frame):
|
|
|
856
845
|
b.OnDraw(None)
|
|
857
846
|
b.canvas.draw_idle()
|
|
858
847
|
|
|
859
|
-
Editor = "notepad"
|
|
860
|
-
|
|
861
|
-
@ignore(ResourceWarning)
|
|
862
|
-
def edit(self, fn):
|
|
863
|
-
if hasattr(fn, '__file__'):
|
|
864
|
-
name, _ = os.path.splitext(fn.__file__)
|
|
865
|
-
fn = name + '.py'
|
|
866
|
-
cmd = '{} "{}"'.format(self.Editor, fn)
|
|
867
|
-
subprocess.Popen(cmd)
|
|
868
|
-
self.message(cmd)
|
|
869
|
-
|
|
870
848
|
def set_title(self, frame):
|
|
871
849
|
ssn = os.path.basename(self.session_file or '--')
|
|
872
850
|
ssn, _ = os.path.splitext(ssn)
|
|
@@ -917,6 +895,8 @@ class Frame(mwx.Frame):
|
|
|
917
895
|
evt.Skip()
|
|
918
896
|
|
|
919
897
|
def Destroy(self):
|
|
898
|
+
for name in list(self.plugins):
|
|
899
|
+
self.unload_plug(name) # => plug.Destroy
|
|
920
900
|
self._mgr.UnInit()
|
|
921
901
|
return mwx.Frame.Destroy(self)
|
|
922
902
|
|
|
@@ -943,9 +923,10 @@ class Frame(mwx.Frame):
|
|
|
943
923
|
return
|
|
944
924
|
|
|
945
925
|
## Set the graph and output window sizes to half & half.
|
|
926
|
+
## ドッキング時に再計算される
|
|
946
927
|
if name == "output" or name is self.output:
|
|
947
928
|
w, h = self.graph.GetClientSize()
|
|
948
|
-
pane.best_size = (w//2, h) #
|
|
929
|
+
pane.best_size = (w//2 - 3, h) # 分割線幅補正 -12pix (Windows only ?)
|
|
949
930
|
|
|
950
931
|
## Force Layer windows to show.
|
|
951
932
|
if interactive:
|
|
@@ -1312,48 +1293,39 @@ class Frame(mwx.Frame):
|
|
|
1312
1293
|
|
|
1313
1294
|
def unload_plug(self, name):
|
|
1314
1295
|
"""Unload plugin and detach the pane from UI manager."""
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
nb.Destroy()
|
|
1349
|
-
|
|
1350
|
-
except Exception as e:
|
|
1351
|
-
traceback.print_exc()
|
|
1352
|
-
wx.CallAfter(wx.MessageBox,
|
|
1353
|
-
f"{e}\n\n" + traceback.format_exc(),
|
|
1354
|
-
f"Error in unloading {name!r}",
|
|
1355
|
-
style=wx.ICON_ERROR)
|
|
1356
|
-
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()
|
|
1357
1329
|
|
|
1358
1330
|
def reload_plug(self, name):
|
|
1359
1331
|
plug = self.get_plug(name)
|
|
@@ -1370,11 +1342,16 @@ class Frame(mwx.Frame):
|
|
|
1370
1342
|
return self.load_plug(plug.__module__, force=1, session=session)
|
|
1371
1343
|
return False
|
|
1372
1344
|
|
|
1345
|
+
@ignore(ResourceWarning)
|
|
1373
1346
|
def edit_plug(self, name):
|
|
1374
1347
|
plug = self.get_plug(name)
|
|
1375
1348
|
if not plug:
|
|
1376
1349
|
return
|
|
1377
|
-
|
|
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)
|
|
1378
1355
|
|
|
1379
1356
|
def inspect_plug(self, name):
|
|
1380
1357
|
"""Dive into the process to inspect plugs in the shell.
|
|
@@ -1717,14 +1694,14 @@ class Frame(mwx.Frame):
|
|
|
1717
1694
|
return None
|
|
1718
1695
|
|
|
1719
1696
|
def save_buffers_as_tiffs(self, path=None, frames=None):
|
|
1720
|
-
"""
|
|
1697
|
+
"""Save buffers to a file as a multi-page tiff."""
|
|
1721
1698
|
if not frames:
|
|
1722
1699
|
frames = self.selected_view.all_frames
|
|
1723
1700
|
if not frames:
|
|
1724
1701
|
return None
|
|
1725
1702
|
|
|
1726
1703
|
if not path:
|
|
1727
|
-
with wx.FileDialog(self, "Save
|
|
1704
|
+
with wx.FileDialog(self, "Save buffers as a multi-page tiff",
|
|
1728
1705
|
defaultFile="Stack-image",
|
|
1729
1706
|
wildcard="TIF file (*.tif)|*.tif",
|
|
1730
1707
|
style=wx.FD_SAVE|wx.FD_OVERWRITE_PROMPT) as dlg:
|
|
@@ -1734,23 +1711,20 @@ class Frame(mwx.Frame):
|
|
|
1734
1711
|
try:
|
|
1735
1712
|
name = os.path.basename(path)
|
|
1736
1713
|
self.message("Saving {!r}...".format(name))
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
append_images=stack[1:])
|
|
1745
|
-
|
|
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:])
|
|
1746
1721
|
self.message("\b done.")
|
|
1722
|
+
wx.MessageBox("{} files successfully saved into\n{!r}.".format(len(stack), path))
|
|
1747
1723
|
return True
|
|
1748
1724
|
except Exception as e:
|
|
1749
1725
|
self.message("\b failed.")
|
|
1750
1726
|
wx.MessageBox(str(e), style=wx.ICON_ERROR)
|
|
1751
1727
|
return False
|
|
1752
|
-
finally:
|
|
1753
|
-
del busy
|
|
1754
1728
|
|
|
1755
1729
|
## --------------------------------
|
|
1756
1730
|
## load/save session
|
mwx/matplot2.py
CHANGED
|
@@ -100,10 +100,7 @@ class MatplotPanel(wx.Panel):
|
|
|
100
100
|
self.toolbar.Show(0)
|
|
101
101
|
|
|
102
102
|
## modeline bar
|
|
103
|
-
self.modeline = wx.StaticText(self,
|
|
104
|
-
self.modeline.write = self.modeline.SetLabel
|
|
105
|
-
self.modeline.read = self.modeline.GetLabel
|
|
106
|
-
self.modeline.SetToolTip("")
|
|
103
|
+
self.modeline = wx.StaticText(self, style=wx.ST_NO_AUTORESIZE)
|
|
107
104
|
|
|
108
105
|
self.modeline.Bind(wx.EVT_MOTION, self.on_modeline_tip)
|
|
109
106
|
self.modeline.Bind(wx.EVT_LEFT_DOWN, lambda v: self.canvas.SetFocus())
|
|
@@ -144,8 +141,8 @@ class MatplotPanel(wx.Panel):
|
|
|
144
141
|
## self.canvas.mpl_connect('draw_event', lambda v: self.handler('canvas_drawn', v))
|
|
145
142
|
|
|
146
143
|
self.canvas.Bind(wx.EVT_CHAR_HOOK, self.on_hotkey_press)
|
|
147
|
-
self.canvas.Bind(wx.EVT_KEY_DOWN, self.
|
|
148
|
-
self.canvas.Bind(wx.EVT_KEY_UP, self.
|
|
144
|
+
self.canvas.Bind(wx.EVT_KEY_DOWN, self.on_hotkey_down)
|
|
145
|
+
self.canvas.Bind(wx.EVT_KEY_UP, self.on_hotkey_up)
|
|
149
146
|
|
|
150
147
|
self.canvas.Bind(wx.EVT_MOUSE_AUX1_DOWN, lambda v: self.handler('Xbutton1 pressed', v))
|
|
151
148
|
self.canvas.Bind(wx.EVT_MOUSE_AUX2_DOWN, lambda v: self.handler('Xbutton2 pressed', v))
|
|
@@ -390,7 +387,7 @@ class MatplotPanel(wx.Panel):
|
|
|
390
387
|
def on_modeline_tip(self, evt): #<wx._core.MouseEvent>
|
|
391
388
|
flag = self.modeline.HitTest(evt.Position)
|
|
392
389
|
if flag == wx.HT_WINDOW_INSIDE:
|
|
393
|
-
self.modeline.
|
|
390
|
+
self.modeline.ToolTip = self.modeline.Label
|
|
394
391
|
evt.Skip()
|
|
395
392
|
|
|
396
393
|
def on_focus_set(self, evt): #<wx._core.FocusEvent>
|
|
@@ -531,11 +528,11 @@ class MatplotPanel(wx.Panel):
|
|
|
531
528
|
def on_hotkey_press(self, evt): #<wx._core.KeyEvent>
|
|
532
529
|
"""Called when a key is pressed."""
|
|
533
530
|
key = hotkey(evt)
|
|
534
|
-
self.__key = regulate_key(key + '
|
|
531
|
+
self.__key = regulate_key(key + '-')
|
|
535
532
|
if self.handler('{} pressed'.format(key), evt) is None:
|
|
536
533
|
evt.Skip()
|
|
537
534
|
|
|
538
|
-
def
|
|
535
|
+
def on_hotkey_down(self, evt): #<wx._core.KeyEvent>
|
|
539
536
|
"""Called when a key is pressed while dragging.
|
|
540
537
|
Specifically called when the mouse is being captured.
|
|
541
538
|
"""
|
|
@@ -544,7 +541,7 @@ class MatplotPanel(wx.Panel):
|
|
|
544
541
|
else:
|
|
545
542
|
evt.Skip()
|
|
546
543
|
|
|
547
|
-
def
|
|
544
|
+
def on_hotkey_up(self, evt): #<wx._core.KeyEvent>
|
|
548
545
|
"""Called when a key is released."""
|
|
549
546
|
key = hotkey(evt)
|
|
550
547
|
self.__key = ''
|
|
@@ -655,17 +652,6 @@ class MatplotPanel(wx.Panel):
|
|
|
655
652
|
del self.Selector
|
|
656
653
|
self.canvas.draw_idle()
|
|
657
654
|
|
|
658
|
-
## def OnShiftLimit(self, evt, r=0.1):
|
|
659
|
-
## w = self.xlim[1] - self.xlim[0]
|
|
660
|
-
## h = self.ylim[1] - self.ylim[0]
|
|
661
|
-
## if 'up' in evt.key: self.ylim += h * r
|
|
662
|
-
## elif 'down' in evt.key: self.ylim -= h * r
|
|
663
|
-
## elif 'left' in evt.key: self.xlim -= w * r
|
|
664
|
-
## elif 'right' in evt.key: self.xlim += w * r
|
|
665
|
-
## if 1:
|
|
666
|
-
## self.toolbar.push_current()
|
|
667
|
-
## self.draw()
|
|
668
|
-
|
|
669
655
|
def zoomlim(self, lim, M, c=None):
|
|
670
656
|
## The limitation of zoom is necessary; If the axes is enlarged too much,
|
|
671
657
|
## the processing speed will significantly slow down.
|
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
|
|
@@ -359,33 +358,6 @@ class AxesImagePhantom(object):
|
|
|
359
358
|
x = l + (nx + 0.5) * ux
|
|
360
359
|
y = t - (ny + 0.5) * uy # Y ピクセルインデクスは座標と逆
|
|
361
360
|
return (x, y)
|
|
362
|
-
|
|
363
|
-
def calc_point(self, x, y, centred=True, inaxes=False):
|
|
364
|
-
"""Computes the nearest pixelated point from a point (x, y).
|
|
365
|
-
If centred, correct the points to the center of the nearest pixel.
|
|
366
|
-
If inaxes, restrict the points in image area.
|
|
367
|
-
"""
|
|
368
|
-
if isinstance(x, (list, tuple)):
|
|
369
|
-
x = np.array(x)
|
|
370
|
-
y = np.array(y)
|
|
371
|
-
l,r,b,t = self.__art.get_extent()
|
|
372
|
-
if inaxes:
|
|
373
|
-
x[x < l] = l
|
|
374
|
-
x[x > r] = r
|
|
375
|
-
y[y < b] = b
|
|
376
|
-
y[y > t] = t
|
|
377
|
-
nx, ny = self.xytopixel(x, y)
|
|
378
|
-
ux, uy = self.xy_unit
|
|
379
|
-
if centred:
|
|
380
|
-
x = l + (nx + 0.5) * ux
|
|
381
|
-
y = t - (ny + 0.5) * uy
|
|
382
|
-
if inaxes:
|
|
383
|
-
x[x > r] -= ux
|
|
384
|
-
y[y < b] += uy
|
|
385
|
-
else:
|
|
386
|
-
x = l + nx * ux
|
|
387
|
-
y = t - ny * uy
|
|
388
|
-
return (x, y)
|
|
389
361
|
|
|
390
362
|
|
|
391
363
|
class GraphPlot(MatplotPanel):
|
|
@@ -589,6 +561,8 @@ class GraphPlot(MatplotPanel):
|
|
|
589
561
|
|
|
590
562
|
self.modeline.Show(1)
|
|
591
563
|
self.Layout()
|
|
564
|
+
|
|
565
|
+
self.writeln()
|
|
592
566
|
|
|
593
567
|
def clear(self):
|
|
594
568
|
MatplotPanel.clear(self)
|
|
@@ -834,7 +808,6 @@ class GraphPlot(MatplotPanel):
|
|
|
834
808
|
else:
|
|
835
809
|
if v == self.__unit: # no effect unless unit changes
|
|
836
810
|
return
|
|
837
|
-
u = self.__unit
|
|
838
811
|
self.__unit = v
|
|
839
812
|
for art in self.__Arts:
|
|
840
813
|
art.update_extent()
|
|
@@ -907,13 +880,12 @@ class GraphPlot(MatplotPanel):
|
|
|
907
880
|
|
|
908
881
|
def trace_point(self, x, y, type=NORMAL):
|
|
909
882
|
"""Puts (override) a message of points x and y."""
|
|
910
|
-
|
|
883
|
+
frame = self.frame
|
|
884
|
+
if frame:
|
|
911
885
|
if not hasattr(x, '__iter__'): # called from OnMotion
|
|
912
|
-
nx, ny =
|
|
913
|
-
z =
|
|
914
|
-
self.message(
|
|
915
|
-
"[{:-4d},{:-4d}] "
|
|
916
|
-
"({:-8.3f},{:-8.3f}) value: {}".format(nx, ny, x, y, z))
|
|
886
|
+
nx, ny = frame.xytopixel(x, y)
|
|
887
|
+
z = frame.xytoc(x, y)
|
|
888
|
+
self.message(f"[{nx:-4d},{ny:-4d}] ({x:-8.3f},{y:-8.3f}) value: {z}")
|
|
917
889
|
return
|
|
918
890
|
|
|
919
891
|
if len(x) == 0: # no selection
|
|
@@ -923,43 +895,41 @@ class GraphPlot(MatplotPanel):
|
|
|
923
895
|
return self.trace_point(x[0], y[0], type)
|
|
924
896
|
|
|
925
897
|
if len(x) == 2: # 2-Selector trace line (called from Selector:setter)
|
|
926
|
-
nx, ny =
|
|
898
|
+
nx, ny = frame.xytopixel(x, y)
|
|
927
899
|
dx = x[1] - x[0]
|
|
928
900
|
dy = y[1] - y[0]
|
|
929
901
|
a = np.arctan2(dy, dx) * 180/pi
|
|
930
902
|
lu = np.hypot(dy, dx)
|
|
931
903
|
li = np.hypot(nx[1]-nx[0], ny[1]-ny[0])
|
|
932
|
-
self.message("[Line] "
|
|
933
|
-
"Length: {:.1f} pixel ({:g}u) "
|
|
934
|
-
"Angle: {:.1f} deg".format(li, lu, a))
|
|
904
|
+
self.message(f"[Line] Length: {li:.1f} pixel ({lu:g}u) Angle: {a:.1f} deg")
|
|
935
905
|
|
|
936
906
|
elif type == REGION: # N-Selector trace polygon (called from Region:setter)
|
|
937
|
-
nx, ny =
|
|
907
|
+
nx, ny = frame.xytopixel(x, y)
|
|
938
908
|
xo, yo = min(nx), min(ny) # top-left
|
|
939
909
|
xr, yr = max(nx), max(ny) # bottom-right
|
|
940
|
-
self.message("[Region] "
|
|
941
|
-
"crop={}:{}:{}:{}".format(xr-xo, yr-yo, xo, yo)) # (W:H:left:top)
|
|
910
|
+
self.message(f"[Region] crop={xr-xo}:{yr-yo}:{xo}:{yo}") # (W:H:left:top)
|
|
942
911
|
|
|
943
912
|
def writeln(self):
|
|
944
913
|
"""Puts (override) attributes of current frame to the modeline."""
|
|
945
914
|
if not self.modeline.IsShown():
|
|
946
915
|
return
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
916
|
+
frame = self.frame
|
|
917
|
+
if frame:
|
|
918
|
+
self.modeline.SetLabel(
|
|
919
|
+
"[{page}/{maxpage}] -{a}- {name} ({data.dtype}:{cmap}{bins}) "
|
|
920
|
+
"[{data.shape[1]}:{data.shape[0]}] {x} [{unit:g}/pixel]".format(
|
|
951
921
|
page = self.__index,
|
|
952
922
|
maxpage = len(self),
|
|
953
|
-
name =
|
|
954
|
-
data =
|
|
955
|
-
cmap =
|
|
956
|
-
bins = ' bin{}'.format(
|
|
957
|
-
unit =
|
|
958
|
-
x = '**' if
|
|
959
|
-
a = '%%' if not
|
|
923
|
+
name = frame.name,
|
|
924
|
+
data = frame.buffer,
|
|
925
|
+
cmap = frame.get_cmap().name,
|
|
926
|
+
bins = ' bin{}'.format(frame.binning) if frame.binning > 1 else '',
|
|
927
|
+
unit = frame.unit,
|
|
928
|
+
x = '**' if frame.localunit else '--',
|
|
929
|
+
a = '%%' if not frame.buffer.flags.writeable else '--'))
|
|
960
930
|
else:
|
|
961
|
-
self.modeline.
|
|
962
|
-
|
|
931
|
+
self.modeline.SetLabel(
|
|
932
|
+
"[{page}/{maxpage}] ---- No buffer (-:-) [-:-] -- [{unit:g}/pixel]".format(
|
|
963
933
|
page = '-',
|
|
964
934
|
maxpage = len(self),
|
|
965
935
|
unit = self.__unit))
|
|
@@ -973,15 +943,16 @@ class GraphPlot(MatplotPanel):
|
|
|
973
943
|
|
|
974
944
|
def write_buffer_to_clipboard(self):
|
|
975
945
|
"""Write buffer data to clipboard."""
|
|
976
|
-
|
|
946
|
+
frame = self.frame
|
|
947
|
+
if not frame:
|
|
977
948
|
self.message("No frame")
|
|
978
949
|
return
|
|
979
950
|
try:
|
|
980
|
-
name =
|
|
981
|
-
data =
|
|
951
|
+
name = frame.name
|
|
952
|
+
data = frame.roi
|
|
982
953
|
GraphPlot.clipboard_name = name
|
|
983
954
|
GraphPlot.clipboard_data = data
|
|
984
|
-
bins, vlim, img = imconvert(data,
|
|
955
|
+
bins, vlim, img = imconvert(data, frame.vlim)
|
|
985
956
|
Clipboard.imwrite(img)
|
|
986
957
|
self.message("Write buffer to clipboard.")
|
|
987
958
|
except Exception as e:
|
|
@@ -1034,10 +1005,6 @@ class GraphPlot(MatplotPanel):
|
|
|
1034
1005
|
self.handler.bind('frame_shown', self.update_colorbar)
|
|
1035
1006
|
else:
|
|
1036
1007
|
self.message("- A frame must exist to create a colorbar.")
|
|
1037
|
-
## self['*dummy*'] = np.random.rand(2,2) # dummy
|
|
1038
|
-
## self.create_colorbar()
|
|
1039
|
-
## del self['*dummy*']
|
|
1040
|
-
pass
|
|
1041
1008
|
|
|
1042
1009
|
## --------------------------------
|
|
1043
1010
|
## matplotlib interfaces
|
|
@@ -1047,9 +1014,9 @@ class GraphPlot(MatplotPanel):
|
|
|
1047
1014
|
"""Pickup image and other arts.
|
|
1048
1015
|
Called (maybe) after mouse buttons are pressed.
|
|
1049
1016
|
"""
|
|
1050
|
-
## canvas 全体に有効だが,分割された axes (colorbar 領域など)
|
|
1051
|
-
## image
|
|
1052
|
-
##
|
|
1017
|
+
## canvas 全体に有効だが,分割された axes (colorbar 領域など) は無効.
|
|
1018
|
+
## image - plot が重なっている場合,plot -> image の順に呼び出される.
|
|
1019
|
+
## 多重呼び出しが起きないように __isPicked フラグで排他制御する.
|
|
1053
1020
|
|
|
1054
1021
|
if evt.mouseevent.button != 1 or not evt.artist.get_visible():
|
|
1055
1022
|
return
|
|
@@ -1118,15 +1085,16 @@ class GraphPlot(MatplotPanel):
|
|
|
1118
1085
|
"""Called before canvas.draw (overridden)."""
|
|
1119
1086
|
if not self.interpolation_mode:
|
|
1120
1087
|
return
|
|
1121
|
-
|
|
1088
|
+
frame = self.frame
|
|
1089
|
+
if frame:
|
|
1122
1090
|
## [dots/pixel] = [dots/u] * [u/pixel]
|
|
1123
|
-
dots = self.ddpu[0] *
|
|
1091
|
+
dots = self.ddpu[0] * frame.unit * frame.binning
|
|
1124
1092
|
|
|
1125
|
-
if
|
|
1126
|
-
|
|
1093
|
+
if frame.get_interpolation() == 'nearest' and dots < 1:
|
|
1094
|
+
frame.set_interpolation(self.interpolation_mode)
|
|
1127
1095
|
|
|
1128
|
-
elif
|
|
1129
|
-
|
|
1096
|
+
elif frame.get_interpolation() != 'nearest' and dots > 1:
|
|
1097
|
+
frame.set_interpolation('nearest')
|
|
1130
1098
|
|
|
1131
1099
|
def OnMotion(self, evt):
|
|
1132
1100
|
"""Called when mouse moves in axes (overridden)."""
|
|
@@ -1135,13 +1103,15 @@ class GraphPlot(MatplotPanel):
|
|
|
1135
1103
|
|
|
1136
1104
|
def OnPageDown(self, evt):
|
|
1137
1105
|
"""Next page."""
|
|
1138
|
-
|
|
1139
|
-
|
|
1106
|
+
i = self.__index
|
|
1107
|
+
if i is not None and i < len(self)-1:
|
|
1108
|
+
self.select(i + 1)
|
|
1140
1109
|
|
|
1141
1110
|
def OnPageUp(self, evt):
|
|
1142
1111
|
"""Previous page."""
|
|
1143
|
-
|
|
1144
|
-
|
|
1112
|
+
i = self.__index
|
|
1113
|
+
if i is not None and i > 0:
|
|
1114
|
+
self.select(i - 1)
|
|
1145
1115
|
|
|
1146
1116
|
def OnHomePosition(self, evt):
|
|
1147
1117
|
self.update_axis()
|
|
@@ -1152,14 +1122,6 @@ class GraphPlot(MatplotPanel):
|
|
|
1152
1122
|
if len(xs) > 1:
|
|
1153
1123
|
self.handler('line_removed', self.frame)
|
|
1154
1124
|
|
|
1155
|
-
## def zoomlim(self, lim, M, c=None): # virtual call from OnZoom, OnScrollZoom
|
|
1156
|
-
## if c is None:
|
|
1157
|
-
## c = (lim[1] + lim[0]) / 2
|
|
1158
|
-
## y = c - M * (c - lim)
|
|
1159
|
-
## if self.frame:
|
|
1160
|
-
## if abs(y[1] - y[0]) > self.frame.unit or M > 1:
|
|
1161
|
-
## return y
|
|
1162
|
-
|
|
1163
1125
|
def OnXAxisPanZoom(self, evt, c=None):
|
|
1164
1126
|
org = self.p_event
|
|
1165
1127
|
M = np.exp(-(evt.x - org.x)/100)
|
|
@@ -1184,11 +1146,33 @@ class GraphPlot(MatplotPanel):
|
|
|
1184
1146
|
## Selector interface
|
|
1185
1147
|
## --------------------------------
|
|
1186
1148
|
|
|
1187
|
-
def calc_point(self, x, y, centred=True):
|
|
1188
|
-
"""
|
|
1189
|
-
If centred, correct the
|
|
1149
|
+
def calc_point(self, x, y, centred=True, inaxes=False):
|
|
1150
|
+
"""Computes the nearest pixelated point from a point (x, y).
|
|
1151
|
+
If centred, correct the points to the center of the nearest pixel.
|
|
1152
|
+
If inaxes, restrict the points in image area.
|
|
1190
1153
|
"""
|
|
1191
|
-
|
|
1154
|
+
frame = self.frame
|
|
1155
|
+
if isinstance(x, (list, tuple)):
|
|
1156
|
+
x = np.array(x)
|
|
1157
|
+
y = np.array(y)
|
|
1158
|
+
l,r,b,t = frame.get_extent()
|
|
1159
|
+
if inaxes:
|
|
1160
|
+
x[x < l] = l
|
|
1161
|
+
x[x > r] = r
|
|
1162
|
+
y[y < b] = b
|
|
1163
|
+
y[y > t] = t
|
|
1164
|
+
nx, ny = frame.xytopixel(x, y)
|
|
1165
|
+
ux, uy = frame.xy_unit
|
|
1166
|
+
if centred:
|
|
1167
|
+
x = l + (nx + 0.5) * ux
|
|
1168
|
+
y = t - (ny + 0.5) * uy
|
|
1169
|
+
if inaxes:
|
|
1170
|
+
x[x > r] -= ux
|
|
1171
|
+
y[y < b] += uy
|
|
1172
|
+
else:
|
|
1173
|
+
x = l + nx * ux
|
|
1174
|
+
y = t - ny * uy
|
|
1175
|
+
return (x, y)
|
|
1192
1176
|
|
|
1193
1177
|
def calc_shiftpoint(self, xo, yo, x, y, centred=True):
|
|
1194
1178
|
"""Restrict point (x, y) from (xo, yo) in pi/8 step angles.
|
mwx/matplot2lg.py
CHANGED
|
@@ -59,8 +59,9 @@ class LinePlot(MatplotPanel):
|
|
|
59
59
|
|
|
60
60
|
## Note for matplotlib >= 3.9.0:
|
|
61
61
|
## axhspan and axvspan now return Rectangles, not Polygons.
|
|
62
|
-
|
|
62
|
+
|
|
63
63
|
#<matplotlib.patches.Polygon>
|
|
64
|
+
#<matplotlib.patches.Rectangle>
|
|
64
65
|
self.__vspan = self.axes.axvspan(0, 0,
|
|
65
66
|
color='none', ls='dashed', lw=1, ec='black', visible=0, zorder=2)
|
|
66
67
|
|
|
@@ -331,15 +332,17 @@ class Histogram(LinePlot):
|
|
|
331
332
|
frame = self.__frame
|
|
332
333
|
if frame:
|
|
333
334
|
x, y = frame.__data
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
335
|
+
if self.region is not None:
|
|
336
|
+
i, j = x.searchsorted(self.region)
|
|
337
|
+
else:
|
|
338
|
+
i, j = np.uint8(self.xlim)
|
|
339
|
+
self.modeline.SetLabel(
|
|
340
|
+
"[--] ---- {name} ({type}:) [{}:{}]".format(i, j,
|
|
337
341
|
name = frame.name,
|
|
338
342
|
type = frame.buffer.dtype,
|
|
339
|
-
|
|
340
|
-
bins = (i, j)))
|
|
343
|
+
))
|
|
341
344
|
else:
|
|
342
|
-
self.modeline.
|
|
345
|
+
self.modeline.SetLabel("")
|
|
343
346
|
|
|
344
347
|
## --------------------------------
|
|
345
348
|
## Motion/Drag actions (override)
|
|
@@ -349,7 +352,10 @@ class Histogram(LinePlot):
|
|
|
349
352
|
if self.__frame:
|
|
350
353
|
x, y = self.__frame.__data
|
|
351
354
|
if len(x) > 1:
|
|
352
|
-
|
|
355
|
+
if self.region is not None:
|
|
356
|
+
i, j = x.searchsorted(self.region)
|
|
357
|
+
else:
|
|
358
|
+
i, j = (0, -1)
|
|
353
359
|
self.__fil.set_xy(list(chain([(x[i],0)], zip(x[i:j],y[i:j]), [(x[j-1],0)])))
|
|
354
360
|
else:
|
|
355
361
|
self.__fil.set_xy([(0,0)])
|
|
@@ -601,19 +607,19 @@ class LineProfile(LinePlot):
|
|
|
601
607
|
return
|
|
602
608
|
frame = self.__frame
|
|
603
609
|
if frame:
|
|
604
|
-
self.modeline.
|
|
605
|
-
|
|
606
|
-
|
|
610
|
+
self.modeline.SetLabel(
|
|
611
|
+
"[--] -{a}- {name} ({type}:{mode}) "
|
|
612
|
+
"[{length}:{width}] {x} [{unit:g}/pixel]".format(
|
|
607
613
|
name = frame.name,
|
|
608
614
|
type = frame.buffer.dtype,
|
|
609
|
-
mode = "
|
|
615
|
+
mode = "logic" if self.__logicp else "pixel",
|
|
610
616
|
width = self.__linewidth,
|
|
611
617
|
length = len(self.plotdata[0]),
|
|
612
|
-
unit = frame.unit
|
|
613
|
-
x = '
|
|
618
|
+
unit = frame.unit,
|
|
619
|
+
x = '**' if frame.localunit else '--',
|
|
614
620
|
a = '%%' if not frame.buffer.flags.writeable else '--'))
|
|
615
621
|
else:
|
|
616
|
-
self.modeline.
|
|
622
|
+
self.modeline.SetLabel("")
|
|
617
623
|
|
|
618
624
|
def write_data_to_clipboard(self):
|
|
619
625
|
"""Write plot data to clipboard."""
|
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)
|
mwx/plugins/ffmpeg_view.py
CHANGED
|
@@ -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.
|
|
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.
|
|
46
|
-
self.parent.
|
|
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):
|
mwx/plugins/frame_listview.py
CHANGED
|
@@ -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 = { #
|
|
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/wxwil.py
CHANGED
|
@@ -69,11 +69,8 @@ class LocalsWatcher(wx.ListCtrl, ListCtrlAutoWidthMixin, CtrlInterface):
|
|
|
69
69
|
def watch(self, locals):
|
|
70
70
|
self.clear()
|
|
71
71
|
if not isinstance(locals, dict):
|
|
72
|
-
## wx.MessageBox("Cannot watch the locals.\n\n"
|
|
73
|
-
## "- {!r} is not a dict object.".format(locals))
|
|
74
72
|
self.unwatch()
|
|
75
73
|
return
|
|
76
|
-
busy = wx.BusyCursor()
|
|
77
74
|
self.target = locals
|
|
78
75
|
try:
|
|
79
76
|
self.Freeze()
|
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
|
])
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
mwx/__init__.py,sha256=nN62CGTWjME7Zz2h-jIRB8MxwuErIkHPGrlBzydkF0o,643
|
|
2
|
+
mwx/bookshelf.py,sha256=UgyVYHiYUL2wEvVw110vWnvkJBtXgYAE5hvz9MMLRsU,5333
|
|
3
|
+
mwx/controls.py,sha256=s6yJzQyYnjCzcjXa6nbTJncxzpMI0E5zYWPn3-cFy5Q,48378
|
|
4
|
+
mwx/framework.py,sha256=cXyfw0-PdkONYMHM-h9OsVIsOnDO3C1f4aDC5aYBP4o,75332
|
|
5
|
+
mwx/graphman.py,sha256=VktL6fnYt2BBo-r7UVgVcqVd7IIOY9vpGBDNLNie088,70606
|
|
6
|
+
mwx/images.py,sha256=_-Eh3xF7Khu42ivkYp97NXIzSNGbjcidqtWjZQFGtqE,47827
|
|
7
|
+
mwx/matplot2.py,sha256=xCJ_ZzdDEWmzctpPaOrzTnwXyHINP4nfFHweoTZa6ug,32899
|
|
8
|
+
mwx/matplot2g.py,sha256=jSyRTW9oUqAKA9L9Rcujxy1QLoFOVg411HjVNElexzQ,64401
|
|
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.0.dist-info/LICENSE,sha256=PGtRKCaTkmUDlBQwpptJAxJtdqxIUtAmdBsaT9nUVkA,1091
|
|
25
|
+
mwxlib-0.97.0.dist-info/METADATA,sha256=3nBiqPuPWhRv2W2keE3GqrTbXBNP9N0iWDOPDKPh6DA,1880
|
|
26
|
+
mwxlib-0.97.0.dist-info/WHEEL,sha256=Z4pYXqR_rTB7OWNDYFOm1qRk0RX6GFP2o8LgvP453Hk,91
|
|
27
|
+
mwxlib-0.97.0.dist-info/top_level.txt,sha256=SI1Mh118AstnUFGPNq5aMNKiAnVNmZk1S9Ij-OwAEpY,4
|
|
28
|
+
mwxlib-0.97.0.dist-info/RECORD,,
|
mwxlib-0.96.7.dist-info/RECORD
DELETED
|
@@ -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=t1d0wXned_XQV5uFYZEdzFhE3d-eCvFb0GIn3W0Uz9E,75227
|
|
5
|
-
mwx/graphman.py,sha256=XoD_wbt5wrmiRf8Q3lpn_eklakE2K-rLfpzfXG1L-Pc,71269
|
|
6
|
-
mwx/images.py,sha256=_-Eh3xF7Khu42ivkYp97NXIzSNGbjcidqtWjZQFGtqE,47827
|
|
7
|
-
mwx/matplot2.py,sha256=-G7z0Osozm9NjLfXvX5UcdFviwbNUktjbd904_g-PqQ,33516
|
|
8
|
-
mwx/matplot2g.py,sha256=22rpdkqJQEJADINPaG5htACutbt8oG1ewO8LMpxaqH4,65237
|
|
9
|
-
mwx/matplot2lg.py,sha256=4KEkl5407P_D4xHKmar6j_cfIBBCEGkm7wC_3CzgxRI,27303
|
|
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=0bzSTfMEjllJheKxZPb4p8Luz6Il3V29bCLBty72U2o,5576
|
|
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.7.dist-info/LICENSE,sha256=PGtRKCaTkmUDlBQwpptJAxJtdqxIUtAmdBsaT9nUVkA,1091
|
|
25
|
-
mwxlib-0.96.7.dist-info/METADATA,sha256=dJYCzwaGevIma7TaUYe9whPB1wOXX_-V6rRmUvJgq6g,1880
|
|
26
|
-
mwxlib-0.96.7.dist-info/WHEEL,sha256=y4mX-SOX4fYIkonsAGA5N0Oy-8_gI4FXw5HNI1xqvWg,91
|
|
27
|
-
mwxlib-0.96.7.dist-info/top_level.txt,sha256=SI1Mh118AstnUFGPNq5aMNKiAnVNmZk1S9Ij-OwAEpY,4
|
|
28
|
-
mwxlib-0.96.7.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|