mwxlib 0.98.6__py3-none-any.whl → 0.99.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.
- mwx/bookshelf.py +66 -55
- mwx/controls.py +46 -37
- mwx/framework.py +22 -13
- mwx/graphman.py +3 -9
- mwx/matplot2g.py +1 -2
- mwx/mgplt.py +5 -7
- mwx/nutshell.py +52 -78
- mwx/plugins/ffmpeg_view.py +14 -3
- mwx/plugins/frame_listview.py +1 -1
- mwx/wxmon.py +2 -5
- {mwxlib-0.98.6.dist-info → mwxlib-0.99.0.dist-info}/METADATA +1 -1
- mwxlib-0.99.0.dist-info/RECORD +28 -0
- {mwxlib-0.98.6.dist-info → mwxlib-0.99.0.dist-info}/WHEEL +1 -1
- mwxlib-0.98.6.dist-info/RECORD +0 -28
- {mwxlib-0.98.6.dist-info → mwxlib-0.99.0.dist-info}/LICENSE +0 -0
- {mwxlib-0.98.6.dist-info → mwxlib-0.99.0.dist-info}/top_level.txt +0 -0
mwx/bookshelf.py
CHANGED
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
import re
|
|
3
3
|
import wx
|
|
4
4
|
|
|
5
|
-
from .utilus import funcall as _F
|
|
6
5
|
from .framework import CtrlInterface, postcall
|
|
7
6
|
|
|
8
7
|
|
|
@@ -18,31 +17,11 @@ class EditorTreeCtrl(wx.TreeCtrl, CtrlInterface):
|
|
|
18
17
|
self.Font = wx.Font(9, wx.DEFAULT, wx.NORMAL, wx.NORMAL)
|
|
19
18
|
|
|
20
19
|
self.parent = parent
|
|
21
|
-
self.target = None
|
|
22
|
-
|
|
23
|
-
self.context = { # DNA<EditorBook>
|
|
24
|
-
None : {
|
|
25
|
-
'buffer_new' : [ None, self.on_buffer_new ],
|
|
26
|
-
'buffer_saved' : [ None, ],
|
|
27
|
-
'buffer_loaded' : [ None, ],
|
|
28
|
-
'buffer_deleted' : [ None, self.on_buffer_deleted ],
|
|
29
|
-
'buffer_activated' : [ None, self.on_buffer_selected ],
|
|
30
|
-
'buffer_inactivated' : [ None, ],
|
|
31
|
-
'buffer_caption_updated' : [ None, self.on_buffer_filename ],
|
|
32
|
-
},
|
|
33
|
-
}
|
|
34
|
-
wx.CallAfter(self.attach, target=parent)
|
|
35
20
|
|
|
36
21
|
## self.Bind(wx.EVT_TREE_ITEM_GETTOOLTIP, self.OnItemTooltip)
|
|
37
22
|
self.Bind(wx.EVT_TREE_SEL_CHANGED, self.OnSelChanged)
|
|
38
23
|
self.Bind(wx.EVT_WINDOW_DESTROY, self.OnDestroy)
|
|
39
24
|
|
|
40
|
-
def delete_item():
|
|
41
|
-
data = self.GetItemData(self.Selection)
|
|
42
|
-
if data:
|
|
43
|
-
data.parent.kill_buffer(data) # the focus moves
|
|
44
|
-
wx.CallAfter(self.SetFocus)
|
|
45
|
-
|
|
46
25
|
def dispatch(evt):
|
|
47
26
|
"""Fork events to the parent."""
|
|
48
27
|
self.parent.handler(self.handler.current_event, evt)
|
|
@@ -54,33 +33,57 @@ class EditorTreeCtrl(wx.TreeCtrl, CtrlInterface):
|
|
|
54
33
|
'*button* released' : [ None, dispatch ],
|
|
55
34
|
},
|
|
56
35
|
0 : {
|
|
57
|
-
'delete pressed' : (0,
|
|
58
|
-
'f5 pressed' : (0,
|
|
59
|
-
'S-f5 pressed' : (0, _F(self.build_tree, clear=1)),
|
|
36
|
+
'delete pressed' : (0, self._delete),
|
|
37
|
+
'f5 pressed' : (0, self._refresh),
|
|
60
38
|
},
|
|
61
39
|
})
|
|
40
|
+
self.context = { # DNA<EditorBook>
|
|
41
|
+
None : {
|
|
42
|
+
'buffer_new' : [ None, self.on_buffer_new ],
|
|
43
|
+
'buffer_saved' : [ None, ],
|
|
44
|
+
'buffer_loaded' : [ None, ],
|
|
45
|
+
'buffer_deleted' : [ None, self.on_buffer_deleted ],
|
|
46
|
+
'buffer_activated' : [ None, self.on_buffer_selected ],
|
|
47
|
+
'buffer_inactivated' : [ None, ],
|
|
48
|
+
'buffer_caption_updated' : [ None, self.on_buffer_filename ],
|
|
49
|
+
},
|
|
50
|
+
}
|
|
51
|
+
def _attach():
|
|
52
|
+
if self and self.parent:
|
|
53
|
+
for editor in self.parent.all_editors:
|
|
54
|
+
editor.handler.append(self.context)
|
|
55
|
+
self.build_tree()
|
|
56
|
+
wx.CallAfter(_attach)
|
|
62
57
|
|
|
63
58
|
def OnDestroy(self, evt):
|
|
64
|
-
if
|
|
65
|
-
self.
|
|
59
|
+
if self and self.parent:
|
|
60
|
+
for editor in self.parent.all_editors:
|
|
61
|
+
editor.handler.remove(self.context)
|
|
66
62
|
evt.Skip()
|
|
67
63
|
|
|
68
|
-
def
|
|
69
|
-
|
|
70
|
-
return
|
|
71
|
-
|
|
72
|
-
self.
|
|
73
|
-
|
|
74
|
-
|
|
64
|
+
def _refresh(self, evt):
|
|
65
|
+
def _item(editor):
|
|
66
|
+
return self._get_item(self.RootItem, editor.Name)
|
|
67
|
+
ls = []
|
|
68
|
+
for editor in self.parent.all_editors:
|
|
69
|
+
if self.IsExpanded(_item(editor)):
|
|
70
|
+
ls.append(editor)
|
|
71
|
+
data = None
|
|
72
|
+
if self.Selection.IsOk():
|
|
73
|
+
data = self.GetItemData(self.Selection)
|
|
74
|
+
if data:
|
|
75
|
+
wx.CallAfter(data.SetFocus)
|
|
76
|
+
wx.CallAfter(self.SetFocus)
|
|
75
77
|
self.build_tree()
|
|
78
|
+
for editor in ls:
|
|
79
|
+
self.Expand(_item(editor))
|
|
76
80
|
|
|
77
|
-
def
|
|
78
|
-
if
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
self.build_tree()
|
|
81
|
+
def _delete(self, evt):
|
|
82
|
+
if self.Selection.IsOk():
|
|
83
|
+
data = self.GetItemData(self.Selection)
|
|
84
|
+
if data:
|
|
85
|
+
data.parent.kill_buffer(data) # the focus moves
|
|
86
|
+
wx.CallAfter(self.SetFocus)
|
|
84
87
|
|
|
85
88
|
## --------------------------------
|
|
86
89
|
## TreeList/Ctrl wrapper interface
|
|
@@ -93,33 +96,39 @@ class EditorTreeCtrl(wx.TreeCtrl, CtrlInterface):
|
|
|
93
96
|
if clear:
|
|
94
97
|
self.DeleteAllItems()
|
|
95
98
|
self.AddRoot(self.Name)
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
self._set_item(self.RootItem, editor.Name, editor.all_buffers)
|
|
99
|
+
for editor in self.parent.all_editors:
|
|
100
|
+
self._set_item(self.RootItem, editor.Name, editor.all_buffers)
|
|
99
101
|
self.Refresh()
|
|
100
102
|
|
|
101
|
-
def
|
|
102
|
-
"""
|
|
103
|
-
Note: Items with the same name are not supported.
|
|
104
|
-
"""
|
|
103
|
+
def _gen_item(self, root, key):
|
|
104
|
+
"""Generates the [root/key] items."""
|
|
105
105
|
item, cookie = self.GetFirstChild(root)
|
|
106
106
|
while item:
|
|
107
107
|
caption = self.GetItemText(item)
|
|
108
108
|
if key == re.sub(r"^\W+\s+(.*)", r"\1", caption):
|
|
109
|
-
|
|
109
|
+
yield item
|
|
110
110
|
item, cookie = self.GetNextChild(root, cookie)
|
|
111
111
|
|
|
112
|
+
def _get_item(self, root, key):
|
|
113
|
+
"""Get the first [root/key] item found."""
|
|
114
|
+
return next(self._gen_item(root, key), None)
|
|
115
|
+
|
|
112
116
|
def _set_item(self, root, key, data):
|
|
113
|
-
"""Set the
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
+
"""Set the [root/key] item with data recursively."""
|
|
118
|
+
for item in self._gen_item(root, key):
|
|
119
|
+
buf = self.GetItemData(item)
|
|
120
|
+
if not buf or buf is data:
|
|
121
|
+
break
|
|
122
|
+
else:
|
|
123
|
+
item = self.AppendItem(root, key)
|
|
124
|
+
try:
|
|
117
125
|
for buf in data:
|
|
118
126
|
self._set_item(item, buf.name, buf)
|
|
119
|
-
|
|
127
|
+
except Exception:
|
|
120
128
|
data.__itemId = item
|
|
121
129
|
self.SetItemData(item, data)
|
|
122
130
|
self.SetItemText(item, data.caption_prefix + data.name)
|
|
131
|
+
return item
|
|
123
132
|
|
|
124
133
|
## --------------------------------
|
|
125
134
|
## Actions for bookshelf interfaces
|
|
@@ -135,10 +144,12 @@ class EditorTreeCtrl(wx.TreeCtrl, CtrlInterface):
|
|
|
135
144
|
## buf.__itemId がない場合がある (delete_buffer 直後など)
|
|
136
145
|
@postcall
|
|
137
146
|
def on_buffer_selected(self, buf):
|
|
138
|
-
self
|
|
147
|
+
if self and buf:
|
|
148
|
+
self.SelectItem(buf.__itemId)
|
|
139
149
|
|
|
140
150
|
def on_buffer_filename(self, buf):
|
|
141
|
-
self
|
|
151
|
+
if self and buf:
|
|
152
|
+
self.SetItemText(buf.__itemId, buf.caption_prefix + buf.name)
|
|
142
153
|
|
|
143
154
|
def OnSelChanged(self, evt):
|
|
144
155
|
if self and self.HasFocus():
|
mwx/controls.py
CHANGED
|
@@ -7,9 +7,9 @@ import wx.lib.platebtn as pb
|
|
|
7
7
|
import wx.lib.scrolledpanel as scrolled
|
|
8
8
|
|
|
9
9
|
from . import images
|
|
10
|
-
from .utilus import SSM
|
|
10
|
+
from .utilus import SSM, warn
|
|
11
11
|
from .utilus import funcall as _F
|
|
12
|
-
from .framework import pack, Menu,
|
|
12
|
+
from .framework import pack, Menu, CtrlInterface
|
|
13
13
|
|
|
14
14
|
import numpy as np
|
|
15
15
|
from numpy import nan, inf # noqa: necessary to eval
|
|
@@ -26,7 +26,7 @@ class Param:
|
|
|
26
26
|
Args:
|
|
27
27
|
name : label
|
|
28
28
|
range : range
|
|
29
|
-
value : std_value (default is
|
|
29
|
+
value : std_value (default is nan)
|
|
30
30
|
fmt : text formatter or format:str (default is '%g')
|
|
31
31
|
`hex` specifies hexadecimal format
|
|
32
32
|
handler : called when control changed
|
|
@@ -84,11 +84,19 @@ class Param:
|
|
|
84
84
|
def __len__(self):
|
|
85
85
|
return len(self.range)
|
|
86
86
|
|
|
87
|
+
def bind(self, action=None, target='control'):
|
|
88
|
+
warn("Use `Param.callback.bind('control')` instead.", DeprecationWarning)
|
|
89
|
+
return self.callback.bind(target, action)
|
|
90
|
+
|
|
91
|
+
def unbind(self, action=None, target='control'):
|
|
92
|
+
warn("Use `Param.callback.unbind('control')` instead.", DeprecationWarning)
|
|
93
|
+
return self.callback.unbind(target, action)
|
|
94
|
+
|
|
87
95
|
def reset(self, v=None, internal_callback=True):
|
|
88
96
|
"""Reset value when indexed (by knobs) with callback."""
|
|
89
97
|
if v is None:
|
|
90
|
-
v = self.std_value
|
|
91
|
-
if np.isnan(v):
|
|
98
|
+
v = self.std_value # reset to std_value
|
|
99
|
+
if np.isnan(v): # do nothing if std_value is nan
|
|
92
100
|
return
|
|
93
101
|
elif isinstance(v, str):
|
|
94
102
|
try:
|
|
@@ -96,7 +104,27 @@ class Param:
|
|
|
96
104
|
except Exception:
|
|
97
105
|
v = self.value
|
|
98
106
|
internal_callback = False
|
|
99
|
-
|
|
107
|
+
|
|
108
|
+
if v is None:
|
|
109
|
+
v = nan
|
|
110
|
+
if np.isnan(v) or np.isinf(v):
|
|
111
|
+
self.__value = v
|
|
112
|
+
for knob in self.knobs:
|
|
113
|
+
knob.update_ctrl(None, notify=False)
|
|
114
|
+
return
|
|
115
|
+
if v != self.__value:
|
|
116
|
+
## If the value is out of range, it will be modified.
|
|
117
|
+
valid = (self.min <= v <= self.max)
|
|
118
|
+
if valid:
|
|
119
|
+
self.__value = v
|
|
120
|
+
elif v < self.min:
|
|
121
|
+
self.__value = self.min
|
|
122
|
+
self.callback('underflow', self)
|
|
123
|
+
else:
|
|
124
|
+
self.__value = self.max
|
|
125
|
+
self.callback('overflow', self)
|
|
126
|
+
for knob in self.knobs:
|
|
127
|
+
knob.update_ctrl(valid, notify=True)
|
|
100
128
|
if internal_callback:
|
|
101
129
|
self.callback('control', self)
|
|
102
130
|
|
|
@@ -129,30 +157,7 @@ class Param:
|
|
|
129
157
|
|
|
130
158
|
@value.setter
|
|
131
159
|
def value(self, v):
|
|
132
|
-
|
|
133
|
-
v = nan
|
|
134
|
-
if np.isnan(v) or np.isinf(v):
|
|
135
|
-
self.__value = v
|
|
136
|
-
for knob in self.knobs:
|
|
137
|
-
knob.update_ctrl(None, notify=False)
|
|
138
|
-
return
|
|
139
|
-
elif v == self.__value:
|
|
140
|
-
for knob in self.knobs:
|
|
141
|
-
knob.update_ctrl(True, notify=False)
|
|
142
|
-
return
|
|
143
|
-
|
|
144
|
-
## If the value is out of range, it will be modified.
|
|
145
|
-
valid = (self.min <= v <= self.max)
|
|
146
|
-
if valid:
|
|
147
|
-
self.__value = v
|
|
148
|
-
elif v < self.min:
|
|
149
|
-
self.__value = self.min
|
|
150
|
-
self.callback('underflow', self)
|
|
151
|
-
else:
|
|
152
|
-
self.__value = self.max
|
|
153
|
-
self.callback('overflow', self)
|
|
154
|
-
for knob in self.knobs:
|
|
155
|
-
knob.update_ctrl(valid, notify=True)
|
|
160
|
+
self.reset(v)
|
|
156
161
|
|
|
157
162
|
@property
|
|
158
163
|
def std_value(self):
|
|
@@ -438,13 +443,11 @@ class Knob(wx.Panel):
|
|
|
438
443
|
self.label.SetLabel(v.name + t)
|
|
439
444
|
self.label.Refresh()
|
|
440
445
|
|
|
441
|
-
## Note: wxAssertionError in text.SetValue
|
|
442
|
-
@postcall
|
|
443
446
|
def update_ctrl(self, valid=True, notify=False):
|
|
444
447
|
"""Called when value is being changed (internal use only)."""
|
|
445
448
|
v = self.__par
|
|
446
449
|
self.ctrl.SetValue(v.index)
|
|
447
|
-
self.text.SetValue
|
|
450
|
+
wx.CallAfter(self.text.SetValue, str(v)) # for wxAssertionError
|
|
448
451
|
if valid:
|
|
449
452
|
if notify:
|
|
450
453
|
if self.text.BackgroundColour != '#ffff80':
|
|
@@ -475,14 +478,12 @@ class Knob(wx.Panel):
|
|
|
475
478
|
j = self.ctrl.GetValue() + bit
|
|
476
479
|
if j != v.index:
|
|
477
480
|
v.index = j
|
|
478
|
-
v.reset(v.value)
|
|
479
481
|
|
|
480
482
|
def OnScroll(self, evt): #<wx._core.ScrollEvent><wx._controls.SpinEvent><wx._core.CommandEvent>
|
|
481
483
|
v = self.__par
|
|
482
484
|
j = self.ctrl.GetValue()
|
|
483
485
|
if j != v.index:
|
|
484
486
|
v.index = j
|
|
485
|
-
v.reset(v.value)
|
|
486
487
|
evt.Skip()
|
|
487
488
|
|
|
488
489
|
def OnMouseWheel(self, evt): #<wx._core.MouseEvent>
|
|
@@ -540,7 +541,7 @@ class Knob(wx.Panel):
|
|
|
540
541
|
self.text.Enable(p)
|
|
541
542
|
|
|
542
543
|
|
|
543
|
-
class
|
|
544
|
+
class KnobCtrlPanel(scrolled.ScrolledPanel):
|
|
544
545
|
"""Scrollable Control Panel
|
|
545
546
|
"""
|
|
546
547
|
def __init__(self, *args, **kwargs):
|
|
@@ -728,7 +729,7 @@ class ControlPanel(scrolled.ScrolledPanel):
|
|
|
728
729
|
except Exception as e: # failed to eval
|
|
729
730
|
print(f"- Failed to reset {p!r}.", e)
|
|
730
731
|
|
|
731
|
-
reset_params = set_params
|
|
732
|
+
reset_params = set_params
|
|
732
733
|
|
|
733
734
|
def copy_to_clipboard(self, checked_only=False):
|
|
734
735
|
params = self.get_params(checked_only)
|
|
@@ -742,6 +743,14 @@ class ControlPanel(scrolled.ScrolledPanel):
|
|
|
742
743
|
self.set_params(text.split('\t'), checked_only)
|
|
743
744
|
|
|
744
745
|
|
|
746
|
+
class ControlPanel(CtrlInterface, KnobCtrlPanel):
|
|
747
|
+
"""Gnuplot control panel.
|
|
748
|
+
"""
|
|
749
|
+
def __init__(self, *args, **kwargs):
|
|
750
|
+
KnobCtrlPanel.__init__(self, *args, **kwargs)
|
|
751
|
+
CtrlInterface.__init__(self)
|
|
752
|
+
|
|
753
|
+
|
|
745
754
|
class Clipboard:
|
|
746
755
|
"""Clipboard interface of text and image
|
|
747
756
|
|
mwx/framework.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#! python3
|
|
2
2
|
"""mwxlib framework.
|
|
3
3
|
"""
|
|
4
|
-
__version__ = "0.
|
|
4
|
+
__version__ = "0.99.0"
|
|
5
5
|
__author__ = "Kazuya O'moto <komoto@jeol.co.jp>"
|
|
6
6
|
|
|
7
7
|
from contextlib import contextmanager
|
|
@@ -178,6 +178,15 @@ def getKeyState(key):
|
|
|
178
178
|
pass
|
|
179
179
|
|
|
180
180
|
|
|
181
|
+
def setKeyState(key, state):
|
|
182
|
+
"""Makes you feel like having pressed/released speckey."""
|
|
183
|
+
vk = wx.UIActionSimulator()
|
|
184
|
+
if state:
|
|
185
|
+
vk.KeyDown(_speckeys_wxkmap[key])
|
|
186
|
+
else:
|
|
187
|
+
vk.KeyUp(_speckeys_wxkmap[key])
|
|
188
|
+
|
|
189
|
+
|
|
181
190
|
def hotkey(evt):
|
|
182
191
|
"""Interpret evt.KeyCode as hotkey:str and overwrite evt.key.
|
|
183
192
|
The modifiers are arranged in the same order as matplotlib as
|
|
@@ -695,7 +704,8 @@ class StatusBar(wx.StatusBar):
|
|
|
695
704
|
|
|
696
705
|
def __call__(self, *args, **kwargs):
|
|
697
706
|
text = ' '.join(str(v) for v in args)
|
|
698
|
-
|
|
707
|
+
if self:
|
|
708
|
+
return self.write(text, **kwargs)
|
|
699
709
|
|
|
700
710
|
def resize(self, field):
|
|
701
711
|
self.SetFieldsCount(len(field))
|
|
@@ -1135,8 +1145,8 @@ class ShellFrame(MiniFrame):
|
|
|
1135
1145
|
skip=[Debugger.__module__, # Don't enter debugger
|
|
1136
1146
|
EventMonitor.__module__, # Don't enter event-hook
|
|
1137
1147
|
FSM.__module__,
|
|
1138
|
-
'fnmatch', 'warnings', 'bdb', 'pdb',
|
|
1139
1148
|
'wx.core', 'wx.lib.eventwatcher',
|
|
1149
|
+
'fnmatch', 'warnings', 'bdb', 'pdb', #'contextlib',
|
|
1140
1150
|
],
|
|
1141
1151
|
)
|
|
1142
1152
|
self.inspector = Inspector(self, name="Inspector")
|
|
@@ -1268,7 +1278,7 @@ class ShellFrame(MiniFrame):
|
|
|
1268
1278
|
|
|
1269
1279
|
self.Scratch.set_attributes(Style=Nautilus.STYLE)
|
|
1270
1280
|
self.Log.set_attributes(ReadOnly=True)
|
|
1271
|
-
self.Help.set_attributes(ReadOnly=
|
|
1281
|
+
self.Help.set_attributes(ReadOnly=False)
|
|
1272
1282
|
|
|
1273
1283
|
self.set_hookable(self.Scratch)
|
|
1274
1284
|
self.set_hookable(self.Log)
|
|
@@ -1335,20 +1345,19 @@ class ShellFrame(MiniFrame):
|
|
|
1335
1345
|
_fsave(self.Scratch, self.SCRATCH_FILE) # save scratch
|
|
1336
1346
|
_fsave(self.Log, self.LOGGING_FILE) # save log
|
|
1337
1347
|
|
|
1338
|
-
with open(self.SESSION_FILE, 'w'
|
|
1348
|
+
with open(self.SESSION_FILE, 'w') as o:
|
|
1339
1349
|
o.write("#! Session file (This file is generated automatically)\n")
|
|
1350
|
+
o.write("self.SetSize({})\n".format(self.Size))
|
|
1351
|
+
o.write("self.SetPosition({})\n".format(self.Position))
|
|
1340
1352
|
|
|
1341
|
-
for book in
|
|
1353
|
+
for book in self.all_editors:
|
|
1342
1354
|
for buf in book.all_buffers:
|
|
1343
1355
|
if buf.mtdelta is not None:
|
|
1344
1356
|
o.write("self.{}.load_file({!r}, {})\n"
|
|
1345
1357
|
.format(book.Name, buf.filename, buf.markline+1))
|
|
1358
|
+
o.write("self.{}.loadPerspective({!r})\n"
|
|
1359
|
+
.format(book.Name, book.savePerspective()))
|
|
1346
1360
|
o.write('\n'.join((
|
|
1347
|
-
"self.SetSize({})".format(self.Size),
|
|
1348
|
-
"self.SetPosition({})".format(self.Position),
|
|
1349
|
-
"self.Scratch.loadPerspective({!r})".format(self.Scratch.savePerspective()),
|
|
1350
|
-
"self.Log.loadPerspective({!r})".format(self.Log.savePerspective()),
|
|
1351
|
-
## Note: Perspectives should be called after all pages have been added.
|
|
1352
1361
|
"self.ghost.loadPerspective({!r})".format(self.ghost.savePerspective()),
|
|
1353
1362
|
"self.watcher.loadPerspective({!r})".format(self.watcher.savePerspective()),
|
|
1354
1363
|
"self._mgr.LoadPerspective({!r})".format(self._mgr.SavePerspective()),
|
|
@@ -1699,8 +1708,7 @@ class ShellFrame(MiniFrame):
|
|
|
1699
1708
|
elif isinstance(obj, str):
|
|
1700
1709
|
filename = "<string>"
|
|
1701
1710
|
editor = self.Scratch
|
|
1702
|
-
buf = editor.find_buffer(filename)
|
|
1703
|
-
or editor.create_buffer(filename)
|
|
1711
|
+
buf = editor.find_buffer(filename) or editor.create_buffer(filename)
|
|
1704
1712
|
with buf.off_readonly():
|
|
1705
1713
|
buf.Text = obj
|
|
1706
1714
|
self.debugger.run(obj, filename)
|
|
@@ -1855,6 +1863,7 @@ class ShellFrame(MiniFrame):
|
|
|
1855
1863
|
shell = self.rootshell.__class__(self, target, name="clone",
|
|
1856
1864
|
style=wx.CLIP_CHILDREN|wx.BORDER_NONE)
|
|
1857
1865
|
self.handler('shell_new', shell)
|
|
1866
|
+
self.Show()
|
|
1858
1867
|
self.console.AddPage(shell, typename(shell.target))
|
|
1859
1868
|
self.popup_window(shell)
|
|
1860
1869
|
shell.SetFocus()
|
mwx/graphman.py
CHANGED
|
@@ -27,7 +27,7 @@ from PIL.TiffImagePlugin import TiffImageFile
|
|
|
27
27
|
from . import framework as mwx
|
|
28
28
|
from .utilus import ignore, warn
|
|
29
29
|
from .utilus import funcall as _F
|
|
30
|
-
from .controls import
|
|
30
|
+
from .controls import KnobCtrlPanel, Icon
|
|
31
31
|
from .framework import CtrlInterface, AuiNotebook, Menu, FSM
|
|
32
32
|
|
|
33
33
|
from .matplot2 import MatplotPanel # noqa
|
|
@@ -260,12 +260,6 @@ class LayerInterface(CtrlInterface):
|
|
|
260
260
|
## thread_type = Thread
|
|
261
261
|
thread = None
|
|
262
262
|
|
|
263
|
-
## layout helper function (deprecated: internal use only)
|
|
264
|
-
pack = mwx.pack
|
|
265
|
-
|
|
266
|
-
## funcall = interactive_call (deprecated: internal use only)
|
|
267
|
-
funcall = staticmethod(_F)
|
|
268
|
-
|
|
269
263
|
## for debug (internal use only)
|
|
270
264
|
pane = property(lambda self: self.parent.get_pane(self))
|
|
271
265
|
|
|
@@ -474,11 +468,11 @@ class LayerInterface(CtrlInterface):
|
|
|
474
468
|
del self.Arts
|
|
475
469
|
|
|
476
470
|
|
|
477
|
-
class Layer(LayerInterface,
|
|
471
|
+
class Layer(LayerInterface, KnobCtrlPanel):
|
|
478
472
|
"""Graphman.Layer
|
|
479
473
|
"""
|
|
480
474
|
def __init__(self, parent, session=None, **kwargs):
|
|
481
|
-
|
|
475
|
+
KnobCtrlPanel.__init__(self, parent, **kwargs)
|
|
482
476
|
LayerInterface.__init__(self, parent, session)
|
|
483
477
|
|
|
484
478
|
|
mwx/matplot2g.py
CHANGED
|
@@ -124,7 +124,6 @@ class AxesImagePhantom:
|
|
|
124
124
|
Note:
|
|
125
125
|
Due to the problem of performance,
|
|
126
126
|
the image pixel size could be reduced by binning.
|
|
127
|
-
( ・ω・)? Current verision of wxagg limits < 24M bytes?
|
|
128
127
|
"""
|
|
129
128
|
def __init__(self, parent, buf, name, show=True,
|
|
130
129
|
localunit=None, aspect=1.0, **attributes):
|
|
@@ -766,7 +765,7 @@ class GraphPlot(MatplotPanel):
|
|
|
766
765
|
## Property of frame / drawer
|
|
767
766
|
## --------------------------------
|
|
768
767
|
|
|
769
|
-
#: image bytes max for loading matplotlib
|
|
768
|
+
#: image bytes max for loading matplotlib (with wxAgg backend)
|
|
770
769
|
nbytes_threshold = 24e6
|
|
771
770
|
|
|
772
771
|
#: image cutoff score percentiles
|
mwx/mgplt.py
CHANGED
|
@@ -13,7 +13,7 @@ from .controls import ControlPanel
|
|
|
13
13
|
|
|
14
14
|
|
|
15
15
|
class Gnuplot:
|
|
16
|
-
"""Gnuplot - gnuplot
|
|
16
|
+
"""Gnuplot backend - gnuplot pipe wrapper.
|
|
17
17
|
"""
|
|
18
18
|
debug = 0
|
|
19
19
|
|
|
@@ -123,15 +123,13 @@ class Gnuplot:
|
|
|
123
123
|
|
|
124
124
|
|
|
125
125
|
class GnuplotFrame(mwx.Frame):
|
|
126
|
-
"""Gnuplot
|
|
126
|
+
"""Gnuplot frontend frame.
|
|
127
127
|
"""
|
|
128
|
-
gnuplot = property(lambda self: self.__gplot) #: single class object
|
|
129
|
-
|
|
130
128
|
def __init__(self, *args, **kwargs):
|
|
131
129
|
mwx.Frame.__init__(self, *args, **kwargs)
|
|
132
130
|
|
|
133
|
-
self.
|
|
134
|
-
self.panel =
|
|
131
|
+
self.gnuplot = Gnuplot()
|
|
132
|
+
self.panel = GnuplotPanel(self)
|
|
135
133
|
|
|
136
134
|
self.menubar["Edit"] = [
|
|
137
135
|
(wx.ID_COPY, "&Copy params\tCtrl-c", "Copy params to clipboard",
|
|
@@ -157,6 +155,6 @@ class GnuplotFrame(mwx.Frame):
|
|
|
157
155
|
|
|
158
156
|
def Destroy(self):
|
|
159
157
|
try:
|
|
160
|
-
del self.
|
|
158
|
+
del self.gnuplot
|
|
161
159
|
finally:
|
|
162
160
|
return mwx.Frame.Destroy(self)
|
mwx/nutshell.py
CHANGED
|
@@ -545,22 +545,19 @@ class EditorInterface(AutoCompInterfaceMixin, CtrlInterface):
|
|
|
545
545
|
self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_VLINE, *v)
|
|
546
546
|
self.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_VLINE, *v)
|
|
547
547
|
|
|
548
|
-
## Custom
|
|
549
|
-
##
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
self.
|
|
558
|
-
self.
|
|
559
|
-
self.
|
|
560
|
-
self.IndicatorSetForeground(0, "red")
|
|
561
|
-
self.IndicatorSetForeground(1, "yellow")
|
|
548
|
+
## Custom indicators ([BUG] indicator=1 is reset when the buffer is udpated.)
|
|
549
|
+
## [10-11] filter_text
|
|
550
|
+
## [2] URL for load_file
|
|
551
|
+
## [3] match_paren
|
|
552
|
+
self.IndicatorSetStyle(10, stc.STC_INDIC_TEXTFORE)
|
|
553
|
+
self.IndicatorSetForeground(10, "red")
|
|
554
|
+
|
|
555
|
+
self.IndicatorSetStyle(11, stc.STC_INDIC_STRAIGHTBOX)
|
|
556
|
+
self.IndicatorSetUnder(11, True)
|
|
557
|
+
self.IndicatorSetAlpha(11, 255)
|
|
558
|
+
self.IndicatorSetOutlineAlpha(11, 255)
|
|
559
|
+
self.IndicatorSetForeground(11, "yellow")
|
|
562
560
|
|
|
563
|
-
## Custom indicator (2) for URL (buffer_modified)
|
|
564
561
|
self.IndicatorSetStyle(2, stc.STC_INDIC_DOTS)
|
|
565
562
|
self.IndicatorSetForeground(2, "light gray")
|
|
566
563
|
try:
|
|
@@ -569,7 +566,6 @@ class EditorInterface(AutoCompInterfaceMixin, CtrlInterface):
|
|
|
569
566
|
except AttributeError:
|
|
570
567
|
pass
|
|
571
568
|
|
|
572
|
-
## Custom indicator (3) for match_paren
|
|
573
569
|
self.IndicatorSetStyle(3, stc.STC_INDIC_DOTS)
|
|
574
570
|
self.IndicatorSetForeground(3, "light gray")
|
|
575
571
|
|
|
@@ -590,34 +586,36 @@ class EditorInterface(AutoCompInterfaceMixin, CtrlInterface):
|
|
|
590
586
|
self.__stylus = {}
|
|
591
587
|
|
|
592
588
|
## Custom constants embedded in wx.stc
|
|
593
|
-
stc.STC_P_WORD3 = 20
|
|
589
|
+
stc.STC_P_WORD3 = 20 # deprecated
|
|
594
590
|
stc.STC_STYLE_CARETLINE = 40
|
|
595
591
|
stc.STC_STYLE_ANNOTATION = 41
|
|
596
592
|
|
|
597
|
-
## Common DnD target and flags
|
|
598
|
-
dnd = None
|
|
599
|
-
dnd_flag = 0 # 1:copy 2:ctrl-pressed
|
|
600
|
-
|
|
601
593
|
def OnDrag(self, evt): #<wx._core.StyledTextEvent>
|
|
602
|
-
EditorInterface.
|
|
594
|
+
EditorInterface.__dnd_from = evt.EventObject
|
|
595
|
+
try:
|
|
596
|
+
EditorInterface.__dnd_flag = (evt.Position < self.bolc) # force copy
|
|
597
|
+
except AttributeError:
|
|
598
|
+
EditorInterface.__dnd_flag = 0
|
|
603
599
|
evt.Skip()
|
|
604
600
|
|
|
605
601
|
def OnDragging(self, evt): #<wx._core.StyledTextEvent>
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
602
|
+
_from = EditorInterface.__dnd_from
|
|
603
|
+
_to = evt.EventObject
|
|
604
|
+
if isinstance(_from, Shell) and _from is not _to: # from shell to buffer
|
|
605
|
+
wx.UIActionSimulator().KeyDown(wx.WXK_CONTROL) # force copy
|
|
606
|
+
try:
|
|
607
|
+
if evt.Position < self.bolc:
|
|
608
|
+
evt.DragResult = wx.DragNone # Don't drop (as readonly)
|
|
609
|
+
elif EditorInterface.__dnd_flag:
|
|
610
|
+
evt.DragResult = wx.DragCopy # Don't move
|
|
611
|
+
except AttributeError:
|
|
612
|
+
pass
|
|
616
613
|
evt.Skip()
|
|
617
614
|
|
|
618
615
|
def OnDragged(self, evt): #<wx._core.StyledTextEvent>
|
|
619
|
-
EditorInterface.
|
|
620
|
-
EditorInterface.
|
|
616
|
+
EditorInterface.__dnd_from = None
|
|
617
|
+
EditorInterface.__dnd_flag = 0
|
|
618
|
+
wx.UIActionSimulator().KeyUp(wx.WXK_CONTROL)
|
|
621
619
|
evt.Skip()
|
|
622
620
|
|
|
623
621
|
## --------------------------------
|
|
@@ -1129,12 +1127,6 @@ class EditorInterface(AutoCompInterfaceMixin, CtrlInterface):
|
|
|
1129
1127
|
if 'bold' in item:
|
|
1130
1128
|
self.SetCaretStyle(stc.STC_CARETSTYLE_BLOCK)
|
|
1131
1129
|
|
|
1132
|
-
## Custom indicator (0,1) for filter_text
|
|
1133
|
-
item = _map(spec.pop(stc.STC_P_WORD3, ''))
|
|
1134
|
-
if item:
|
|
1135
|
-
self.IndicatorSetForeground(0, item.get('fore') or "red")
|
|
1136
|
-
self.IndicatorSetForeground(1, item.get('back') or "yellow")
|
|
1137
|
-
|
|
1138
1130
|
## Apply the rest of the style
|
|
1139
1131
|
for key, value in spec.items():
|
|
1140
1132
|
self.StyleSetSpec(key, value)
|
|
@@ -1187,7 +1179,7 @@ class EditorInterface(AutoCompInterfaceMixin, CtrlInterface):
|
|
|
1187
1179
|
self.ScrollToLine(vl - m)
|
|
1188
1180
|
|
|
1189
1181
|
def _calc_vline(self, line):
|
|
1190
|
-
"""Virtual line
|
|
1182
|
+
"""Virtual line number in the buffer window."""
|
|
1191
1183
|
pos = self.PositionFromLine(line)
|
|
1192
1184
|
w, h = self.PointFromPosition(pos)
|
|
1193
1185
|
return self.FirstVisibleLine + h//self.TextHeight(0)
|
|
@@ -1318,7 +1310,7 @@ class EditorInterface(AutoCompInterfaceMixin, CtrlInterface):
|
|
|
1318
1310
|
def filter_text(self, text=None):
|
|
1319
1311
|
"""Show indicators for the selected text."""
|
|
1320
1312
|
self.__itextlines = []
|
|
1321
|
-
for i in
|
|
1313
|
+
for i in (10, 11,):
|
|
1322
1314
|
self.SetIndicatorCurrent(i)
|
|
1323
1315
|
self.IndicatorClearRange(0, self.TextLength)
|
|
1324
1316
|
if text is None:
|
|
@@ -1331,7 +1323,7 @@ class EditorInterface(AutoCompInterfaceMixin, CtrlInterface):
|
|
|
1331
1323
|
lines = []
|
|
1332
1324
|
for p in self.search_text(text):
|
|
1333
1325
|
lines.append(self.LineFromPosition(p))
|
|
1334
|
-
for i in
|
|
1326
|
+
for i in (10, 11,):
|
|
1335
1327
|
self.SetIndicatorCurrent(i)
|
|
1336
1328
|
self.IndicatorFillRange(p, lw)
|
|
1337
1329
|
self.__itextlines = sorted(set(lines)) # keep order, no duplication
|
|
@@ -1661,7 +1653,6 @@ class Buffer(EditorInterface, EditWindow):
|
|
|
1661
1653
|
stc.STC_P_DEFNAME : "fore:#0000ff,bold",
|
|
1662
1654
|
stc.STC_P_WORD : "fore:#0000ff",
|
|
1663
1655
|
stc.STC_P_WORD2 : "fore:#b8007f",
|
|
1664
|
-
stc.STC_P_WORD3 : "fore:#ff0000,back:#ffff00", # optional for search word
|
|
1665
1656
|
stc.STC_P_DECORATOR : "fore:#e08040",
|
|
1666
1657
|
}
|
|
1667
1658
|
|
|
@@ -1693,18 +1684,17 @@ class Buffer(EditorInterface, EditWindow):
|
|
|
1693
1684
|
"""Timestamp delta (for checking external mod).
|
|
1694
1685
|
|
|
1695
1686
|
Returns:
|
|
1696
|
-
None :
|
|
1687
|
+
None : no file
|
|
1697
1688
|
= 0 : a file
|
|
1698
1689
|
> 0 : a file edited externally
|
|
1699
1690
|
< 0 : a url file
|
|
1700
1691
|
"""
|
|
1701
1692
|
fn = self.filename
|
|
1702
|
-
if fn:
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
return self.__mtime # None or specified value
|
|
1693
|
+
if os.path.isfile(fn):
|
|
1694
|
+
return os.path.getmtime(fn) - self.__mtime
|
|
1695
|
+
if re.match(url_re, fn):
|
|
1696
|
+
return -1
|
|
1697
|
+
return None
|
|
1708
1698
|
|
|
1709
1699
|
@property
|
|
1710
1700
|
def caption_prefix(self):
|
|
@@ -1753,7 +1743,7 @@ class Buffer(EditorInterface, EditWindow):
|
|
|
1753
1743
|
return EditorInterface.post_command_hook(self, evt)
|
|
1754
1744
|
post_command_hook.__name__ = str('post_command_dispatch') # alias
|
|
1755
1745
|
|
|
1756
|
-
def __init__(self, parent, filename
|
|
1746
|
+
def __init__(self, parent, filename, **kwargs):
|
|
1757
1747
|
EditWindow.__init__(self, parent, **kwargs)
|
|
1758
1748
|
EditorInterface.__init__(self)
|
|
1759
1749
|
|
|
@@ -1908,7 +1898,7 @@ class Buffer(EditorInterface, EditWindow):
|
|
|
1908
1898
|
self.handler('buffer_modified', self)
|
|
1909
1899
|
evt.Skip()
|
|
1910
1900
|
|
|
1911
|
-
def OnCallTipClick(self, evt):
|
|
1901
|
+
def OnCallTipClick(self, evt): #<wx._stc.StyledTextEvent>
|
|
1912
1902
|
if self.CallTipActive():
|
|
1913
1903
|
self.CallTipCancel()
|
|
1914
1904
|
pos, tip, more = self._calltips
|
|
@@ -1916,23 +1906,24 @@ class Buffer(EditorInterface, EditWindow):
|
|
|
1916
1906
|
self.CallTipShow(pos, tip, N=None)
|
|
1917
1907
|
evt.Skip()
|
|
1918
1908
|
|
|
1919
|
-
def OnIndicatorClick(self, evt):
|
|
1909
|
+
def OnIndicatorClick(self, evt): #<wx._stc.StyledTextEvent>
|
|
1920
1910
|
if self.SelectedText or not wx.GetKeyState(wx.WXK_CONTROL):
|
|
1921
1911
|
## Processing text selection, dragging, or dragging+
|
|
1922
1912
|
evt.Skip()
|
|
1923
1913
|
return
|
|
1924
1914
|
pos = evt.Position
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
1915
|
+
i = 2
|
|
1916
|
+
if self.IndicatorValueAt(i, pos): # [C-indic click]
|
|
1917
|
+
p = self.IndicatorStart(i, pos)
|
|
1918
|
+
q = self.IndicatorEnd(i, pos)
|
|
1928
1919
|
url = self.GetTextRange(p, q).strip()
|
|
1929
1920
|
self.message("URL {!r}".format(url))
|
|
1930
|
-
if wx.GetKeyState(wx.WXK_SHIFT):
|
|
1931
|
-
## Note: post-call for the confirmation dialog.
|
|
1932
|
-
wx.CallAfter(self.parent.load_file, url)
|
|
1933
|
-
else:
|
|
1921
|
+
if wx.GetKeyState(wx.WXK_SHIFT): # [C-S-indic click]
|
|
1934
1922
|
import webbrowser
|
|
1935
1923
|
return webbrowser.open(url)
|
|
1924
|
+
else:
|
|
1925
|
+
## Note: post-call for the confirmation dialog.
|
|
1926
|
+
wx.CallAfter(self.parent.load_file, url)
|
|
1936
1927
|
self.anchor = pos # Clear selection
|
|
1937
1928
|
|
|
1938
1929
|
def on_modified(self, buf):
|
|
@@ -2423,8 +2414,6 @@ class EditorBook(AuiNotebook, CtrlInterface):
|
|
|
2423
2414
|
buf._Buffer__mtime = 0 # => need_buffer_save
|
|
2424
2415
|
self.swap_buffer(buf)
|
|
2425
2416
|
|
|
2426
|
-
open_buffer = find_file # for backward compatibility
|
|
2427
|
-
|
|
2428
2417
|
def save_file(self, filename, buf=None, verbose=True):
|
|
2429
2418
|
"""Save the current buffer to a file.
|
|
2430
2419
|
"""
|
|
@@ -2679,7 +2668,6 @@ class Nautilus(EditorInterface, Shell):
|
|
|
2679
2668
|
stc.STC_P_DEFNAME : "fore:#3a96ff,bold",
|
|
2680
2669
|
stc.STC_P_WORD : "fore:#80c0ff",
|
|
2681
2670
|
stc.STC_P_WORD2 : "fore:#ff80ff",
|
|
2682
|
-
stc.STC_P_WORD3 : "fore:#ff0000,back:#ffff00", # optional for search word
|
|
2683
2671
|
stc.STC_P_DECORATOR : "fore:#ff8040",
|
|
2684
2672
|
}
|
|
2685
2673
|
|
|
@@ -2762,9 +2750,6 @@ class Nautilus(EditorInterface, Shell):
|
|
|
2762
2750
|
|
|
2763
2751
|
self.Bind(stc.EVT_STC_UPDATEUI, self.OnUpdate) # skip to brace matching
|
|
2764
2752
|
self.Bind(stc.EVT_STC_CALLTIP_CLICK, self.OnCallTipClick)
|
|
2765
|
-
self.Bind(stc.EVT_STC_START_DRAG, self.OnDrag)
|
|
2766
|
-
self.Bind(stc.EVT_STC_DRAG_OVER, self.OnDragging)
|
|
2767
|
-
self.Bind(stc.EVT_STC_DO_DROP, self.OnDragging)
|
|
2768
2753
|
|
|
2769
2754
|
self.Bind(wx.EVT_WINDOW_DESTROY, self.OnDestroy)
|
|
2770
2755
|
|
|
@@ -3043,17 +3028,6 @@ class Nautilus(EditorInterface, Shell):
|
|
|
3043
3028
|
self.parent.handler('add_help', self._calltips[1])
|
|
3044
3029
|
evt.Skip()
|
|
3045
3030
|
|
|
3046
|
-
def OnDrag(self, evt): #<wx._core.StyledTextEvent>
|
|
3047
|
-
EditorInterface.dnd_flag = (evt.Position < self.bolc) # copy
|
|
3048
|
-
evt.Skip()
|
|
3049
|
-
|
|
3050
|
-
def OnDragging(self, evt): #<wx._core.StyledTextEvent>
|
|
3051
|
-
if evt.Position < self.bolc:
|
|
3052
|
-
evt.DragResult = wx.DragNone # Don't drop (as readonly)
|
|
3053
|
-
elif EditorInterface.dnd_flag:
|
|
3054
|
-
evt.DragResult = wx.DragCopy # Don't move
|
|
3055
|
-
evt.Skip()
|
|
3056
|
-
|
|
3057
3031
|
def OnSpace(self, evt):
|
|
3058
3032
|
"""Called when space pressed."""
|
|
3059
3033
|
if not self.CanEdit():
|
mwx/plugins/ffmpeg_view.py
CHANGED
|
@@ -150,11 +150,12 @@ class Plugin(Layer):
|
|
|
150
150
|
## self.mc.Bind(wx.EVT_KEY_UP, self.on_hotkey_up)
|
|
151
151
|
self.mc.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown)
|
|
152
152
|
self.mc.Bind(wx.EVT_KEY_UP, self.OnKeyUp)
|
|
153
|
+
|
|
154
|
+
self.Bind(wx.EVT_SHOW, self.OnShow)
|
|
153
155
|
|
|
154
156
|
def Destroy(self):
|
|
155
157
|
try:
|
|
156
158
|
self.parent.handler.unbind("unknown_format", self.load_media)
|
|
157
|
-
self.mc.Stop()
|
|
158
159
|
finally:
|
|
159
160
|
return Layer.Destroy(self)
|
|
160
161
|
|
|
@@ -166,6 +167,12 @@ class Plugin(Layer):
|
|
|
166
167
|
if self.handler('{} released'.format(hotkey(evt)), evt) is None:
|
|
167
168
|
evt.Skip()
|
|
168
169
|
|
|
170
|
+
def OnShow(self, evt):
|
|
171
|
+
if not evt.IsShown():
|
|
172
|
+
if self.mc:
|
|
173
|
+
self.mc.Stop()
|
|
174
|
+
evt.Skip()
|
|
175
|
+
|
|
169
176
|
def OnMediaLoaded(self, evt):
|
|
170
177
|
self.ss.range = (0, self.video_dur, 0.01)
|
|
171
178
|
self.to.range = (0, self.video_dur, 0.01)
|
|
@@ -187,8 +194,11 @@ class Plugin(Layer):
|
|
|
187
194
|
self.video_fps = eval(v['avg_frame_rate']) # averaged frame rate
|
|
188
195
|
self.video_dur = eval(v['duration']) # duration [s]
|
|
189
196
|
w, h = v['width'], v['height']
|
|
190
|
-
|
|
191
|
-
|
|
197
|
+
try:
|
|
198
|
+
if v['tags']['rotate'] in ('90', '270'):
|
|
199
|
+
w, h = h, w # transpose
|
|
200
|
+
except KeyError:
|
|
201
|
+
pass
|
|
192
202
|
self.video_size = w, h
|
|
193
203
|
self._path = path
|
|
194
204
|
self.message(f"Loaded {path!r} successfully.")
|
|
@@ -272,6 +282,7 @@ class Plugin(Layer):
|
|
|
272
282
|
return
|
|
273
283
|
fout = "{}_clip".format(os.path.splitext(self._path)[0])
|
|
274
284
|
with wx.FileDialog(self, "Save as",
|
|
285
|
+
defaultDir=os.path.dirname(fout),
|
|
275
286
|
defaultFile=os.path.basename(fout),
|
|
276
287
|
wildcard="Media file (*.mp4)|*.mp4|"
|
|
277
288
|
"Animiation (*.gif)|*.gif",
|
mwx/plugins/frame_listview.py
CHANGED
|
@@ -241,7 +241,7 @@ class CheckList(wx.ListCtrl, ListCtrlAutoWidthMixin, CtrlInterface):
|
|
|
241
241
|
|
|
242
242
|
|
|
243
243
|
class Plugin(Layer):
|
|
244
|
-
"""Property list of
|
|
244
|
+
"""Property list of Graph buffers.
|
|
245
245
|
"""
|
|
246
246
|
menukey = "Plugins/Extensions/&Buffer listbox\tCtrl+b"
|
|
247
247
|
caption = "Property list"
|
mwx/wxmon.py
CHANGED
|
@@ -7,7 +7,7 @@ import wx
|
|
|
7
7
|
import wx.lib.eventwatcher as ew
|
|
8
8
|
from wx.lib.mixins.listctrl import ListCtrlAutoWidthMixin
|
|
9
9
|
|
|
10
|
-
from .utilus import where
|
|
10
|
+
from .utilus import where
|
|
11
11
|
from .controls import Icon, Clipboard
|
|
12
12
|
from .framework import CtrlInterface, Menu
|
|
13
13
|
|
|
@@ -174,10 +174,7 @@ class EventMonitor(wx.ListCtrl, ListCtrlAutoWidthMixin, CtrlInterface):
|
|
|
174
174
|
name = self.get_name(event)
|
|
175
175
|
source = ew._makeSourceString(obj) + " id=0x{:X}".format(id(evt))
|
|
176
176
|
stamp = 1
|
|
177
|
-
|
|
178
|
-
with ignore(DeprecationWarning):
|
|
179
|
-
attribs = ew._makeAttribString(evt)
|
|
180
|
-
|
|
177
|
+
attribs = ew._makeAttribString(evt)
|
|
181
178
|
data = self.__items
|
|
182
179
|
for i, item in enumerate(data):
|
|
183
180
|
if item[0] == event:
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
mwx/__init__.py,sha256=nN62CGTWjME7Zz2h-jIRB8MxwuErIkHPGrlBzydkF0o,643
|
|
2
|
+
mwx/bookshelf.py,sha256=so-xSLq08sMlJBErTxOaDoKUAMa_g1CkIP2pNnff68c,5607
|
|
3
|
+
mwx/controls.py,sha256=WYd0nbpXL7eiE5E7l7jG49pm_u4mfgHI4c1dop4lsMM,48103
|
|
4
|
+
mwx/framework.py,sha256=28_DX0eYwintdgBaO-06ds0NGevwXu_UdYmXjqTy4os,75587
|
|
5
|
+
mwx/graphman.py,sha256=N34F5GXpN3ZEMfUIOswlM-OCIB1KObC6X1NTq_Qc2dk,69973
|
|
6
|
+
mwx/images.py,sha256=_-Eh3xF7Khu42ivkYp97NXIzSNGbjcidqtWjZQFGtqE,47827
|
|
7
|
+
mwx/matplot2.py,sha256=xCJ_ZzdDEWmzctpPaOrzTnwXyHINP4nfFHweoTZa6ug,32899
|
|
8
|
+
mwx/matplot2g.py,sha256=gCXa8X1MEMP7n_mG73h3SkWKuNZOfjVKUTWNRXXK11c,64310
|
|
9
|
+
mwx/matplot2lg.py,sha256=JRWjWnLJUytbSq6wxs4P0gbVUr3xoLSF6Wwqd5V_pJI,27404
|
|
10
|
+
mwx/mgplt.py,sha256=0WJ1RN_Y0a4Y3rz1C_Lx-WhumtOMdb1N49guX9aZZ_o,5602
|
|
11
|
+
mwx/nutshell.py,sha256=xoHTyWZ46geGy3u4aU8k8_-mr520EdGcvuQRO4TBU_A,140715
|
|
12
|
+
mwx/utilus.py,sha256=B76pDg6_kW8FMNdQ6xO0Bwy4KJ0laY98Gg6N3iqV7c8,37325
|
|
13
|
+
mwx/wxmon.py,sha256=Pq8XXigM_isJd80yiqG18iRVdArJpsePpxfnZOkk-Uw,12573
|
|
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=Mmen75o6LyA5QEHB8sCFSPCIPvEaALKzrgomym3fGAU,10721
|
|
19
|
+
mwx/plugins/fft_view.py,sha256=xxTDD-_z4l18u4t2ybPB3xAMIslJmJ0gQlTxEqJUhNI,2782
|
|
20
|
+
mwx/plugins/frame_listview.py,sha256=yEYPCdLHLSMTJwTv6iYAh3Lo4lJvYfp5BxTLP3FhW9Y,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=fumUG1F5M9TL-Dfqni4G85uk7TmvnUunTbdcPDV0vfo,16857
|
|
24
|
+
mwxlib-0.99.0.dist-info/LICENSE,sha256=PGtRKCaTkmUDlBQwpptJAxJtdqxIUtAmdBsaT9nUVkA,1091
|
|
25
|
+
mwxlib-0.99.0.dist-info/METADATA,sha256=Ix7YJKkft0nZZfhvPm-XOgN65HwIZF3T6asdSvhsCP0,7411
|
|
26
|
+
mwxlib-0.99.0.dist-info/WHEEL,sha256=cVxcB9AmuTcXqmwrtPhNK88dr7IR_b6qagTj0UvIEbY,91
|
|
27
|
+
mwxlib-0.99.0.dist-info/top_level.txt,sha256=SI1Mh118AstnUFGPNq5aMNKiAnVNmZk1S9Ij-OwAEpY,4
|
|
28
|
+
mwxlib-0.99.0.dist-info/RECORD,,
|
mwxlib-0.98.6.dist-info/RECORD
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
mwx/__init__.py,sha256=nN62CGTWjME7Zz2h-jIRB8MxwuErIkHPGrlBzydkF0o,643
|
|
2
|
-
mwx/bookshelf.py,sha256=Y4xI2SrEO22DrI1hyyfFx7DfFZA8znOzX9RWMPsA2BE,5137
|
|
3
|
-
mwx/controls.py,sha256=jhru4HiIijb3QJz2elGt0in9soaR3xilgHsfItYY0JI,47595
|
|
4
|
-
mwx/framework.py,sha256=rp93Nh7eqeAWGpkjxp-NY84RYBfmI1Ahn_tauavWSbg,75475
|
|
5
|
-
mwx/graphman.py,sha256=A53ufapRAysL0wTCr1anrg_T_PqpumonnYn-swaC598,70165
|
|
6
|
-
mwx/images.py,sha256=_-Eh3xF7Khu42ivkYp97NXIzSNGbjcidqtWjZQFGtqE,47827
|
|
7
|
-
mwx/matplot2.py,sha256=xCJ_ZzdDEWmzctpPaOrzTnwXyHINP4nfFHweoTZa6ug,32899
|
|
8
|
-
mwx/matplot2g.py,sha256=3hS0ilXCif0mZkSufE_Rf-taRs3m1hIxiIFMuioYYuc,64371
|
|
9
|
-
mwx/matplot2lg.py,sha256=JRWjWnLJUytbSq6wxs4P0gbVUr3xoLSF6Wwqd5V_pJI,27404
|
|
10
|
-
mwx/mgplt.py,sha256=r56SFryorIgO12mvHJY-z6uwWsaPEqk6pHYwKWqbTY4,5663
|
|
11
|
-
mwx/nutshell.py,sha256=9SjAwZB0NkSe7K-REBXEaqYwgML7JVKbp2HkI6cLM54,141807
|
|
12
|
-
mwx/utilus.py,sha256=B76pDg6_kW8FMNdQ6xO0Bwy4KJ0laY98Gg6N3iqV7c8,37325
|
|
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=epO_26sPmdDyr_lApa2Jtgxp-yCEdW0OEz0_QbrFEuM,10427
|
|
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=fumUG1F5M9TL-Dfqni4G85uk7TmvnUunTbdcPDV0vfo,16857
|
|
24
|
-
mwxlib-0.98.6.dist-info/LICENSE,sha256=PGtRKCaTkmUDlBQwpptJAxJtdqxIUtAmdBsaT9nUVkA,1091
|
|
25
|
-
mwxlib-0.98.6.dist-info/METADATA,sha256=RDfB4NPf48FHJKeGXjSM72yYzMlOlrs5nqqPqO45ToU,7411
|
|
26
|
-
mwxlib-0.98.6.dist-info/WHEEL,sha256=Mdi9PDNwEZptOjTlUcAth7XJDFtKrHYaQMPulZeBCiQ,91
|
|
27
|
-
mwxlib-0.98.6.dist-info/top_level.txt,sha256=SI1Mh118AstnUFGPNq5aMNKiAnVNmZk1S9Ij-OwAEpY,4
|
|
28
|
-
mwxlib-0.98.6.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|