Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
小 白蛋
Intellij Community
Commits
ab427880
Commit
ab427880
authored
10 years ago
by
Dmitry Batrak
Browse files
Options
Download
Email Patches
Plain Diff
IDEA-125021 Improve multi-caret copy-paste logic
parent
86622599
Changes
9
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
platform/lang-impl/src/com/intellij/codeInsight/editorActions/CopyHandler.java
+4
-3
...c/com/intellij/codeInsight/editorActions/CopyHandler.java
platform/platform-api/src/com/intellij/codeInsight/editorActions/TextBlockTransferable.java
+1
-1
...llij/codeInsight/editorActions/TextBlockTransferable.java
platform/platform-api/src/com/intellij/codeInsight/editorActions/TextBlockTransferableData.java
+1
-1
.../codeInsight/editorActions/TextBlockTransferableData.java
platform/platform-api/src/com/intellij/openapi/editor/CaretStateTransferableData.java
+56
-0
...m/intellij/openapi/editor/CaretStateTransferableData.java
platform/platform-api/src/com/intellij/openapi/editor/ClipboardTextPerCaretSplitter.java
+15
-3
...ntellij/openapi/editor/ClipboardTextPerCaretSplitter.java
platform/platform-api/src/com/intellij/openapi/editor/CopyPasteSupport.java
+212
-0
...api/src/com/intellij/openapi/editor/CopyPasteSupport.java
platform/platform-api/src/com/intellij/openapi/editor/EditorModificationUtil.java
+11
-144
...c/com/intellij/openapi/editor/EditorModificationUtil.java
platform/platform-impl/src/com/intellij/openapi/editor/impl/SelectionModelImpl.java
+1
-10
.../com/intellij/openapi/editor/impl/SelectionModelImpl.java
platform/platform-tests/testSrc/com/intellij/openapi/editor/EditorMultiCaretTest.java
+32
-0
...Src/com/intellij/openapi/editor/EditorMultiCaretTest.java
with
333 additions
and
162 deletions
+333
-162
platform/lang-impl/src/com/intellij/codeInsight/editorActions/CopyHandler.java
+
4
-
3
View file @
ab427880
...
...
@@ -37,8 +37,6 @@ import java.util.ArrayList;
import
java.util.List
;
public
class
CopyHandler
extends
EditorActionHandler
{
private
static
final
Logger
LOG
=
Logger
.
getInstance
(
CopyHandler
.
class
);
private
final
EditorActionHandler
myOriginalAction
;
public
CopyHandler
(
final
EditorActionHandler
originalHandler
)
{
...
...
@@ -93,7 +91,10 @@ public class CopyHandler extends EditorActionHandler {
transferableDatas
.
addAll
(
processor
.
collectTransferableData
(
file
,
editor
,
startOffsets
,
endOffsets
));
}
String
rawText
=
TextBlockTransferable
.
convertLineSeparators
(
selectionModel
.
getSelectedText
(
true
),
"\n"
,
transferableDatas
);
String
text
=
editor
.
getCaretModel
().
supportsMultipleCarets
()
?
CopyPasteSupport
.
getSelectedTextForClipboard
(
editor
,
transferableDatas
)
:
selectionModel
.
getSelectedText
();
String
rawText
=
TextBlockTransferable
.
convertLineSeparators
(
text
,
"\n"
,
transferableDatas
);
String
escapedText
=
null
;
for
(
CopyPastePreProcessor
processor
:
Extensions
.
getExtensions
(
CopyPastePreProcessor
.
EP_NAME
))
{
escapedText
=
processor
.
preprocessOnCopy
(
file
,
startOffsets
,
endOffsets
,
rawText
);
...
...
This diff is collapsed.
Click to expand it.
platform/la
ng-impl
/src/com/intellij/codeInsight/editorActions/TextBlockTransferable.java
→
platform/
p
la
tform-api
/src/com/intellij/codeInsight/editorActions/TextBlockTransferable.java
+
1
-
1
View file @
ab427880
...
...
@@ -30,7 +30,7 @@ import java.util.Collection;
import
java.util.Collections
;
import
java.util.List
;
class
TextBlockTransferable
implements
Transferable
{
public
class
TextBlockTransferable
implements
Transferable
{
private
final
Collection
<
TextBlockTransferableData
>
myExtraData
;
private
final
RawText
myRawText
;
private
final
String
myText
;
...
...
This diff is collapsed.
Click to expand it.
platform/la
ng-impl
/src/com/intellij/codeInsight/editorActions/TextBlockTransferableData.java
→
platform/
p
la
tform-api
/src/com/intellij/codeInsight/editorActions/TextBlockTransferableData.java
+
1
-
1
View file @
ab427880
/*
* Copyright 2000-20
09
JetBrains s.r.o.
* Copyright 2000-20
14
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.
...
...
This diff is collapsed.
Click to expand it.
platform/platform-api/src/com/intellij/openapi/editor/CaretStateTransferableData.java
0 → 100644
+
56
-
0
View file @
ab427880
/*
* Copyright 2000-2014 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.intellij.openapi.editor
;
import
com.intellij.codeInsight.editorActions.TextBlockTransferableData
;
import
java.awt.datatransfer.DataFlavor
;
public
class
CaretStateTransferableData
implements
TextBlockTransferableData
{
public
static
final
DataFlavor
FLAVOR
=
new
DataFlavor
(
CaretStateTransferableData
.
class
,
"Caret state"
);
public
final
int
[]
startOffsets
;
public
final
int
[]
endOffsets
;
public
CaretStateTransferableData
(
int
[]
startOffsets
,
int
[]
endOffsets
)
{
this
.
startOffsets
=
startOffsets
;
this
.
endOffsets
=
endOffsets
;
}
@Override
public
DataFlavor
getFlavor
()
{
return
FLAVOR
;
}
@Override
public
int
getOffsetCount
()
{
return
startOffsets
.
length
+
endOffsets
.
length
;
}
@Override
public
int
getOffsets
(
int
[]
offsets
,
int
index
)
{
System
.
arraycopy
(
startOffsets
,
0
,
offsets
,
index
,
startOffsets
.
length
);
System
.
arraycopy
(
endOffsets
,
0
,
offsets
,
index
+
startOffsets
.
length
,
endOffsets
.
length
);
return
index
+
getOffsetCount
();
}
@Override
public
int
setOffsets
(
int
[]
offsets
,
int
index
)
{
System
.
arraycopy
(
offsets
,
index
,
startOffsets
,
0
,
startOffsets
.
length
);
System
.
arraycopy
(
offsets
,
index
+
startOffsets
.
length
,
endOffsets
,
0
,
endOffsets
.
length
);
return
index
+
getOffsetCount
();
}
}
This diff is collapsed.
Click to expand it.
platform/platform-api/src/com/intellij/openapi/editor/ClipboardTextPerCaretSplitter.java
+
15
-
3
View file @
ab427880
...
...
@@ -15,12 +15,16 @@
*/
package
com.intellij.openapi.editor
;
import
org.jetbrains.annotations.NotNull
;
import
org.jetbrains.annotations.Nullable
;
import
java.util.ArrayList
;
import
java.util.Collections
;
import
java.util.List
;
public
class
ClipboardTextPerCaretSplitter
{
public
List
<
String
>
split
(
String
input
,
int
caretCount
)
{
@NotNull
public
List
<
String
>
split
(
@NotNull
String
input
,
@Nullable
CaretStateTransferableData
caretData
,
int
caretCount
)
{
if
(
caretCount
<=
0
)
{
throw
new
IllegalArgumentException
(
"Caret count must be positive"
);
}
...
...
@@ -28,9 +32,17 @@ public class ClipboardTextPerCaretSplitter {
return
Collections
.
singletonList
(
input
);
}
List
<
String
>
result
=
new
ArrayList
<
String
>(
caretCount
);
String
[]
lines
=
input
.
split
(
"\n"
,
-
1
);
int
sourceCaretCount
=
caretData
==
null
?
-
1
:
caretData
.
startOffsets
.
length
;
String
[]
lines
=
sourceCaretCount
==
1
||
sourceCaretCount
==
caretCount
?
null
:
input
.
split
(
"\n"
,
-
1
);
for
(
int
i
=
0
;
i
<
caretCount
;
i
++)
{
if
(
lines
.
length
==
0
)
{
if
(
sourceCaretCount
==
1
)
{
result
.
add
(
input
);
}
else
if
(
sourceCaretCount
==
caretCount
)
{
//noinspection ConstantConditions
result
.
add
(
new
String
(
input
.
substring
(
caretData
.
startOffsets
[
i
],
caretData
.
endOffsets
[
i
])));
}
else
if
(
lines
.
length
==
0
)
{
result
.
add
(
""
);
}
else
if
(
lines
.
length
==
1
)
{
...
...
This diff is collapsed.
Click to expand it.
platform/platform-api/src/com/intellij/openapi/editor/CopyPasteSupport.java
0 → 100644
+
212
-
0
View file @
ab427880
/*
* Copyright 2000-2014 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.intellij.openapi.editor
;
import
com.intellij.codeInsight.editorActions.TextBlockTransferable
;
import
com.intellij.codeInsight.editorActions.TextBlockTransferableData
;
import
com.intellij.openapi.application.ApplicationManager
;
import
com.intellij.openapi.diagnostic.Logger
;
import
com.intellij.openapi.ide.CopyPasteManager
;
import
com.intellij.openapi.util.TextRange
;
import
com.intellij.openapi.util.text.LineTokenizer
;
import
com.intellij.util.Producer
;
import
org.jetbrains.annotations.NotNull
;
import
org.jetbrains.annotations.Nullable
;
import
java.awt.datatransfer.DataFlavor
;
import
java.awt.datatransfer.StringSelection
;
import
java.awt.datatransfer.Transferable
;
import
java.awt.datatransfer.UnsupportedFlavorException
;
import
java.io.IOException
;
import
java.util.ArrayList
;
import
java.util.Collection
;
import
java.util.Iterator
;
import
java.util.List
;
public
class
CopyPasteSupport
{
private
static
final
Logger
LOG
=
Logger
.
getInstance
(
CopyPasteSupport
.
class
);
private
CopyPasteSupport
()
{
}
public
static
void
copySelectionToClipboard
(
@NotNull
Editor
editor
)
{
ApplicationManager
.
getApplication
().
assertIsDispatchThread
();
List
<
TextBlockTransferableData
>
extraData
=
new
ArrayList
<
TextBlockTransferableData
>();
String
s
=
editor
.
getCaretModel
().
supportsMultipleCarets
()
?
getSelectedTextForClipboard
(
editor
,
extraData
)
:
editor
.
getSelectionModel
().
getSelectedText
();
if
(
s
==
null
)
return
;
s
=
TextBlockTransferable
.
convertLineSeparators
(
s
,
"\n"
,
extraData
);
Transferable
contents
=
editor
.
getCaretModel
().
supportsMultipleCarets
()
?
new
TextBlockTransferable
(
s
,
extraData
,
null
)
:
new
StringSelection
(
s
);
CopyPasteManager
.
getInstance
().
setContents
(
contents
);
}
public
static
String
getSelectedTextForClipboard
(
@NotNull
Editor
editor
,
@NotNull
Collection
<
TextBlockTransferableData
>
extraDataCollector
)
{
final
StringBuilder
buf
=
new
StringBuilder
();
String
separator
=
""
;
List
<
Caret
>
carets
=
editor
.
getCaretModel
().
getAllCarets
();
int
[]
startOffsets
=
new
int
[
carets
.
size
()];
int
[]
endOffsets
=
new
int
[
carets
.
size
()];
for
(
int
i
=
0
;
i
<
carets
.
size
();
i
++)
{
buf
.
append
(
separator
);
String
caretSelectedText
=
carets
.
get
(
i
).
getSelectedText
();
startOffsets
[
i
]
=
buf
.
length
();
if
(
caretSelectedText
!=
null
)
{
buf
.
append
(
caretSelectedText
);
}
endOffsets
[
i
]
=
buf
.
length
();
separator
=
"\n"
;
}
extraDataCollector
.
add
(
new
CaretStateTransferableData
(
startOffsets
,
endOffsets
));
return
buf
.
toString
();
}
public
static
TextRange
pasteFromClipboard
(
Editor
editor
)
{
return
pasteTransferable
(
editor
,
(
Producer
<
Transferable
>)
null
);
}
public
static
TextRange
pasteTransferable
(
Editor
editor
,
final
Transferable
content
)
{
return
pasteTransferable
(
editor
,
new
Producer
<
Transferable
>()
{
@Nullable
@Override
public
Transferable
produce
()
{
return
content
;
}
});
}
@Nullable
public
static
TextRange
pasteTransferable
(
final
Editor
editor
,
@Nullable
Producer
<
Transferable
>
producer
)
{
Transferable
content
=
getTransferable
(
producer
);
if
(
content
==
null
)
return
null
;
String
text
=
getStringContent
(
content
);
if
(
text
==
null
)
return
null
;
if
(
editor
.
getCaretModel
().
supportsMultipleCarets
())
{
int
caretCount
=
editor
.
getCaretModel
().
getCaretCount
();
if
(
caretCount
==
1
&&
editor
.
isColumnMode
())
{
int
pastedLineCount
=
LineTokenizer
.
calcLineCount
(
text
,
true
);
EditorModificationUtil
.
deleteSelectedText
(
editor
);
Caret
caret
=
editor
.
getCaretModel
().
getPrimaryCaret
();
for
(
int
i
=
0
;
i
<
pastedLineCount
-
1
;
i
++)
{
caret
=
caret
.
clone
(
false
);
if
(
caret
==
null
)
{
break
;
}
}
caretCount
=
editor
.
getCaretModel
().
getCaretCount
();
}
CaretStateTransferableData
caretData
=
null
;
try
{
caretData
=
content
.
isDataFlavorSupported
(
CaretStateTransferableData
.
FLAVOR
)
?
(
CaretStateTransferableData
)
content
.
getTransferData
(
CaretStateTransferableData
.
FLAVOR
)
:
null
;
}
catch
(
Exception
e
)
{
LOG
.
error
(
e
);
}
final
Iterator
<
String
>
segments
=
new
ClipboardTextPerCaretSplitter
().
split
(
text
,
caretData
,
caretCount
).
iterator
();
editor
.
getCaretModel
().
runForEachCaret
(
new
CaretAction
()
{
@Override
public
void
perform
(
Caret
caret
)
{
EditorModificationUtil
.
insertStringAtCaret
(
editor
,
segments
.
next
(),
false
,
true
);
}
});
return
null
;
}
else
{
int
caretOffset
=
editor
.
getCaretModel
().
getOffset
();
EditorModificationUtil
.
insertStringAtCaret
(
editor
,
text
,
false
,
true
);
return
new
TextRange
(
caretOffset
,
caretOffset
+
text
.
length
());
}
}
public
static
void
pasteTransferableAsBlock
(
Editor
editor
,
@Nullable
Producer
<
Transferable
>
producer
)
{
Transferable
content
=
getTransferable
(
producer
);
if
(
content
==
null
)
return
;
String
text
=
getStringContent
(
content
);
if
(
text
==
null
)
return
;
int
caretLine
=
editor
.
getCaretModel
().
getLogicalPosition
().
line
;
int
originalCaretLine
=
caretLine
;
int
selectedLinesCount
=
0
;
final
SelectionModel
selectionModel
=
editor
.
getSelectionModel
();
if
(
selectionModel
.
hasBlockSelection
())
{
final
LogicalPosition
start
=
selectionModel
.
getBlockStart
();
final
LogicalPosition
end
=
selectionModel
.
getBlockEnd
();
assert
start
!=
null
;
assert
end
!=
null
;
LogicalPosition
caret
=
new
LogicalPosition
(
Math
.
min
(
start
.
line
,
end
.
line
),
Math
.
min
(
start
.
column
,
end
.
column
));
selectedLinesCount
=
Math
.
abs
(
end
.
line
-
start
.
line
);
caretLine
=
caret
.
line
;
EditorModificationUtil
.
deleteSelectedText
(
editor
);
editor
.
getCaretModel
().
moveToLogicalPosition
(
caret
);
}
LogicalPosition
caretToRestore
=
editor
.
getCaretModel
().
getLogicalPosition
();
String
[]
lines
=
LineTokenizer
.
tokenize
(
text
.
toCharArray
(),
false
);
if
(
lines
.
length
>
1
||
selectedLinesCount
==
0
)
{
int
longestLineLength
=
0
;
for
(
int
i
=
0
;
i
<
lines
.
length
;
i
++)
{
String
line
=
lines
[
i
];
longestLineLength
=
Math
.
max
(
longestLineLength
,
line
.
length
());
editor
.
getCaretModel
().
moveToLogicalPosition
(
new
LogicalPosition
(
caretLine
+
i
,
caretToRestore
.
column
));
EditorModificationUtil
.
insertStringAtCaret
(
editor
,
line
,
false
,
true
);
}
caretToRestore
=
new
LogicalPosition
(
originalCaretLine
,
caretToRestore
.
column
+
longestLineLength
);
}
else
{
for
(
int
i
=
0
;
i
<=
selectedLinesCount
;
i
++)
{
editor
.
getCaretModel
().
moveToLogicalPosition
(
new
LogicalPosition
(
caretLine
+
i
,
caretToRestore
.
column
));
EditorModificationUtil
.
insertStringAtCaret
(
editor
,
text
,
false
,
true
);
}
caretToRestore
=
new
LogicalPosition
(
originalCaretLine
,
caretToRestore
.
column
+
text
.
length
());
}
editor
.
getCaretModel
().
moveToLogicalPosition
(
caretToRestore
);
EditorModificationUtil
.
zeroWidthBlockSelectionAtCaretColumn
(
editor
,
caretLine
,
caretLine
+
selectedLinesCount
);
}
@Nullable
private
static
String
getStringContent
(
@NotNull
Transferable
content
)
{
RawText
raw
=
RawText
.
fromTransferable
(
content
);
if
(
raw
!=
null
)
return
raw
.
rawText
;
try
{
return
(
String
)
content
.
getTransferData
(
DataFlavor
.
stringFlavor
);
}
catch
(
UnsupportedFlavorException
ignore
)
{
}
catch
(
IOException
ignore
)
{
}
return
null
;
}
private
static
Transferable
getTransferable
(
Producer
<
Transferable
>
producer
)
{
Transferable
content
=
null
;
if
(
producer
!=
null
)
{
content
=
producer
.
produce
();
}
else
{
CopyPasteManager
manager
=
CopyPasteManager
.
getInstance
();
if
(
manager
.
areDataFlavorsAvailable
(
DataFlavor
.
stringFlavor
))
{
content
=
manager
.
getContents
();
}
}
return
content
;
}
}
This diff is collapsed.
Click to expand it.
platform/platform-api/src/com/intellij/openapi/editor/EditorModificationUtil.java
+
11
-
144
View file @
ab427880
...
...
@@ -19,20 +19,14 @@ import com.intellij.codeStyle.CodeStyleFacade;
import
com.intellij.openapi.editor.actionSystem.EditorActionManager
;
import
com.intellij.openapi.editor.event.DocumentEvent
;
import
com.intellij.openapi.editor.event.MockDocumentEvent
;
import
com.intellij.openapi.ide.CopyPasteManager
;
import
com.intellij.openapi.project.Project
;
import
com.intellij.openapi.util.TextRange
;
import
com.intellij.openapi.util.text.LineTokenizer
;
import
com.intellij.psi.PsiDocumentManager
;
import
com.intellij.util.Producer
;
import
org.jetbrains.annotations.NotNull
;
import
org.jetbrains.annotations.Nullable
;
import
java.awt.datatransfer.DataFlavor
;
import
java.awt.datatransfer.Transferable
;
import
java.awt.datatransfer.UnsupportedFlavorException
;
import
java.io.IOException
;
import
java.util.Iterator
;
import
java.util.List
;
public
class
EditorModificationUtil
{
...
...
@@ -99,7 +93,7 @@ public class EditorModificationUtil {
zeroWidthBlockSelectionAtCaretColumn
(
editor
,
startLine
,
endLine
);
}
p
rivate
static
void
zeroWidthBlockSelectionAtCaretColumn
(
final
Editor
editor
,
final
int
startLine
,
final
int
endLine
)
{
p
ublic
static
void
zeroWidthBlockSelectionAtCaretColumn
(
final
Editor
editor
,
final
int
startLine
,
final
int
endLine
)
{
int
caretColumn
=
editor
.
getCaretModel
().
getLogicalPosition
().
column
;
editor
.
getSelectionModel
().
setBlockSelection
(
new
LogicalPosition
(
startLine
,
caretColumn
),
new
LogicalPosition
(
endLine
,
caretColumn
));
}
...
...
@@ -181,112 +175,21 @@ public class EditorModificationUtil {
return
offset
;
}
/**
* @deprecated Use {@link com.intellij.openapi.editor.CopyPasteSupport#pasteTransferable(Editor, com.intellij.util.Producer)} instead.
* (to remove in IDEA 15)
*/
@Nullable
public
static
TextRange
pasteTransferable
(
final
Editor
editor
,
@Nullable
Producer
<
Transferable
>
producer
)
{
String
text
=
getStringContent
(
producer
);
if
(
text
==
null
)
return
null
;
if
(
editor
.
getCaretModel
().
supportsMultipleCarets
())
{
int
caretCount
=
editor
.
getCaretModel
().
getCaretCount
();
if
(
caretCount
==
1
&&
editor
.
isColumnMode
())
{
int
pastedLineCount
=
LineTokenizer
.
calcLineCount
(
text
,
true
);
deleteSelectedText
(
editor
);
Caret
caret
=
editor
.
getCaretModel
().
getPrimaryCaret
();
for
(
int
i
=
0
;
i
<
pastedLineCount
-
1
;
i
++)
{
caret
=
caret
.
clone
(
false
);
if
(
caret
==
null
)
{
break
;
}
}
caretCount
=
editor
.
getCaretModel
().
getCaretCount
();
}
final
Iterator
<
String
>
segments
=
new
ClipboardTextPerCaretSplitter
().
split
(
text
,
caretCount
).
iterator
();
editor
.
getCaretModel
().
runForEachCaret
(
new
CaretAction
()
{
@Override
public
void
perform
(
Caret
caret
)
{
insertStringAtCaret
(
editor
,
segments
.
next
(),
false
,
true
);
}
});
return
null
;
}
else
{
int
caretOffset
=
editor
.
getCaretModel
().
getOffset
();
insertStringAtCaret
(
editor
,
text
,
false
,
true
);
return
new
TextRange
(
caretOffset
,
caretOffset
+
text
.
length
());
}
return
CopyPasteSupport
.
pasteTransferable
(
editor
,
producer
);
}
/**
* @deprecated Use {@link com.intellij.openapi.editor.CopyPasteSupport#pasteTransferableAsBlock(Editor, com.intellij.util.Producer)} instead.
* (to remove in IDEA 15)
*/
public
static
void
pasteTransferableAsBlock
(
Editor
editor
,
@Nullable
Producer
<
Transferable
>
producer
)
{
String
text
=
getStringContent
(
producer
);
if
(
text
==
null
)
return
;
int
caretLine
=
editor
.
getCaretModel
().
getLogicalPosition
().
line
;
int
originalCaretLine
=
caretLine
;
int
selectedLinesCount
=
0
;
final
SelectionModel
selectionModel
=
editor
.
getSelectionModel
();
if
(
selectionModel
.
hasBlockSelection
())
{
final
LogicalPosition
start
=
selectionModel
.
getBlockStart
();
final
LogicalPosition
end
=
selectionModel
.
getBlockEnd
();
assert
start
!=
null
;
assert
end
!=
null
;
LogicalPosition
caret
=
new
LogicalPosition
(
Math
.
min
(
start
.
line
,
end
.
line
),
Math
.
min
(
start
.
column
,
end
.
column
));
selectedLinesCount
=
Math
.
abs
(
end
.
line
-
start
.
line
);
caretLine
=
caret
.
line
;
deleteSelectedText
(
editor
);
editor
.
getCaretModel
().
moveToLogicalPosition
(
caret
);
}
LogicalPosition
caretToRestore
=
editor
.
getCaretModel
().
getLogicalPosition
();
String
[]
lines
=
LineTokenizer
.
tokenize
(
text
.
toCharArray
(),
false
);
if
(
lines
.
length
>
1
||
selectedLinesCount
==
0
)
{
int
longestLineLength
=
0
;
for
(
int
i
=
0
;
i
<
lines
.
length
;
i
++)
{
String
line
=
lines
[
i
];
longestLineLength
=
Math
.
max
(
longestLineLength
,
line
.
length
());
editor
.
getCaretModel
().
moveToLogicalPosition
(
new
LogicalPosition
(
caretLine
+
i
,
caretToRestore
.
column
));
insertStringAtCaret
(
editor
,
line
,
false
,
true
);
}
caretToRestore
=
new
LogicalPosition
(
originalCaretLine
,
caretToRestore
.
column
+
longestLineLength
);
}
else
{
for
(
int
i
=
0
;
i
<=
selectedLinesCount
;
i
++)
{
editor
.
getCaretModel
().
moveToLogicalPosition
(
new
LogicalPosition
(
caretLine
+
i
,
caretToRestore
.
column
));
insertStringAtCaret
(
editor
,
text
,
false
,
true
);
}
caretToRestore
=
new
LogicalPosition
(
originalCaretLine
,
caretToRestore
.
column
+
text
.
length
());
}
editor
.
getCaretModel
().
moveToLogicalPosition
(
caretToRestore
);
zeroWidthBlockSelectionAtCaretColumn
(
editor
,
caretLine
,
caretLine
+
selectedLinesCount
);
}
@Nullable
private
static
String
getStringContent
(
@Nullable
Producer
<
Transferable
>
producer
)
{
Transferable
content
=
null
;
if
(
producer
!=
null
)
{
content
=
producer
.
produce
();
}
else
{
CopyPasteManager
manager
=
CopyPasteManager
.
getInstance
();
if
(
manager
.
areDataFlavorsAvailable
(
DataFlavor
.
stringFlavor
))
{
content
=
manager
.
getContents
();
}
}
if
(
content
==
null
)
return
null
;
RawText
raw
=
RawText
.
fromTransferable
(
content
);
if
(
raw
!=
null
)
return
raw
.
rawText
;
try
{
return
(
String
)
content
.
getTransferData
(
DataFlavor
.
stringFlavor
);
}
catch
(
UnsupportedFlavorException
ignore
)
{
}
catch
(
IOException
ignore
)
{
}
return
null
;
CopyPasteSupport
.
pasteTransferableAsBlock
(
editor
,
producer
);
}
/**
...
...
@@ -494,40 +397,4 @@ public class EditorModificationUtil {
CaretModel
caretModel
=
editor
.
getCaretModel
();
caretModel
.
moveToOffset
(
caretModel
.
getOffset
()
+
caretShift
);
}
/** @deprecated use {@link #pasteTransferable(Editor, Producer)} (to remove in IDEA 14) */
@SuppressWarnings
(
"UnusedDeclaration"
)
public
static
TextRange
pasteFromClipboard
(
Editor
editor
)
{
return
pasteTransferable
(
editor
,
null
);
}
/** @deprecated use {@link #pasteTransferable(Editor, Producer)} (to remove in IDEA 14) */
@SuppressWarnings
(
"SpellCheckingInspection,UnusedDeclaration"
)
public
static
TextRange
pasteFromTransferrable
(
final
Transferable
content
,
Editor
editor
)
{
return
pasteTransferable
(
editor
,
new
Producer
<
Transferable
>()
{
@Nullable
@Override
public
Transferable
produce
()
{
return
content
;
}
});
}
@SuppressWarnings
(
"UnusedDeclaration"
)
/** @deprecated use {@link #pasteTransferableAsBlock(Editor, Producer)} (to remove in IDEA 14) */
public
static
void
pasteFromClipboardAsBlock
(
Editor
editor
)
{
pasteTransferableAsBlock
(
editor
,
(
Producer
<
Transferable
>)
null
);
}
@SuppressWarnings
(
"UnusedDeclaration"
)
/** @deprecated use {@link #pasteTransferableAsBlock(Editor, Producer)} (to remove in IDEA 14) */
public
static
void
pasteTransferableAsBlock
(
Editor
editor
,
@Nullable
final
Transferable
content
)
{
pasteTransferableAsBlock
(
editor
,
new
Producer
<
Transferable
>()
{
@Nullable
@Override
public
Transferable
produce
()
{
return
content
;
}
});
}
}
This diff is collapsed.
Click to expand it.
platform/platform-impl/src/com/intellij/openapi/editor/impl/SelectionModelImpl.java
+
1
-
10
View file @
ab427880
...
...
@@ -36,16 +36,13 @@ import com.intellij.openapi.editor.ex.DocumentEx;
import
com.intellij.openapi.editor.ex.PrioritizedDocumentListener
;
import
com.intellij.openapi.editor.ex.util.EditorUtil
;
import
com.intellij.openapi.editor.markup.TextAttributes
;
import
com.intellij.openapi.ide.CopyPasteManager
;
import
com.intellij.openapi.util.Pair
;
import
com.intellij.openapi.util.text.StringUtil
;
import
com.intellij.util.ArrayUtil
;
import
com.intellij.util.containers.ContainerUtil
;
import
gnu.trove.TIntArrayList
;
import
org.jetbrains.annotations.NotNull
;
import
org.jetbrains.annotations.Nullable
;
import
java.awt.datatransfer.StringSelection
;
import
java.util.Collection
;
import
java.util.Iterator
;
import
java.util.LinkedList
;
...
...
@@ -570,13 +567,7 @@ public class SelectionModelImpl implements SelectionModel, PrioritizedDocumentLi
@Override
public
void
copySelectionToClipboard
()
{
validateContext
(
true
);
String
s
=
getSelectedText
(
true
);
if
(
s
==
null
)
return
;
s
=
StringUtil
.
convertLineSeparators
(
s
);
StringSelection
contents
=
new
StringSelection
(
s
);
CopyPasteManager
.
getInstance
().
setContents
(
contents
);
CopyPasteSupport
.
copySelectionToClipboard
(
myEditor
);
}
@Override
...
...
This diff is collapsed.
Click to expand it.
platform/platform-tests/testSrc/com/intellij/openapi/editor/EditorMultiCaretTest.java
+
32
-
0
View file @
ab427880
...
...
@@ -245,6 +245,38 @@ public class EditorMultiCaretTest extends AbstractEditorTest {
"seven<caret>"
);
}
public
void
testCopyMultilineFromOneCaretPasteIntoTwo
()
throws
Exception
{
init
(
"<selection>one\n"
+
"two<caret></selection>\n"
+
"three\n"
+
"four"
,
TestFileType
.
TEXT
);
executeAction
(
"EditorCopy"
);
executeAction
(
"EditorTextStart"
);
executeAction
(
"EditorCloneCaretBelow"
);
executeAction
(
"EditorPaste"
);
checkResultByText
(
"one\n"
+
"two<caret>one\n"
+
"one\n"
+
"two<caret>two\n"
+
"three\n"
+
"four"
);
}
public
void
testCopyPasteDoesNothingWithUnevenSelection
()
throws
Exception
{
init
(
"<selection>one\n"
+
"two<caret></selection>\n"
+
"<selection>three<caret></selection>\n"
+
"four"
,
TestFileType
.
TEXT
);
executeAction
(
"EditorCopy"
);
executeAction
(
"EditorPaste"
);
checkResultByText
(
"one\n"
+
"two<caret>\n"
+
"three<caret>\n"
+
"four"
);
}
public
void
testEscapeAfterDragDown
()
throws
Exception
{
init
(
"line1\n"
+
"line2"
,
...
...
This diff is collapsed.
Click to expand it.
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
Menu
Projects
Groups
Snippets
Help