Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
小 白蛋
Intellij Community
Commits
84dc26d1
Commit
84dc26d1
authored
8 years ago
by
Dmitry Trofimov
Browse files
Options
Download
Plain Diff
Merge branch 'pandas-view' of
https://github.com/fitermay/intellij-community
into pandas-view
parents
e5373f61
a506ecbf
Changes
25
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
python/helpers/pydev/_pydev_bundle/pydev_console_utils.py
+1
-12
python/helpers/pydev/_pydev_bundle/pydev_console_utils.py
python/helpers/pydev/_pydevd_bundle/pydevd_comm.py
+1
-11
python/helpers/pydev/_pydevd_bundle/pydevd_comm.py
python/helpers/pydev/_pydevd_bundle/pydevd_vars.py
+144
-37
python/helpers/pydev/_pydevd_bundle/pydevd_vars.py
python/pydevSrc/com/jetbrains/python/debugger/ArrayChunk.java
+55
-1
...on/pydevSrc/com/jetbrains/python/debugger/ArrayChunk.java
python/pydevSrc/com/jetbrains/python/debugger/ArrayChunkBuilder.java
+89
-0
...vSrc/com/jetbrains/python/debugger/ArrayChunkBuilder.java
python/pydevSrc/com/jetbrains/python/debugger/pydev/ProtocolParser.java
+53
-19
...c/com/jetbrains/python/debugger/pydev/ProtocolParser.java
python/src/META-INF/python-core-common.xml
+1
-1
python/src/META-INF/python-core-common.xml
python/src/com/jetbrains/python/debugger/array/ArrayTableCellRenderer.java
+6
-5
...tbrains/python/debugger/array/ArrayTableCellRenderer.java
python/src/com/jetbrains/python/debugger/array/AsyncArrayTableModel.java
+54
-26
...jetbrains/python/debugger/array/AsyncArrayTableModel.java
python/src/com/jetbrains/python/debugger/array/JBTableWithRowHeaders.java
+61
-55
...etbrains/python/debugger/array/JBTableWithRowHeaders.java
python/src/com/jetbrains/python/debugger/array/NumpyArrayTable.java
+25
-314
.../com/jetbrains/python/debugger/array/NumpyArrayTable.java
python/src/com/jetbrains/python/debugger/array/TableChunkDatasource.java
+34
-0
...jetbrains/python/debugger/array/TableChunkDatasource.java
python/src/com/jetbrains/python/debugger/containerview/ColoredCellRenderer.java
+25
-0
...ns/python/debugger/containerview/ColoredCellRenderer.java
python/src/com/jetbrains/python/debugger/containerview/NumericContainerRendererForm.form
+3
-3
.../debugger/containerview/NumericContainerRendererForm.form
python/src/com/jetbrains/python/debugger/containerview/NumericContainerRendererForm.java
+102
-0
.../debugger/containerview/NumericContainerRendererForm.java
python/src/com/jetbrains/python/debugger/containerview/NumericContainerViewTable.java
+283
-0
...hon/debugger/containerview/NumericContainerViewTable.java
python/src/com/jetbrains/python/debugger/containerview/PyNumericViewUtil.java
+87
-0
...ains/python/debugger/containerview/PyNumericViewUtil.java
python/src/com/jetbrains/python/debugger/containerview/PyViewNumericContainerAction.java
+38
-51
.../debugger/containerview/PyViewNumericContainerAction.java
python/src/com/jetbrains/python/debugger/containerview/ViewNumericContainerDialog.java
+60
-0
...on/debugger/containerview/ViewNumericContainerDialog.java
python/src/com/jetbrains/python/debugger/dataframe/DataFrameTable.java
+64
-0
...m/jetbrains/python/debugger/dataframe/DataFrameTable.java
with
1186 additions
and
535 deletions
+1186
-535
python/helpers/pydev/_pydev_bundle/pydev_console_utils.py
+
1
-
12
View file @
84dc26d1
...
...
@@ -434,20 +434,9 @@ class BaseInterpreterInterface:
return
xml
def
getArray
(
self
,
attr
,
roffset
,
coffset
,
rows
,
cols
,
format
):
xml
=
"<xml>"
name
=
attr
.
split
(
"
\t
"
)[
-
1
]
array
=
pydevd_vars
.
eval_in_context
(
name
,
self
.
get_namespace
(),
self
.
get_namespace
())
array
,
metaxml
,
r
,
c
,
f
=
pydevd_vars
.
array_to_meta_xml
(
array
,
name
,
format
)
xml
+=
metaxml
format
=
'%'
+
f
if
rows
==
-
1
and
cols
==
-
1
:
rows
=
r
cols
=
c
xml
+=
pydevd_vars
.
array_to_xml
(
array
,
roffset
,
coffset
,
rows
,
cols
,
format
)
xml
+=
"</xml>"
return
xml
return
pydevd_vars
.
table_like_struct_to_xml
(
array
,
name
,
roffset
,
coffset
,
rows
,
cols
,
format
)
def
evaluate
(
self
,
expression
):
xml
=
"<xml>"
...
...
This diff is collapsed.
Click to expand it.
python/helpers/pydev/_pydevd_bundle/pydevd_comm.py
+
1
-
11
View file @
84dc26d1
...
...
@@ -988,17 +988,7 @@ class InternalGetArray(InternalThreadCommand):
try
:
frame
=
pydevd_vars
.
find_frame
(
self
.
thread_id
,
self
.
frame_id
)
var
=
pydevd_vars
.
eval_in_context
(
self
.
name
,
frame
.
f_globals
,
frame
.
f_locals
)
xml
=
"<xml>"
var
,
metaxml
,
rows
,
cols
,
format
=
pydevd_vars
.
array_to_meta_xml
(
var
,
self
.
name
,
self
.
format
)
xml
+=
metaxml
self
.
format
=
'%'
+
format
if
self
.
rows
==
-
1
and
self
.
cols
==
-
1
:
self
.
rows
=
rows
self
.
cols
=
cols
xml
+=
pydevd_vars
.
array_to_xml
(
var
,
self
.
roffset
,
self
.
coffset
,
self
.
rows
,
self
.
cols
,
self
.
format
)
xml
+=
"</xml>"
xml
=
pydevd_vars
.
table_like_struct_to_xml
(
var
,
self
.
name
,
self
.
roffset
,
self
.
coffset
,
self
.
rows
,
self
.
cols
,
self
.
format
)
cmd
=
dbg
.
cmd_factory
.
make_get_array_message
(
self
.
sequence
,
xml
)
dbg
.
writer
.
add_command
(
cmd
)
except
:
...
...
This diff is collapsed.
Click to expand it.
python/helpers/pydev/_pydevd_bundle/pydevd_vars.py
+
144
-
37
View file @
84dc26d1
...
...
@@ -2,8 +2,8 @@
resolution/conversion to XML.
"""
import
pickle
from
_pydevd_bundle.pydevd_constants
import
*
#
@UnusedWildImport
from
types
import
*
#
@UnusedWildImport
from
_pydevd_bundle.pydevd_constants
import
*
#
@UnusedWildImport
from
types
import
*
#
@UnusedWildImport
from
_pydevd_bundle.pydevd_custom_frames
import
get_custom_frame
from
_pydevd_bundle.pydevd_xml
import
*
...
...
@@ -13,7 +13,7 @@ try:
from
StringIO
import
StringIO
except
ImportError
:
from
io
import
StringIO
import
sys
#
@Reimport
import
sys
#
@Reimport
from
_pydev_imps._pydev_saved_modules
import
threading
import
traceback
...
...
@@ -22,25 +22,28 @@ from _pydev_bundle.pydev_imports import Exec, quote, execfile
from
_pydevd_bundle.pydevd_utils
import
to_string
#-------------------------------------------------------------------------- defining true and false for earlier versions
# -------------------------------------------------------------------------- defining true and false for earlier versions
try
:
__setFalse
=
False
except
:
import
__builtin__
setattr
(
__builtin__
,
'True'
,
1
)
setattr
(
__builtin__
,
'False'
,
0
)
#------------------------------------------------------------------------------------------------------ class for errors
class
VariableError
(
RuntimeError
):
pass
# ------------------------------------------------------------------------------------------------------ class for errors
class
VariableError
(
RuntimeError
):
pass
class
FrameNotFoundError
(
RuntimeError
):
pass
class
FrameNotFoundError
(
RuntimeError
):
pass
def
_iter_frames
(
initialFrame
):
'''NO-YIELD VERSION: Iterates through all the frames starting at the specified frame (which will be the first returned item)'''
#cannot use yield
#
cannot use yield
frames
=
[]
while
initialFrame
is
not
None
:
...
...
@@ -49,6 +52,7 @@ def _iter_frames(initialFrame):
return
frames
def
dump_frames
(
thread_id
):
sys
.
stdout
.
write
(
'dumping frames
\n
'
)
if
thread_id
!=
get_thread_id
(
threading
.
currentThread
()):
...
...
@@ -59,21 +63,25 @@ def dump_frames(thread_id):
sys
.
stdout
.
write
(
'%s
\n
'
%
pickle
.
dumps
(
frame
))
#===============================================================================
#
===============================================================================
# AdditionalFramesContainer
#===============================================================================
#
===============================================================================
class
AdditionalFramesContainer
:
lock
=
thread
.
allocate_lock
()
additional_frames
=
{}
#
dict of dicts
additional_frames
=
{}
#
dict of dicts
def
add_additional_frame_by_id
(
thread_id
,
frames_by_id
):
AdditionalFramesContainer
.
additional_frames
[
thread_id
]
=
frames_by_id
addAdditionalFrameById
=
add_additional_frame_by_id
# Backward compatibility
addAdditionalFrameById
=
add_additional_frame_by_id
# Backward compatibility
def
remove_additional_frame_by_id
(
thread_id
):
del
AdditionalFramesContainer
.
additional_frames
[
thread_id
]
removeAdditionalFrameById
=
remove_additional_frame_by_id
# Backward compatibility
...
...
@@ -89,9 +97,9 @@ def find_frame(thread_id, frame_id):
""" returns a frame on the thread that has a given frame_id """
try
:
curr_thread_id
=
get_thread_id
(
threading
.
currentThread
())
if
thread_id
!=
curr_thread_id
:
if
thread_id
!=
curr_thread_id
:
try
:
return
get_custom_frame
(
thread_id
,
frame_id
)
#I.e.: thread_id could be a stackless frame id + thread_id.
return
get_custom_frame
(
thread_id
,
frame_id
)
#
I.e.: thread_id could be a stackless frame id + thread_id.
except
:
pass
...
...
@@ -120,12 +128,12 @@ def find_frame(thread_id, frame_id):
del
frame
#Important: python can hold a reference to the frame from the current context
#if an exception is raised, so, if we don't explicitly add those deletes
#we might have those variables living much more than we'd want to.
#
Important: python can hold a reference to the frame from the current context
#
if an exception is raised, so, if we don't explicitly add those deletes
#
we might have those variables living much more than we'd want to.
#I.e.: sys.exc_info holding reference to frame that raises exception (so, other places
#need to call sys.exc_clear())
#
I.e.: sys.exc_info holding reference to frame that raises exception (so, other places
#
need to call sys.exc_clear())
del
curFrame
if
frameFound
is
None
:
...
...
@@ -155,6 +163,7 @@ def find_frame(thread_id, frame_id):
traceback
.
print_exc
()
return
None
def
getVariable
(
thread_id
,
frame_id
,
scope
,
attrs
):
"""
returns the value of a variable
...
...
@@ -170,14 +179,14 @@ def getVariable(thread_id, frame_id, scope, attrs):
not the frame (as we don't care about the frame in this case).
"""
if
scope
==
'BY_ID'
:
if
thread_id
!=
get_thread_id
(
threading
.
currentThread
())
:
if
thread_id
!=
get_thread_id
(
threading
.
currentThread
()):
raise
VariableError
(
"getVariable: must execute on same thread"
)
try
:
import
gc
objects
=
gc
.
get_objects
()
except
:
pass
#Not all python variants have it.
pass
#
Not all python variants have it.
else
:
frame_id
=
int
(
frame_id
)
for
var
in
objects
:
...
...
@@ -190,7 +199,7 @@ def getVariable(thread_id, frame_id, scope, attrs):
return
var
#If it didn't return previously, we coudn't find it by id (i.e.: alrceady garbage collected).
#
If it didn't return previously, we coudn't find it by id (i.e.: alrceady garbage collected).
sys
.
stderr
.
write
(
'Unable to find object with id: %s
\n
'
%
(
frame_id
,))
return
None
...
...
@@ -328,37 +337,38 @@ def evaluate_expression(thread_id, frame_id, expression, doExec):
if
frame
is
None
:
return
#Not using frame.f_globals because of https://sourceforge.net/tracker2/?func=detail&aid=2541355&group_id=85796&atid=577329
#(Names not resolved in generator expression in method)
#See message: http://mail.python.org/pipermail/python-list/2009-January/526522.html
#
Not using frame.f_globals because of https://sourceforge.net/tracker2/?func=detail&aid=2541355&group_id=85796&atid=577329
#
(Names not resolved in generator expression in method)
#
See message: http://mail.python.org/pipermail/python-list/2009-January/526522.html
updated_globals
=
{}
updated_globals
.
update
(
frame
.
f_globals
)
updated_globals
.
update
(
frame
.
f_locals
)
#locals later because it has precedence over the actual globals
updated_globals
.
update
(
frame
.
f_locals
)
#
locals later because it has precedence over the actual globals
try
:
expression
=
str
(
expression
.
replace
(
'@LINE@'
,
'
\n
'
))
if
doExec
:
try
:
#try to make it an eval (if it is an eval we can print it, otherwise we'll exec it and
#it will have whatever the user actually did)
#
try to make it an eval (if it is an eval we can print it, otherwise we'll exec it and
#
it will have whatever the user actually did)
compiled
=
compile
(
expression
,
'<string>'
,
'eval'
)
except
:
Exec
(
expression
,
updated_globals
,
frame
.
f_locals
)
pydevd_save_locals
.
save_locals
(
frame
)
else
:
result
=
eval
(
compiled
,
updated_globals
,
frame
.
f_locals
)
if
result
is
not
None
:
#Only print if it's not None (as python does)
if
result
is
not
None
:
#
Only print if it's not None (as python does)
sys
.
stdout
.
write
(
'%s
\n
'
%
(
result
,))
return
else
:
return
eval_in_context
(
expression
,
updated_globals
,
frame
.
f_locals
)
finally
:
#Should not be kept alive if an exception happens and this frame is kept in the stack.
#
Should not be kept alive if an exception happens and this frame is kept in the stack.
del
updated_globals
del
frame
def
change_attr_expression
(
thread_id
,
frame_id
,
attr
,
expression
,
dbg
):
'''Changes some attribute in a given frame.
'''
...
...
@@ -385,7 +395,7 @@ def change_attr_expression(thread_id, frame_id, attr, expression, dbg):
pydevd_save_locals
.
save_locals
(
frame
)
return
frame
.
f_locals
[
attr
]
#default way (only works for changing it in the topmost frame)
#
default way (only works for changing it in the topmost frame)
result
=
eval
(
expression
,
frame
.
f_globals
,
frame
.
f_locals
)
Exec
(
'%s=%s'
%
(
attr
,
expression
),
frame
.
f_globals
,
frame
.
f_locals
)
return
result
...
...
@@ -394,16 +404,35 @@ def change_attr_expression(thread_id, frame_id, attr, expression, dbg):
except
Exception
:
traceback
.
print_exc
()
MAXIMUM_ARRAY_SIZE
=
100
MAX_SLICE_SIZE
=
1000
def
table_like_struct_to_xml
(
array
,
name
,
roffset
,
coffset
,
rows
,
cols
,
format
):
_
,
type_name
,
_
=
get_type
(
array
)
if
type_name
==
'ndarray'
:
array
,
metaxml
,
r
,
c
,
f
=
array_to_meta_xml
(
array
,
name
,
format
)
xml
=
metaxml
format
=
'%'
+
f
if
rows
==
-
1
and
cols
==
-
1
:
rows
=
r
cols
=
c
xml
+=
array_to_xml
(
array
,
roffset
,
coffset
,
rows
,
cols
,
format
)
elif
type_name
==
'DataFrame'
:
xml
=
dataframe_to_xml
(
array
,
name
,
roffset
,
coffset
,
rows
,
cols
,
format
)
else
:
raise
VariableError
(
"Do not know how to convert type %s to table"
%
(
type_name
))
return
"<xml>%s</xml>"
%
xml
def
array_to_xml
(
array
,
roffset
,
coffset
,
rows
,
cols
,
format
):
xml
=
""
rows
=
min
(
rows
,
MAXIMUM_ARRAY_SIZE
)
cols
=
min
(
cols
,
MAXIMUM_ARRAY_SIZE
)
#there is no obvious rule for slicing (at least 5 choices)
# there is no obvious rule for slicing (at least 5 choices)
if
len
(
array
)
==
1
and
(
rows
>
1
or
cols
>
1
):
array
=
array
[
0
]
if
array
.
size
>
len
(
array
):
...
...
@@ -489,11 +518,11 @@ def array_to_meta_xml(array, name, format):
elif
l
==
2
:
rows
=
min
(
array
.
shape
[
-
2
],
MAX_SLICE_SIZE
)
cols
=
min
(
array
.
shape
[
-
1
],
MAX_SLICE_SIZE
)
if
cols
<
array
.
shape
[
-
1
]
or
rows
<
array
.
shape
[
-
2
]:
if
cols
<
array
.
shape
[
-
1
]
or
rows
<
array
.
shape
[
-
2
]:
reslice
=
'[0:%s, 0:%s]'
%
(
rows
,
cols
)
array
=
array
[
0
:
rows
,
0
:
cols
]
#avoid slice duplication
#
avoid slice duplication
if
not
slice
.
endswith
(
reslice
):
slice
+=
reslice
...
...
@@ -501,8 +530,86 @@ def array_to_meta_xml(array, name, format):
if
type
in
"biufc"
:
bounds
=
(
array
.
min
(),
array
.
max
())
xml
=
'<array slice=
\"
%s
\"
rows=
\"
%s
\"
cols=
\"
%s
\"
format=
\"
%s
\"
type=
\"
%s
\"
max=
\"
%s
\"
min=
\"
%s
\"
/>'
%
\
(
slice
,
rows
,
cols
,
format
,
type
,
bounds
[
1
],
bounds
[
0
])
(
slice
,
rows
,
cols
,
format
,
type
,
bounds
[
1
],
bounds
[
0
])
return
array
,
xml
,
rows
,
cols
,
format
def
dataframe_to_xml
(
df
,
name
,
roffset
,
coffset
,
rows
,
cols
,
format
):
"""
:type df: pandas.core.frame.DataFrame
:type name: str
:type coffset: int
:type roffset: int
:type rows: int
:type cols: int
:type format: str
"""
num_rows
=
min
(
df
.
shape
[
0
],
MAX_SLICE_SIZE
)
num_cols
=
min
(
df
.
shape
[
1
],
MAX_SLICE_SIZE
)
if
(
num_rows
,
num_cols
)
!=
df
.
shape
:
df
=
df
.
iloc
[
0
:
num_rows
,
0
:
num_cols
]
slice
=
'.iloc[0:%s, 0:%s]'
%
(
num_rows
,
num_cols
)
else
:
slice
=
''
slice
=
name
+
slice
xml
=
'<array slice=
\"
%s
\"
rows=
\"
%s
\"
cols=
\"
%s
\"
format=
\"\"
type=
\"\"
max=
\"
0
\"
min=
\"
0
\"
/>
\n
'
%
\
(
slice
,
num_rows
,
num_cols
)
if
(
rows
,
cols
)
==
(
-
1
,
-
1
):
rows
,
cols
=
num_rows
,
num_cols
rows
=
min
(
rows
,
MAXIMUM_ARRAY_SIZE
)
cols
=
min
(
min
(
cols
,
MAXIMUM_ARRAY_SIZE
),
num_cols
)
# need to precompute column bounds here before slicing!
col_bounds
=
[
None
]
*
cols
for
col
in
range
(
cols
):
dtype
=
df
.
dtypes
.
iloc
[
col
].
kind
if
dtype
in
"biufc"
:
cvalues
=
df
.
iloc
[:,
col
]
bounds
=
(
cvalues
.
min
(),
cvalues
.
max
())
else
:
bounds
=
(
0
,
0
)
col_bounds
[
col
]
=
bounds
df
=
df
.
iloc
[
roffset
:
roffset
+
rows
,
coffset
:
coffset
+
cols
]
rows
,
cols
=
df
.
shape
def
default_format
(
type
):
if
type
==
'f'
:
return
'.5f'
elif
type
==
'i'
or
type
==
'u'
:
return
'd'
else
:
return
's'
xml
+=
"<headerdata rows=
\"
%s
\"
cols=
\"
%s
\"
>
\n
"
%
(
rows
,
cols
)
format
=
format
.
replace
(
'%'
,
''
)
col_formats
=
[]
for
col
in
range
(
cols
):
label
=
df
.
axes
[
1
].
values
[
col
]
if
isinstance
(
label
,
tuple
):
label
=
'/'
.
join
(
label
)
label
=
str
(
label
)
dtype
=
df
.
dtypes
.
iloc
[
col
].
kind
fmt
=
format
if
(
dtype
==
'f'
and
format
)
else
default_format
(
dtype
)
col_formats
.
append
(
'%'
+
fmt
)
bounds
=
col_bounds
[
col
]
xml
+=
'<colheader index=
\"
%s
\"
label=
\"
%s
\"
type=
\"
%s
\"
format=
\"
%s
\"
max=
\"
%s
\"
min=
\"
%s
\"
/>
\n
'
%
\
(
str
(
col
),
label
,
dtype
,
fmt
,
bounds
[
1
],
bounds
[
0
])
for
row
,
label
in
enumerate
(
iter
(
df
.
axes
[
0
])):
if
isinstance
(
label
,
tuple
):
label
=
'/'
.
join
(
label
)
xml
+=
"<rowheader index=
\"
%s
\"
label =
\"
%s
\"
/>
\n
"
%
\
(
str
(
row
),
label
)
xml
+=
"</headerdata>
\n
"
xml
+=
"<arraydata rows=
\"
%s
\"
cols=
\"
%s
\"
/>
\n
"
%
(
rows
,
cols
)
for
row
in
range
(
rows
):
xml
+=
"<row index=
\"
%s
\"
/>
\n
"
%
str
(
row
)
for
col
in
range
(
cols
):
value
=
df
.
iat
[
row
,
col
]
value
=
col_formats
[
col
]
%
value
xml
+=
var_to_xml
(
value
,
''
)
return
xml
This diff is collapsed.
Click to expand it.
python/pydevSrc/com/jetbrains/python/debugger/ArrayChunk.java
+
55
-
1
View file @
84dc26d1
...
...
@@ -18,6 +18,8 @@ package com.jetbrains.python.debugger;
import
org.jetbrains.annotations.NotNull
;
import
org.jetbrains.annotations.Nullable
;
import
java.util.List
;
/**
* @author amarch
*/
...
...
@@ -31,6 +33,10 @@ public class ArrayChunk {
private
final
String
myFormat
;
private
final
String
myType
;
private
final
Object
[][]
myData
;
private
final
List
<
String
>
myRowLabels
;
private
final
List
<
ColHeader
>
myColHeaders
;
public
ArrayChunk
(
@NotNull
PyDebugValue
value
,
String
slicePresentation
,
...
...
@@ -40,7 +46,7 @@ public class ArrayChunk {
String
min
,
String
format
,
String
type
,
@Nullable
Object
[][]
data
)
{
@Nullable
Object
[][]
data
,
List
<
String
>
labels
,
List
<
ColHeader
>
headers
)
{
myValue
=
value
;
mySlicePresentation
=
slicePresentation
;
myRows
=
rows
;
...
...
@@ -50,6 +56,8 @@ public class ArrayChunk {
myFormat
=
format
;
myType
=
type
;
myData
=
data
;
myRowLabels
=
labels
;
myColHeaders
=
headers
;
}
public
PyDebugValue
getValue
()
{
...
...
@@ -87,4 +95,50 @@ public class ArrayChunk {
public
Object
[][]
getData
()
{
return
myData
;
}
public
List
<
String
>
getRowLabels
()
{
return
myRowLabels
;
}
public
List
<
ColHeader
>
getColHeaders
()
{
return
myColHeaders
;
}
public
static
class
ColHeader
{
private
final
String
myLabel
;
private
final
String
myType
;
private
final
String
myFormat
;
private
final
String
myMax
;
private
final
String
myMin
;
public
ColHeader
(
String
label
,
String
type
,
String
format
,
String
max
,
String
min
)
{
myLabel
=
label
;
myType
=
type
;
myFormat
=
format
;
myMax
=
max
;
myMin
=
min
;
}
public
String
getLabel
()
{
return
myLabel
;
}
public
String
getType
()
{
return
myType
;
}
public
String
getFormat
()
{
return
myFormat
;
}
public
String
getMax
()
{
return
myMax
;
}
public
String
getMin
()
{
return
myMin
;
}
}
}
This diff is collapsed.
Click to expand it.
python/pydevSrc/com/jetbrains/python/debugger/ArrayChunkBuilder.java
0 → 100644
+
89
-
0
View file @
84dc26d1
/*
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
com.jetbrains.python.debugger
;
import
java.util.List
;
public
class
ArrayChunkBuilder
{
private
PyDebugValue
myValue
;
private
String
myPresentation
;
private
int
myRows
;
private
int
myColumns
;
private
String
myMax
;
private
String
myMin
;
private
String
myFormat
;
private
String
myType
;
private
Object
[][]
myData
=
null
;
private
List
<
String
>
myRowLabels
=
null
;
private
List
<
ArrayChunk
.
ColHeader
>
myColHeaders
=
null
;
public
ArrayChunkBuilder
setValue
(
PyDebugValue
value
)
{
myValue
=
value
;
return
this
;
}
public
ArrayChunkBuilder
setSlicePresentation
(
String
presentation
)
{
myPresentation
=
presentation
;
return
this
;
}
public
ArrayChunkBuilder
setRows
(
int
rows
)
{
myRows
=
rows
;
return
this
;
}
public
ArrayChunkBuilder
setColumns
(
int
columns
)
{
myColumns
=
columns
;
return
this
;
}
public
ArrayChunkBuilder
setMax
(
String
max
)
{
myMax
=
max
;
return
this
;
}
public
ArrayChunkBuilder
setMin
(
String
min
)
{
myMin
=
min
;
return
this
;
}
public
ArrayChunkBuilder
setFormat
(
String
format
)
{
myFormat
=
format
;
return
this
;
}
public
ArrayChunkBuilder
setType
(
String
type
)
{
myType
=
type
;
return
this
;
}
public
ArrayChunkBuilder
setData
(
Object
[][]
data
)
{
myData
=
data
;
return
this
;
}
public
void
setRowLabels
(
List
<
String
>
rowLabels
)
{
myRowLabels
=
rowLabels
;
}
public
void
setColHeaders
(
List
<
ArrayChunk
.
ColHeader
>
colHeaders
)
{
myColHeaders
=
colHeaders
;
}
public
ArrayChunk
createArrayChunk
()
{
return
new
ArrayChunk
(
myValue
,
myPresentation
,
myRows
,
myColumns
,
myMax
,
myMin
,
myFormat
,
myType
,
myData
,
myRowLabels
,
myColHeaders
);
}
}
\ No newline at end of file
This diff is collapsed.
Click to expand it.
python/pydevSrc/com/jetbrains/python/debugger/pydev/ProtocolParser.java
+
53
-
19
View file @
84dc26d1
package
com.jetbrains.python.debugger.pydev
;
import
com.google.common.collect.Lists
;
import
com.intellij.openapi.util.text.StringUtil
;
import
com.jetbrains.python.debugger.*
;
import
com.thoughtworks.xstream.io.naming.NoNameCoder
;
...
...
@@ -33,13 +34,14 @@ public class ProtocolParser {
reader
.
moveDown
();
if
(
"arg"
.
equals
(
reader
.
getNodeName
()))
{
signature
.
addArgument
(
readString
(
reader
,
"name"
,
""
),
readString
(
reader
,
"type"
,
""
));
}
else
if
(
"return"
.
equals
(
reader
.
getNodeName
()))
{
}
else
if
(
"return"
.
equals
(
reader
.
getNodeName
()))
{
signature
.
addReturnType
(
readString
(
reader
,
"type"
,
""
));
}
else
{
}
else
{
throw
new
PyDebuggerException
(
"Expected <arg> or <return>, found "
+
reader
.
getNodeName
());
}
reader
.
moveUp
();
}
...
...
@@ -54,9 +56,11 @@ public class ProtocolParser {
boolean
isAsyncio
;
if
(
eventName
.
equals
(
"threading_event"
))
{
isAsyncio
=
false
;
}
else
if
(
eventName
.
equals
(
"asyncio_event"
))
{
}
else
if
(
eventName
.
equals
(
"asyncio_event"
))
{
isAsyncio
=
true
;
}
else
{
}
else
{
throw
new
PyDebuggerException
(
"Expected <threading_event> or <asyncio_event>, found "
+
reader
.
getNodeName
());
}
...
...
@@ -73,7 +77,8 @@ public class ProtocolParser {
String
parentThread
=
readString
(
reader
,
"parent"
,
""
);
if
(!
parentThread
.
isEmpty
())
{
threadingEvent
=
new
PyThreadEvent
(
time
,
thread_id
,
name
,
parentThread
,
isAsyncio
);
}
else
{
}
else
{
threadingEvent
=
new
PyThreadEvent
(
time
,
thread_id
,
name
,
isAsyncio
);
}
}
...
...
@@ -269,28 +274,57 @@ public class ProtocolParser {
public
static
ArrayChunk
parseArrayValues
(
final
String
text
,
final
PyFrameAccessor
frameAccessor
)
throws
PyDebuggerException
{
final
XppReader
reader
=
openReader
(
text
,
false
);
ArrayChunk
result
=
n
ull
;
ArrayChunk
Builder
result
=
n
ew
ArrayChunkBuilder
()
;
if
(
reader
.
hasMoreChildren
())
{
reader
.
moveDown
();
if
(!
"array"
.
equals
(
reader
.
getNodeName
()))
{
throw
new
PyDebuggerException
(
"Expected <array> at first node, found "
+
reader
.
getNodeName
());
}
String
slice
=
readString
(
reader
,
"slice"
,
null
);
int
rows
=
readInt
(
reader
,
"rows"
,
null
);
int
cols
=
readInt
(
reader
,
"cols"
,
null
);
String
format
=
"%"
+
readString
(
reader
,
"format"
,
null
);
String
type
=
readString
(
reader
,
"type"
,
null
);
String
max
=
readString
(
reader
,
"max"
,
null
);
String
min
=
readString
(
reader
,
"min"
,
null
);
result
=
new
ArrayChunk
(
new
PyDebugValue
(
slice
,
null
,
null
,
null
,
false
,
false
,
false
,
frameAccessor
),
slice
,
rows
,
cols
,
max
,
min
,
format
,
type
,
null
);
result
.
setSlicePresentation
(
slice
);
result
.
setRows
(
readInt
(
reader
,
"rows"
,
null
));
result
.
setColumns
(
readInt
(
reader
,
"cols"
,
null
));
result
.
setFormat
(
"%"
+
readString
(
reader
,
"format"
,
null
));
result
.
setType
(
readString
(
reader
,
"type"
,
null
));
result
.
setMax
(
readString
(
reader
,
"max"
,
null
));
result
.
setMin
(
readString
(
reader
,
"min"
,
null
));
result
.
setValue
(
new
PyDebugValue
(
slice
,
null
,
null
,
null
,
false
,
false
,
false
,
frameAccessor
));
reader
.
moveUp
();
}
if
(
"headerdata"
.
equals
(
reader
.
peekNextChild
()))
{
parseArrayHeaderData
(
reader
,
result
);
}
Object
[][]
data
=
parseArrayValues
(
reader
,
frameAccessor
);
return
new
ArrayChunk
(
result
.
getValue
(),
result
.
getSlicePresentation
(),
result
.
getRows
(),
result
.
getColumns
(),
result
.
getMax
(),
result
.
getMin
(),
result
.
getFormat
(),
result
.
getType
(),
data
);
result
.
setData
(
data
);
return
result
.
createArrayChunk
();
}
private
static
void
parseArrayHeaderData
(
XppReader
reader
,
ArrayChunkBuilder
result
)
throws
PyDebuggerException
{
List
<
String
>
rowHeaders
=
Lists
.
newArrayList
();
List
<
ArrayChunk
.
ColHeader
>
colHeaders
=
Lists
.
newArrayList
();
reader
.
moveDown
();
while
(
reader
.
hasMoreChildren
())
{
reader
.
moveDown
();
if
(
"colheader"
.
equals
(
reader
.
getNodeName
()))
{
colHeaders
.
add
(
new
ArrayChunk
.
ColHeader
(
readString
(
reader
,
"label"
,
null
),
readString
(
reader
,
"type"
,
null
),
readString
(
reader
,
"format"
,
null
),
readString
(
reader
,
"max"
,
null
),
readString
(
reader
,
"min"
,
null
)));
}
else
if
(
"rowheader"
.
equals
(
reader
.
getNodeName
()))
{
rowHeaders
.
add
(
readString
(
reader
,
"label"
,
null
));
}
else
{
throw
new
PyDebuggerException
(
"Invalid node name"
+
reader
.
getNodeName
());
}
reader
.
moveUp
();
}
result
.
setColHeaders
(
colHeaders
);
result
.
setRowLabels
(
rowHeaders
);
reader
.
moveUp
();
}
public
static
Object
[][]
parseArrayValues
(
final
XppReader
reader
,
final
PyFrameAccessor
frameAccessor
)
throws
PyDebuggerException
{
...
...
This diff is collapsed.
Click to expand it.
python/src/META-INF/python-core-common.xml
+
1
-
1
View file @
84dc26d1
...
...
@@ -799,7 +799,7 @@
<add-to-group
group-id=
"Internal"
/>
</action>
<action
id=
"PyDebugger.ViewArray"
class=
"com.jetbrains.python.debugger.
array.PyViewArray
Action"
text=
"View as Array"
>
<action
id=
"PyDebugger.ViewArray"
class=
"com.jetbrains.python.debugger.
containerview.PyViewNumericContainer
Action"
text=
"View as Array"
>
<add-to-group
group-id=
"XDebugger.ValueGroup"
anchor=
"after"
relative-to-action=
"Debugger.Tree.AddToWatches"
/>
</action>
...
...
This diff is collapsed.
Click to expand it.
python/src/com/jetbrains/python/debugger/array/ArrayTableCellRenderer.java
+
6
-
5
View file @
84dc26d1
...
...
@@ -17,6 +17,8 @@ package com.jetbrains.python.debugger.array;
import
com.intellij.ui.JBColor
;
import
com.intellij.util.ui.UIUtil
;
import
com.jetbrains.python.debugger.containerview.ColoredCellRenderer
;
import
com.jetbrains.python.debugger.containerview.PyNumericViewUtil
;
import
javax.swing.*
;
import
javax.swing.border.LineBorder
;
...
...
@@ -26,14 +28,14 @@ import java.awt.*;
/**
* @author amarch
*/
class
ArrayTableCellRenderer
extends
DefaultTableCellRenderer
{
class
ArrayTableCellRenderer
extends
DefaultTableCellRenderer
implements
ColoredCellRenderer
{
private
double
myMin
=
Double
.
MIN_VALUE
;
private
double
myMax
=
Double
.
MIN_VALUE
;
private
String
myComplexMin
;
private
String
myComplexMax
;
private
boolean
myColored
=
true
;
private
String
myType
;
private
final
String
myType
;
public
ArrayTableCellRenderer
(
double
min
,
double
max
,
String
type
)
{
setHorizontalAlignment
(
CENTER
);
...
...
@@ -62,9 +64,8 @@ class ArrayTableCellRenderer extends DefaultTableCellRenderer {
if
(
myMax
!=
myMin
)
{
if
(
myColored
&&
value
!=
null
)
{
try
{
double
rangedValue
=
NumpyArrayTable
.
getRangedValue
(
value
.
toString
(),
myType
,
myMin
,
myMax
,
myComplexMax
,
myComplexMin
);
//noinspection UseJBColor
this
.
setBackground
(
new
Color
((
int
)
Math
.
round
(
255
*
rangedValue
),
0
,
(
int
)
Math
.
round
(
255
*
(
1
-
rangedValue
)),
130
));
double
rangedValue
=
PyNumericViewUtil
.
getRangedValue
(
value
.
toString
(),
myType
,
myMin
,
myMax
,
myComplexMax
,
myComplexMin
);
this
.
setBackground
(
PyNumericViewUtil
.
rangedValueToColor
(
rangedValue
));
}
catch
(
NumberFormatException
ignored
)
{
}
...
...
This diff is collapsed.
Click to expand it.
python/src/com/jetbrains/python/debugger/array/AsyncArrayTableModel.java
+
54
-
26
View file @
84dc26d1
...
...
@@ -24,9 +24,11 @@ import com.intellij.openapi.util.Pair;
import
com.intellij.util.ConcurrencyUtil
;
import
com.intellij.util.ui.UIUtil
;
import
com.jetbrains.python.debugger.ArrayChunk
;
import
com.jetbrains.python.debugger.PyDebugValue
;
import
com.jetbrains.python.debugger.ArrayChunkBuilder
;
import
org.jetbrains.annotations.NotNull
;
import
javax.swing.table.AbstractTableModel
;
import
javax.swing.table.TableModel
;
import
java.util.concurrent.*
;
/**
...
...
@@ -39,7 +41,7 @@ public class AsyncArrayTableModel extends AbstractTableModel {
private
int
myRows
;
private
int
myColumns
;
private
final
NumpyArrayTabl
e
myProvider
;
private
final
TableChunkDatasourc
e
myProvider
;
private
final
ExecutorService
myExecutorService
=
ConcurrencyUtil
.
newSingleThreadExecutor
(
"Python async table"
);
...
...
@@ -48,16 +50,14 @@ public class AsyncArrayTableModel extends AbstractTableModel {
private
LoadingCache
<
Pair
<
Integer
,
Integer
>,
ListenableFuture
<
ArrayChunk
>>
myChunkCache
=
CacheBuilder
.
newBuilder
().
build
(
new
CacheLoader
<
Pair
<
Integer
,
Integer
>,
ListenableFuture
<
ArrayChunk
>>()
{
@Override
public
ListenableFuture
<
ArrayChunk
>
load
(
final
Pair
<
Integer
,
Integer
>
key
)
throws
Exception
{
final
PyDebugValue
value
=
myProvider
.
getDebugValue
();
final
PyDebugValue
slicedValue
=
new
PyDebugValue
(
myProvider
.
getSliceText
(),
value
.
getType
(),
value
.
getTypeQualifier
(),
value
.
getValue
(),
value
.
isContainer
(),
value
.
isReturnedVal
(),
value
.
isErrorOnEval
(),
value
.
getParent
(),
value
.
getFrameAccessor
());
public
ListenableFuture
<
ArrayChunk
>
load
(
@NotNull
final
Pair
<
Integer
,
Integer
>
key
)
throws
Exception
{
ListenableFutureTask
<
ArrayChunk
>
task
=
ListenableFutureTask
.
create
(()
->
value
.
getFrameAccessor
()
.
getArrayItems
(
slicedValue
,
key
.
first
,
key
.
second
,
Math
.
min
(
CHUNK_ROW_SIZE
,
getRowCount
()
-
key
.
first
),
Math
.
min
(
CHUNK_COL_SIZE
,
getColumnCount
()
-
key
.
second
),
myProvider
.
getFormat
()));
ListenableFutureTask
<
ArrayChunk
>
task
=
ListenableFutureTask
.
create
(()
->
{
ArrayChunk
chunk
=
myProvider
.
getChunk
(
key
.
first
,
key
.
second
,
Math
.
min
(
CHUNK_ROW_SIZE
,
getRowCount
()
-
key
.
first
),
Math
.
min
(
CHUNK_COL_SIZE
,
getColumnCount
()
-
key
.
second
));
handleChunkAdded
(
key
.
first
,
key
.
second
,
chunk
);
return
chunk
;
});
myExecutorService
.
execute
(
task
);
...
...
@@ -65,7 +65,7 @@ public class AsyncArrayTableModel extends AbstractTableModel {
}
});
public
AsyncArrayTableModel
(
int
rows
,
int
columns
,
NumpyArrayTabl
e
provider
)
{
public
AsyncArrayTableModel
(
int
rows
,
int
columns
,
TableChunkDatasourc
e
provider
)
{
myRows
=
rows
;
myColumns
=
columns
;
myProvider
=
provider
;
...
...
@@ -73,14 +73,6 @@ public class AsyncArrayTableModel extends AbstractTableModel {
@Override
public
boolean
isCellEditable
(
int
row
,
int
col
)
{
//Pair<Integer, Integer> key = itemToChunkKey(row, col);
//try {
// return myChunkCache.get(key).isDone();
//}
//catch (ExecutionException e) {
// return false;
//}
//TODO: make it editable
return
false
;
}
...
...
@@ -160,13 +152,11 @@ public class AsyncArrayTableModel extends AbstractTableModel {
Pair
<
Integer
,
Integer
>
key
=
itemToChunkKey
(
roffset
*
CHUNK_ROW_SIZE
,
coffset
*
CHUNK_COL_SIZE
);
final
Object
[][]
chunkData
=
new
Object
[
CHUNK_ROW_SIZE
][
CHUNK_COL_SIZE
];
for
(
int
r
=
0
;
r
<
CHUNK_ROW_SIZE
;
r
++)
{
for
(
int
c
=
0
;
c
<
CHUNK_COL_SIZE
;
c
++)
{
chunkData
[
r
][
c
]
=
data
[
roffset
*
CHUNK_ROW_SIZE
+
r
][
coffset
*
CHUNK_COL_SIZE
+
c
];
}
System
.
arraycopy
(
data
[
roffset
*
CHUNK_ROW_SIZE
+
r
],
coffset
*
30
,
chunkData
[
r
],
0
,
CHUNK_COL_SIZE
);
}
myChunkCache
.
put
(
key
,
new
ListenableFuture
<
ArrayChunk
>()
{
@Override
public
void
addListener
(
Runnable
listener
,
Executor
executor
)
{
public
void
addListener
(
@NotNull
Runnable
listener
,
@NotNull
Executor
executor
)
{
}
...
...
@@ -187,15 +177,53 @@ public class AsyncArrayTableModel extends AbstractTableModel {
@Override
public
ArrayChunk
get
()
throws
InterruptedException
,
ExecutionException
{
return
new
ArrayChunk
(
chunk
.
getValue
(),
null
,
0
,
0
,
null
,
null
,
null
,
null
,
chunkData
);
return
new
ArrayChunkBuilder
().
setValue
(
chunk
.
getValue
()).
setSlicePresentation
(
null
).
setRows
(
0
).
setColumns
(
0
).
setMax
(
null
)
.
setMin
(
null
).
setFormat
(
null
).
setType
(
null
).
setData
(
chunkData
).
createArrayChunk
();
}
@Override
public
ArrayChunk
get
(
long
timeout
,
TimeUnit
unit
)
throws
InterruptedException
,
ExecutionException
,
TimeoutException
{
return
new
ArrayChunk
(
chunk
.
getValue
(),
null
,
0
,
0
,
null
,
null
,
null
,
null
,
chunkData
);
return
new
ArrayChunkBuilder
().
setValue
(
chunk
.
getValue
()).
setSlicePresentation
(
null
).
setRows
(
0
).
setColumns
(
0
).
setMax
(
null
)
.
setMin
(
null
).
setFormat
(
null
).
setType
(
null
).
setData
(
chunkData
).
createArrayChunk
();
}
});
}
}
handleChunkAdded
(
0
,
0
,
chunk
);
}
protected
void
handleChunkAdded
(
Integer
rowOffset
,
Integer
colOffset
,
ArrayChunk
chunk
)
{
}
public
TableModel
getRowHeaderModel
()
{
return
new
RowNumberHeaderModel
();
}
private
class
RowNumberHeaderModel
extends
AbstractTableModel
{
@Override
public
int
getRowCount
()
{
return
AsyncArrayTableModel
.
this
.
getRowCount
();
}
@Override
public
int
getColumnCount
()
{
return
1
;
}
@Override
public
String
getColumnName
(
int
column
)
{
if
(
column
==
0
)
{
return
" "
;
}
throw
new
IllegalArgumentException
(
"Table only has one column"
);
}
@Override
public
Object
getValueAt
(
int
rowIndex
,
int
columnIndex
)
{
return
Integer
.
toString
(
rowIndex
);
}
}
}
\ No newline at end of file
This diff is collapsed.
Click to expand it.
python/src/com/jetbrains/python/debugger/array/JBTableWithRowHeaders.java
+
61
-
55
View file @
84dc26d1
...
...
@@ -21,12 +21,10 @@ import org.jetbrains.annotations.NotNull;
import
javax.swing.*
;
import
javax.swing.event.ListSelectionEvent
;
import
javax.swing.event.ListSelectionListener
;
import
javax.swing.event.TableModelEvent
;
import
javax.swing.event.TableModelListener
;
import
javax.swing.table.DefaultTableCellRenderer
;
import
javax.swing.table.JTableHeader
;
import
javax.swing.table.Table
Column
;
import
javax.swing.table.Table
Model
;
import
java.awt.*
;
import
java.awt.event.MouseListener
;
import
java.beans.PropertyChangeEvent
;
...
...
@@ -39,59 +37,47 @@ public class JBTableWithRowHeaders extends JBTable {
private
final
JBScrollPane
myScrollPane
;
private
RowHeaderTable
myRowHeaderTable
;
public
JBScrollPane
getScrollPane
()
{
return
myScrollPane
;
}
public
JBTableWithRowHeaders
()
{
setAutoResizeMode
(
JTable
.
AUTO_RESIZE_SUBSEQUENT_COLUMNS
);
setRowSelectionAllowed
(
false
);
setMaxItemsForSizeCalculation
(
50
);
setTableHeader
(
new
CustomTableHeader
(
this
));
getTableHeader
().
setDefaultRenderer
(
new
ArrayTableForm
.
ColumnHeaderRenderer
());
getTableHeader
().
setDefaultRenderer
(
new
ColumnHeaderRenderer
());
getTableHeader
().
setReorderingAllowed
(
false
);
myScrollPane
=
new
JBScrollPane
(
this
);
JBTableWithRowHeaders
.
RowHeaderTable
row
Table
=
new
JBTableWithRowHeaders
.
RowHeaderTable
(
this
);
myScrollPane
.
setRowHeaderView
(
row
Table
);
myRowHeader
Table
=
new
JBTableWithRowHeaders
.
RowHeaderTable
(
this
);
myScrollPane
.
setRowHeaderView
(
myRowHeader
Table
);
myScrollPane
.
setCorner
(
ScrollPaneConstants
.
UPPER_LEFT_CORNER
,
rowTable
.
getTableHeader
());
myRowHeaderTable
.
getTableHeader
());
}
setRowHeaderTable
(
rowTable
);
public
JBScrollPane
getScrollPane
()
{
return
myScrollPane
;
}
public
boolean
getScrollableTracksViewportWidth
()
{
return
getPreferredSize
().
width
<
getParent
().
getWidth
();
}
public
RowHeaderTable
getRowHeaderTable
()
{
return
myRowHeaderTable
;
}
public
void
setRowHeaderTable
(
RowHeaderTable
rowHeaderTable
)
{
myRowHeaderTable
=
rowHeaderTable
;
@Override
public
void
setModel
(
@NotNull
TableModel
model
)
{
super
.
setModel
(
model
);
if
(
model
instanceof
AsyncArrayTableModel
)
{
myRowHeaderTable
.
setModel
(((
AsyncArrayTableModel
)
model
).
getRowHeaderModel
());
}
}
public
static
class
RowHeaderTable
extends
JBTable
implements
PropertyChangeListener
,
TableModelListener
{
private
JTable
myMainTable
;
private
int
myRowShift
=
0
;
public
RowHeaderTable
(
JTable
table
)
{
myMainTable
=
table
;
myMainTable
.
getModel
().
addTableModelListener
(
this
);
setFocusable
(
false
);
setAutoCreateColumnsFromModel
(
false
);
setSelectionModel
(
myMainTable
.
getSelectionModel
());
setSelectionMode
(
ListSelectionModel
.
SINGLE_SELECTION
);
TableColumn
column
=
new
TableColumn
();
column
.
setHeaderValue
(
" "
);
addColumn
(
column
);
column
.
setCellRenderer
(
new
RowNumberRenderer
());
getColumnModel
().
getColumn
(
0
).
setPreferredWidth
(
50
);
setPreferredScrollableViewportSize
(
getPreferredSize
());
setRowHeight
(
myMainTable
.
getRowHeight
());
MouseListener
[]
listeners
=
getMouseListeners
();
for
(
MouseListener
l
:
listeners
)
{
...
...
@@ -105,9 +91,16 @@ public class JBTableWithRowHeaders extends JBTable {
super
.
paintComponent
(
g
);
}
@Override
public
int
getRowCount
()
{
return
myMainTable
.
getRowCount
();
public
void
setModel
(
@NotNull
TableModel
model
)
{
setAutoCreateColumnsFromModel
(
true
);
super
.
setModel
(
model
);
if
(
getColumnModel
().
getColumnCount
()
>
0
)
{
getColumnModel
().
getColumn
(
0
).
setPreferredWidth
(
50
);
getColumnModel
().
getColumn
(
0
).
setCellRenderer
(
new
RowNumberRenderer
());
setPreferredScrollableViewportSize
(
getPreferredSize
());
}
}
@Override
...
...
@@ -116,14 +109,6 @@ public class JBTableWithRowHeaders extends JBTable {
return
super
.
getRowHeight
(
row
);
}
@Override
public
Object
getValueAt
(
int
row
,
int
column
)
{
return
Integer
.
toString
(
row
+
myRowShift
);
}
public
void
setRowShift
(
int
shift
)
{
myRowShift
=
shift
;
}
@Override
public
boolean
isCellEditable
(
int
row
,
int
column
)
{
...
...
@@ -131,10 +116,6 @@ public class JBTableWithRowHeaders extends JBTable {
}
@Override
public
void
setValueAt
(
Object
value
,
int
row
,
int
column
)
{
}
public
void
propertyChange
(
PropertyChangeEvent
e
)
{
if
(
"selectionModel"
.
equals
(
e
.
getPropertyName
()))
{
setSelectionModel
(
myMainTable
.
getSelectionModel
());
...
...
@@ -145,17 +126,12 @@ public class JBTableWithRowHeaders extends JBTable {
}
if
(
"model"
.
equals
(
e
.
getPropertyName
()))
{
myMainTable
.
getModel
().
addTableModelListener
(
this
);
revalidate
();
}
}
@Override
public
void
tableChanged
(
TableModelEvent
e
)
{
revalidate
();
}
private
class
RowNumberRenderer
extends
DefaultTableCellRenderer
{
private
static
class
RowNumberRenderer
extends
DefaultTableCellRenderer
{
public
RowNumberRenderer
()
{
setHorizontalAlignment
(
SwingConstants
.
CENTER
);
}
...
...
@@ -189,12 +165,7 @@ public class JBTableWithRowHeaders extends JBTable {
public
CustomTableHeader
(
JTable
table
)
{
super
();
setColumnModel
(
table
.
getColumnModel
());
table
.
getColumnModel
().
getSelectionModel
().
addListSelectionListener
(
new
ListSelectionListener
()
{
@Override
public
void
valueChanged
(
ListSelectionEvent
e
)
{
repaint
();
}
});
table
.
getColumnModel
().
getSelectionModel
().
addListSelectionListener
(
e
->
repaint
());
}
@Override
...
...
@@ -202,4 +173,39 @@ public class JBTableWithRowHeaders extends JBTable {
repaint
();
}
}
public
static
class
ColumnHeaderRenderer
extends
DefaultTableHeaderCellRenderer
{
@Override
public
Component
getTableCellRendererComponent
(
JTable
table
,
Object
value
,
boolean
selected
,
boolean
focused
,
int
row
,
int
column
)
{
super
.
getTableCellRendererComponent
(
table
,
value
,
selected
,
focused
,
row
,
column
);
int
selectedColumn
=
table
.
getSelectedColumn
();
if
(
selectedColumn
==
column
)
{
setFont
(
getFont
().
deriveFont
(
Font
.
BOLD
));
}
return
this
;
}
}
public
static
class
DefaultTableHeaderCellRenderer
extends
DefaultTableCellRenderer
{
public
DefaultTableHeaderCellRenderer
()
{
setHorizontalAlignment
(
CENTER
);
setHorizontalTextPosition
(
LEFT
);
setVerticalAlignment
(
BOTTOM
);
setOpaque
(
false
);
}
@Override
public
Component
getTableCellRendererComponent
(
JTable
table
,
Object
value
,
boolean
isSelected
,
boolean
hasFocus
,
int
row
,
int
column
)
{
super
.
getTableCellRendererComponent
(
table
,
value
,
isSelected
,
hasFocus
,
row
,
column
);
JTableHeader
tableHeader
=
table
.
getTableHeader
();
if
(
tableHeader
!=
null
)
{
setForeground
(
tableHeader
.
getForeground
());
}
setBorder
(
UIManager
.
getBorder
(
"TableHeader.cellBorder"
));
return
this
;
}
}
}
This diff is collapsed.
Click to expand it.
python/src/com/jetbrains/python/debugger/array/NumpyArrayTable.java
+
25
-
314
View file @
84dc26d1
...
...
@@ -15,211 +15,52 @@
*/
package
com.jetbrains.python.debugger.array
;
import
com.intellij.codeInsight.hint.HintManager
;
import
com.intellij.openapi.application.ApplicationManager
;
import
com.intellij.openapi.diagnostic.Logger
;
import
com.intellij.openapi.editor.RangeMarker
;
import
com.intellij.openapi.project.Project
;
import
com.intellij.openapi.util.Pair
;
import
com.intellij.util.ui.UIUtil
;
import
com.jetbrains.python.debugger.*
;
import
com.jetbrains.python.debugger.ArrayChunk
;
import
com.jetbrains.python.debugger.PyDebugValue
;
import
com.jetbrains.python.debugger.containerview.ColoredCellRenderer
;
import
com.jetbrains.python.debugger.containerview.NumericContainerViewTable
;
import
com.jetbrains.python.debugger.containerview.ViewNumericContainerDialog
;
import
org.jetbrains.annotations.NotNull
;
import
javax.swing.*
;
import
java.awt.*
;
import
java.awt.event.*
;
import
java.util.regex.Matcher
;
import
java.util.regex.Pattern
;
/**
* @author amarch
*/
public
class
NumpyArrayTable
{
private
final
PyDebugValue
myValue
;
private
final
PyViewArrayAction
.
ViewArrayDialog
myDialog
;
private
final
ArrayTableForm
myComponent
;
private
final
JTable
myTable
;
private
Project
myProject
;
private
PyDebuggerEvaluator
myEvaluator
;
private
String
myDtypeKind
;
private
ArrayTableCellRenderer
myTableCellRenderer
;
private
AsyncArrayTableModel
myPagingModel
;
private
final
static
int
COLUMNS_IN_DEFAULT_SLICE
=
40
;
private
final
static
int
ROWS_IN_DEFAULT_SLICE
=
40
;
private
final
static
int
COLUMNS_IN_DEFAULT_VIEW
=
1000
;
private
final
static
int
ROWS_IN_DEFAULT_VIEW
=
1000
;
private
static
final
Pattern
PY_COMPLEX_NUMBER
=
Pattern
.
compile
(
"([+-]?[.\\d^j]*)([+-]?[e.\\d]*j)?"
);
public
final
class
NumpyArrayTable
extends
NumericContainerViewTable
{
private
final
static
int
HUGE_ARRAY_SIZE
=
1000
*
1000
;
private
final
static
String
LOAD_SMALLER_SLICE
=
"Full slice too large and would slow down debugger, shrunk to smaller slice."
;
private
final
static
String
DISABLE_COLOR_FOR_HUGE_ARRAY
=
"Disable color because array too big and calculating min and max would slow down debugging."
;
private
static
final
Logger
LOG
=
Logger
.
getInstance
(
"#com.jetbrains.python.debugger.array.NumpyArrayValueProvi
der
"
)
;
private
ArrayTableCellRenderer
myArrayTableCellRen
der
er
;
public
NumpyArrayTable
(
@NotNull
Project
project
,
@NotNull
PyViewArrayAction
.
ViewArrayDialog
dialog
,
@NotNull
PyDebugValue
value
)
{
myValue
=
value
;
myDialog
=
dialog
;
myComponent
=
new
ArrayTableForm
(
project
,
new
KeyAdapter
()
{
@Override
public
void
keyPressed
(
KeyEvent
e
)
{
if
(
e
.
getKeyCode
()
==
KeyEvent
.
VK_ENTER
)
{
doReslice
();
}
}
},
new
KeyAdapter
()
{
@Override
public
void
keyPressed
(
KeyEvent
e
)
{
if
(
e
.
getKeyCode
()
==
KeyEvent
.
VK_ENTER
)
{
doApplyFormat
();
}
}
});
myTable
=
myComponent
.
getTable
();
myProject
=
project
;
myEvaluator
=
new
PyDebuggerEvaluator
(
project
,
getDebugValue
().
getFrameAccessor
());
}
public
ArrayTableForm
getComponent
()
{
return
myComponent
;
}
private
void
initComponent
()
{
myComponent
.
getColoredCheckbox
().
setEnabled
(
false
);
myComponent
.
getColoredCheckbox
().
addItemListener
(
new
ItemListener
()
{
@Override
public
void
itemStateChanged
(
ItemEvent
e
)
{
if
(
e
.
getSource
()
==
myComponent
.
getColoredCheckbox
())
{
if
(
myTable
.
getRowCount
()
>
0
&&
myTable
.
getColumnCount
()
>
0
&&
myTable
.
getCellRenderer
(
0
,
0
)
instanceof
ArrayTableCellRenderer
)
{
ArrayTableCellRenderer
renderer
=
(
ArrayTableCellRenderer
)
myTable
.
getCellRenderer
(
0
,
0
);
if
(
myComponent
.
getColoredCheckbox
().
isSelected
())
{
renderer
.
setColored
(
true
);
}
else
{
renderer
.
setColored
(
false
);
}
}
myComponent
.
getScrollPane
().
repaint
();
}
}
});
//make value name read-only
myComponent
.
getSliceTextField
().
addFocusListener
(
new
FocusListener
()
{
@Override
public
void
focusGained
(
FocusEvent
e
)
{
myComponent
.
getSliceTextField
().
getDocument
().
createGuardedBlock
(
0
,
getNodeFullName
().
length
());
}
@Override
public
void
focusLost
(
FocusEvent
e
)
{
RangeMarker
block
=
myComponent
.
getSliceTextField
().
getDocument
().
getRangeGuard
(
0
,
getNodeFullName
().
length
());
if
(
block
!=
null
)
{
myComponent
.
getSliceTextField
().
getDocument
().
removeGuardedBlock
(
block
);
}
}
});
}
public
void
disableColor
()
{
myTableCellRenderer
.
setMin
(
Double
.
MAX_VALUE
);
myTableCellRenderer
.
setMax
(
Double
.
MIN_VALUE
);
myTableCellRenderer
.
setColored
(
false
);
UIUtil
.
invokeLaterIfNeeded
(()
->
{
myComponent
.
getColoredCheckbox
().
setSelected
(
false
);
myComponent
.
getColoredCheckbox
().
setEnabled
(
false
);
if
(
myTable
.
getColumnCount
()
>
0
)
{
myTable
.
setDefaultRenderer
(
myTable
.
getColumnClass
(
0
),
myTableCellRenderer
);
}
});
}
public
PyDebugValue
getDebugValue
()
{
return
myValue
;
}
public
PyFrameAccessor
getEvaluator
()
{
return
myValue
.
getFrameAccessor
();
@NotNull
ViewNumericContainerDialog
dialog
,
@NotNull
PyDebugValue
value
)
{
super
(
project
,
dialog
,
value
);
}
public
void
init
()
{
init
(
getDebugValue
().
getEvaluationExpression
(),
false
);
@Override
protected
AsyncArrayTableModel
createTableModel
(
int
rowCount
,
int
columnCount
)
{
return
new
AsyncArrayTableModel
(
rowCount
,
columnCount
,
this
);
}
public
void
init
(
final
String
slice
,
final
boolean
inPlace
)
{
initComponent
();
ApplicationManager
.
getApplication
().
executeOnPooledThread
(()
->
{
final
PyDebugValue
value
=
getDebugValue
();
PyDebugValue
parent
=
value
.
getParent
();
final
PyDebugValue
slicedValue
=
new
PyDebugValue
(
slice
,
value
.
getType
(),
null
,
value
.
getValue
(),
value
.
isContainer
(),
value
.
isReturnedVal
(),
value
.
isErrorOnEval
(),
parent
,
value
.
getFrameAccessor
());
final
String
format
=
getFormat
().
isEmpty
()
?
"%"
:
getFormat
();
try
{
initUi
(
value
.
getFrameAccessor
()
.
getArrayItems
(
slicedValue
,
0
,
0
,
-
1
,
-
1
,
format
),
inPlace
);
}
catch
(
PyDebuggerException
e
)
{
showError
(
e
.
getMessage
());
}
});
@Override
protected
ColoredCellRenderer
createCellRenderer
(
double
minValue
,
double
maxValue
,
ArrayChunk
chunk
)
{
myArrayTableCellRenderer
=
new
ArrayTableCellRenderer
(
minValue
,
maxValue
,
chunk
.
getType
());
fillColorRange
(
chunk
.
getMin
(),
chunk
.
getMax
());
return
myArrayTableCellRenderer
;
}
private
void
initUi
(
@NotNull
final
ArrayChunk
chunk
,
final
boolean
inPlace
)
{
myPagingModel
=
new
AsyncArrayTableModel
(
Math
.
min
(
chunk
.
getRows
(),
ROWS_IN_DEFAULT_VIEW
),
Math
.
min
(
chunk
.
getColumns
(),
COLUMNS_IN_DEFAULT_VIEW
),
this
);
myPagingModel
.
addToCache
(
chunk
);
myDtypeKind
=
chunk
.
getType
();
UIUtil
.
invokeLaterIfNeeded
(()
->
{
myTable
.
setModel
(
myPagingModel
);
myComponent
.
getSliceTextField
().
setText
(
chunk
.
getSlicePresentation
());
myComponent
.
getFormatTextField
().
setText
(
chunk
.
getFormat
());
myDialog
.
setTitle
(
getTitlePresentation
(
chunk
.
getSlicePresentation
()));
myTableCellRenderer
=
new
ArrayTableCellRenderer
(
Double
.
MIN_VALUE
,
Double
.
MIN_VALUE
,
chunk
.
getType
());
fillColorRange
(
chunk
.
getMin
(),
chunk
.
getMax
());
if
(!
isNumeric
())
{
disableColor
();
}
else
{
myComponent
.
getColoredCheckbox
().
setEnabled
(
true
);
}
if
(!
inPlace
)
{
myComponent
.
getScrollPane
().
getViewport
().
setViewPosition
(
new
Point
(
0
,
0
));
JBTableWithRowHeaders
.
RowHeaderTable
rowTable
=
((
JBTableWithRowHeaders
)
myTable
).
getRowHeaderTable
();
rowTable
.
setRowShift
(
0
);
}
((
AsyncArrayTableModel
)
myTable
.
getModel
()).
fireTableDataChanged
();
((
AsyncArrayTableModel
)
myTable
.
getModel
()).
fireTableCellUpdated
(
0
,
0
);
if
(
myTable
.
getColumnCount
()
>
0
)
{
myTable
.
setDefaultRenderer
(
myTable
.
getColumnClass
(
0
),
myTableCellRenderer
);
}
});
}
private
static
String
getTitlePresentation
(
String
slice
)
{
@Override
protected
final
String
getTitlePresentation
(
String
slice
)
{
return
"Array View: "
+
slice
;
}
private
void
fillColorRange
(
String
minValue
,
String
maxValue
)
{
double
min
;
double
max
;
if
(
"c"
.
equals
(
myDtypeKind
))
{
min
=
0
;
max
=
1
;
myTableCellRenderer
.
setComplexMin
(
minValue
);
myTableCellRenderer
.
setComplexMax
(
maxValue
);
my
Array
TableCellRenderer
.
setComplexMin
(
minValue
);
my
Array
TableCellRenderer
.
setComplexMax
(
maxValue
);
}
else
if
(
"b"
.
equals
(
myDtypeKind
))
{
min
=
minValue
.
equals
(
"True"
)
?
1
:
0
;
...
...
@@ -230,145 +71,15 @@ public class NumpyArrayTable {
max
=
Double
.
parseDouble
(
maxValue
);
}
myTableCellRenderer
.
setMin
(
min
);
myTableCellRenderer
.
setMax
(
max
);
}
public
String
getSliceText
()
{
return
myComponent
.
getSliceTextField
().
getText
();
myArrayTableCellRenderer
.
setMin
(
min
);
myArrayTableCellRenderer
.
setMax
(
max
);
}
@Override
public
boolean
isNumeric
()
{
if
(
myDtypeKind
!=
null
)
{
return
"biufc"
.
contains
(
myDtypeKind
.
substring
(
0
,
1
));
}
return
false
;
}
private
void
initTableModel
(
final
boolean
inPlace
)
{
myPagingModel
=
new
AsyncArrayTableModel
(
myPagingModel
.
getRowCount
(),
myPagingModel
.
getColumnCount
(),
this
);
UIUtil
.
invokeLaterIfNeeded
(()
->
{
myTable
.
setModel
(
myPagingModel
);
if
(!
inPlace
)
{
myComponent
.
getScrollPane
().
getViewport
().
setViewPosition
(
new
Point
(
0
,
0
));
JBTableWithRowHeaders
.
RowHeaderTable
rowTable
=
((
JBTableWithRowHeaders
)
myTable
).
getRowHeaderTable
();
rowTable
.
setRowShift
(
0
);
}
((
AsyncArrayTableModel
)
myTable
.
getModel
()).
fireTableDataChanged
();
((
AsyncArrayTableModel
)
myTable
.
getModel
()).
fireTableCellUpdated
(
0
,
0
);
if
(
myTable
.
getColumnCount
()
>
0
)
{
myTable
.
setDefaultRenderer
(
myTable
.
getColumnClass
(
0
),
myTableCellRenderer
);
}
});
}
public
String
correctStringValue
(
@NotNull
Object
value
)
{
if
(
value
instanceof
String
)
{
String
corrected
=
(
String
)
value
;
if
(
isNumeric
())
{
if
(
corrected
.
startsWith
(
"\'"
)
||
corrected
.
startsWith
(
"\""
))
{
corrected
=
corrected
.
substring
(
1
,
corrected
.
length
()
-
1
);
}
}
return
corrected
;
}
else
if
(
value
instanceof
Integer
)
{
return
Integer
.
toString
((
Integer
)
value
);
}
return
value
.
toString
();
}
public
void
setDtypeKind
(
String
dtype
)
{
this
.
myDtypeKind
=
dtype
;
}
public
void
showError
(
String
message
)
{
myDialog
.
setError
(
message
);
}
public
void
showInfoHint
(
final
String
message
)
{
UIUtil
.
invokeLaterIfNeeded
(()
->
{
if
(
myComponent
.
getSliceTextField
().
getEditor
()
!=
null
)
{
HintManager
.
getInstance
().
showInformationHint
(
myComponent
.
getSliceTextField
().
getEditor
(),
message
);
}
});
}
private
void
doReslice
()
{
clearErrorMessage
();
init
(
getSliceText
(),
false
);
}
private
void
clearErrorMessage
()
{
showError
(
null
);
}
private
void
doApplyFormat
()
{
reset
();
}
private
void
reset
()
{
clearErrorMessage
();
initTableModel
(
true
);
}
/**
* @return double presentation from [0:1] range
*/
public
static
double
getRangedValue
(
String
value
,
String
type
,
double
min
,
double
max
,
String
complexMax
,
String
complexMin
)
{
if
(
"iuf"
.
contains
(
type
))
{
return
(
Double
.
parseDouble
(
value
)
-
min
)
/
(
max
-
min
);
}
else
if
(
"b"
.
equals
(
type
))
{
return
value
.
equals
(
"True"
)
?
1
:
0
;
}
else
if
(
"c"
.
equals
(
type
))
{
return
getComplexRangedValue
(
value
,
complexMax
,
complexMin
);
}
return
0
;
}
/**
* type complex128 in numpy is compared by next rule:
* A + Bj > C +Dj if A > C or A == C and B > D
*/
private
static
double
getComplexRangedValue
(
String
value
,
String
complexMax
,
String
complexMin
)
{
Pair
<
Double
,
Double
>
med
=
parsePyComplex
(
value
);
Pair
<
Double
,
Double
>
max
=
parsePyComplex
(
complexMax
);
Pair
<
Double
,
Double
>
min
=
parsePyComplex
(
complexMin
);
double
range
=
(
med
.
first
-
min
.
first
)
/
(
max
.
first
-
min
.
first
);
if
(
max
.
first
.
equals
(
min
.
first
))
{
range
=
(
med
.
second
-
min
.
second
)
/
(
max
.
second
-
min
.
second
);
}
return
range
;
}
private
static
Pair
<
Double
,
Double
>
parsePyComplex
(
@NotNull
String
pyComplexValue
)
{
if
(
pyComplexValue
.
startsWith
(
"("
)
&&
pyComplexValue
.
endsWith
(
")"
))
{
pyComplexValue
=
pyComplexValue
.
substring
(
1
,
pyComplexValue
.
length
()
-
1
);
}
Matcher
matcher
=
PY_COMPLEX_NUMBER
.
matcher
(
pyComplexValue
);
if
(
matcher
.
matches
())
{
String
real
=
matcher
.
group
(
1
);
String
imag
=
matcher
.
group
(
2
);
if
(
real
.
contains
(
"j"
)
&&
imag
==
null
)
{
return
new
Pair
(
new
Double
(
0.0
),
Double
.
parseDouble
(
real
.
substring
(
0
,
real
.
length
()
-
1
)));
}
else
{
return
new
Pair
(
Double
.
parseDouble
(
real
),
Double
.
parseDouble
(
imag
.
substring
(
0
,
imag
.
length
()
-
1
)));
}
}
else
{
throw
new
IllegalArgumentException
(
"Not a valid python complex value: "
+
pyComplexValue
);
}
}
public
String
getNodeFullName
()
{
return
getDebugValue
().
getEvaluationExpression
();
}
public
String
getFormat
()
{
return
myComponent
.
getFormatTextField
().
getText
();
}
}
This diff is collapsed.
Click to expand it.
python/src/com/jetbrains/python/debugger/array/TableChunkDatasource.java
0 → 100644
+
34
-
0
View file @
84dc26d1
/*
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
com.jetbrains.python.debugger.array
;
import
com.jetbrains.python.debugger.ArrayChunk
;
import
com.jetbrains.python.debugger.PyDebuggerException
;
import
org.jetbrains.annotations.NotNull
;
/**
* Created by Alla on 4/23/2016.
*/
public
interface
TableChunkDatasource
{
String
correctStringValue
(
@NotNull
Object
value
);
void
showError
(
String
message
);
ArrayChunk
getChunk
(
int
rowOffset
,
int
colOffset
,
int
rows
,
int
cols
)
throws
PyDebuggerException
;
}
This diff is collapsed.
Click to expand it.
python/src/com/jetbrains/python/debugger/containerview/ColoredCellRenderer.java
0 → 100644
+
25
-
0
View file @
84dc26d1
/*
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
com.jetbrains.python.debugger.containerview
;
import
javax.swing.table.TableCellRenderer
;
/**
* Created by Yuli Fiterman on 5/10/2016.
*/
public
interface
ColoredCellRenderer
extends
TableCellRenderer
{
void
setColored
(
boolean
colored
);
}
This diff is collapsed.
Click to expand it.
python/src/com/jetbrains/python/debugger/
array/ArrayTable
Form.form
→
python/src/com/jetbrains/python/debugger/
containerview/NumericContainerRenderer
Form.form
+
3
-
3
View file @
84dc26d1
<?xml version="1.0" encoding="UTF-8"?>
<form
xmlns=
"http://www.intellij.com/uidesigner/form/"
version=
"1"
bind-to-class=
"com.jetbrains.python.debugger.
array.ArrayTable
Form"
>
<grid
id=
"27dc6"
binding=
"myMainPanel"
layout-manager=
"GridLayoutManager"
row-count=
"
2
"
column-count=
"5"
same-size-horizontally=
"false"
same-size-vertically=
"false"
hgap=
"-1"
vgap=
"-1"
>
<form
xmlns=
"http://www.intellij.com/uidesigner/form/"
version=
"1"
bind-to-class=
"com.jetbrains.python.debugger.
containerview.NumericContainerRenderer
Form"
>
<grid
id=
"27dc6"
binding=
"myMainPanel"
layout-manager=
"GridLayoutManager"
row-count=
"
3
"
column-count=
"5"
same-size-horizontally=
"false"
same-size-vertically=
"false"
hgap=
"-1"
vgap=
"-1"
>
<margin
top=
"0"
left=
"0"
bottom=
"0"
right=
"0"
/>
<constraints>
<xy
x=
"20"
y=
"20"
width=
"608"
height=
"375"
/>
...
...
@@ -18,7 +18,7 @@
</properties>
<border
type=
"none"
/>
<children>
<component
id=
"c7f7c"
class=
"com.
intellij.ui.table.JBTable
"
binding=
"myTable"
custom-create=
"true"
>
<component
id=
"c7f7c"
class=
"com.
jetbrains.python.debugger.array.JBTableWithRowHeaders
"
binding=
"myTable"
custom-create=
"true"
>
<constraints/>
<properties>
<autoResizeMode
value=
"0"
/>
...
...
This diff is collapsed.
Click to expand it.
python/src/com/jetbrains/python/debugger/
array/ArrayTable
Form.java
→
python/src/com/jetbrains/python/debugger/
containerview/NumericContainerRenderer
Form.java
+
102
-
0
View file @
84dc26d1
/*
* Copyright 2000-201
4
JetBrains s.r.o.
* Copyright 2000-201
6
JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
...
...
@@ -13,144 +13,90 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
com.jetbrains.python.debugger.
array
;
package
com.jetbrains.python.debugger.
containerview
;
import
com.intellij.openapi.editor.Editor
;
import
com.intellij.openapi.editor.ex.EditorEx
;
import
com.intellij.openapi.project.Project
;
import
com.intellij.ui.EditorTextField
;
import
com.intellij.ui.components.JBScrollPane
;
import
com.intellij.ui.table.JBTable
;
import
com.intellij.xdebugger.impl.ui.tree.nodes.XValueNodeImpl
;
import
com.jetbrains.python.PythonFileType
;
import
com.jetbrains.python.debugger.
PyDebugValue
;
import
com.jetbrains.python.debugger.
array.JBTableWithRowHeaders
;
import
org.jetbrains.annotations.NotNull
;
import
javax.swing.*
;
import
javax.swing.event.ListSelectionEvent
;
import
javax.swing.event.ListSelectionListener
;
import
javax.swing.table.DefaultTableCellRenderer
;
import
javax.swing.table.DefaultTableModel
;
import
javax.swing.table.JTableHeader
;
import
java.awt.*
;
import
java.awt.event.KeyListener
;
/**
*
@author amarch
*
Created by Yuli Fiterman on 5/10/2016.
*/
public
class
ArrayTableForm
{
private
EditorTextField
mySliceTextField
;
private
JCheckBox
myColoredCheckbox
;
private
EditorTextField
myFormatTextField
;
private
JBScrollPane
myScrollPane
;
private
JLabel
myFormatLabel
;
private
JPanel
myFormatPanel
;
private
JPanel
myMainPanel
;
private
JTable
myTable
;
private
final
Project
myProject
;
private
KeyListener
myResliceCallback
;
private
KeyListener
myReformatCallback
;
private
static
final
String
DATA_LOADING_IN_PROCESS
=
"Please wait, load array data."
;
private
static
final
String
NOT_APPLICABLE
=
"View not applicable for "
;
public
ArrayTableForm
(
@NotNull
Project
project
,
KeyListener
resliceCallback
,
KeyListener
reformatCallback
)
{
myProject
=
project
;
public
class
NumericContainerRendererForm
{
protected
final
Project
myProject
;
protected
final
KeyListener
myReformatCallback
;
protected
final
KeyListener
myResliceCallback
;
protected
JBScrollPane
myScrollPane
;
protected
EditorTextField
mySliceTextField
;
protected
JBTableWithRowHeaders
myTable
;
protected
EditorTextField
myFormatTextField
;
protected
JCheckBox
myColoredCheckbox
;
protected
JPanel
myFormatPanel
;
protected
JPanel
myMainPanel
;
protected
JLabel
myFormatLabel
;
public
NumericContainerRendererForm
(
@NotNull
Project
project
,
KeyListener
resliceCallback
,
KeyListener
reformatCallback
)
{
myResliceCallback
=
resliceCallback
;
myProject
=
project
;
myReformatCallback
=
reformatCallback
;
}
private
void
createUIComponents
()
{
mySliceTextField
=
new
EditorTextField
(
""
,
myProject
,
PythonFileType
.
INSTANCE
)
{
@Override
protected
EditorEx
createEditor
()
{
EditorEx
editor
=
super
.
createEditor
();
editor
.
getContentComponent
().
addKeyListener
(
myResliceCallback
);
return
editor
;
}
};
myTable
=
new
JBTableWithRowHeaders
();
myScrollPane
=
((
JBTableWithRowHeaders
)
myTable
).
getScrollPane
();
public
JBTable
getTable
()
{
return
myTable
;
}
myFormatTextField
=
new
EditorTextField
(
""
,
myProject
,
PythonFileType
.
INSTANCE
)
{
@Override
protected
EditorEx
createEditor
()
{
EditorEx
editor
=
super
.
createEditor
();
editor
.
getContentComponent
().
addKeyListener
(
myReformatCallback
);
return
editor
;
}
};
public
JPanel
getMainPanel
()
{
return
myMainPanel
;
}
public
EditorTextField
getSliceTextField
()
{
return
mySliceTextField
;
}
public
EditorTextField
getFormatTextField
()
{
return
myFormatTextField
;
}
public
JTable
getTable
()
{
return
myTable
;
}
public
JCheckBox
getColoredCheckbox
()
{
return
myColoredCheckbox
;
}
//public void setDefaultStatus() {
// if (myTable != null) {
//myTable.getEmptyText().setText(DATA_LOADING_IN_PROCESS);
//}
//}
//public void setNotApplicableStatus(PyDebugValue node) {
// myTable.getEmptyText().setText(NOT_APPLICABLE + node.getName());
//}
public
JComponent
getMainPanel
()
{
return
myMainPanel
;
}
public
JBScrollPane
getScrollPane
()
{
return
myScrollPane
;
}
public
static
class
ColumnHeaderRenderer
extends
DefaultTableHeaderCellRenderer
{
@Override
public
Component
getTableCellRendererComponent
(
JTable
table
,
Object
value
,
boolean
selected
,
boolean
focused
,
int
row
,
int
column
)
{
super
.
getTableCellRendererComponent
(
table
,
value
,
selected
,
focused
,
row
,
column
);
int
selectedColumn
=
table
.
getSelectedColumn
();
if
(
selectedColumn
==
column
)
{
setFont
(
getFont
().
deriveFont
(
Font
.
BOLD
));
}
return
this
;
}
public
EditorTextField
getFormatTextField
()
{
return
myFormatTextField
;
}
public
static
class
DefaultTableHeaderCellRenderer
extends
DefaultTableCellRenderer
{
public
DefaultTableHeaderCellRenderer
()
{
setHorizontalAlignment
(
CENTER
);
setHorizontalTextPosition
(
LEFT
);
setVerticalAlignment
(
BOTTOM
);
setOpaque
(
false
);
}
protected
void
createUIComponents
()
{
mySliceTextField
=
new
EditorTextField
(
""
,
myProject
,
PythonFileType
.
INSTANCE
)
{
@Override
protected
EditorEx
createEditor
()
{
EditorEx
editor
=
super
.
createEditor
();
editor
.
getContentComponent
().
addKeyListener
(
myResliceCallback
);
return
editor
;
}
};
@Override
public
Component
getTableCellRendererComponent
(
JTable
table
,
Object
value
,
boolean
isSelected
,
boolean
hasFocus
,
int
row
,
int
column
)
{
super
.
getTableCellRendererComponent
(
table
,
value
,
isSelected
,
hasFocus
,
row
,
column
);
JTableHeader
tableHeader
=
table
.
getTableHeader
();
if
(
tableHeader
!=
null
)
{
setForeground
(
tableHeader
.
getForeground
());
myFormatTextField
=
new
EditorTextField
(
""
,
myProject
,
PythonFileType
.
INSTANCE
)
{
@Override
protected
EditorEx
createEditor
()
{
EditorEx
editor
=
super
.
createEditor
();
editor
.
getContentComponent
().
addKeyListener
(
myReformatCallback
);
return
editor
;
}
setBorder
(
UIManager
.
getBorder
(
"TableHeader.cellBorder"
));
return
this
;
}
};
myTable
=
new
JBTableWithRowHeaders
();
myScrollPane
=
myTable
.
getScrollPane
();
}
}
This diff is collapsed.
Click to expand it.
python/src/com/jetbrains/python/debugger/containerview/NumericContainerViewTable.java
0 → 100644
+
283
-
0
View file @
84dc26d1
/*
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
com.jetbrains.python.debugger.containerview
;
import
com.intellij.openapi.application.ApplicationManager
;
import
com.intellij.openapi.diagnostic.Logger
;
import
com.intellij.openapi.editor.RangeMarker
;
import
com.intellij.openapi.project.Project
;
import
com.intellij.util.ui.UIUtil
;
import
com.jetbrains.python.debugger.ArrayChunk
;
import
com.jetbrains.python.debugger.PyDebugValue
;
import
com.jetbrains.python.debugger.PyDebuggerException
;
import
com.jetbrains.python.debugger.array.AsyncArrayTableModel
;
import
com.jetbrains.python.debugger.array.TableChunkDatasource
;
import
org.jetbrains.annotations.NotNull
;
import
javax.swing.*
;
import
java.awt.*
;
import
java.awt.event.*
;
/**
* Created by Yuli Fiterman 5/10/2016.
*/
public
abstract
class
NumericContainerViewTable
implements
TableChunkDatasource
{
protected
final
static
int
COLUMNS_IN_DEFAULT_VIEW
=
1000
;
protected
final
static
int
ROWS_IN_DEFAULT_VIEW
=
1000
;
protected
static
final
Logger
LOG
=
Logger
.
getInstance
(
"#com.jetbrains.python.debugger.containerview.NumericContainerViewTable"
);
protected
final
PyDebugValue
myValue
;
protected
final
ViewNumericContainerDialog
myDialog
;
protected
final
NumericContainerRendererForm
myComponent
;
protected
final
JTable
myTable
;
protected
final
Project
myProject
;
protected
String
myDtypeKind
;
protected
ColoredCellRenderer
myTableCellRenderer
;
protected
AsyncArrayTableModel
myPagingModel
;
public
NumericContainerViewTable
(
@NotNull
Project
project
,
@NotNull
ViewNumericContainerDialog
dialog
,
@NotNull
PyDebugValue
value
)
{
myProject
=
project
;
myDialog
=
dialog
;
myComponent
=
createForm
(
project
,
new
KeyAdapter
()
{
@Override
public
void
keyPressed
(
KeyEvent
e
)
{
if
(
e
.
getKeyCode
()
==
KeyEvent
.
VK_ENTER
)
{
doReslice
();
}
}
},
new
KeyAdapter
()
{
@Override
public
void
keyPressed
(
KeyEvent
e
)
{
if
(
e
.
getKeyCode
()
==
KeyEvent
.
VK_ENTER
)
{
doApplyFormat
();
}
}
});
myValue
=
value
;
myTable
=
myComponent
.
getTable
();
}
private
void
initUi
(
@NotNull
final
ArrayChunk
chunk
,
final
boolean
inPlace
)
{
myPagingModel
=
createTableModel
(
Math
.
min
(
chunk
.
getRows
(),
ROWS_IN_DEFAULT_VIEW
),
Math
.
min
(
chunk
.
getColumns
(),
COLUMNS_IN_DEFAULT_VIEW
));
myPagingModel
.
addToCache
(
chunk
);
myDtypeKind
=
chunk
.
getType
();
UIUtil
.
invokeLaterIfNeeded
(()
->
{
myTable
.
setModel
(
myPagingModel
);
myComponent
.
getSliceTextField
().
setText
(
chunk
.
getSlicePresentation
());
myComponent
.
getFormatTextField
().
setText
(
chunk
.
getFormat
());
myDialog
.
setTitle
(
getTitlePresentation
(
chunk
.
getSlicePresentation
()));
myTableCellRenderer
=
createCellRenderer
(
Double
.
MIN_VALUE
,
Double
.
MIN_VALUE
,
chunk
);
if
(!
isNumeric
())
{
disableColor
();
}
else
{
myComponent
.
getColoredCheckbox
().
setEnabled
(
true
);
}
if
(!
inPlace
)
{
myComponent
.
getScrollPane
().
getViewport
().
setViewPosition
(
new
Point
(
0
,
0
));
}
((
AsyncArrayTableModel
)
myTable
.
getModel
()).
fireTableDataChanged
();
((
AsyncArrayTableModel
)
myTable
.
getModel
()).
fireTableCellUpdated
(
0
,
0
);
if
(
myTable
.
getColumnCount
()
>
0
)
{
myTable
.
setDefaultRenderer
(
myTable
.
getColumnClass
(
0
),
myTableCellRenderer
);
}
});
}
private
void
disableColor
()
{
myTableCellRenderer
.
setColored
(
false
);
UIUtil
.
invokeLaterIfNeeded
(()
->
{
myComponent
.
getColoredCheckbox
().
setSelected
(
false
);
myComponent
.
getColoredCheckbox
().
setEnabled
(
false
);
if
(
myTable
.
getColumnCount
()
>
0
)
{
myTable
.
setDefaultRenderer
(
myTable
.
getColumnClass
(
0
),
myTableCellRenderer
);
}
});
}
protected
abstract
AsyncArrayTableModel
createTableModel
(
int
rowCount
,
int
columnCount
);
protected
abstract
ColoredCellRenderer
createCellRenderer
(
double
minValue
,
double
maxValue
,
ArrayChunk
chunk
);
private
void
initTableModel
(
final
boolean
inPlace
)
{
myPagingModel
=
createTableModel
(
myPagingModel
.
getRowCount
(),
myPagingModel
.
getColumnCount
());
UIUtil
.
invokeLaterIfNeeded
(()
->
{
myTable
.
setModel
(
myPagingModel
);
if
(!
inPlace
)
{
myComponent
.
getScrollPane
().
getViewport
().
setViewPosition
(
new
Point
(
0
,
0
));
}
((
AsyncArrayTableModel
)
myTable
.
getModel
()).
fireTableDataChanged
();
((
AsyncArrayTableModel
)
myTable
.
getModel
()).
fireTableCellUpdated
(
0
,
0
);
if
(
myTable
.
getColumnCount
()
>
0
)
{
myTable
.
setDefaultRenderer
(
myTable
.
getColumnClass
(
0
),
myTableCellRenderer
);
}
});
}
@NotNull
private
static
NumericContainerRendererForm
createForm
(
@NotNull
Project
project
,
KeyListener
resliceCallback
,
KeyAdapter
formatCallback
)
{
return
new
NumericContainerRendererForm
(
project
,
resliceCallback
,
formatCallback
);
}
protected
abstract
String
getTitlePresentation
(
String
slice
);
public
final
NumericContainerRendererForm
getComponent
()
{
return
myComponent
;
}
private
void
initComponent
()
{
myComponent
.
getColoredCheckbox
().
setEnabled
(
false
);
myComponent
.
getColoredCheckbox
().
addItemListener
(
e
->
{
if
(
e
.
getSource
()
==
myComponent
.
getColoredCheckbox
())
{
if
(
myTable
.
getRowCount
()
>
0
&&
myTable
.
getColumnCount
()
>
0
&&
myTable
.
getCellRenderer
(
0
,
0
)
instanceof
ColoredCellRenderer
)
{
ColoredCellRenderer
renderer
=
(
ColoredCellRenderer
)
myTable
.
getCellRenderer
(
0
,
0
);
if
(
myComponent
.
getColoredCheckbox
().
isSelected
())
{
renderer
.
setColored
(
true
);
}
else
{
renderer
.
setColored
(
false
);
}
}
if
(
myTableCellRenderer
!=
null
)
{
myTableCellRenderer
.
setColored
(
myComponent
.
getColoredCheckbox
().
isSelected
());
}
myComponent
.
getScrollPane
().
repaint
();
}
});
//make value name read-only
myComponent
.
getSliceTextField
().
addFocusListener
(
new
FocusListener
()
{
@Override
public
void
focusGained
(
FocusEvent
e
)
{
myComponent
.
getSliceTextField
().
getDocument
().
createGuardedBlock
(
0
,
getNodeFullName
().
length
());
}
@Override
public
void
focusLost
(
FocusEvent
e
)
{
RangeMarker
block
=
myComponent
.
getSliceTextField
().
getDocument
().
getRangeGuard
(
0
,
getNodeFullName
().
length
());
if
(
block
!=
null
)
{
myComponent
.
getSliceTextField
().
getDocument
().
removeGuardedBlock
(
block
);
}
}
});
}
public
PyDebugValue
getDebugValue
()
{
return
myValue
;
}
public
void
init
()
{
init
(
getDebugValue
().
getEvaluationExpression
(),
false
);
}
public
void
init
(
final
String
slice
,
final
boolean
inPlace
)
{
initComponent
();
myComponent
.
getSliceTextField
().
setText
(
slice
);
ApplicationManager
.
getApplication
().
executeOnPooledThread
(()
->
{
final
PyDebugValue
value
=
getDebugValue
();
PyDebugValue
parent
=
value
.
getParent
();
final
PyDebugValue
slicedValue
=
new
PyDebugValue
(
slice
,
value
.
getType
(),
null
,
value
.
getValue
(),
value
.
isContainer
(),
value
.
isReturnedVal
(),
value
.
isErrorOnEval
(),
parent
,
value
.
getFrameAccessor
());
final
String
format
=
getFormat
().
isEmpty
()
?
"%"
:
getFormat
();
try
{
initUi
(
value
.
getFrameAccessor
()
.
getArrayItems
(
slicedValue
,
0
,
0
,
-
1
,
-
1
,
format
),
inPlace
);
}
catch
(
PyDebuggerException
e
)
{
showError
(
e
.
getMessage
());
}
});
}
public
String
getSliceText
()
{
return
myComponent
.
getSliceTextField
().
getText
();
}
@Override
public
ArrayChunk
getChunk
(
int
rowOffset
,
int
colOffset
,
int
rows
,
int
cols
)
throws
PyDebuggerException
{
final
PyDebugValue
slicedValue
=
new
PyDebugValue
(
getSliceText
(),
myValue
.
getType
(),
myValue
.
getTypeQualifier
(),
myValue
.
getValue
(),
myValue
.
isContainer
(),
myValue
.
isErrorOnEval
(),
myValue
.
isReturnedVal
(),
myValue
.
getParent
(),
myValue
.
getFrameAccessor
());
return
myValue
.
getFrameAccessor
().
getArrayItems
(
slicedValue
,
rowOffset
,
colOffset
,
rows
,
cols
,
getFormat
());
}
public
abstract
boolean
isNumeric
();
@Override
public
final
String
correctStringValue
(
@NotNull
Object
value
)
{
if
(
value
instanceof
String
)
{
String
corrected
=
(
String
)
value
;
if
(
isNumeric
())
{
if
(
corrected
.
startsWith
(
"\'"
)
||
corrected
.
startsWith
(
"\""
))
{
corrected
=
corrected
.
substring
(
1
,
corrected
.
length
()
-
1
);
}
}
return
corrected
;
}
else
if
(
value
instanceof
Integer
)
{
return
Integer
.
toString
((
Integer
)
value
);
}
return
value
.
toString
();
}
@Override
public
final
void
showError
(
String
message
)
{
myDialog
.
setError
(
message
);
}
protected
final
void
doReslice
()
{
clearErrorMessage
();
init
(
getSliceText
(),
false
);
}
private
void
clearErrorMessage
()
{
showError
(
null
);
}
protected
final
void
doApplyFormat
()
{
reset
();
}
private
void
reset
()
{
clearErrorMessage
();
initTableModel
(
true
);
}
public
final
String
getNodeFullName
()
{
return
getDebugValue
().
getEvaluationExpression
();
}
public
final
String
getFormat
()
{
return
myComponent
.
getFormatTextField
().
getText
();
}
}
This diff is collapsed.
Click to expand it.
python/src/com/jetbrains/python/debugger/containerview/PyNumericViewUtil.java
0 → 100644
+
87
-
0
View file @
84dc26d1
/*
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
com.jetbrains.python.debugger.containerview
;
import
com.intellij.openapi.util.Pair
;
import
org.jetbrains.annotations.NotNull
;
import
java.awt.*
;
import
java.util.regex.Matcher
;
import
java.util.regex.Pattern
;
/**
* Created by Yuli Fiterman on 5/10/2016.
*/
public
class
PyNumericViewUtil
{
private
static
final
Pattern
PY_COMPLEX_NUMBER
=
Pattern
.
compile
(
"([+-]?[.\\d^j]*)([+-]?[e.\\d]*j)?"
);
/**
* @return double presentation from [0:1] range
*/
public
static
double
getRangedValue
(
String
value
,
String
type
,
double
min
,
double
max
,
String
complexMax
,
String
complexMin
)
{
if
(
"iuf"
.
contains
(
type
))
{
return
(
Double
.
parseDouble
(
value
)
-
min
)
/
(
max
-
min
);
}
else
if
(
"b"
.
equals
(
type
))
{
return
value
.
equals
(
"True"
)
?
1
:
0
;
}
else
if
(
"c"
.
equals
(
type
))
{
return
getComplexRangedValue
(
value
,
complexMax
,
complexMin
);
}
return
0
;
}
public
static
Color
rangedValueToColor
(
double
rangedValue
)
{
//noinspection UseJBColor
return
new
Color
((
int
)
Math
.
round
(
255
*
rangedValue
),
0
,
(
int
)
Math
.
round
(
255
*
(
1
-
rangedValue
)),
130
);
}
/**
* type complex128 in numpy is compared by next rule:
* A + Bj > C +Dj if A > C or A == C and B > D
*/
private
static
double
getComplexRangedValue
(
String
value
,
String
complexMax
,
String
complexMin
)
{
Pair
<
Double
,
Double
>
med
=
parsePyComplex
(
value
);
Pair
<
Double
,
Double
>
max
=
parsePyComplex
(
complexMax
);
Pair
<
Double
,
Double
>
min
=
parsePyComplex
(
complexMin
);
double
range
=
(
med
.
first
-
min
.
first
)
/
(
max
.
first
-
min
.
first
);
if
(
max
.
first
.
equals
(
min
.
first
))
{
range
=
(
med
.
second
-
min
.
second
)
/
(
max
.
second
-
min
.
second
);
}
return
range
;
}
private
static
Pair
<
Double
,
Double
>
parsePyComplex
(
@NotNull
String
pyComplexValue
)
{
if
(
pyComplexValue
.
startsWith
(
"("
)
&&
pyComplexValue
.
endsWith
(
")"
))
{
pyComplexValue
=
pyComplexValue
.
substring
(
1
,
pyComplexValue
.
length
()
-
1
);
}
Matcher
matcher
=
PY_COMPLEX_NUMBER
.
matcher
(
pyComplexValue
);
if
(
matcher
.
matches
())
{
String
real
=
matcher
.
group
(
1
);
String
imag
=
matcher
.
group
(
2
);
if
(
real
.
contains
(
"j"
)
&&
imag
==
null
)
{
return
new
Pair
<>(
new
Double
(
0.0
),
Double
.
parseDouble
(
real
.
substring
(
0
,
real
.
length
()
-
1
)));
}
else
{
return
new
Pair
<>(
Double
.
parseDouble
(
real
),
Double
.
parseDouble
(
imag
.
substring
(
0
,
imag
.
length
()
-
1
)));
}
}
else
{
throw
new
IllegalArgumentException
(
"Not a valid python complex value: "
+
pyComplexValue
);
}
}
}
This diff is collapsed.
Click to expand it.
python/src/com/jetbrains/python/debugger/
array/PyViewArray
Action.java
→
python/src/com/jetbrains/python/debugger/
containerview/PyViewNumericContainer
Action.java
+
38
-
51
View file @
84dc26d1
/*
* Copyright 2000-201
4
JetBrains s.r.o.
* Copyright 2000-201
6
JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
...
...
@@ -13,33 +13,53 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
com.jetbrains.python.debugger.
array
;
package
com.jetbrains.python.debugger.
containerview
;
import
com.intellij.openapi.actionSystem.AnActionEvent
;
import
com.intellij.openapi.actionSystem.DataContext
;
import
com.intellij.openapi.project.Project
;
import
com.intellij.openapi.ui.DialogWrapper
;
import
com.intellij.xdebugger.impl.ui.tree.XDebuggerTree
;
import
com.intellij.xdebugger.impl.ui.tree.actions.XDebuggerTreeActionBase
;
import
com.intellij.xdebugger.impl.ui.tree.nodes.XValueNodeImpl
;
import
com.jetbrains.python.debugger.PyDebugValue
;
import
com.jetbrains.python.debugger.array.NumpyArrayTable
;
import
com.jetbrains.python.debugger.dataframe.DataFrameTable
;
import
org.jetbrains.annotations.NotNull
;
import
org.jetbrains.annotations.Nullable
;
import
javax.swing.*
;
import
javax.swing.tree.TreePath
;
/**
* @author amarch
*/
public
class
PyView
Array
Action
extends
XDebuggerTreeActionBase
{
public
class
PyView
NumericContainer
Action
extends
XDebuggerTreeActionBase
{
@Override
protected
void
perform
(
XValueNodeImpl
node
,
@NotNull
String
nodeName
,
AnActionEvent
e
)
{
Project
p
=
e
.
getProject
();
if
(
p
!=
null
&&
node
!=
null
&&
node
.
getValueContainer
()
instanceof
PyDebugValue
&&
node
.
isComputed
())
{
final
ViewArrayDialog
dialog
=
new
ViewArrayDialog
(
p
,
(
PyDebugValue
)(
node
.
getValueContainer
()));
PyDebugValue
debugValue
=
(
PyDebugValue
)
node
.
getValueContainer
();
String
nodeType
=
debugValue
.
getType
();
final
ViewNumericContainerDialog
dialog
;
if
(
"ndarray"
.
equals
(
nodeType
))
{
dialog
=
new
ViewNumericContainerDialog
(
p
,
(
dialogWrapper
)
->
{
NumpyArrayTable
arrayTable
=
new
NumpyArrayTable
(
p
,
dialogWrapper
,
debugValue
);
arrayTable
.
init
();
return
arrayTable
.
getComponent
().
getMainPanel
();
});
}
else
if
((
"DataFrame"
.
equals
(
nodeType
)))
{
dialog
=
new
ViewNumericContainerDialog
(
p
,
(
dialogWrapper
)
->
{
DataFrameTable
dataFrameTable
=
new
DataFrameTable
(
p
,
dialogWrapper
,
debugValue
);
dataFrameTable
.
init
();
return
dataFrameTable
.
getComponent
().
getMainPanel
();
});
}
else
{
throw
new
IllegalStateException
(
"Cannot render node type: "
+
nodeType
);
}
dialog
.
show
();
}
}
...
...
@@ -65,54 +85,21 @@ public class PyViewArrayAction extends XDebuggerTreeActionBase {
String
nodeType
=
debugValue
.
getType
();
if
(
"ndarray"
.
equals
(
nodeType
))
{
e
.
getPresentation
().
setText
(
"View as Array"
);
e
.
getPresentation
().
setVisible
(
true
);
return
;
}
else
if
((
"DataFrame"
.
equals
(
nodeType
)))
{
e
.
getPresentation
().
setText
(
"View as DataFrame"
);
e
.
getPresentation
().
setVisible
(
true
);
}
else
{
e
.
getPresentation
().
setVisible
(
false
);
}
}
}
e
.
getPresentation
().
setVisible
(
false
);
}
protected
static
class
ViewArrayDialog
extends
DialogWrapper
{
private
Project
myProject
;
private
NumpyArrayTable
myNumpyArrayTable
;
private
ViewArrayDialog
(
@NotNull
Project
project
,
PyDebugValue
debugValue
)
{
super
(
project
,
false
);
setModal
(
false
);
setCancelButtonText
(
"Close"
);
setCrossClosesWindow
(
true
);
myProject
=
project
;
myNumpyArrayTable
=
new
NumpyArrayTable
(
myProject
,
this
,
debugValue
);
myNumpyArrayTable
.
init
();
init
();
}
public
void
setError
(
String
text
)
{
//todo: think about this usage
setErrorText
(
text
);
}
@Override
@NotNull
protected
Action
[]
createActions
()
{
return
new
Action
[]{
getCancelAction
()};
}
@Override
protected
String
getDimensionServiceKey
()
{
return
"#com.jetbrains.python.actions.view.array.PyViewArrayAction"
;
}
@Override
protected
JComponent
createCenterPanel
()
{
return
myNumpyArrayTable
.
getComponent
().
getMainPanel
();
}
public
ArrayTableForm
getComponent
()
{
return
myNumpyArrayTable
.
getComponent
();
else
{
e
.
getPresentation
().
setVisible
(
false
);
}
}
}
}
This diff is collapsed.
Click to expand it.
python/src/com/jetbrains/python/debugger/containerview/ViewNumericContainerDialog.java
0 → 100644
+
60
-
0
View file @
84dc26d1
/*
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
com.jetbrains.python.debugger.containerview
;
import
com.intellij.openapi.project.Project
;
import
com.intellij.openapi.ui.DialogWrapper
;
import
org.jetbrains.annotations.NotNull
;
import
javax.swing.*
;
import
java.util.function.Function
;
/**
* Created by Yuli Fiterman on 5/10/2016.
*/
public
class
ViewNumericContainerDialog
extends
DialogWrapper
{
private
final
JComponent
myMainPanel
;
ViewNumericContainerDialog
(
@NotNull
Project
project
,
Function
<
ViewNumericContainerDialog
,
JComponent
>
tableSupplier
)
{
super
(
project
,
false
);
setModal
(
false
);
setCancelButtonText
(
"Close"
);
setCrossClosesWindow
(
true
);
myMainPanel
=
tableSupplier
.
apply
(
this
);
init
();
}
public
void
setError
(
String
text
)
{
//todo: think about this usage
setErrorText
(
text
);
}
@Override
@NotNull
protected
Action
[]
createActions
()
{
return
new
Action
[]{
getCancelAction
()};
}
@Override
protected
String
getDimensionServiceKey
()
{
return
"#com.jetbrains.python.actions.view.array.PyViewNumericContainerAction"
;
}
@Override
protected
JComponent
createCenterPanel
()
{
return
myMainPanel
;
}
}
This diff is collapsed.
Click to expand it.
python/src/com/jetbrains/python/debugger/dataframe/DataFrameTable.java
0 → 100644
+
64
-
0
View file @
84dc26d1
/*
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
com.jetbrains.python.debugger.dataframe
;
import
com.intellij.openapi.project.Project
;
import
com.intellij.util.ui.UIUtil
;
import
com.jetbrains.python.debugger.*
;
import
com.jetbrains.python.debugger.array.AsyncArrayTableModel
;
import
com.jetbrains.python.debugger.containerview.ColoredCellRenderer
;
import
com.jetbrains.python.debugger.containerview.NumericContainerViewTable
;
import
com.jetbrains.python.debugger.array.TableChunkDatasource
;
import
com.jetbrains.python.debugger.containerview.NumericContainerRendererForm
;
import
com.jetbrains.python.debugger.containerview.ViewNumericContainerDialog
;
import
org.jetbrains.annotations.NotNull
;
import
java.awt.*
;
import
java.awt.event.*
;
/**
* @author amarch
*/
/* A bunch of this is copied from NumpyArrayTable*/
public
class
DataFrameTable
extends
NumericContainerViewTable
implements
TableChunkDatasource
{
private
Project
myProject
;
public
DataFrameTable
(
@NotNull
Project
project
,
@NotNull
ViewNumericContainerDialog
dialog
,
@NotNull
PyDebugValue
value
)
{
super
(
project
,
dialog
,
value
);
}
@Override
protected
AsyncArrayTableModel
createTableModel
(
int
rowCount
,
int
columnCount
)
{
return
new
DataFrameTableModel
(
rowCount
,
columnCount
,
this
);
}
@Override
protected
ColoredCellRenderer
createCellRenderer
(
double
minValue
,
double
maxValue
,
ArrayChunk
chunk
)
{
return
new
DataFrameTableCellRenderer
();
}
@Override
public
boolean
isNumeric
()
{
return
true
;
}
protected
final
String
getTitlePresentation
(
String
slice
)
{
return
"DataFrame View: "
+
slice
;
}
}
This diff is collapsed.
Click to expand it.
Prev
1
2
Next
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment