diff options
Diffstat (limited to 'platform/platform-api/src/com/intellij/openapi')
25 files changed, 577 insertions, 682 deletions
diff --git a/platform/platform-api/src/com/intellij/openapi/actionSystem/IdeActions.java b/platform/platform-api/src/com/intellij/openapi/actionSystem/IdeActions.java index 1d4fea4c01de..049bde52f582 100644 --- a/platform/platform-api/src/com/intellij/openapi/actionSystem/IdeActions.java +++ b/platform/platform-api/src/com/intellij/openapi/actionSystem/IdeActions.java @@ -36,6 +36,8 @@ public interface IdeActions { @NonNls String ACTION_EDITOR_SELECT_WORD_AT_CARET = "EditorSelectWord"; @NonNls String ACTION_EDITOR_UNSELECT_WORD_AT_CARET = "EditorUnSelectWord"; @NonNls String ACTION_EDITOR_BACKSPACE = "EditorBackSpace"; + @NonNls String ACTION_EDITOR_MOVE_CARET_LEFT_WITH_SELECTION = "EditorLeftWithSelection"; + @NonNls String ACTION_EDITOR_MOVE_CARET_RIGHT_WITH_SELECTION = "EditorRightWithSelection"; @NonNls String ACTION_EDITOR_MOVE_CARET_UP = "EditorUp"; @NonNls String ACTION_EDITOR_MOVE_CARET_LEFT = "EditorLeft"; @NonNls String ACTION_EDITOR_MOVE_CARET_DOWN = "EditorDown"; @@ -269,7 +271,7 @@ public interface IdeActions { String ACTION_UNDO = "$Undo"; String ACTION_REDO = "$Redo"; String GROUP_REFACTOR = "RefactoringMenu"; - String SELECTED_CHANGES_ROLLBACK = "RollbackLineStatusChanges"; + String SELECTED_CHANGES_ROLLBACK = "Vcs.RollbackChangedLines"; String CHANGES_VIEW_ROLLBACK = "ChangesView.Rollback"; String CONSOLE_CLEAR_ALL = "ConsoleView.ClearAll"; diff --git a/platform/platform-api/src/com/intellij/openapi/actionSystem/ex/ComboBoxAction.java b/platform/platform-api/src/com/intellij/openapi/actionSystem/ex/ComboBoxAction.java index 92a1d9c8b42c..7398bf706c78 100644 --- a/platform/platform-api/src/com/intellij/openapi/actionSystem/ex/ComboBoxAction.java +++ b/platform/platform-api/src/com/intellij/openapi/actionSystem/ex/ComboBoxAction.java @@ -110,10 +110,10 @@ public abstract class ComboBoxAction extends AnAction implements CustomComponent private boolean myMouseInside = false; private JBPopup myPopup; private boolean myForceTransparent = false; - private Boolean myForceEnabled = null; public ComboBoxButton(Presentation presentation) { myPresentation = presentation; + setEnabled(myPresentation.isEnabled()); setModel(new MyButtonModel()); setHorizontalAlignment(LEFT); setFocusable(false); @@ -207,12 +207,6 @@ public abstract class ComboBoxAction extends AnAction implements CustomComponent } } - @Override - public void setEnabled(final boolean enabled) { - super.setEnabled(enabled); - myForceEnabled = enabled; - } - public void setForceTransparent(boolean transparent) { myForceTransparent = transparent; } @@ -282,7 +276,6 @@ public abstract class ComboBoxAction extends AnAction implements CustomComponent private void initButton() { setIcon(myPresentation.getIcon()); - setEnabled(myPresentation.isEnabled()); setText(myPresentation.getText()); updateTooltipText(myPresentation.getDescription()); updateButtonSize(); @@ -383,7 +376,7 @@ public abstract class ComboBoxAction extends AnAction implements CustomComponent final Dimension size = getSize(); final boolean isEmpty = getIcon() == null && StringUtil.isEmpty(getText()); - final Color textColor = (myForceEnabled == null ? myPresentation.isEnabled() : myForceEnabled) + final Color textColor = isEnabled() ? UIManager.getColor("Panel.foreground") : UIUtil.getInactiveTextColor(); if (myForceTransparent) { diff --git a/platform/platform-api/src/com/intellij/openapi/diff/DiffRequestFactory.java b/platform/platform-api/src/com/intellij/openapi/diff/DiffRequestFactory.java index 78f07a04b4a9..e2c9175ac915 100644 --- a/platform/platform-api/src/com/intellij/openapi/diff/DiffRequestFactory.java +++ b/platform/platform-api/src/com/intellij/openapi/diff/DiffRequestFactory.java @@ -16,6 +16,7 @@ package com.intellij.openapi.diff; import com.intellij.openapi.components.ServiceManager; +import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.VirtualFile; import org.jetbrains.annotations.NotNull; @@ -59,4 +60,12 @@ public abstract class DiffRequestFactory { Project project, @Nullable ActionButtonPresentation okButtonPresentation, @Nullable ActionButtonPresentation cancelButtonPresentation); + + public abstract MergeRequest create3WayDiffRequest(String leftText, + String rightText, + String originalContent, + @Nullable FileType type, + Project project, + @Nullable ActionButtonPresentation okButtonPresentation, + @Nullable ActionButtonPresentation cancelButtonPresentation); } diff --git a/platform/platform-api/src/com/intellij/openapi/diff/FragmentContent.java b/platform/platform-api/src/com/intellij/openapi/diff/FragmentContent.java index 26537316b4e9..d630bad790df 100644 --- a/platform/platform-api/src/com/intellij/openapi/diff/FragmentContent.java +++ b/platform/platform-api/src/com/intellij/openapi/diff/FragmentContent.java @@ -41,18 +41,28 @@ public class FragmentContent extends DiffContent { private final FileType myType; private final MyDocumentsSynchronizer mySynchonizer; public static final Key<Document> ORIGINAL_DOCUMENT = new Key<Document>("ORIGINAL_DOCUMENT"); + private final boolean myForceReadOnly; public FragmentContent(@NotNull DiffContent original, @NotNull TextRange range, Project project, VirtualFile file) { - this(original, range, project, file != null ? DiffContentUtil.getContentType(file) : null); + this(original, range, project, file, false); + } + + public FragmentContent(@NotNull DiffContent original, @NotNull TextRange range, Project project, VirtualFile file, boolean forceReadOnly) { + this(original, range, project, file != null ? DiffContentUtil.getContentType(file) : null, forceReadOnly); } public FragmentContent(@NotNull DiffContent original, @NotNull TextRange range, Project project, FileType fileType) { + this(original, range, project, fileType, false); + } + + public FragmentContent(@NotNull DiffContent original, @NotNull TextRange range, Project project, FileType fileType, boolean forceReadOnly) { RangeMarker rangeMarker = original.getDocument().createRangeMarker(range.getStartOffset(), range.getEndOffset(), true); rangeMarker.setGreedyToLeft(true); rangeMarker.setGreedyToRight(true); mySynchonizer = new MyDocumentsSynchronizer(project, rangeMarker); myOriginal = original; myType = fileType; + myForceReadOnly = forceReadOnly; } public FragmentContent(DiffContent original, TextRange range, Project project) { @@ -152,7 +162,7 @@ public class FragmentContent extends DiffContent { String textInRange = originalDocument.getCharsSequence().subSequence(myRangeMarker.getStartOffset(), myRangeMarker.getEndOffset()).toString(); final Document result = EditorFactory.getInstance().createDocument(textInRange); - result.setReadOnly(!originalDocument.isWritable()); + result.setReadOnly(myForceReadOnly || !originalDocument.isWritable()); result.putUserData(ORIGINAL_DOCUMENT, originalDocument); return result; } diff --git a/platform/platform-api/src/com/intellij/openapi/diff/MergeRequest.java b/platform/platform-api/src/com/intellij/openapi/diff/MergeRequest.java index 29243f7b9be0..ce8d56044f96 100644 --- a/platform/platform-api/src/com/intellij/openapi/diff/MergeRequest.java +++ b/platform/platform-api/src/com/intellij/openapi/diff/MergeRequest.java @@ -25,7 +25,7 @@ import org.jetbrains.annotations.Nullable; * @see DiffRequestFactory#createMergeRequest */ public abstract class MergeRequest extends DiffRequest { - protected MergeRequest(Project project) { + protected MergeRequest(@Nullable Project project) { super(project); } diff --git a/platform/platform-api/src/com/intellij/openapi/editor/CaretStateTransferableData.java b/platform/platform-api/src/com/intellij/openapi/editor/CaretStateTransferableData.java deleted file mode 100644 index f0d2085cbb6b..000000000000 --- a/platform/platform-api/src/com/intellij/openapi/editor/CaretStateTransferableData.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * 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(); - } -} diff --git a/platform/platform-api/src/com/intellij/openapi/editor/ClipboardTextPerCaretSplitter.java b/platform/platform-api/src/com/intellij/openapi/editor/ClipboardTextPerCaretSplitter.java deleted file mode 100644 index a3e62412f4a4..000000000000 --- a/platform/platform-api/src/com/intellij/openapi/editor/ClipboardTextPerCaretSplitter.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * 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 org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -public class ClipboardTextPerCaretSplitter { - @NotNull - public List<String> split(@NotNull String input, @Nullable CaretStateTransferableData caretData, int caretCount) { - if (caretCount <= 0) { - throw new IllegalArgumentException("Caret count must be positive"); - } - if (caretCount == 1) { - return Collections.singletonList(input); - } - List<String> result = new ArrayList<String>(caretCount); - 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 (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) { - result.add(lines[0]); - } - else if (lines.length % caretCount == 0) { - StringBuilder b = new StringBuilder(); - int linesPerSegment = lines.length / caretCount; - for (int j = 0; j < linesPerSegment; j++) { - if (j > 0) { - b.append('\n'); - } - b.append(lines[i * linesPerSegment + j]); - } - result.add(b.toString()); - } - else { - result.add(i < lines.length ? lines[i] : ""); - } - } - return result; - } -} diff --git a/platform/platform-api/src/com/intellij/openapi/editor/CopyPasteSupport.java b/platform/platform-api/src/com/intellij/openapi/editor/CopyPasteSupport.java deleted file mode 100644 index 7095080aa13d..000000000000 --- a/platform/platform-api/src/com/intellij/openapi/editor/CopyPasteSupport.java +++ /dev/null @@ -1,212 +0,0 @@ -/* - * 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; - } -} diff --git a/platform/platform-api/src/com/intellij/openapi/editor/EditorCopyPasteHelper.java b/platform/platform-api/src/com/intellij/openapi/editor/EditorCopyPasteHelper.java new file mode 100644 index 000000000000..f698d34efb50 --- /dev/null +++ b/platform/platform-api/src/com/intellij/openapi/editor/EditorCopyPasteHelper.java @@ -0,0 +1,53 @@ +/* + * 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.openapi.components.ServiceManager; +import com.intellij.openapi.util.TextRange; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.awt.datatransfer.Transferable; + +/** + * Support for data transfer between editor and clipboard. + */ +public abstract class EditorCopyPasteHelper { + public static EditorCopyPasteHelper getInstance() { + return ServiceManager.getService(EditorCopyPasteHelper.class); + } + + /** + * Copies text selected in editor to clipboard. + */ + public abstract void copySelectionToClipboard(@NotNull Editor editor); + + /** + * Pastes from clipboard into editor at caret(s) position. + * + * @return ranges of text in the document, corresponding to pasted fragments, if paste succeeds, or <code>null</code> otherwise + */ + @Nullable + public abstract TextRange[] pasteFromClipboard(@NotNull Editor editor); + + /** + * Pastes given Transferable instance into editor at caret(s) position. + * + * @return ranges of text in the document, corresponding to pasted fragments, if paste succeeds, or <code>null</code> otherwise + */ + @Nullable + public abstract TextRange[] pasteTransferable(@NotNull Editor editor, @NotNull Transferable content); +} diff --git a/platform/platform-api/src/com/intellij/openapi/editor/EditorModificationUtil.java b/platform/platform-api/src/com/intellij/openapi/editor/EditorModificationUtil.java index ee5527967440..6ba31d7edb47 100644 --- a/platform/platform-api/src/com/intellij/openapi/editor/EditorModificationUtil.java +++ b/platform/platform-api/src/com/intellij/openapi/editor/EditorModificationUtil.java @@ -19,14 +19,19 @@ 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.List; public class EditorModificationUtil { @@ -176,22 +181,100 @@ public class EditorModificationUtil { } /** - * @deprecated Use {@link com.intellij.openapi.editor.CopyPasteSupport#pasteTransferable(Editor, com.intellij.util.Producer)} instead. + * @deprecated Use {@link com.intellij.openapi.editor.EditorCopyPasteHelper} methods instead. * (to remove in IDEA 15) */ @Nullable public static TextRange pasteTransferable(final Editor editor, @Nullable Producer<Transferable> producer) { - return CopyPasteSupport.pasteTransferable(editor, producer); + EditorCopyPasteHelper helper = EditorCopyPasteHelper.getInstance(); + if (producer == null) { + TextRange[] ranges = helper.pasteFromClipboard(editor); + return ranges != null && ranges.length == 1 ? ranges[0] : null; + } + Transferable transferable = producer.produce(); + if (transferable == null) { + return null; + } + TextRange[] ranges = helper.pasteTransferable(editor, transferable); + return ranges != null && ranges.length == 1 ? ranges[0] : null; } - /** - * @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) { - CopyPasteSupport.pasteTransferableAsBlock(editor, 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; + + 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(@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; + } /** * Calculates difference in columns between current editor caret position and end of the logical line fragment displayed * on a current visual line. diff --git a/platform/platform-api/src/com/intellij/openapi/editor/LazyRangeMarkerFactory.java b/platform/platform-api/src/com/intellij/openapi/editor/LazyRangeMarkerFactory.java index 3780e3a79e0c..942a33aaace8 100644 --- a/platform/platform-api/src/com/intellij/openapi/editor/LazyRangeMarkerFactory.java +++ b/platform/platform-api/src/com/intellij/openapi/editor/LazyRangeMarkerFactory.java @@ -15,276 +15,19 @@ */ package com.intellij.openapi.editor; -import com.intellij.codeStyle.CodeStyleFacade; -import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.components.ServiceManager; -import com.intellij.openapi.editor.event.DocumentAdapter; -import com.intellij.openapi.editor.event.DocumentEvent; -import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.Computable; -import com.intellij.openapi.util.Key; -import com.intellij.openapi.util.UserDataHolderBase; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.util.SmartList; -import com.intellij.util.containers.WeakList; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.List; - -public class LazyRangeMarkerFactory { - private final Project myProject; - private static final Key<WeakList<LazyMarker>> LAZY_MARKERS_KEY = Key.create("LAZY_MARKERS_KEY"); +public abstract class LazyRangeMarkerFactory { public static LazyRangeMarkerFactory getInstance(Project project) { return ServiceManager.getService(project, LazyRangeMarkerFactory.class); } - public LazyRangeMarkerFactory(@NotNull Project project, @NotNull final FileDocumentManager fileDocumentManager) { - myProject = project; - - EditorFactory.getInstance().getEventMulticaster().addDocumentListener(new DocumentAdapter() { - @Override - public void beforeDocumentChange(DocumentEvent e) { - transformRangeMarkers(e); - } - - @Override - public void documentChanged(DocumentEvent e) { - transformRangeMarkers(e); - } - - private void transformRangeMarkers(@NotNull DocumentEvent e) { - Document document = e.getDocument(); - VirtualFile file = fileDocumentManager.getFile(document); - if (file == null) { - return; - } - - WeakList<LazyMarker> lazyMarkers = file.getUserData(LAZY_MARKERS_KEY); - if (lazyMarkers == null) { - return; - } - - List<LazyMarker> markers = lazyMarkers.toStrongList(); - List<LazyMarker> markersToRemove = null; - for (LazyMarker marker : markers) { - if (file.equals(marker.getFile()) && marker.documentChanged(document) != null) { - if (markersToRemove == null) { - markersToRemove = new SmartList<LazyMarker>(); - } - markersToRemove.add(marker); - } - } - if (markersToRemove != null) { - lazyMarkers.removeAll(markersToRemove); - } - } - }, project); - } - - private static void addToLazyMarkersList(@NotNull LazyMarker marker, @NotNull VirtualFile file) { - WeakList<LazyMarker> markers = file.getUserData(LAZY_MARKERS_KEY); - - if (markers == null) { - markers = file.putUserDataIfAbsent(LAZY_MARKERS_KEY, new WeakList<LazyMarker>()); - } - markers.add(marker); - } - @NotNull - public RangeMarker createRangeMarker(@NotNull final VirtualFile file, final int offset) { - return ApplicationManager.getApplication().runReadAction(new Computable<RangeMarker>() { - @Override - public RangeMarker compute() { - // even for already loaded document do not create range marker yet - wait until it really needed when e.g. user clicked to jump to OpenFileDescriptor - final LazyMarker marker = new OffsetLazyMarker(file, offset); - addToLazyMarkersList(marker, file); - return marker; - } - }); - } + public abstract RangeMarker createRangeMarker(@NotNull final VirtualFile file, final int offset); @NotNull - public RangeMarker createRangeMarker(@NotNull final VirtualFile file, final int line, final int column, final boolean persistent) { - return ApplicationManager.getApplication().runReadAction(new Computable<RangeMarker>() { - @Override - public RangeMarker compute() { - final Document document = FileDocumentManager.getInstance().getCachedDocument(file); - if (document != null) { - final int offset = calculateOffset(myProject, file, document, line, column); - return document.createRangeMarker(offset, offset, persistent); - } - - final LazyMarker marker = new LineColumnLazyMarker(file, line, column); - addToLazyMarkersList(marker, file); - return marker; - } - }); - } - - private abstract static class LazyMarker extends UserDataHolderBase implements RangeMarker { - private RangeMarker myDelegate; - private final VirtualFile myFile; - protected final int myInitialOffset; - - private LazyMarker(@NotNull VirtualFile file, int offset) { - myFile = file; - myInitialOffset = offset; - } - - @NotNull - public VirtualFile getFile() { - return myFile; - } - - @Nullable - protected final RangeMarker getOrCreateDelegate() { - if (myDelegate == null) { - Document document = FileDocumentManager.getInstance().getDocument(myFile); - if (document == null) { - return null; - } - myDelegate = createDelegate(myFile, document); - } - return myDelegate; - } - - @Nullable - protected final RangeMarker documentChanged(@NotNull Document document) { - if (myDelegate == null) { - myDelegate = createDelegate(myFile, document); - } - return myDelegate; - } - - @Nullable - protected abstract RangeMarker createDelegate(@NotNull VirtualFile file, @NotNull Document document); - - @Override - @NotNull - public Document getDocument() { - RangeMarker delegate = getOrCreateDelegate(); - if (delegate == null) { - //noinspection ConstantConditions - return FileDocumentManager.getInstance().getDocument(myFile); - } - return delegate.getDocument(); - } - - @Override - public int getStartOffset() { - return myDelegate == null ? myInitialOffset : myDelegate.getStartOffset(); - } - - - @Override - public int getEndOffset() { - return myDelegate == null ? myInitialOffset : myDelegate.getEndOffset(); - } - - @Override - public boolean isValid() { - RangeMarker delegate = getOrCreateDelegate(); - return delegate != null && delegate.isValid(); - } - - @Override - public void setGreedyToLeft(boolean greedy) { - getOrCreateDelegate().setGreedyToLeft(greedy); - } - - @Override - public void setGreedyToRight(boolean greedy) { - getOrCreateDelegate().setGreedyToRight(greedy); - } - - @Override - public boolean isGreedyToRight() { - return getOrCreateDelegate().isGreedyToRight(); - } - - @Override - public boolean isGreedyToLeft() { - return getOrCreateDelegate().isGreedyToLeft(); - } - - @Override - public void dispose() { - RangeMarker delegate = getOrCreateDelegate(); - if (delegate != null) { - delegate.dispose(); - } - } - } - - private static class OffsetLazyMarker extends LazyMarker { - private OffsetLazyMarker(@NotNull VirtualFile file, int offset) { - super(file, offset); - } - - @Override - @NotNull - public RangeMarker createDelegate(@NotNull VirtualFile file, @NotNull final Document document) { - final int offset = Math.min(myInitialOffset, document.getTextLength()); - return document.createRangeMarker(offset, offset); - } - } - - private class LineColumnLazyMarker extends LazyMarker { - private final int myLine; - private final int myColumn; - - private LineColumnLazyMarker(@NotNull VirtualFile file, int line, int column) { - super(file, -1); - myLine = line; - myColumn = column; - } - - @Override - @Nullable - public RangeMarker createDelegate(@NotNull VirtualFile file, @NotNull Document document) { - if (document.getTextLength() == 0 && !(myLine == 0 && myColumn == 0)) { - return null; - } - - int offset = calculateOffset(myProject, file, document, myLine, myColumn); - return document.createRangeMarker(offset, offset); - } - - @Override - public int getStartOffset() { - getOrCreateDelegate(); - return super.getStartOffset(); - } - - @Override - public int getEndOffset() { - getOrCreateDelegate(); - return super.getEndOffset(); - } - } - - private static int calculateOffset(@NotNull Project project, @NotNull VirtualFile file, @NotNull Document document, final int line, final int column) { - int offset; - if (line < document.getLineCount()) { - final int lineStart = document.getLineStartOffset(line); - final int lineEnd = document.getLineEndOffset(line); - final CharSequence docText = document.getCharsSequence(); - final int tabSize = CodeStyleFacade.getInstance(project).getTabSize(file.getFileType()); - - offset = lineStart; - int col = 0; - while (offset < lineEnd && col < column) { - col += docText.charAt(offset) == '\t' ? tabSize : 1; - offset++; - } - } - else { - offset = document.getTextLength(); - } - return offset; - } - + public abstract RangeMarker createRangeMarker(@NotNull final VirtualFile file, final int line, final int column, final boolean persistent); } diff --git a/platform/platform-api/src/com/intellij/openapi/editor/actionSystem/DialogAwareDataContext.java b/platform/platform-api/src/com/intellij/openapi/editor/actionSystem/DialogAwareDataContext.java new file mode 100644 index 000000000000..c49645254ebd --- /dev/null +++ b/platform/platform-api/src/com/intellij/openapi/editor/actionSystem/DialogAwareDataContext.java @@ -0,0 +1,54 @@ +/* + * 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.actionSystem; + +import com.intellij.ide.DataManager; +import com.intellij.openapi.actionSystem.DataContext; +import com.intellij.openapi.actionSystem.DataKey; +import com.intellij.openapi.editor.Editor; +import org.jetbrains.annotations.NonNls; + +import java.util.HashMap; +import java.util.Map; + +import static com.intellij.openapi.actionSystem.CommonDataKeys.*; +import static com.intellij.openapi.actionSystem.PlatformDataKeys.PROJECT_FILE_DIRECTORY; + +/** +* @author Konstantin Bulenkov +*/ +final class DialogAwareDataContext implements DataContext { + private static final DataKey[] keys = {PROJECT, PROJECT_FILE_DIRECTORY, EDITOR, VIRTUAL_FILE, PSI_FILE}; + private final Map<String, Object> values = new HashMap<String, Object>(); + + DialogAwareDataContext(DataContext context) { + for (DataKey key : keys) { + values.put(key.getName(), key.getData(context)); + } + } + + @Override + public Object getData(@NonNls String dataId) { + if (values.keySet().contains(dataId)) { + return values.get(dataId); + } + final Editor editor = (Editor)values.get(EDITOR.getName()); + if (editor != null) { + return DataManager.getInstance().getDataContext(editor.getContentComponent()).getData(dataId); + } + return null; + } +} diff --git a/platform/platform-api/src/com/intellij/openapi/editor/actionSystem/EditorAction.java b/platform/platform-api/src/com/intellij/openapi/editor/actionSystem/EditorAction.java index 217ff70c3fb5..945c52022984 100644 --- a/platform/platform-api/src/com/intellij/openapi/editor/actionSystem/EditorAction.java +++ b/platform/platform-api/src/com/intellij/openapi/editor/actionSystem/EditorAction.java @@ -26,6 +26,8 @@ import org.jetbrains.annotations.Nullable; import java.awt.event.KeyEvent; +import static com.intellij.openapi.actionSystem.CommonDataKeys.PROJECT; + public abstract class EditorAction extends AnAction implements DumbAware { private EditorActionHandler myHandler; private boolean myHandlersLoaded; @@ -126,14 +128,14 @@ public abstract class EditorAction extends AnAction implements DumbAware { } private static DataContext getProjectAwareDataContext(final Editor editor, @NotNull final DataContext original) { - if (CommonDataKeys.PROJECT.getData(original) == editor.getProject()) { - return original; + if (PROJECT.getData(original) == editor.getProject()) { + return new DialogAwareDataContext(original); } return new DataContext() { @Override public Object getData(String dataId) { - if (CommonDataKeys.PROJECT.is(dataId)) { + if (PROJECT.is(dataId)) { return editor.getProject(); } return original.getData(dataId); diff --git a/platform/platform-api/src/com/intellij/openapi/editor/highlighter/FragmentedEditorHighlighter.java b/platform/platform-api/src/com/intellij/openapi/editor/highlighter/FragmentedEditorHighlighter.java index 9cd9ab29f4cd..db138237af81 100644 --- a/platform/platform-api/src/com/intellij/openapi/editor/highlighter/FragmentedEditorHighlighter.java +++ b/platform/platform-api/src/com/intellij/openapi/editor/highlighter/FragmentedEditorHighlighter.java @@ -71,31 +71,17 @@ public class FragmentedEditorHighlighter implements EditorHighlighter { if (range.getEndOffset() >= iterator.getStart()) { int relativeStart = Math.max(iterator.getStart() - range.getStartOffset(), 0); int relativeEnd = Math.min(iterator.getEnd() - range.getStartOffset(), range.getLength() + 1); - boolean merged = false; - if (myMergeByTextAttributes && !myPieces.isEmpty()) { - Element element = myPieces.get(myPieces.size() - 1); - if (element.getEnd() >= offset + relativeStart && - Comparing.equal(element.getAttributes(), iterator.getTextAttributes()) && - Comparing.equal(element.getElementType(), iterator.getTokenType())) { - merged = true; - myPieces.add(new Element(element.getStart(), - offset + relativeEnd, - iterator.getTokenType(), - iterator.getTextAttributes())); - } - } - if (!merged) { - myPieces.add(new Element(offset + relativeStart, - offset + relativeEnd, - iterator.getTokenType(), - iterator.getTextAttributes())); - } + + addElement(new Element(offset + relativeStart, + offset + relativeEnd, + iterator.getTokenType(), + iterator.getTextAttributes())); } if (range.getEndOffset() < iterator.getEnd()) { offset += range.getLength() + 1 + myAdditionalOffset; // myAdditionalOffset because of extra line - for shoene separators int lastEnd = myPieces.isEmpty() ? -1 : myPieces.get(myPieces.size() - 1).getEnd(); - myPieces.add(new Element(Math.max(offset - 1 - myAdditionalOffset, lastEnd), offset, null, TextAttributes.ERASE_MARKER)); + addElement(new Element(Math.max(offset - 1 - myAdditionalOffset, lastEnd), offset, null, TextAttributes.ERASE_MARKER)); index++; continue; } @@ -104,6 +90,26 @@ public class FragmentedEditorHighlighter implements EditorHighlighter { } } + private void addElement(@NotNull Element element) { + boolean merged = false; + if (myMergeByTextAttributes && !myPieces.isEmpty()) { + Element oldElement = myPieces.get(myPieces.size() - 1); + if (oldElement.getEnd() >= element.getStart() && + Comparing.equal(oldElement.getAttributes(), element.getAttributes()) && + Comparing.equal(oldElement.getElementType(), element.getElementType())) { + merged = true; + myPieces.remove(myPieces.size() - 1); + myPieces.add(new Element(oldElement.getStart(), + element.getEnd(), + element.getElementType(), + element.getAttributes())); + } + } + if (!merged) { + myPieces.add(element); + } + } + @NotNull @Override public HighlighterIterator createIterator(int startOffset) { diff --git a/platform/platform-api/src/com/intellij/openapi/fileChooser/FileChooserDescriptorFactory.java b/platform/platform-api/src/com/intellij/openapi/fileChooser/FileChooserDescriptorFactory.java index 1e43287a1d94..c958dbca878e 100644 --- a/platform/platform-api/src/com/intellij/openapi/fileChooser/FileChooserDescriptorFactory.java +++ b/platform/platform-api/src/com/intellij/openapi/fileChooser/FileChooserDescriptorFactory.java @@ -19,9 +19,11 @@ import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.ui.UIBundle; +import org.jetbrains.annotations.NotNull; public class FileChooserDescriptorFactory { - private FileChooserDescriptorFactory() { } + private FileChooserDescriptorFactory() { + } public static FileChooserDescriptor createAllButJarContentsDescriptor() { return new FileChooserDescriptor(true, true, true, true, false, true); @@ -83,7 +85,18 @@ public class FileChooserDescriptorFactory { } public static FileChooserDescriptor createSingleFileDescriptor(final FileType fileType) { - return new FileChooserDescriptor(true, false, false, false, false, false) { + return createSingleFileDescriptor(fileType, false); + } + + /** + * Creates file descriptor with certain type and (possible) folders. + * @param fileType supported type + * @param supportDirectories support directories or not + * @return descriptor + */ + @NotNull + public static FileChooserDescriptor createSingleFileDescriptor(final FileType fileType, final boolean supportDirectories) { + return new FileChooserDescriptor(true, supportDirectories, false, false, false, false) { @Override public boolean isFileVisible(final VirtualFile file, final boolean showHiddenFiles) { return file.isDirectory() || file.getFileType() == fileType; @@ -91,18 +104,22 @@ public class FileChooserDescriptorFactory { @Override public boolean isFileSelectable(final VirtualFile file) { - return super.isFileSelectable(file) && file.getFileType() == fileType; + return super.isFileSelectable(file) && (file.getFileType() == fileType || ((file.isDirectory() && supportDirectories))); } }; } - /** @deprecated use {@link #createSingleFileNoJarsDescriptor()} (to be removed in IDEA 15) */ + /** + * @deprecated use {@link #createSingleFileNoJarsDescriptor()} (to be removed in IDEA 15) + */ @SuppressWarnings({"UnusedDeclaration", "deprecation"}) public static FileChooserDescriptorBuilder onlyFiles() { return FileChooserDescriptorBuilder.onlyFiles(); } - /** @deprecated use {@link #createSingleFileOrFolderDescriptor()} ()} (to be removed in IDEA 15) */ + /** + * @deprecated use {@link #createSingleFileOrFolderDescriptor()} ()} (to be removed in IDEA 15) + */ @SuppressWarnings({"UnusedDeclaration", "deprecation"}) public static FileChooserDescriptorBuilder filesAndFolders() { return FileChooserDescriptorBuilder.filesAndFolders(); diff --git a/platform/platform-api/src/com/intellij/openapi/fileEditor/FileEditorManager.java b/platform/platform-api/src/com/intellij/openapi/fileEditor/FileEditorManager.java index 366f69db9cc6..b9589574059d 100644 --- a/platform/platform-api/src/com/intellij/openapi/fileEditor/FileEditorManager.java +++ b/platform/platform-api/src/com/intellij/openapi/fileEditor/FileEditorManager.java @@ -30,7 +30,7 @@ public abstract class FileEditorManager { public static final Key<Boolean> USE_CURRENT_WINDOW = Key.create("OpenFile.searchForOpen"); - public static FileEditorManager getInstance(Project project) { + public static FileEditorManager getInstance(@NotNull Project project) { return project.getComponent(FileEditorManager.class); } diff --git a/platform/platform-api/src/com/intellij/openapi/fileEditor/OpenFileDescriptor.java b/platform/platform-api/src/com/intellij/openapi/fileEditor/OpenFileDescriptor.java index 9ec804def43d..fdf32b9adcba 100644 --- a/platform/platform-api/src/com/intellij/openapi/fileEditor/OpenFileDescriptor.java +++ b/platform/platform-api/src/com/intellij/openapi/fileEditor/OpenFileDescriptor.java @@ -55,34 +55,31 @@ public class OpenFileDescriptor implements Navigatable { private boolean myUseCurrentWindow = false; public OpenFileDescriptor(@NotNull Project project, @NotNull VirtualFile file, int offset) { - this(project, file, -1, -1, offset, null, false); + this(project, file, -1, -1, offset, false); } public OpenFileDescriptor(@NotNull Project project, @NotNull VirtualFile file, int logicalLine, int logicalColumn) { - this(project, file, logicalLine, logicalColumn, -1, null, false); + this(project, file, logicalLine, logicalColumn, -1, false); } public OpenFileDescriptor(@NotNull Project project, @NotNull VirtualFile file, int logicalLine, int logicalColumn, boolean persistent) { - this(project, file, logicalLine, logicalColumn, -1, null, persistent); + this(project, file, logicalLine, logicalColumn, -1, persistent); } public OpenFileDescriptor(@NotNull Project project, @NotNull VirtualFile file) { - this(project, file, -1, -1, -1, null, false); + this(project, file, -1, -1, -1, false); } private OpenFileDescriptor(@NotNull Project project, @NotNull VirtualFile file, - int logicalLine, int logicalColumn, int offset, @Nullable RangeMarker rangeMarker, boolean persistent) { + int logicalLine, int logicalColumn, int offset, boolean persistent) { myProject = project; myFile = file; myLogicalLine = logicalLine; myLogicalColumn = logicalColumn; myOffset = offset; - if (rangeMarker != null) { - myRangeMarker = rangeMarker; - } - else if (offset >= 0) { + if (offset >= 0) { myRangeMarker = LazyRangeMarkerFactory.getInstance(project).createRangeMarker(file, offset); } else if (logicalLine >= 0 ){ diff --git a/platform/platform-api/src/com/intellij/openapi/ui/Banner.java b/platform/platform-api/src/com/intellij/openapi/ui/Banner.java index 3f4a92aec5ff..8dbe02228bae 100644 --- a/platform/platform-api/src/com/intellij/openapi/ui/Banner.java +++ b/platform/platform-api/src/com/intellij/openapi/ui/Banner.java @@ -16,6 +16,8 @@ package com.intellij.openapi.ui; import com.intellij.icons.AllIcons; +import com.intellij.openapi.options.OptionsBundle; +import com.intellij.openapi.project.Project; import com.intellij.ui.components.labels.LinkLabel; import com.intellij.ui.components.labels.LinkListener; import com.intellij.ui.components.panels.NonOpaquePanel; @@ -35,7 +37,7 @@ import java.util.Set; class Banner extends NonOpaquePanel implements PropertyChangeListener{ private int myBannerMinHeight; private final JComponent myText = new MyText(); - + private final JLabel myProjectIcon = new JLabel(AllIcons.General.ProjectConfigurableBanner, SwingConstants.LEFT); private final NonOpaquePanel myActionsPanel = new NonOpaquePanel(new FlowLayout(FlowLayout.RIGHT, 2, 2)); private final Map<Action, LinkLabel> myActions = new HashMap<Action, LinkLabel>(); @@ -45,7 +47,10 @@ class Banner extends NonOpaquePanel implements PropertyChangeListener{ setBorder(new EmptyBorder(2, 6, 2, 4)); - add(myText, BorderLayout.CENTER); + myProjectIcon.setVisible(false); + myProjectIcon.setBorder(new EmptyBorder(0, 12, 0, 4)); + add(myText, BorderLayout.WEST); + add(myProjectIcon, BorderLayout.CENTER); add(myActionsPanel, BorderLayout.EAST); } @@ -112,6 +117,17 @@ class Banner extends NonOpaquePanel implements PropertyChangeListener{ repaint(); } + public void forProject(Project project) { + if (project != null) { + myProjectIcon.setVisible(true); + myProjectIcon.setText(OptionsBundle.message(project.isDefault() + ? "configurable.default.project.tooltip" + : "configurable.current.project.tooltip")); + } else { + myProjectIcon.setVisible(false); + } + } + public void setText(@NotNull final String... text) { myText.removeAll(); for (int i = 0; i < text.length; i++) { diff --git a/platform/platform-api/src/com/intellij/openapi/ui/ComboBoxTableRenderer.java b/platform/platform-api/src/com/intellij/openapi/ui/ComboBoxTableRenderer.java index 5d2ecafb1b7e..c02f27af5d4b 100644 --- a/platform/platform-api/src/com/intellij/openapi/ui/ComboBoxTableRenderer.java +++ b/platform/platform-api/src/com/intellij/openapi/ui/ComboBoxTableRenderer.java @@ -46,6 +46,7 @@ public class ComboBoxTableRenderer<T> extends JLabel implements TableCellRendere private WeakReference<ListPopup> myPopupRef; private ChangeEvent myChangeEvent = null; private T myValue; + private boolean myPaintArrow = true; protected EventListenerList myListenerList = new EventListenerList(); @@ -80,6 +81,10 @@ public class ComboBoxTableRenderer<T> extends JLabel implements TableCellRendere return null; } + public void setPaintArrow(final boolean paintArrow) { + myPaintArrow = paintArrow; + } + protected Runnable onChosen(@NotNull final T value) { stopCellEditing(value); @@ -94,7 +99,7 @@ public class ComboBoxTableRenderer<T> extends JLabel implements TableCellRendere protected void paintComponent(Graphics g) { super.paintComponent(g); - if (!StringUtil.isEmpty(getText())) { + if (!StringUtil.isEmpty(getText()) && myPaintArrow) { final Rectangle r = getBounds(); final Insets i = getInsets(); final int x = r.width - i.right - AllIcons.General.ArrowDown.getIconWidth(); diff --git a/platform/platform-api/src/com/intellij/openapi/ui/DetailsComponent.java b/platform/platform-api/src/com/intellij/openapi/ui/DetailsComponent.java index 34aaa93d2741..463d950ae900 100644 --- a/platform/platform-api/src/com/intellij/openapi/ui/DetailsComponent.java +++ b/platform/platform-api/src/com/intellij/openapi/ui/DetailsComponent.java @@ -16,7 +16,7 @@ package com.intellij.openapi.ui; -import com.intellij.openapi.util.registry.Registry; +import com.intellij.openapi.project.Project; import com.intellij.ui.components.panels.NonOpaquePanel; import com.intellij.ui.components.panels.Wrapper; import com.intellij.util.ArrayUtil; @@ -45,15 +45,21 @@ public class DetailsComponent { private final NonOpaquePanel myBanner; private String[] myBannerText; - private boolean myDetailsEnabled = !Registry.is("ide.new.project.settings"); + private boolean myDetailsEnabled; private String[] myPrefix; private String[] myText; private final Wrapper myContentGutter = new Wrapper(); - private boolean myPaintBorder = !Registry.is("ide.new.project.settings"); + private boolean myPaintBorder; public DetailsComponent() { + this(true, true); + } + + public DetailsComponent(boolean detailsEnabled, boolean paintBorder) { + myDetailsEnabled = detailsEnabled; + myPaintBorder = paintBorder; myComponent = new JPanel(new BorderLayout()) { @Override protected void paintComponent(final Graphics g) { @@ -110,7 +116,7 @@ public class DetailsComponent { myBanner = new NonOpaquePanel(new BorderLayout()); myBannerLabel = new Banner(); - if (!Registry.is("ide.new.project.settings")) { + if (myDetailsEnabled) { myBanner.add(myBannerLabel, BorderLayout.CENTER); } @@ -174,6 +180,9 @@ public class DetailsComponent { } } + public void forProject(Project project) { + myBannerLabel.forProject(project); + } public void setPrefix(@Nullable String... prefix) { myPrefix = prefix; diff --git a/platform/platform-api/src/com/intellij/openapi/ui/FixedComboBoxEditor.java b/platform/platform-api/src/com/intellij/openapi/ui/FixedComboBoxEditor.java index 25c52c75b077..6ef25dddb5bc 100644 --- a/platform/platform-api/src/com/intellij/openapi/ui/FixedComboBoxEditor.java +++ b/platform/platform-api/src/com/intellij/openapi/ui/FixedComboBoxEditor.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2010 JetBrains s.r.o. + * 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. @@ -17,6 +17,7 @@ package com.intellij.openapi.ui; import com.intellij.openapi.util.SystemInfo; import com.intellij.ui.Gray; +import com.intellij.util.ReflectionUtil; import com.intellij.util.ui.MacUIUtil; import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.Nullable; @@ -34,7 +35,6 @@ import java.awt.event.FocusEvent; import java.awt.event.FocusListener; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; -import java.lang.reflect.Field; import java.lang.reflect.Method; /** @@ -118,17 +118,7 @@ public class FixedComboBoxEditor implements ComboBoxEditor { final ComboBoxUI ui = comboBox.getUI(); ComboPopup popup = null; if (ui instanceof BasicComboBoxUI) { - try { - final Field popupField = BasicComboBoxUI.class.getDeclaredField("popup"); - popupField.setAccessible(true); - popup = (ComboPopup)popupField.get(ui); - } - catch (NoSuchFieldException e1) { - popup = null; - } - catch (IllegalAccessException e1) { - popup = null; - } + popup = ReflectionUtil.getField(BasicComboBoxUI.class, ui, ComboPopup.class, "popup"); } return popup; diff --git a/platform/platform-api/src/com/intellij/openapi/ui/MasterDetailsComponent.java b/platform/platform-api/src/com/intellij/openapi/ui/MasterDetailsComponent.java index 816349ed1c37..6c13964d5789 100644 --- a/platform/platform-api/src/com/intellij/openapi/ui/MasterDetailsComponent.java +++ b/platform/platform-api/src/com/intellij/openapi/ui/MasterDetailsComponent.java @@ -111,7 +111,7 @@ public abstract class MasterDetailsComponent implements Configurable, DetailsCom protected MyNode myRoot = new MyRootNode(); protected Tree myTree = new Tree(); - private final DetailsComponent myDetails = new DetailsComponent(); + private final DetailsComponent myDetails = new DetailsComponent(!Registry.is("ide.new.project.settings"), !Registry.is("ide.new.project.settings")); protected JPanel myWholePanel; public JPanel myNorthPanel = new JPanel(new BorderLayout()); @@ -131,12 +131,9 @@ public abstract class MasterDetailsComponent implements Configurable, DetailsCom protected MasterDetailsComponent(MasterDetailsState state) { myState = state; - mySplitter = new JBSplitter(false, .2f); + mySplitter = Registry.is("ide.new.project.settings") ? new OnePixelSplitter(false, .2f) : new JBSplitter(false, .2f); mySplitter.setSplitterProportionKey("ProjectStructure.SecondLevelElements"); mySplitter.setHonorComponentsMinimumSize(true); - if (Registry.is("ide.new.project.settings")) { - mySplitter.setOnePixelMode(); - } installAutoScroll(); reInitWholePanelIfNeeded(); @@ -300,6 +297,7 @@ public abstract class MasterDetailsComponent implements Configurable, DetailsCom @NotNull public JComponent createComponent() { + myTree.updateUI(); reInitWholePanelIfNeeded(); updateSelectionFromTree(); @@ -962,7 +960,11 @@ public abstract class MasterDetailsComponent implements Configurable, DetailsCom myPreselection != null ? myPreselection.getDefaultIndex() : 0, true); final ListPopup listPopup = popupFactory.createListPopup(step); listPopup.setHandleAutoSelectionBeforeShow(true); - listPopup.showUnderneathOf(myNorthPanel); + if (e instanceof AnActionButton.AnActionEventWrapper) { + ((AnActionButton.AnActionEventWrapper)e).showPopup(listPopup); + } else { + listPopup.showUnderneathOf(myNorthPanel); + } } } diff --git a/platform/platform-api/src/com/intellij/openapi/ui/NamedConfigurable.java b/platform/platform-api/src/com/intellij/openapi/ui/NamedConfigurable.java index 12b84f8db465..e619473197e7 100644 --- a/platform/platform-api/src/com/intellij/openapi/ui/NamedConfigurable.java +++ b/platform/platform-api/src/com/intellij/openapi/ui/NamedConfigurable.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * 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. @@ -18,10 +18,12 @@ package com.intellij.openapi.ui; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.options.Configurable; +import com.intellij.openapi.util.registry.Registry; import com.intellij.ui.DocumentAdapter; import org.jetbrains.annotations.Nullable; import javax.swing.*; +import javax.swing.border.EmptyBorder; import javax.swing.event.DocumentEvent; import java.awt.*; @@ -55,6 +57,11 @@ public abstract class NamedConfigurable<T> implements Configurable { } }); } + if (Registry.is("ide.new.project.settings")) { + myNamePanel.setBorder(new EmptyBorder(10, 10, 6, 10)); + } else { + myNamePanel.setBorder(new EmptyBorder(0,0,0,0)); + } } public boolean isNameEditable() { diff --git a/platform/platform-api/src/com/intellij/openapi/ui/OnePixelDivider.java b/platform/platform-api/src/com/intellij/openapi/ui/OnePixelDivider.java new file mode 100644 index 000000000000..2b0097005dc1 --- /dev/null +++ b/platform/platform-api/src/com/intellij/openapi/ui/OnePixelDivider.java @@ -0,0 +1,233 @@ +/* + * 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.ui; + +import com.intellij.openapi.Disposable; +import com.intellij.openapi.util.Disposer; +import com.intellij.openapi.util.SystemInfo; +import com.intellij.openapi.util.Weighted; +import com.intellij.openapi.wm.IdeGlassPane; +import com.intellij.openapi.wm.IdeGlassPaneUtil; +import com.intellij.ui.Gray; +import com.intellij.ui.JBColor; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; + +/** + * @author Konstantin Bulenkov + */ +public class OnePixelDivider extends Divider { + private boolean myVertical; + private Splitter mySplitter; + private boolean myResizeEnabled; + private boolean mySwitchOrientationEnabled; + protected Point myPoint; + private IdeGlassPane myGlassPane; + private final MouseAdapter myListener = new MyMouseAdapter(); + private Disposable myDisposable; + + public OnePixelDivider(boolean vertical, Splitter splitter) { + super(new GridBagLayout()); + mySplitter = splitter; + myResizeEnabled = true; + mySwitchOrientationEnabled = false; + setFocusable(false); + enableEvents(AWTEvent.MOUSE_EVENT_MASK | AWTEvent.MOUSE_MOTION_EVENT_MASK); + //setOpaque(false); + setOrientation(vertical); + setBackground(new JBColor(Gray._153.withAlpha(128), Gray._100.withAlpha(128))); + } + + @Override + public void addNotify() { + super.addNotify(); + init(); + } + + @Override + public void removeNotify() { + super.removeNotify(); + if (myDisposable != null && !Disposer.isDisposed(myDisposable)) { + Disposer.dispose(myDisposable); + } + } + + private boolean dragging = false; + private class MyMouseAdapter extends MouseAdapter implements Weighted { + @Override + public void mousePressed(MouseEvent e) { + dragging = isInDragZone(e); + _processMouseEvent(e); + } + + boolean isInDragZone(MouseEvent e) { + final MouseEvent event = getTargetEvent(e); + final Point p = event.getPoint(); + final int r = Math.abs(isVertical() ? p.y : p.x); + return r < 6; + } + + @Override + public void mouseReleased(MouseEvent e) { + _processMouseEvent(e); + dragging = false; + } + + @Override + public void mouseMoved(MouseEvent e) { + final OnePixelDivider divider = OnePixelDivider.this; + if (isInDragZone(e)) { + myGlassPane.setCursor(divider.getCursor(), divider); + } else { + myGlassPane.setCursor(null, divider); + } + _processMouseMotionEvent(e); + } + + @Override + public void mouseDragged(MouseEvent e) { + _processMouseMotionEvent(e); + } + @Override + public double getWeight() { + return 1; + } + private void _processMouseMotionEvent(MouseEvent e) { + MouseEvent event = getTargetEvent(e); + if (event == null) { + myGlassPane.setCursor(null, myListener); + return; + } + + processMouseMotionEvent(event); + if (event.isConsumed()) { + e.consume(); + } + } + + private void _processMouseEvent(MouseEvent e) { + MouseEvent event = getTargetEvent(e); + if (event == null) { + myGlassPane.setCursor(null, myListener); + return; + } + + processMouseEvent(event); + if (event.isConsumed()) { + e.consume(); + } + } + } + + private MouseEvent getTargetEvent(MouseEvent e) { + return SwingUtilities.convertMouseEvent(e.getComponent(), e, this); + } + + private void init() { + myGlassPane = IdeGlassPaneUtil.find(this); + myDisposable = Disposer.newDisposable(); + myGlassPane.addMouseMotionPreprocessor(myListener, myDisposable); + myGlassPane.addMousePreprocessor(myListener, myDisposable); + } + + public void setOrientation(boolean vertical) { + removeAll(); + myVertical = vertical; + final int cursorType = isVertical() ? Cursor.N_RESIZE_CURSOR : Cursor.W_RESIZE_CURSOR; + setCursor(Cursor.getPredefinedCursor(cursorType)); + } + + @Override + protected void processMouseMotionEvent(MouseEvent e) { + super.processMouseMotionEvent(e); + if (!myResizeEnabled) return; + if (MouseEvent.MOUSE_DRAGGED == e.getID() && dragging) { + myPoint = SwingUtilities.convertPoint(this, e.getPoint(), mySplitter); + float proportion; + final float firstMinProportion = getMinProportion(mySplitter.getFirstComponent()); + final float secondMinProportion = getMinProportion(mySplitter.getSecondComponent()); + if (isVertical()) { + if (getHeight() > 0) { + proportion = Math.min(1.0f, Math + .max(.0f, Math.min(Math.max(firstMinProportion, (float)myPoint.y / (float)mySplitter.getHeight()), 1 - secondMinProportion))); + mySplitter.setProportion(proportion); + } + } + else { + if (getWidth() > 0) { + proportion = Math.min(1.0f, Math.max(.0f, Math.min( + Math.max(firstMinProportion, (float)myPoint.x / (float)mySplitter.getWidth()), 1 - secondMinProportion))); + mySplitter.setProportion(proportion); + } + } + } + } + + private float getMinProportion(JComponent component) { + if (component != null && + mySplitter.getFirstComponent() != null && + mySplitter.getFirstComponent().isVisible() && + mySplitter.getSecondComponent() != null && + mySplitter.getSecondComponent().isVisible()) { + if (isVertical()) { + return (float)component.getMinimumSize().height / (float)(mySplitter.getHeight() - 1); + } else { + return (float)component.getMinimumSize().width / (float)(mySplitter.getWidth() - 1); + } + } + + return 0.0f; + } + + @Override + protected void processMouseEvent(MouseEvent e) { + super.processMouseEvent(e); + if (e.getID() == MouseEvent.MOUSE_CLICKED) { + if (mySwitchOrientationEnabled + && e.getClickCount() == 1 + && SwingUtilities.isLeftMouseButton(e) && (SystemInfo.isMac ? e.isMetaDown() : e.isControlDown())) { + mySplitter.setOrientation(!mySplitter.getOrientation()); + } + if (myResizeEnabled && e.getClickCount() == 2) { + mySplitter.setProportion(.5f); + } + } + } + + public void setResizeEnabled(boolean resizeEnabled) { + myResizeEnabled = resizeEnabled; + if (!myResizeEnabled) { + setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); + } + else { + setCursor(isVertical() ? + Cursor.getPredefinedCursor(Cursor.N_RESIZE_CURSOR) : + Cursor.getPredefinedCursor(Cursor.W_RESIZE_CURSOR)); + } + } + + public void setSwitchOrientationEnabled(boolean switchOrientationEnabled) { + mySwitchOrientationEnabled = switchOrientationEnabled; + } + + + public boolean isVertical() { + return myVertical; + } +} diff --git a/platform/platform-api/src/com/intellij/openapi/wm/FocusCommand.java b/platform/platform-api/src/com/intellij/openapi/wm/FocusCommand.java index fc9eec268ece..6c40a04f5831 100644 --- a/platform/platform-api/src/com/intellij/openapi/wm/FocusCommand.java +++ b/platform/platform-api/src/com/intellij/openapi/wm/FocusCommand.java @@ -43,7 +43,7 @@ public abstract class FocusCommand extends ActiveRunnable implements Expirable { private boolean myInvalidatesPendingFurtherRequestors = true; private Expirable myExpirable; - public static final Logger LOG = Logger.getInstance("#com.intellij.openapi.wm.FocusCommand"); + private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.wm.FocusCommand"); public boolean isForced() { return myForced; |