mwxlib 0.99.8__py3-none-any.whl → 1.0.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/__init__.py +1 -1
- mwx/controls.py +97 -119
- mwx/framework.py +27 -22
- mwx/graphman.py +30 -40
- mwx/images.py +13 -0
- mwx/matplot2.py +1 -1
- mwx/matplot2g.py +24 -31
- mwx/nutshell.py +29 -26
- mwx/plugins/ffmpeg_view.py +0 -1
- mwx/plugins/fft_view.py +1 -1
- mwx/plugins/frame_listview.py +1 -1
- mwx/plugins/line_profile.py +1 -1
- mwx/utilus.py +2 -0
- mwx/wxpdb.py +0 -9
- mwx/wxwit.py +0 -2
- {mwxlib-0.99.8.dist-info → mwxlib-1.0.0.dist-info}/METADATA +8 -13
- mwxlib-1.0.0.dist-info/RECORD +28 -0
- {mwxlib-0.99.8.dist-info → mwxlib-1.0.0.dist-info}/WHEEL +1 -1
- mwxlib-0.99.8.dist-info/RECORD +0 -28
- {mwxlib-0.99.8.dist-info → mwxlib-1.0.0.dist-info}/LICENSE +0 -0
- {mwxlib-0.99.8.dist-info → mwxlib-1.0.0.dist-info}/top_level.txt +0 -0
mwx/__init__.py
CHANGED
|
@@ -8,7 +8,7 @@ from .framework import Frame, MiniFrame, ShellFrame, deb
|
|
|
8
8
|
|
|
9
9
|
## Controls
|
|
10
10
|
from .controls import Param, LParam, Knob, ControlPanel, Clipboard, Icon
|
|
11
|
-
from .controls import Button, ToggleButton, TextCtrl, Choice, Gauge, Indicator
|
|
11
|
+
from .controls import Button, ToggleButton, ClassicButton, TextCtrl, Choice, Gauge, Indicator
|
|
12
12
|
|
|
13
13
|
## Plugman
|
|
14
14
|
## from .graphman import Frame as GraphmanFrame, Layer, Thread, Graph
|
mwx/controls.py
CHANGED
|
@@ -823,8 +823,17 @@ class Clipboard:
|
|
|
823
823
|
## --------------------------------
|
|
824
824
|
## Wx custom controls and bitmaps
|
|
825
825
|
## --------------------------------
|
|
826
|
-
|
|
827
|
-
|
|
826
|
+
|
|
827
|
+
class Icon(wx.Bitmap):
|
|
828
|
+
"""Returns an iconic bitmap with the specified size (w, h).
|
|
829
|
+
|
|
830
|
+
The key is either Icon.provided_arts or Icon.custom_images key.
|
|
831
|
+
If the key is empty it returns a transparent bitmap, otherwise NullBitmap.
|
|
832
|
+
|
|
833
|
+
Note:
|
|
834
|
+
A null (0-shaped) bitmap fails with AssertionError from 4.1.1
|
|
835
|
+
"""
|
|
836
|
+
provided_arts = {
|
|
828
837
|
'cut' : wx.ART_CUT,
|
|
829
838
|
'copy' : wx.ART_COPY,
|
|
830
839
|
'paste' : wx.ART_PASTE,
|
|
@@ -858,32 +867,69 @@ if 1:
|
|
|
858
867
|
'|<-' : wx.ART_GOTO_FIRST,
|
|
859
868
|
'->|' : wx.ART_GOTO_LAST,
|
|
860
869
|
}
|
|
861
|
-
|
|
870
|
+
custom_images = {
|
|
862
871
|
k:v for k, v in vars(images).items()
|
|
863
872
|
if isinstance(v, wx.lib.embeddedimage.PyEmbeddedImage)
|
|
864
873
|
}
|
|
865
|
-
|
|
866
|
-
class Icon(wx.Bitmap):
|
|
867
|
-
"""Returns an iconic bitmap with the specified size (w, h).
|
|
868
|
-
|
|
869
|
-
The key is either Icon.provided_arts or Icon.custom_images key.
|
|
870
|
-
If the key is empty it returns a transparent bitmap, otherwise NullBitmap.
|
|
871
|
-
|
|
872
|
-
Note:
|
|
873
|
-
A null (0-shaped) bitmap fails with AssertionError from 4.1.1
|
|
874
|
-
"""
|
|
875
|
-
provided_arts = _provided_arts
|
|
876
|
-
custom_images = _custom_images
|
|
877
874
|
|
|
878
875
|
def __init__(self, *args, **kwargs):
|
|
879
876
|
try:
|
|
880
|
-
bmp = _getBitmap1(*args, **kwargs)
|
|
877
|
+
bmp = Icon._getBitmap1(*args, **kwargs)
|
|
881
878
|
except TypeError:
|
|
882
|
-
bmp = _getBitmap2(*args, **kwargs)
|
|
879
|
+
bmp = Icon._getBitmap2(*args, **kwargs)
|
|
883
880
|
wx.Bitmap.__init__(self, bmp)
|
|
884
881
|
|
|
885
882
|
@staticmethod
|
|
886
|
-
def
|
|
883
|
+
def _getBitmap1(key, size=None):
|
|
884
|
+
if isinstance(key, wx.Bitmap):
|
|
885
|
+
if size and key.Size != size:
|
|
886
|
+
key = (key.ConvertToImage()
|
|
887
|
+
.Scale(*size, wx.IMAGE_QUALITY_NEAREST)
|
|
888
|
+
.ConvertToBitmap())
|
|
889
|
+
return key #<wx.Bitmap>
|
|
890
|
+
if not size:
|
|
891
|
+
size = (16, 16)
|
|
892
|
+
if key:
|
|
893
|
+
try:
|
|
894
|
+
art = Icon.custom_images.get(key)
|
|
895
|
+
bmp = art.GetBitmap()
|
|
896
|
+
except Exception:
|
|
897
|
+
art = Icon.provided_arts.get(key)
|
|
898
|
+
bmp = wx.ArtProvider.GetBitmap(art or key, wx.ART_OTHER, size)
|
|
899
|
+
return bmp
|
|
900
|
+
|
|
901
|
+
## Note: null (0-shaped) bitmap fails with AssertionError from 4.1.1
|
|
902
|
+
elif key == '':
|
|
903
|
+
bmp = wx.Bitmap(size)
|
|
904
|
+
with wx.MemoryDC(bmp) as dc:
|
|
905
|
+
dc.SetBackground(wx.Brush('black'))
|
|
906
|
+
dc.Clear()
|
|
907
|
+
bmp.SetMaskColour('black') # return dummy-sized blank bitmap
|
|
908
|
+
return bmp
|
|
909
|
+
|
|
910
|
+
return wx.NullBitmap # The standard wx controls accept this,
|
|
911
|
+
|
|
912
|
+
@staticmethod
|
|
913
|
+
def _getBitmap2(back, fore, size=None, subsize=3/4):
|
|
914
|
+
if not size:
|
|
915
|
+
size = (16, 16)
|
|
916
|
+
if isinstance(subsize, float):
|
|
917
|
+
subsize = wx.Size(size) * subsize
|
|
918
|
+
back = Icon._getBitmap1(back, size)
|
|
919
|
+
fore = Icon._getBitmap1(fore, subsize)
|
|
920
|
+
x = size[0] - subsize[0]
|
|
921
|
+
y = size[1] - subsize[1]
|
|
922
|
+
with wx.MemoryDC(back) as dc:
|
|
923
|
+
## dc = wx.GCDC(dc)
|
|
924
|
+
## dc.DrawBitmap(fore, x, y, useMask=True)
|
|
925
|
+
gc = wx.GraphicsContext.Create(dc)
|
|
926
|
+
gc.DrawBitmap(fore, x, y, *subsize)
|
|
927
|
+
return back
|
|
928
|
+
|
|
929
|
+
@staticmethod
|
|
930
|
+
def bullet(colour, ec=None, size=None, radius=4):
|
|
931
|
+
if not size:
|
|
932
|
+
size = (16, 16)
|
|
887
933
|
bmp = wx.Bitmap(size)
|
|
888
934
|
with wx.MemoryDC(bmp) as dc:
|
|
889
935
|
dc.SetBackground(wx.Brush('black'))
|
|
@@ -910,55 +956,24 @@ class Icon(wx.Bitmap):
|
|
|
910
956
|
return bmp
|
|
911
957
|
|
|
912
958
|
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
if key.Size != size:
|
|
916
|
-
key = (key.ConvertToImage()
|
|
917
|
-
.Scale(*size, wx.IMAGE_QUALITY_NEAREST)
|
|
918
|
-
.ConvertToBitmap())
|
|
919
|
-
return key
|
|
920
|
-
if key:
|
|
921
|
-
try:
|
|
922
|
-
art = _custom_images.get(key)
|
|
923
|
-
bmp = art.GetBitmap()
|
|
924
|
-
except Exception:
|
|
925
|
-
art = _provided_arts.get(key)
|
|
926
|
-
bmp = wx.ArtProvider.GetBitmap(art or key, wx.ART_OTHER, size)
|
|
927
|
-
return bmp
|
|
928
|
-
|
|
929
|
-
## Note: null (0-shaped) bitmap fails with AssertionError from 4.1.1
|
|
930
|
-
elif key == '':
|
|
931
|
-
bmp = wx.Bitmap(size)
|
|
932
|
-
with wx.MemoryDC(bmp) as dc:
|
|
933
|
-
dc.SetBackground(wx.Brush('black'))
|
|
934
|
-
dc.Clear()
|
|
935
|
-
bmp.SetMaskColour('black') # return dummy-sized blank bitmap
|
|
936
|
-
return bmp
|
|
959
|
+
class ClassicButton(wx.Button):
|
|
960
|
+
"""Flat button
|
|
937
961
|
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
return back
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
def _Icon(v):
|
|
957
|
-
if isinstance(v, (str, bytes)):
|
|
958
|
-
return Icon(v)
|
|
959
|
-
if isinstance(v, wx.lib.embeddedimage.PyEmbeddedImage):
|
|
960
|
-
return v.GetBitmap()
|
|
961
|
-
return v
|
|
962
|
+
Args:
|
|
963
|
+
label : button label
|
|
964
|
+
handler : event handler when the button is pressed
|
|
965
|
+
icon : key:str or bitmap for button icon
|
|
966
|
+
**kwargs: keywords for wx.lib.platebtn.PlateButton
|
|
967
|
+
"""
|
|
968
|
+
def __init__(self, parent, label='', handler=None, icon=None, **kwargs):
|
|
969
|
+
wx.Button.__init__(self, parent, -1, label, **kwargs)
|
|
970
|
+
|
|
971
|
+
if handler:
|
|
972
|
+
self.Bind(wx.EVT_BUTTON, _F(handler))
|
|
973
|
+
|
|
974
|
+
self.SetToolTip(_Tip(handler.__doc__))
|
|
975
|
+
if icon:
|
|
976
|
+
self.SetBitmap(Icon(icon))
|
|
962
977
|
|
|
963
978
|
|
|
964
979
|
class Button(pb.PlateButton):
|
|
@@ -970,17 +985,6 @@ class Button(pb.PlateButton):
|
|
|
970
985
|
icon : key:str or bitmap for button icon
|
|
971
986
|
**kwargs: keywords for wx.lib.platebtn.PlateButton
|
|
972
987
|
"""
|
|
973
|
-
@property
|
|
974
|
-
def icon(self):
|
|
975
|
-
"""Icon key:str or bitmap."""
|
|
976
|
-
return self.__icon
|
|
977
|
-
|
|
978
|
-
@icon.setter
|
|
979
|
-
def icon(self, v):
|
|
980
|
-
self.__icon = v
|
|
981
|
-
self.SetBitmap(_Icon(v))
|
|
982
|
-
self.Refresh()
|
|
983
|
-
|
|
984
988
|
def __init__(self, parent, label='', handler=None, icon=None, **kwargs):
|
|
985
989
|
kwargs.setdefault('style', pb.PB_STYLE_DEFAULT | pb.PB_STYLE_SQUARE)
|
|
986
990
|
pb.PlateButton.__init__(self, parent, -1, label, **kwargs)
|
|
@@ -988,8 +992,9 @@ class Button(pb.PlateButton):
|
|
|
988
992
|
if handler:
|
|
989
993
|
self.Bind(wx.EVT_BUTTON, _F(handler))
|
|
990
994
|
|
|
991
|
-
self.
|
|
992
|
-
|
|
995
|
+
self.SetToolTip(_Tip(handler.__doc__))
|
|
996
|
+
if icon:
|
|
997
|
+
self.SetBitmap(Icon(icon))
|
|
993
998
|
|
|
994
999
|
def SetBitmap(self, bmp):
|
|
995
1000
|
"""Set the bitmap displayed in the button.
|
|
@@ -998,7 +1003,8 @@ class Button(pb.PlateButton):
|
|
|
998
1003
|
try:
|
|
999
1004
|
pb.PlateButton.SetBitmap(self, bmp)
|
|
1000
1005
|
except Exception:
|
|
1001
|
-
self._bmp =
|
|
1006
|
+
self._bmp['enable'] = None
|
|
1007
|
+
self._bmp['disable'] = None
|
|
1002
1008
|
|
|
1003
1009
|
|
|
1004
1010
|
class ToggleButton(wx.ToggleButton):
|
|
@@ -1013,29 +1019,19 @@ class ToggleButton(wx.ToggleButton):
|
|
|
1013
1019
|
Note:
|
|
1014
1020
|
To get the status, check Value or event.GetInt or event.IsChecked.
|
|
1015
1021
|
"""
|
|
1016
|
-
@property
|
|
1017
|
-
def icon(self):
|
|
1018
|
-
"""Icon key:str or bitmap."""
|
|
1019
|
-
return self.__icon
|
|
1020
|
-
|
|
1021
|
-
@icon.setter
|
|
1022
|
-
def icon(self, v):
|
|
1023
|
-
self.__icon = v
|
|
1024
|
-
if isinstance(v, tuple):
|
|
1025
|
-
self.SetBitmap(_Icon(v[0]))
|
|
1026
|
-
self.SetBitmapPressed(_Icon(v[1]))
|
|
1027
|
-
elif v:
|
|
1028
|
-
self.SetBitmap(_Icon(v))
|
|
1029
|
-
self.Refresh()
|
|
1030
|
-
|
|
1031
1022
|
def __init__(self, parent, label='', handler=None, icon=None, **kwargs):
|
|
1032
1023
|
wx.ToggleButton.__init__(self, parent, -1, label, **kwargs)
|
|
1033
1024
|
|
|
1034
1025
|
if handler:
|
|
1035
1026
|
self.Bind(wx.EVT_TOGGLEBUTTON, _F(handler))
|
|
1036
1027
|
|
|
1037
|
-
self.
|
|
1038
|
-
|
|
1028
|
+
self.SetToolTip(_Tip(handler.__doc__))
|
|
1029
|
+
if icon:
|
|
1030
|
+
try:
|
|
1031
|
+
self.SetBitmap(Icon(icon[0]))
|
|
1032
|
+
self.SetBitmapPressed(Icon(icon[1]))
|
|
1033
|
+
except Exception:
|
|
1034
|
+
self.SetBitmap(Icon(icon))
|
|
1039
1035
|
|
|
1040
1036
|
|
|
1041
1037
|
class TextCtrl(wx.Control):
|
|
@@ -1057,15 +1053,6 @@ class TextCtrl(wx.Control):
|
|
|
1057
1053
|
|
|
1058
1054
|
value = Value #: internal use only
|
|
1059
1055
|
|
|
1060
|
-
@property
|
|
1061
|
-
def icon(self):
|
|
1062
|
-
"""Icon key:str or bitmap."""
|
|
1063
|
-
return self._btn.icon
|
|
1064
|
-
|
|
1065
|
-
@icon.setter
|
|
1066
|
-
def icon(self, v):
|
|
1067
|
-
self._btn.icon = v
|
|
1068
|
-
|
|
1069
1056
|
def __init__(self, parent, label='', handler=None, updater=None,
|
|
1070
1057
|
icon=None, readonly=False, size=(-1,-1), **kwargs):
|
|
1071
1058
|
wx.Control.__init__(self, parent, size=size, style=wx.BORDER_NONE)
|
|
@@ -1077,8 +1064,8 @@ class TextCtrl(wx.Control):
|
|
|
1077
1064
|
self._ctrl = wx.TextCtrl(self, **kwargs)
|
|
1078
1065
|
self._btn = Button(self, label, None, icon,
|
|
1079
1066
|
size=(-1,-1) if label or icon else (0,0))
|
|
1080
|
-
self._ctrl.
|
|
1081
|
-
self._btn.
|
|
1067
|
+
self._ctrl.SetToolTip(_Tip(handler.__doc__))
|
|
1068
|
+
self._btn.SetToolTip(_Tip(updater.__doc__))
|
|
1082
1069
|
|
|
1083
1070
|
self.SetSizer(
|
|
1084
1071
|
pack(self, (
|
|
@@ -1134,15 +1121,6 @@ class Choice(wx.Control):
|
|
|
1134
1121
|
lambda self,v: self._ctrl.SetItems(v),
|
|
1135
1122
|
doc="combobox items:list")
|
|
1136
1123
|
|
|
1137
|
-
@property
|
|
1138
|
-
def icon(self):
|
|
1139
|
-
"""Icon key:str or bitmap."""
|
|
1140
|
-
return self._btn.icon
|
|
1141
|
-
|
|
1142
|
-
@icon.setter
|
|
1143
|
-
def icon(self, v):
|
|
1144
|
-
self._btn.icon = v
|
|
1145
|
-
|
|
1146
1124
|
def __init__(self, parent, label='', handler=None, updater=None,
|
|
1147
1125
|
icon=None, readonly=False, size=(-1,-1), **kwargs):
|
|
1148
1126
|
wx.Control.__init__(self, parent, size=size, style=wx.BORDER_NONE)
|
|
@@ -1154,8 +1132,8 @@ class Choice(wx.Control):
|
|
|
1154
1132
|
self._ctrl = wx.ComboBox(self, **kwargs)
|
|
1155
1133
|
self._btn = Button(self, label, None, icon,
|
|
1156
1134
|
size=(-1,-1) if label or icon else (0,0))
|
|
1157
|
-
self._ctrl.
|
|
1158
|
-
self._btn.
|
|
1135
|
+
self._ctrl.SetToolTip(_Tip(handler.__doc__))
|
|
1136
|
+
self._btn.SetToolTip(_Tip(updater.__doc__))
|
|
1159
1137
|
|
|
1160
1138
|
self.SetSizer(
|
|
1161
1139
|
pack(self, (
|
mwx/framework.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#! python3
|
|
2
2
|
"""mwxlib framework.
|
|
3
3
|
"""
|
|
4
|
-
__version__ = "0.
|
|
4
|
+
__version__ = "1.0.0"
|
|
5
5
|
__author__ = "Kazuya O'moto <komoto@jeol.co.jp>"
|
|
6
6
|
|
|
7
7
|
from contextlib import contextmanager
|
|
@@ -165,22 +165,6 @@ _speckeys = {
|
|
|
165
165
|
|
|
166
166
|
_speckeys_wxkmap = dict((v, k) for k, v in _speckeys.items())
|
|
167
167
|
|
|
168
|
-
def getKeyState(key):
|
|
169
|
-
"""Returns state of speckey (cf. wx.GetKeyState)."""
|
|
170
|
-
try:
|
|
171
|
-
return wx.GetKeyState(_speckeys_wxkmap[key])
|
|
172
|
-
except KeyError:
|
|
173
|
-
pass
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
def setKeyState(key, state):
|
|
177
|
-
"""Makes you feel like having pressed/released speckey."""
|
|
178
|
-
vk = wx.UIActionSimulator()
|
|
179
|
-
if state:
|
|
180
|
-
vk.KeyDown(_speckeys_wxkmap[key])
|
|
181
|
-
else:
|
|
182
|
-
vk.KeyUp(_speckeys_wxkmap[key])
|
|
183
|
-
|
|
184
168
|
|
|
185
169
|
def hotkey(evt):
|
|
186
170
|
"""Interpret evt.KeyCode as hotkey:str and overwrite evt.key.
|
|
@@ -226,10 +210,29 @@ class KeyCtrlInterfaceMixin:
|
|
|
226
210
|
spec-map : 'C-c'
|
|
227
211
|
esc-map : 'escape'
|
|
228
212
|
"""
|
|
213
|
+
message = print # override this in subclass
|
|
214
|
+
|
|
229
215
|
@postcall
|
|
230
216
|
def post_message(self, *args, **kwargs):
|
|
231
217
|
return self.message(*args, **kwargs)
|
|
232
218
|
|
|
219
|
+
@staticmethod
|
|
220
|
+
def getKeyState(key):
|
|
221
|
+
"""Returns state of speckey (cf. wx.GetKeyState)."""
|
|
222
|
+
try:
|
|
223
|
+
return wx.GetKeyState(_speckeys_wxkmap[key])
|
|
224
|
+
except KeyError:
|
|
225
|
+
pass
|
|
226
|
+
|
|
227
|
+
@staticmethod
|
|
228
|
+
def setKeyState(key, state):
|
|
229
|
+
"""Makes you feel like having pressed/released speckey."""
|
|
230
|
+
vk = wx.UIActionSimulator()
|
|
231
|
+
if state:
|
|
232
|
+
vk.KeyDown(_speckeys_wxkmap[key])
|
|
233
|
+
else:
|
|
234
|
+
vk.KeyUp(_speckeys_wxkmap[key])
|
|
235
|
+
|
|
233
236
|
def make_keymap(self, keymap):
|
|
234
237
|
"""Make a basis of extension map in the handler.
|
|
235
238
|
"""
|
|
@@ -259,9 +262,8 @@ class KeyCtrlInterfaceMixin:
|
|
|
259
262
|
})
|
|
260
263
|
|
|
261
264
|
def pre_command_hook(self, evt):
|
|
262
|
-
"""
|
|
263
|
-
Check text selection for [C-c/C-x].
|
|
264
|
-
"""
|
|
265
|
+
"""Called when entering extension mode (internal use only)."""
|
|
266
|
+
## Check text selection for [C-c/C-x].
|
|
265
267
|
wnd = wx.Window.FindFocus()
|
|
266
268
|
if isinstance(wnd, wx.TextEntry) and wnd.StringSelection\
|
|
267
269
|
or isinstance(wnd, stc.StyledTextCtrl) and wnd.SelectedText:
|
|
@@ -272,6 +274,7 @@ class KeyCtrlInterfaceMixin:
|
|
|
272
274
|
evt.Skip()
|
|
273
275
|
|
|
274
276
|
def post_command_hook(self, evt):
|
|
277
|
+
"""Called when exiting extension mode (internal use only)."""
|
|
275
278
|
keymap = self.handler.previous_state
|
|
276
279
|
if keymap:
|
|
277
280
|
self.message("{} {}".format(keymap, evt.key))
|
|
@@ -334,8 +337,6 @@ class CtrlInterface(KeyCtrlInterfaceMixin):
|
|
|
334
337
|
"""
|
|
335
338
|
handler = property(lambda self: self.__handler)
|
|
336
339
|
|
|
337
|
-
message = print # override this in subclass
|
|
338
|
-
|
|
339
340
|
def __init__(self):
|
|
340
341
|
self.__key = ''
|
|
341
342
|
self.__button = ''
|
|
@@ -1736,6 +1737,8 @@ class ShellFrame(MiniFrame):
|
|
|
1736
1737
|
self.popup_window(self.linfo)
|
|
1737
1738
|
self.add_log("<-- Beginning of debugger\r\n")
|
|
1738
1739
|
self.indicator.Value = 2
|
|
1740
|
+
if wx.IsBusy():
|
|
1741
|
+
wx.EndBusyCursor()
|
|
1739
1742
|
|
|
1740
1743
|
def on_debug_next(self, frame):
|
|
1741
1744
|
"""Called from cmdloop."""
|
|
@@ -1772,6 +1775,8 @@ class ShellFrame(MiniFrame):
|
|
|
1772
1775
|
del shell.locals
|
|
1773
1776
|
del shell.globals
|
|
1774
1777
|
self.indicator.Value = 1
|
|
1778
|
+
if wx.IsBusy():
|
|
1779
|
+
wx.EndBusyCursor()
|
|
1775
1780
|
|
|
1776
1781
|
def set_hookable(self, editor, traceable=True):
|
|
1777
1782
|
"""Bind pointer to set/unset trace."""
|
mwx/graphman.py
CHANGED
|
@@ -166,8 +166,8 @@ class Thread:
|
|
|
166
166
|
msg += '\n\n'
|
|
167
167
|
try:
|
|
168
168
|
self.event.clear() # suspend
|
|
169
|
-
if wx.MessageBox(
|
|
170
|
-
"Do you want to terminate the process?",
|
|
169
|
+
if wx.MessageBox( # Confirm terminatation.
|
|
170
|
+
msg + "Do you want to terminate the process?",
|
|
171
171
|
style=wx.OK|wx.CANCEL|wx.ICON_WARNING) == wx.OK:
|
|
172
172
|
self.Stop()
|
|
173
173
|
return False
|
|
@@ -574,8 +574,9 @@ class MyFileDropLoader(wx.FileDropTarget):
|
|
|
574
574
|
for fn in filenames:
|
|
575
575
|
name, ext = os.path.splitext(fn)
|
|
576
576
|
if ext == '.py' or os.path.isdir(fn):
|
|
577
|
-
self.loader.load_plug(fn, show=1,
|
|
578
|
-
|
|
577
|
+
self.loader.load_plug(fn, show=1,
|
|
578
|
+
floating_pos=pos,
|
|
579
|
+
force=wx.GetKeyState(wx.WXK_ALT))
|
|
579
580
|
elif ext == '.jssn':
|
|
580
581
|
self.loader.load_session(fn)
|
|
581
582
|
elif ext == '.index':
|
|
@@ -946,6 +947,7 @@ class Frame(mwx.Frame):
|
|
|
946
947
|
shown = plug.IsShown()
|
|
947
948
|
except AttributeError:
|
|
948
949
|
shown = pane.IsShown()
|
|
950
|
+
|
|
949
951
|
if show and not shown:
|
|
950
952
|
if isinstance(win, aui.AuiNotebook):
|
|
951
953
|
j = win.GetPageIndex(plug)
|
|
@@ -962,6 +964,11 @@ class Frame(mwx.Frame):
|
|
|
962
964
|
else:
|
|
963
965
|
win.handler('page_closed', win)
|
|
964
966
|
|
|
967
|
+
if pane.dock_direction:
|
|
968
|
+
pane.Dock()
|
|
969
|
+
else:
|
|
970
|
+
pane.Float()
|
|
971
|
+
|
|
965
972
|
## Modify the floating position of the pane when displayed.
|
|
966
973
|
## Note: This is a known bug in wxWidgets 3.17 -- 3.20,
|
|
967
974
|
## and will be fixed in wxPython 4.2.1.
|
|
@@ -972,39 +979,27 @@ class Frame(mwx.Frame):
|
|
|
972
979
|
self._mgr.Update()
|
|
973
980
|
return (show != shown)
|
|
974
981
|
|
|
975
|
-
def update_pane(self, name,
|
|
976
|
-
"""Update the layout of the pane.
|
|
982
|
+
def update_pane(self, name, **props):
|
|
983
|
+
"""Update the layout of the pane (internal use only).
|
|
977
984
|
|
|
978
985
|
Note:
|
|
979
986
|
This is called automatically from load_plug,
|
|
980
987
|
and should not be called directly from user.
|
|
981
988
|
"""
|
|
982
989
|
pane = self.get_pane(name)
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
pane.dock_row = kwargs.get('row', 0)
|
|
987
|
-
pane.dock_proportion = kwargs.get('prop') or pane.dock_proportion
|
|
988
|
-
pane.floating_pos = kwargs.get('floating_pos') or pane.floating_pos
|
|
989
|
-
pane.floating_size = kwargs.get('floating_size') or pane.floating_size
|
|
990
|
+
for k, v in props.items():
|
|
991
|
+
if v is not None:
|
|
992
|
+
setattr(pane, k, v)
|
|
990
993
|
|
|
991
994
|
plug = self.get_plug(name)
|
|
992
995
|
if plug:
|
|
993
996
|
dock = plug.dockable
|
|
994
|
-
if not isinstance(dock, bool):
|
|
995
|
-
|
|
997
|
+
if not isinstance(dock, bool):
|
|
998
|
+
pane.dock_direction = dock
|
|
996
999
|
if not plug.caption:
|
|
997
1000
|
pane.CaptionVisible(False) # no caption bar
|
|
998
1001
|
pane.Gripper(dock not in (0, 5)) # show a grip when docked
|
|
999
1002
|
pane.Dockable(dock)
|
|
1000
|
-
|
|
1001
|
-
dock = kwargs.get('dock')
|
|
1002
|
-
pane.dock_direction = dock or 0
|
|
1003
|
-
if dock:
|
|
1004
|
-
pane.Dock()
|
|
1005
|
-
else:
|
|
1006
|
-
pane.Float()
|
|
1007
|
-
return self.show_pane(name, show)
|
|
1008
1003
|
|
|
1009
1004
|
def OnPaneClose(self, evt): #<wx.aui.AuiManagerEvent>
|
|
1010
1005
|
pane = evt.GetPane()
|
|
@@ -1113,9 +1108,9 @@ class Frame(mwx.Frame):
|
|
|
1113
1108
|
self.register(cls, module)
|
|
1114
1109
|
return module
|
|
1115
1110
|
|
|
1116
|
-
def load_plug(self, root, force=False, session=None,
|
|
1117
|
-
|
|
1118
|
-
|
|
1111
|
+
def load_plug(self, root, force=False, session=None, show=False,
|
|
1112
|
+
dock=0, floating_pos=None, floating_size=None,
|
|
1113
|
+
**kwargs):
|
|
1119
1114
|
"""Load plugin.
|
|
1120
1115
|
|
|
1121
1116
|
Args:
|
|
@@ -1126,10 +1121,6 @@ class Frame(mwx.Frame):
|
|
|
1126
1121
|
session : Conditions for initializing the plug and starting session
|
|
1127
1122
|
show : the pane is shown after loaded
|
|
1128
1123
|
dock : dock_direction (1:top, 2:right, 3:bottom, 4:left, 5:center)
|
|
1129
|
-
layer : dock_layer
|
|
1130
|
-
pos : dock_pos
|
|
1131
|
-
row : dock_row position
|
|
1132
|
-
prop : dock_proportion < 1e6 ?
|
|
1133
1124
|
floating_pos: posision of floating window
|
|
1134
1125
|
floating_size: size of floating window
|
|
1135
1126
|
|
|
@@ -1141,14 +1132,16 @@ class Frame(mwx.Frame):
|
|
|
1141
1132
|
Note:
|
|
1142
1133
|
The root module must have a class Plugin <Layer>
|
|
1143
1134
|
"""
|
|
1144
|
-
props = dict(
|
|
1145
|
-
floating_pos=floating_pos,
|
|
1135
|
+
props = dict(dock_direction=dock,
|
|
1136
|
+
floating_pos=floating_pos,
|
|
1137
|
+
floating_size=floating_size)
|
|
1146
1138
|
|
|
1147
1139
|
_dirname, name = split_paths(root)
|
|
1148
1140
|
|
|
1149
1141
|
plug = self.get_plug(name)
|
|
1150
1142
|
if plug and not force:
|
|
1151
1143
|
self.update_pane(name, **props)
|
|
1144
|
+
self.show_pane(name, show)
|
|
1152
1145
|
try:
|
|
1153
1146
|
if session:
|
|
1154
1147
|
plug.load_session(session)
|
|
@@ -1178,15 +1171,11 @@ class Frame(mwx.Frame):
|
|
|
1178
1171
|
if name not in self.plugins:
|
|
1179
1172
|
raise NameError("Plugin name must not be the same as any other panes")
|
|
1180
1173
|
|
|
1174
|
+
show = show or pane.IsShown()
|
|
1181
1175
|
props.update(
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
pos = pane.dock_pos,
|
|
1186
|
-
row = pane.dock_row,
|
|
1187
|
-
prop = pane.dock_proportion,
|
|
1188
|
-
floating_pos = floating_pos or pane.floating_pos[:], # copy (pane unloaded)
|
|
1189
|
-
floating_size = floating_size or pane.floating_size[:], # copy
|
|
1176
|
+
dock_direction = pane.IsDocked() and pane.dock_direction,
|
|
1177
|
+
floating_pos = floating_pos or pane.floating_pos[:], # copy unloading pane
|
|
1178
|
+
floating_size = floating_size or pane.floating_size[:], # copy unloading pane
|
|
1190
1179
|
)
|
|
1191
1180
|
except (AttributeError, NameError) as e:
|
|
1192
1181
|
traceback.print_exc()
|
|
@@ -1248,6 +1237,7 @@ class Frame(mwx.Frame):
|
|
|
1248
1237
|
plug.Name = name
|
|
1249
1238
|
|
|
1250
1239
|
self.update_pane(name, **props)
|
|
1240
|
+
self.show_pane(name, show)
|
|
1251
1241
|
|
|
1252
1242
|
## Create a menu
|
|
1253
1243
|
plug.__Menu_item = None
|
mwx/images.py
CHANGED
|
@@ -135,6 +135,19 @@ clock = PyEmbeddedImage(
|
|
|
135
135
|
b'vqHBv3R3pmbxzgwz4Z+EaTXtwqIogrzjxIJ4QVVV1UyihxgjFv3/K09Bu/lEkBgg5rLZH+fT'
|
|
136
136
|
b'5dvfn7iFAAAAAElFTkSuQmCC')
|
|
137
137
|
|
|
138
|
+
#----------------------------------------------------------------------
|
|
139
|
+
cog = PyEmbeddedImage(
|
|
140
|
+
b'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAQAAAC1+jfqAAAABGdBTUEAAK/INwWK6QAAABl0'
|
|
141
|
+
b'RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAGSSURBVCjPVVFNSwJhEF78Ad79'
|
|
142
|
+
b'Cf6PvXQRsotUlzKICosuRYmR2RJR0KE6lBFFZVEbpFBSqKu2rum6llFS9HHI4iUhT153n6Zt'
|
|
143
|
+
b'IWMOM+/MM88z7wwH7s9Ub16SJcnbmrNcxVm2q7Z8/QPvEOtntpj92NkCqITLepEpjix7xQti'
|
|
144
|
+
b'LOoQ2b6+E7YAN/5nfOEJ2WbKqOIOJ4bYVMEQx4LfBBQDsvFMhUcCVU1/CxVXmDBGA5ZETrhD'
|
|
145
|
+
b'CQVcYAPbyEJBhvrnBVPiSpNr6cYDNCQwo4zzU/ySckkgDYuNuVpI42T9k4gLKGMPs/xPzzov'
|
|
146
|
+
b'QiY2hQYe0jlJfyNNhTqiWDYBq/wBMcSRpnyPzu1oS7WtxjVBSthU1vgVksiQ3Dn6Gp5ah2YO'
|
|
147
|
+
b'KQo5GiuHPA6xT1EKpxQNCNYejgIR457KKio0S56YckjSa9jo//3mrj+BV0QQagqGTOo+Y7gZ'
|
|
148
|
+
b'If1puP3WHoLhEb2PjTlCTCWGXtbp8DCX3hZuOdaIc9A+aQvWk4ihq95p67a7nP+u+Ws+r0dq'
|
|
149
|
+
b'l9z/zv0NCYhdCPKZ7oYAAAAASUVORK5CYII=')
|
|
150
|
+
|
|
138
151
|
#----------------------------------------------------------------------
|
|
139
152
|
colour = PyEmbeddedImage(
|
|
140
153
|
b'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0'
|
mwx/matplot2.py
CHANGED
|
@@ -387,7 +387,7 @@ class MatplotPanel(wx.Panel):
|
|
|
387
387
|
def on_modeline_tip(self, evt): #<wx._core.MouseEvent>
|
|
388
388
|
flag = self.modeline.HitTest(evt.Position)
|
|
389
389
|
if flag == wx.HT_WINDOW_INSIDE:
|
|
390
|
-
self.modeline.
|
|
390
|
+
self.modeline.SetToolTip(self.modeline.Label)
|
|
391
391
|
evt.Skip()
|
|
392
392
|
|
|
393
393
|
def on_focus_set(self, evt): #<wx._core.FocusEvent>
|
mwx/matplot2g.py
CHANGED
|
@@ -21,7 +21,7 @@ from .matplot2 import MatplotPanel
|
|
|
21
21
|
from .matplot2 import NORMAL, DRAGGING, PAN, ZOOM, MARK, LINE, REGION
|
|
22
22
|
|
|
23
23
|
|
|
24
|
-
def
|
|
24
|
+
def _to_cvtype(src):
|
|
25
25
|
"""Convert the image to a type that can be applied to the cv2 function.
|
|
26
26
|
Note:
|
|
27
27
|
CV2 normally accepts uint8/16 and float32/64.
|
|
@@ -31,33 +31,18 @@ def _imcv(src):
|
|
|
31
31
|
return src
|
|
32
32
|
|
|
33
33
|
|
|
34
|
-
def _to_buffer(img):
|
|
35
|
-
if isinstance(img, Image.Image):
|
|
36
|
-
## return np.asarray(img) # ref
|
|
37
|
-
return np.array(img) # copy
|
|
38
|
-
|
|
39
|
-
if isinstance(img, wx.Bitmap):
|
|
40
|
-
img = img.ConvertToImage()
|
|
41
|
-
|
|
42
|
-
if isinstance(img, wx.Image):
|
|
43
|
-
w, h = img.GetSize()
|
|
44
|
-
buf = np.frombuffer(img.GetDataBuffer(), dtype='uint8')
|
|
45
|
-
return buf.reshape(h, w, 3)
|
|
46
|
-
return img
|
|
47
|
-
|
|
48
|
-
|
|
49
34
|
def _to_array(x):
|
|
50
35
|
if isinstance(x, (list, tuple)):
|
|
51
36
|
x = np.array(x)
|
|
52
37
|
return x
|
|
53
38
|
|
|
54
39
|
|
|
55
|
-
def
|
|
56
|
-
"""Convert buffer to image<uint8>
|
|
40
|
+
def _to_image(src, cutoff=0, threshold=None, binning=1):
|
|
41
|
+
"""Convert buffer to image <uint8>
|
|
57
42
|
|
|
58
43
|
>>> dst = (src-a) * 255 / (b-a)
|
|
59
44
|
|
|
60
|
-
cf. convertScaleAbs(src[, dst[, alpha[, beta]]]) -> dst<uint8>
|
|
45
|
+
cf. convertScaleAbs(src[, dst[, alpha[, beta]]]) -> dst <uint8>
|
|
61
46
|
|
|
62
47
|
>>> dst = |src * alpha + beta|
|
|
63
48
|
alpha = 255 / (b-a)
|
|
@@ -80,13 +65,13 @@ def imconvert(src, cutoff=0, threshold=None, binning=1):
|
|
|
80
65
|
|
|
81
66
|
if bins > 1:
|
|
82
67
|
## src = src[::bins,::bins]
|
|
83
|
-
src =
|
|
68
|
+
src = _to_cvtype(src)
|
|
84
69
|
src = cv2.resize(src, None, fx=1/bins, fy=1/bins, interpolation=cv2.INTER_AREA)
|
|
85
70
|
|
|
86
|
-
if src.dtype == np.uint8:
|
|
87
|
-
return bins, (0,255), src
|
|
71
|
+
if src.dtype == np.uint8: # RGB or gray image <uint8>
|
|
72
|
+
return bins, (0, 255), src
|
|
88
73
|
|
|
89
|
-
if hasattr(cutoff, '__iter__'):
|
|
74
|
+
if hasattr(cutoff, '__iter__'): # cutoff vlim:list is specified.
|
|
90
75
|
a, b = cutoff
|
|
91
76
|
elif cutoff > 0:
|
|
92
77
|
a = np.percentile(src, cutoff)
|
|
@@ -133,8 +118,17 @@ class AxesImagePhantom:
|
|
|
133
118
|
self.__aspect_ratio = aspect
|
|
134
119
|
self.__attributes = attributes
|
|
135
120
|
self.__attributes['localunit'] = self.__localunit
|
|
136
|
-
|
|
137
|
-
|
|
121
|
+
if isinstance(buf, Image.Image):
|
|
122
|
+
buf = np.array(buf) # copy buffer to array
|
|
123
|
+
if isinstance(buf, wx.Bitmap):
|
|
124
|
+
buf = buf.ConvertToImage() # bitmap to image
|
|
125
|
+
if isinstance(buf, wx.Image): # image to RGB array
|
|
126
|
+
w, h = buf.GetSize()
|
|
127
|
+
buf = np.frombuffer(buf.GetDataBuffer(), dtype='uint8').reshape(h, w, 3)
|
|
128
|
+
if buf.ndim > 2:
|
|
129
|
+
buf = cv2.cvtColor(buf, cv2.COLOR_RGB2GRAY) # RGB to grayscale
|
|
130
|
+
self.__buf = buf
|
|
131
|
+
bins, vlim, img = _to_image(self.__buf,
|
|
138
132
|
cutoff = self.parent.score_percentile,
|
|
139
133
|
threshold = self.parent.nbytes_threshold,
|
|
140
134
|
)
|
|
@@ -279,9 +273,8 @@ class AxesImagePhantom:
|
|
|
279
273
|
def update_buffer(self, buf=None):
|
|
280
274
|
"""Update buffer and the image (internal use only)."""
|
|
281
275
|
if buf is not None:
|
|
282
|
-
self.__buf =
|
|
283
|
-
|
|
284
|
-
bins, vlim, img = imconvert(self.__buf,
|
|
276
|
+
self.__buf = buf
|
|
277
|
+
bins, vlim, img = _to_image(self.__buf,
|
|
285
278
|
cutoff = self.parent.score_percentile,
|
|
286
279
|
threshold = self.parent.nbytes_threshold,
|
|
287
280
|
)
|
|
@@ -951,7 +944,7 @@ class GraphPlot(MatplotPanel):
|
|
|
951
944
|
data = frame.roi
|
|
952
945
|
GraphPlot.clipboard_name = name
|
|
953
946
|
GraphPlot.clipboard_data = data
|
|
954
|
-
bins, vlim, img =
|
|
947
|
+
bins, vlim, img = _to_image(data, frame.vlim)
|
|
955
948
|
Clipboard.imwrite(img)
|
|
956
949
|
self.message("Write buffer to clipboard.")
|
|
957
950
|
except Exception as e:
|
|
@@ -965,12 +958,12 @@ class GraphPlot(MatplotPanel):
|
|
|
965
958
|
data = GraphPlot.clipboard_data
|
|
966
959
|
if name:
|
|
967
960
|
self.message("Read buffer from clipboard.")
|
|
968
|
-
self.load(data)
|
|
969
961
|
GraphPlot.clipboard_name = None
|
|
970
962
|
GraphPlot.clipboard_data = None
|
|
971
963
|
else:
|
|
972
964
|
self.message("Read image from clipboard.")
|
|
973
|
-
|
|
965
|
+
data = Clipboard.imread()
|
|
966
|
+
self.load(data)
|
|
974
967
|
except Exception as e:
|
|
975
968
|
traceback.print_exc()
|
|
976
969
|
self.message("- No data in clipboard.", e)
|
mwx/nutshell.py
CHANGED
|
@@ -49,7 +49,6 @@ py_where_re = r'> +([^*?"<>|\r\n]+?):([0-9]+)'
|
|
|
49
49
|
py_break_re = r'at ([^*?"<>|\r\n]+?):([0-9]+)'
|
|
50
50
|
|
|
51
51
|
## Custom constants in wx.stc
|
|
52
|
-
stc.STC_P_WORD3 = 20 # deprecated
|
|
53
52
|
stc.STC_STYLE_CARETLINE = 40
|
|
54
53
|
stc.STC_STYLE_ANNOTATION = 41
|
|
55
54
|
|
|
@@ -635,9 +634,9 @@ class EditorInterface(AutoCompInterfaceMixin, CtrlInterface):
|
|
|
635
634
|
|
|
636
635
|
self.IndicatorSetStyle(11, stc.STC_INDIC_STRAIGHTBOX)
|
|
637
636
|
self.IndicatorSetUnder(11, True)
|
|
638
|
-
self.IndicatorSetAlpha(11,
|
|
639
|
-
self.IndicatorSetOutlineAlpha(11,
|
|
640
|
-
self.IndicatorSetForeground(11, "
|
|
637
|
+
self.IndicatorSetAlpha(11, 60)
|
|
638
|
+
self.IndicatorSetOutlineAlpha(11, 60)
|
|
639
|
+
self.IndicatorSetForeground(11, "light gray")
|
|
641
640
|
|
|
642
641
|
self.IndicatorSetStyle(2, stc.STC_INDIC_DOTS)
|
|
643
642
|
self.IndicatorSetForeground(2, "light gray")
|
|
@@ -804,11 +803,11 @@ class EditorInterface(AutoCompInterfaceMixin, CtrlInterface):
|
|
|
804
803
|
self.mark = self.cpos
|
|
805
804
|
|
|
806
805
|
def set_pointer(self):
|
|
807
|
-
if self.pointer == self.cline:
|
|
806
|
+
if self.pointer == self.cline: # toggle
|
|
808
807
|
self.pointer = -1
|
|
809
808
|
else:
|
|
810
|
-
self.pointer = self.cline
|
|
811
|
-
|
|
809
|
+
self.pointer = self.cline # reset
|
|
810
|
+
self.red_pointer = -1
|
|
812
811
|
|
|
813
812
|
def exchange_point_and_mark(self):
|
|
814
813
|
p = self.cpos
|
|
@@ -1419,15 +1418,15 @@ class EditorInterface(AutoCompInterfaceMixin, CtrlInterface):
|
|
|
1419
1418
|
def _format(ln):
|
|
1420
1419
|
return "{:4d} {}".format(ln+1, self.GetLine(ln).strip())
|
|
1421
1420
|
|
|
1422
|
-
pts = self.StyleGetSize(stc.STC_STYLE_DEFAULT)
|
|
1423
|
-
self.StyleSetSize(stc.STC_STYLE_DEFAULT, pts-1)
|
|
1421
|
+
## pts = self.StyleGetSize(stc.STC_STYLE_DEFAULT)
|
|
1422
|
+
## self.StyleSetSize(stc.STC_STYLE_DEFAULT, pts-1)
|
|
1424
1423
|
|
|
1425
1424
|
self.AutoCompSetSeparator(ord('\n'))
|
|
1426
1425
|
self.AutoCompShow(0, '\n'.join(map(_format, self.__itextlines)))
|
|
1427
1426
|
self.AutoCompSelect("{:4d}".format(self.cline+1))
|
|
1428
1427
|
self.Bind(stc.EVT_STC_AUTOCOMP_SELECTION, self.on_itext_selection)
|
|
1429
1428
|
|
|
1430
|
-
self.StyleSetSize(stc.STC_STYLE_DEFAULT, pts)
|
|
1429
|
+
## self.StyleSetSize(stc.STC_STYLE_DEFAULT, pts)
|
|
1431
1430
|
|
|
1432
1431
|
def on_itext_exit(self, evt):
|
|
1433
1432
|
"""Called when exiting filter_text mode."""
|
|
@@ -2144,7 +2143,6 @@ class Buffer(EditorInterface, EditWindow):
|
|
|
2144
2143
|
self.AnnotationSetStyle(lx, stc.STC_STYLE_ANNOTATION)
|
|
2145
2144
|
self.AnnotationSetText(lx, msg)
|
|
2146
2145
|
self.message(e)
|
|
2147
|
-
## print(msg, file=sys.__stderr__)
|
|
2148
2146
|
else:
|
|
2149
2147
|
self.code = code
|
|
2150
2148
|
del self.pointer # Reset pointer (debugger hook point).
|
|
@@ -2583,19 +2581,21 @@ class Interpreter(interpreter.Interpreter):
|
|
|
2583
2581
|
interpreter.Interpreter.showtraceback(self)
|
|
2584
2582
|
|
|
2585
2583
|
t, v, tb = sys.exc_info()
|
|
2586
|
-
|
|
2587
|
-
|
|
2584
|
+
while tb.tb_next:
|
|
2585
|
+
tb = tb.tb_next
|
|
2586
|
+
v.lineno = tb.tb_lineno
|
|
2587
|
+
v.filename = tb.tb_frame.f_code.co_filename
|
|
2588
2588
|
try:
|
|
2589
2589
|
self.parent.handler('interp_error', v)
|
|
2590
2590
|
except AttributeError:
|
|
2591
2591
|
pass
|
|
2592
2592
|
|
|
2593
|
-
def showsyntaxerror(self, filename=None):
|
|
2593
|
+
def showsyntaxerror(self, filename=None, **kwargs):
|
|
2594
2594
|
"""Display the syntax error that just occurred.
|
|
2595
2595
|
|
|
2596
2596
|
(override) Pass the syntax error info to the parent:shell.
|
|
2597
2597
|
"""
|
|
2598
|
-
interpreter.Interpreter.showsyntaxerror(self, filename)
|
|
2598
|
+
interpreter.Interpreter.showsyntaxerror(self, filename, **kwargs)
|
|
2599
2599
|
|
|
2600
2600
|
t, v, tb = sys.exc_info()
|
|
2601
2601
|
try:
|
|
@@ -2711,7 +2711,6 @@ class Nautilus(EditorInterface, Shell):
|
|
|
2711
2711
|
obj.this = inspect.getmodule(obj)
|
|
2712
2712
|
obj.shell = self # overwrite the facade <wx.py.shell.ShellFacade>
|
|
2713
2713
|
except AttributeError:
|
|
2714
|
-
## print("- cannot overwrite target vars:", e)
|
|
2715
2714
|
pass
|
|
2716
2715
|
self.parent.handler('title_window', obj)
|
|
2717
2716
|
|
|
@@ -3206,8 +3205,8 @@ class Nautilus(EditorInterface, Shell):
|
|
|
3206
3205
|
Note:
|
|
3207
3206
|
This is called before run, execute, and original magic.
|
|
3208
3207
|
"""
|
|
3209
|
-
sep1 = "
|
|
3210
|
-
sep2 = "`@=+-/*%<>&|^~,; \t#" # [@] ops, delims, and whitespaces
|
|
3208
|
+
sep1 = "`@=;\r\n#" # [`] no ops, no spaces, no comma
|
|
3209
|
+
sep2 = "`@=+-/*%<>&|^~,; \t\r\n#" # [@] ops, delims, and whitespaces
|
|
3211
3210
|
|
|
3212
3211
|
def _popiter(ls, f):
|
|
3213
3212
|
pred = f if callable(f) else re.compile(f).match
|
|
@@ -3276,9 +3275,10 @@ class Nautilus(EditorInterface, Shell):
|
|
|
3276
3275
|
Delete target shell to prevent referencing the dead shell.
|
|
3277
3276
|
"""
|
|
3278
3277
|
def _del():
|
|
3278
|
+
obj = self.target
|
|
3279
3279
|
try:
|
|
3280
|
-
if not
|
|
3281
|
-
del
|
|
3280
|
+
if not obj.shell:
|
|
3281
|
+
del obj.shell # delete the facade <wx.py.shell.ShellFacade>
|
|
3282
3282
|
except AttributeError:
|
|
3283
3283
|
pass
|
|
3284
3284
|
wx.CallAfter(_del)
|
|
@@ -3288,11 +3288,14 @@ class Nautilus(EditorInterface, Shell):
|
|
|
3288
3288
|
Reset localvars assigned for the shell target.
|
|
3289
3289
|
"""
|
|
3290
3290
|
self.trace_position()
|
|
3291
|
-
|
|
3291
|
+
obj = self.target
|
|
3292
3292
|
try:
|
|
3293
|
-
self
|
|
3293
|
+
obj.self = obj
|
|
3294
|
+
obj.this = inspect.getmodule(obj)
|
|
3295
|
+
obj.shell = self # overwrite the facade <wx.py.shell.ShellFacade>
|
|
3294
3296
|
except AttributeError:
|
|
3295
3297
|
pass
|
|
3298
|
+
self.parent.handler('title_window', obj)
|
|
3296
3299
|
|
|
3297
3300
|
def on_inactivated(self, shell):
|
|
3298
3301
|
"""Called when shell:self is inactivated.
|
|
@@ -3328,7 +3331,7 @@ class Nautilus(EditorInterface, Shell):
|
|
|
3328
3331
|
|
|
3329
3332
|
def on_interp_error(self, e):
|
|
3330
3333
|
ln = self.LineFromPosition(self.bolc)
|
|
3331
|
-
self.
|
|
3334
|
+
self.red_pointer = ln + e.lineno - 1
|
|
3332
3335
|
|
|
3333
3336
|
## --------------------------------
|
|
3334
3337
|
## Attributes of the shell
|
|
@@ -3652,11 +3655,11 @@ class Nautilus(EditorInterface, Shell):
|
|
|
3652
3655
|
lines = [int(ln) for fn, ln in err if fn == filename]
|
|
3653
3656
|
if lines:
|
|
3654
3657
|
region = self.get_region(self.cline)
|
|
3655
|
-
|
|
3658
|
+
lx = region[0] + lines[-1] - 1
|
|
3659
|
+
self.red_pointer = lx
|
|
3656
3660
|
self.message(e)
|
|
3657
|
-
## print(msg, file=sys.__stderr__)
|
|
3658
3661
|
else:
|
|
3659
|
-
del self.
|
|
3662
|
+
del self.red_pointer
|
|
3660
3663
|
self.message("Evaluated {!r} successfully.".format(filename))
|
|
3661
3664
|
else:
|
|
3662
3665
|
self.message("No region")
|
mwx/plugins/ffmpeg_view.py
CHANGED
mwx/plugins/fft_view.py
CHANGED
mwx/plugins/frame_listview.py
CHANGED
|
@@ -243,7 +243,7 @@ class CheckList(wx.ListCtrl, ListCtrlAutoWidthMixin, CtrlInterface):
|
|
|
243
243
|
class Plugin(Layer):
|
|
244
244
|
"""Property list of Graph buffers.
|
|
245
245
|
"""
|
|
246
|
-
menukey = "Plugins/Extensions/&Buffer listbox\
|
|
246
|
+
menukey = "Plugins/Extensions/&Buffer listbox\tAlt+b"
|
|
247
247
|
caption = "Property list"
|
|
248
248
|
dockable = False
|
|
249
249
|
|
mwx/plugins/line_profile.py
CHANGED
|
@@ -8,7 +8,7 @@ from mwx.matplot2lg import LineProfile
|
|
|
8
8
|
class Plugin(Layer):
|
|
9
9
|
"""Line profile of the currently selected buffers.
|
|
10
10
|
"""
|
|
11
|
-
menukey = "Plugins/Extensions/&Line profile\
|
|
11
|
+
menukey = "Plugins/Extensions/&Line profile\tAlt+l"
|
|
12
12
|
caption = "Line profile"
|
|
13
13
|
dockable = False
|
|
14
14
|
|
mwx/utilus.py
CHANGED
mwx/wxpdb.py
CHANGED
|
@@ -295,10 +295,6 @@ class Debugger(Pdb):
|
|
|
295
295
|
self.__hookpoint = None
|
|
296
296
|
self.indents = ' ' * 2
|
|
297
297
|
self.stdin.input = '' # clear stdin buffer
|
|
298
|
-
def _continue():
|
|
299
|
-
if wx.IsBusy():
|
|
300
|
-
wx.EndBusyCursor()
|
|
301
|
-
wx.CallAfter(_continue)
|
|
302
298
|
|
|
303
299
|
def on_debug_mark(self, frame):
|
|
304
300
|
"""Called when interaction."""
|
|
@@ -365,11 +361,6 @@ class Debugger(Pdb):
|
|
|
365
361
|
|
|
366
362
|
## Note: Required to terminate the reader of threading pdb.
|
|
367
363
|
self.send_input('\n')
|
|
368
|
-
|
|
369
|
-
def _continue():
|
|
370
|
-
if wx.IsBusy():
|
|
371
|
-
wx.EndBusyCursor()
|
|
372
|
-
wx.CallAfter(_continue)
|
|
373
364
|
|
|
374
365
|
def on_trace_hook(self, frame):
|
|
375
366
|
"""Called when a breakppoint is reached."""
|
mwx/wxwit.py
CHANGED
|
@@ -217,8 +217,6 @@ def dump(widget=None):
|
|
|
217
217
|
def watchit(widget=None, **kwargs):
|
|
218
218
|
"""Wx.py tool for watching widget tree structure and events."""
|
|
219
219
|
from wx.lib.inspection import InspectionTool
|
|
220
|
-
if widget:
|
|
221
|
-
kwargs.update(locals=widget.__dict__)
|
|
222
220
|
it = InspectionTool()
|
|
223
221
|
it.Init(**kwargs)
|
|
224
222
|
it.Show(widget)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: mwxlib
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 1.0.0
|
|
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
|
|
@@ -39,22 +39,17 @@ These instructions will get you a copy of the project up and running on your loc
|
|
|
39
39
|
- ~~Python 2.7~~ (PY2 support has ended since 0.50)
|
|
40
40
|
- ~~Python 3.5~~ (PY35 support has ended since 0.70)
|
|
41
41
|
- ~~Python 3.7~~ (PY37 support has ended since 0.80)
|
|
42
|
-
- Python 3.8 -- 3.9 (
|
|
43
|
-
|
|
42
|
+
- ~~Python 3.8 -- 3.9~~ (Deprecated since 0.90)
|
|
43
|
+
- Python 3.10 -- 3.12
|
|
44
|
+
- wxpython >= 4.2.2 (recommended)
|
|
44
45
|
- numpy
|
|
45
46
|
- pillow
|
|
46
47
|
- matplotlib
|
|
47
48
|
- opencv-python
|
|
48
|
-
- Python 3.
|
|
49
|
-
-
|
|
50
|
-
-
|
|
51
|
-
|
|
52
|
-
- matplotlib
|
|
53
|
-
- opencv-python
|
|
54
|
-
- Python 3.12
|
|
55
|
-
- A version of wxpython for PY312 has not yet released on PyPi.
|
|
56
|
-
* You can download the snapshot from https://wxpython.org/Phoenix/snapshot-builds/,
|
|
57
|
-
* or the latest snapshot from Azure Pipelines https://alldunn.visualstudio.com/wxPython-CI/_build?definitionId=2&_a=summary
|
|
49
|
+
- Python 3.13
|
|
50
|
+
- There are some bugs in mwxlib that remain unfixed.
|
|
51
|
+
- A version of wxpython for PY313 has released on PyPi.
|
|
52
|
+
* You can also download the snapshot from https://wxpython.org/Phoenix/snapshot-builds/,
|
|
58
53
|
|
|
59
54
|
|
|
60
55
|
### Installing
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
mwx/__init__.py,sha256=psabnAMei5VzB2TsB2qBNLrIZMX0LiqjlXCpNGmDejk,668
|
|
2
|
+
mwx/bookshelf.py,sha256=so-xSLq08sMlJBErTxOaDoKUAMa_g1CkIP2pNnff68c,5607
|
|
3
|
+
mwx/controls.py,sha256=LZqee9K8uPxs-Iqcp1zMMNBjFpGPrHbcMaIBuBOL7oo,47647
|
|
4
|
+
mwx/framework.py,sha256=vtufV2jjqdTr2CRhbJYY_NbJMtqft9uKCzZR12dfgk0,75809
|
|
5
|
+
mwx/graphman.py,sha256=1GGBk4kJYRQ7zkvO2rvHxHoINrIfHSB7cabQKWhTyaI,69669
|
|
6
|
+
mwx/images.py,sha256=oxCn0P-emiWujSS2gUgU5TUnr5cPjix2jBcjOBDr24I,48701
|
|
7
|
+
mwx/matplot2.py,sha256=zA56jIdRUdzu-wrmPai1PSOjzqV2Erqw2yFKW-jwdA8,32901
|
|
8
|
+
mwx/matplot2g.py,sha256=xQeHKHAZkLZ2tY-rlTXEIKue1Iw9Vo73l6z_3GSQVCQ,64422
|
|
9
|
+
mwx/matplot2lg.py,sha256=JRWjWnLJUytbSq6wxs4P0gbVUr3xoLSF6Wwqd5V_pJI,27404
|
|
10
|
+
mwx/mgplt.py,sha256=M5rt-H7Uq1OHnlFvMA4a3945UBvppbR9L_mw8NL_YZ0,5602
|
|
11
|
+
mwx/nutshell.py,sha256=pNGLBlVYz6D4LNjosCjXaopcITkQ2-qGVQ6zGmVJJYQ,141850
|
|
12
|
+
mwx/utilus.py,sha256=Yyw8L1f-ikhyd7wtFXYtsOswofWxmB4GAmLOZnhUXeU,37388
|
|
13
|
+
mwx/wxmon.py,sha256=yzWqrbY6LzpfRwQeytYUeqFhFuLVm_XEvrVAL_k0HBQ,12756
|
|
14
|
+
mwx/wxpdb.py,sha256=--TQr-_zs9dWPYV2V4s3Zr4abvN14o5wD8anT9frHUg,18875
|
|
15
|
+
mwx/wxwil.py,sha256=hhyB1lPrF9ixeObxCOKQv0Theu-B-kpJg_yVU3EGSNg,5406
|
|
16
|
+
mwx/wxwit.py,sha256=1hHtMi2YEy2T_LnUpwdmrIdtCuvxMOFyykqnbq6jLP0,7294
|
|
17
|
+
mwx/plugins/__init__.py,sha256=jnJ-Sl9XJ_7BFDslD_r7dsbxsOT57q_IaEriV53XIGY,41
|
|
18
|
+
mwx/plugins/ffmpeg_view.py,sha256=ZKkSLpyuzpVuRbaPib04rChzlwAifNp3pcgxABeqE4k,10693
|
|
19
|
+
mwx/plugins/fft_view.py,sha256=08A_Y73XirV7kXpwf-v0mUA0Hr0MOfdMXv3tvL1hvWA,2789
|
|
20
|
+
mwx/plugins/frame_listview.py,sha256=gowjQ-ARNonMkDSXkQgPKq4U9YBJ-vQ0jK2krBVOdCs,10420
|
|
21
|
+
mwx/plugins/line_profile.py,sha256=zzm6_7lnAnNepLbh07ordp3nRWDFQJtu719ZVjrVf8s,819
|
|
22
|
+
mwx/py/__init__.py,sha256=xykgfOytOwNuvXsfkLoumFZSTN-iBsHOjczYXngjmUE,12
|
|
23
|
+
mwx/py/filling.py,sha256=fumUG1F5M9TL-Dfqni4G85uk7TmvnUunTbdcPDV0vfo,16857
|
|
24
|
+
mwxlib-1.0.0.dist-info/LICENSE,sha256=PGtRKCaTkmUDlBQwpptJAxJtdqxIUtAmdBsaT9nUVkA,1091
|
|
25
|
+
mwxlib-1.0.0.dist-info/METADATA,sha256=IyWzRxDY-vYI_37c6GQ5WgZFAc93d5vfuqaGY8_s3dI,7259
|
|
26
|
+
mwxlib-1.0.0.dist-info/WHEEL,sha256=OVMc5UfuAQiSplgO0_WdW7vXVGAt9Hdd6qtN4HotdyA,91
|
|
27
|
+
mwxlib-1.0.0.dist-info/top_level.txt,sha256=SI1Mh118AstnUFGPNq5aMNKiAnVNmZk1S9Ij-OwAEpY,4
|
|
28
|
+
mwxlib-1.0.0.dist-info/RECORD,,
|
mwxlib-0.99.8.dist-info/RECORD
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
mwx/__init__.py,sha256=U7n9X8JAWdzOavKvVqecHdE4ooiXcCB5DSPCKWxfTnY,653
|
|
2
|
-
mwx/bookshelf.py,sha256=so-xSLq08sMlJBErTxOaDoKUAMa_g1CkIP2pNnff68c,5607
|
|
3
|
-
mwx/controls.py,sha256=5RDA9YgxrxCmjrHOU6XgA_5tcOU1UEwqU4tFEuBNcrk,47648
|
|
4
|
-
mwx/framework.py,sha256=lxqSl_IrGp7ZAUPKJWP5JaUUm3vhaOCjAujFVPocPXg,75501
|
|
5
|
-
mwx/graphman.py,sha256=qX5aHEw4u9iGR8lNpZkXDnGPVMhyAH6NnBapiaUbKZw,70265
|
|
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=M5rt-H7Uq1OHnlFvMA4a3945UBvppbR9L_mw8NL_YZ0,5602
|
|
11
|
-
mwx/nutshell.py,sha256=zJULq1K8WiOBUncMpXE8HbunqUULa9MUt0hBET5jmgs,141810
|
|
12
|
-
mwx/utilus.py,sha256=iizdVrbwL1lX7eTfsMmltFz4IfHqTXVM37wwlPQ3A3Y,37346
|
|
13
|
-
mwx/wxmon.py,sha256=yzWqrbY6LzpfRwQeytYUeqFhFuLVm_XEvrVAL_k0HBQ,12756
|
|
14
|
-
mwx/wxpdb.py,sha256=lLowkkAgMhPFHAfklD7wZHq0qbSMjRxnBFtSajmVgME,19133
|
|
15
|
-
mwx/wxwil.py,sha256=hhyB1lPrF9ixeObxCOKQv0Theu-B-kpJg_yVU3EGSNg,5406
|
|
16
|
-
mwx/wxwit.py,sha256=l7uq6NgGBhay-uAE1pQgWziSAGO9QZPJ4EpEBw1P9xU,7357
|
|
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.8.dist-info/LICENSE,sha256=PGtRKCaTkmUDlBQwpptJAxJtdqxIUtAmdBsaT9nUVkA,1091
|
|
25
|
-
mwxlib-0.99.8.dist-info/METADATA,sha256=C8n66k4LeYcPBb91oVSh7D68pfZI2d1JteEJn3F4UQU,7411
|
|
26
|
-
mwxlib-0.99.8.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
|
|
27
|
-
mwxlib-0.99.8.dist-info/top_level.txt,sha256=SI1Mh118AstnUFGPNq5aMNKiAnVNmZk1S9Ij-OwAEpY,4
|
|
28
|
-
mwxlib-0.99.8.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|