per document readonly fragment modification exception handler
[fedora-idea.git] / platform-api / src / com / intellij / openapi / editor / EditorModificationUtil.java
blobbb0f12a2273f3fd21028aea332baf89f5c28601f
1 /*
2 * Copyright 2000-2007 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package com.intellij.openapi.editor;
18 import com.intellij.codeStyle.CodeStyleFacade;
19 import com.intellij.openapi.editor.actionSystem.EditorActionManager;
20 import com.intellij.openapi.editor.event.DocumentEvent;
21 import com.intellij.openapi.editor.event.MockDocumentEvent;
22 import com.intellij.openapi.ide.CopyPasteManager;
23 import com.intellij.openapi.project.Project;
24 import com.intellij.openapi.util.TextRange;
25 import com.intellij.openapi.util.text.LineTokenizer;
26 import com.intellij.openapi.util.text.StringUtil;
27 import org.jetbrains.annotations.Nullable;
29 import java.awt.datatransfer.Clipboard;
30 import java.awt.datatransfer.DataFlavor;
31 import java.awt.datatransfer.Transferable;
32 import java.awt.datatransfer.UnsupportedFlavorException;
33 import java.io.IOException;
35 public class EditorModificationUtil {
36 private EditorModificationUtil() {}
38 public static void deleteSelectedText(Editor editor) {
39 SelectionModel selectionModel = editor.getSelectionModel();
40 if (selectionModel.hasBlockSelection()) deleteBlockSelection(editor);
41 if(!selectionModel.hasSelection()) return;
43 int selectionStart = selectionModel.getSelectionStart();
44 int selectionEnd = selectionModel.getSelectionEnd();
46 editor.getCaretModel().moveToOffset(selectionStart);
47 selectionModel.removeSelection();
48 editor.getDocument().deleteString(selectionStart, selectionEnd);
49 editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
52 public static void deleteBlockSelection(Editor editor) {
53 SelectionModel selectionModel = editor.getSelectionModel();
54 if (!selectionModel.hasBlockSelection()) return;
56 int startLine = selectionModel.getBlockStart().line;
57 int endLine = selectionModel.getBlockEnd().line;
59 int[] starts = selectionModel.getBlockSelectionStarts();
60 int[] ends = selectionModel.getBlockSelectionEnds();
62 for (int i = starts.length - 1; i >= 0; i--) {
63 editor.getDocument().deleteString(starts[i], ends[i]);
66 editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
68 zeroWidthBlockSelectionAtCaretColumn(editor, startLine, endLine);
71 private static void zeroWidthBlockSelectionAtCaretColumn(final Editor editor, final int startLine, final int endLine) {
72 int caretColumn = editor.getCaretModel().getLogicalPosition().column;
73 editor.getSelectionModel().setBlockSelection(new LogicalPosition(startLine, caretColumn), new LogicalPosition(endLine, caretColumn));
76 public static void insertStringAtCaret(Editor editor, String s) {
77 insertStringAtCaret(editor, s, false, true);
80 public static int insertStringAtCaret(Editor editor, String s, boolean toProcessOverwriteMode, boolean toMoveCaret) {
81 final SelectionModel selectionModel = editor.getSelectionModel();
82 if (selectionModel.hasSelection()) {
83 editor.getCaretModel().moveToOffset(selectionModel.getSelectionStart());
86 int oldOffset = editor.getCaretModel().getOffset();
88 String filler = calcStringToFillVitualSpace(editor);
89 if (filler.length() > 0) {
90 s = filler + s;
93 if (editor.isInsertMode() || !toProcessOverwriteMode) {
94 if (selectionModel.hasSelection()) {
95 editor.getDocument().replaceString(selectionModel.getSelectionStart(), selectionModel.getSelectionEnd(), s);
96 } else {
97 editor.getDocument().insertString(oldOffset, s);
99 } else {
100 deleteSelectedText(editor);
101 Document document = editor.getDocument();
102 int lineNumber = editor.getCaretModel().getLogicalPosition().line;
103 if (lineNumber >= document.getLineCount()){
104 return insertStringAtCaret(editor, s, false, toMoveCaret);
107 int endOffset = document.getLineEndOffset(lineNumber);
108 document.replaceString(oldOffset, Math.min(endOffset, oldOffset + s.length()), s);
111 int offset = oldOffset + s.length();
112 if (toMoveCaret){
113 editor.getCaretModel().moveToOffset(offset);
114 editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
115 selectionModel.removeSelection();
118 return offset;
121 @Nullable
122 public static TextRange pasteFromClipboard(Editor editor) {
123 return pasteFromTransferrable(getClipboardContent(editor), editor);
126 @Nullable
127 public static TextRange pasteFromTransferrable(Transferable content, Editor editor) {
128 if (content != null) {
129 try {
130 String s = getStringContent(content);
132 int caretOffset = editor.getCaretModel().getOffset();
133 insertStringAtCaret(editor, s, false, true);
134 return new TextRange(caretOffset, caretOffset + s.length());
135 } catch (Exception exception) {
136 editor.getComponent().getToolkit().beep();
140 return null;
143 private static String getStringContent(final Transferable content) throws UnsupportedFlavorException, IOException {
144 RawText raw = null;
145 try {
146 raw = (RawText)content.getTransferData(RawText.FLAVOR);
148 catch (UnsupportedFlavorException e) {
149 // OK. raw will be null and we'll get plain string
151 catch (IOException e) {
152 // OK. raw will be null and we'll get plain string
155 String s;
156 if (raw != null) {
157 s = raw.rawText;
159 else {
160 s = (String)content.getTransferData(DataFlavor.stringFlavor);
163 s = StringUtil.convertLineSeparators(s);
164 return s;
167 private static Transferable getClipboardContent(Editor editor) {
168 Transferable content;
169 Project project = editor.getProject();
171 if (project != null) {
172 content = CopyPasteManager.getInstance().getContents();
173 } else {
174 Clipboard clipboard = editor.getComponent().getToolkit().getSystemClipboard();
175 content = clipboard.getContents(editor.getComponent());
177 return content;
180 public static void pasteFromClipboardAsBlock(Editor editor) {
181 Transferable content = getClipboardContent(editor);
183 if (content != null) {
184 try {
185 int caretLine = editor.getCaretModel().getLogicalPosition().line;
186 int originalCaretLine = caretLine;
188 int selectedLinesCount = 0;
189 final SelectionModel selectionModel = editor.getSelectionModel();
190 if (selectionModel.hasBlockSelection()) {
191 final LogicalPosition start = selectionModel.getBlockStart();
192 final LogicalPosition end = selectionModel.getBlockEnd();
193 assert start != null;
194 assert end != null;
195 LogicalPosition caret = new LogicalPosition(Math.min(start.line, end.line), Math.min(start.column, end.column));
196 selectedLinesCount = Math.abs(end.line - start.line);
197 caretLine = caret.line;
199 deleteSelectedText(editor);
200 editor.getCaretModel().moveToLogicalPosition(caret);
203 LogicalPosition caretToRestore = editor.getCaretModel().getLogicalPosition();
204 String s = getStringContent(content);
206 String[] lines = LineTokenizer.tokenize(s.toCharArray(), false);
207 if (lines.length > 1 || selectedLinesCount <= 1) {
208 int longestLineLength = 0;
209 for (String line : lines) {
210 longestLineLength = Math.max(longestLineLength, line.length());
211 insertStringAtCaret(editor, line, false, true);
212 editor.getCaretModel().moveCaretRelatively(-line.length(), 1, false, false, true);
214 caretToRestore = new LogicalPosition(originalCaretLine, caretToRestore.column + longestLineLength);
216 else {
217 for (int i = 0; i <= selectedLinesCount; i++) {
218 insertStringAtCaret(editor, s, false, true);
219 editor.getCaretModel().moveCaretRelatively(-s.length(), 1, false, false, true);
221 caretToRestore = new LogicalPosition(originalCaretLine, caretToRestore.column + s.length());
223 editor.getCaretModel().moveToLogicalPosition(caretToRestore);
224 zeroWidthBlockSelectionAtCaretColumn(editor, caretLine, caretLine + selectedLinesCount);
225 } catch (Exception exception) {
226 editor.getComponent().getToolkit().beep();
231 public static int calcAfterLineEnd(Editor editor) {
232 Document document = editor.getDocument();
233 LogicalPosition logicalPosition = editor.getCaretModel().getLogicalPosition();
234 int columnNumber = logicalPosition.column;
235 int lineNumber = logicalPosition.line;
236 if (lineNumber >= document.getLineCount()) {
237 return columnNumber;
239 int lineEndOffset = document.getLineEndOffset(lineNumber);
240 int lineEndColumnNumber = editor.offsetToLogicalPosition(lineEndOffset).column;
241 return columnNumber - lineEndColumnNumber;
244 public static String calcStringToFillVitualSpace(Editor editor) {
245 int afterLineEnd = calcAfterLineEnd(editor);
246 if (afterLineEnd > 0) {
247 final Project project = editor.getProject();
248 StringBuilder buf = new StringBuilder();
249 final Document doc = editor.getDocument();
250 final int caretOffset = editor.getCaretModel().getOffset();
251 boolean atLineStart = caretOffset >= doc.getTextLength() || doc.getLineStartOffset(doc.getLineNumber(caretOffset)) == caretOffset;
252 if (atLineStart && project != null) {
253 String properIndent = CodeStyleFacade.getInstance(project).getLineIndent(editor);
254 if (properIndent != null) {
255 int tabSize = editor.getSettings().getTabSize(project);
256 for (int i = 0; i < properIndent.length(); i++) {
257 if (properIndent.charAt(i) == ' ') {
258 afterLineEnd--;
260 else if (properIndent.charAt(i) == '\t') {
261 if (afterLineEnd < tabSize) {
262 break;
264 afterLineEnd -= tabSize;
266 buf.append(properIndent.charAt(i));
267 if (afterLineEnd == 0) break;
272 for (int i = 0; i < afterLineEnd; i++) {
273 buf.append(' ');
276 return buf.toString();
279 return "";
282 public static void typeInStringAtCaretHonorBlockSelection(final Editor editor, final String str, final boolean toProcessOverwriteMode)
283 throws ReadOnlyFragmentModificationException
285 Document doc = editor.getDocument();
286 final SelectionModel selectionModel = editor.getSelectionModel();
287 if (selectionModel.hasBlockSelection()) {
288 RangeMarker guard = selectionModel.getBlockSelectionGuard();
289 if (guard != null) {
290 DocumentEvent evt = new MockDocumentEvent(doc, editor.getCaretModel().getOffset());
291 ReadOnlyFragmentModificationException e = new ReadOnlyFragmentModificationException(evt, guard);
292 EditorActionManager.getInstance().getReadonlyFragmentModificationHandler(doc).handle(e);
294 else {
295 final LogicalPosition start = selectionModel.getBlockStart();
296 final LogicalPosition end = selectionModel.getBlockEnd();
297 assert start != null;
298 assert end != null;
300 int column = Math.min(start.column, end.column);
301 int startLine = Math.min(start.line, end.line);
302 int endLine = Math.max(start.line, end.line);
303 deleteBlockSelection(editor);
304 for (int i = startLine; i <= endLine; i++) {
305 editor.getCaretModel().moveToLogicalPosition(new LogicalPosition(i, column));
306 insertStringAtCaret(editor, str, toProcessOverwriteMode, true);
308 selectionModel.setBlockSelection(new LogicalPosition(startLine, column + str.length()),
309 new LogicalPosition(endLine, column + str.length()));
312 else {
313 insertStringAtCaret(editor, str, toProcessOverwriteMode, true);