From 84737d253b8f0dd147f8d1290291d4d9716dec59 Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Wed, 15 Dec 2010 17:54:33 +0300 Subject: [PATCH 01/16] IDEA-63127 false positive on mismatched bracket in string --- .../codeInsight/daemon/impl/DefaultHighlightVisitor.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DefaultHighlightVisitor.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DefaultHighlightVisitor.java index 1d2f5e256b31..c569d0cab7f1 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DefaultHighlightVisitor.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DefaultHighlightVisitor.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2010 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. From 87c19d89320ebcac45f896f46010d6d4603e9a9c Mon Sep 17 00:00:00 2001 From: Eugene Kudelevsky Date: Fri, 17 Dec 2010 15:27:34 +0300 Subject: [PATCH 02/16] EA-24555 fix NPE --- .../android/src/org/jetbrains/android/run/DeviceChooser.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/android/src/org/jetbrains/android/run/DeviceChooser.java b/plugins/android/src/org/jetbrains/android/run/DeviceChooser.java index 7dbc0fb1ca5d..5b3966493860 100644 --- a/plugins/android/src/org/jetbrains/android/run/DeviceChooser.java +++ b/plugins/android/src/org/jetbrains/android/run/DeviceChooser.java @@ -255,7 +255,7 @@ public class DeviceChooser extends DialogWrapper implements AndroidDebugBridge.I chooser.show(); avd = chooser.getSelectedAvd(); if (chooser.getExitCode() != OK_EXIT_CODE) return; - assert avd != null; + if (avd == null) return; } myFacet.launchEmulator(avd != null ? avd.getName() : null, "", null); } From 156df98a64c5776cbccfcbc0ee4ae4850c401014 Mon Sep 17 00:00:00 2001 From: Denis Zhdanov Date: Fri, 17 Dec 2010 15:42:44 +0300 Subject: [PATCH 03/16] IDEA-62781 SoftWrapping in Diff View: Breaks Background Coloring 1. Soft wrap introduced virtual space shows the same background as the one used around it now; 2. Added ability to expand selection to soft wraps-introduced virtual space. It's affects only visual representation, no symbols are introduced during, say, performing selection copy to clipboard buffer; --- .../injected/editor/SelectionModelWindow.java | 30 ++- .../openapi/editor/SelectionModel.java | 30 +++ .../openapi/editor/VisualPosition.java | 22 ++ .../openapi/editor/impl/EditorImpl.java | 239 +++++++++++++----- .../editor/impl/SelectionModelImpl.java | 130 +++++++++- .../textarea/TextComponentSelectionModel.java | 26 +- 6 files changed, 406 insertions(+), 71 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/injected/editor/SelectionModelWindow.java b/platform/lang-impl/src/com/intellij/injected/editor/SelectionModelWindow.java index 86aebc669ea3..d094df6e7648 100644 --- a/platform/lang-impl/src/com/intellij/injected/editor/SelectionModelWindow.java +++ b/platform/lang-impl/src/com/intellij/injected/editor/SelectionModelWindow.java @@ -19,12 +19,14 @@ package com.intellij.injected.editor; import com.intellij.openapi.editor.LogicalPosition; import com.intellij.openapi.editor.RangeMarker; import com.intellij.openapi.editor.SelectionModel; -import com.intellij.openapi.editor.markup.TextAttributes; +import com.intellij.openapi.editor.VisualPosition; import com.intellij.openapi.editor.event.SelectionListener; import com.intellij.openapi.editor.ex.EditorEx; -import com.intellij.openapi.util.TextRange; +import com.intellij.openapi.editor.markup.TextAttributes; import com.intellij.openapi.util.ProperTextRange; +import com.intellij.openapi.util.TextRange; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; /** * @author cdr @@ -44,10 +46,22 @@ public class SelectionModelWindow implements SelectionModel { return myDocument.hostToInjected(myHostModel.getSelectionStart()); } + @Nullable + @Override + public VisualPosition getSelectionStartPosition() { + return myHostModel.getSelectionStartPosition(); + } + public int getSelectionEnd() { return myDocument.hostToInjected(myHostModel.getSelectionEnd()); } + @Nullable + @Override + public VisualPosition getSelectionEndPosition() { + return myHostModel.getSelectionEndPosition(); + } + public String getSelectedText() { return myHostModel.getSelectedText(); } @@ -56,6 +70,12 @@ public class SelectionModelWindow implements SelectionModel { return myDocument.hostToInjected(myHostModel.getLeadSelectionOffset()); } + @Nullable + @Override + public VisualPosition getLeadSelectionPosition() { + return myHostModel.getLeadSelectionPosition(); + } + public boolean hasSelection() { return myHostModel.hasSelection(); } @@ -65,6 +85,12 @@ public class SelectionModelWindow implements SelectionModel { myHostModel.setSelection(hostRange.getStartOffset(), hostRange.getEndOffset()); } + @Override + public void setSelection(@NotNull VisualPosition startPosition, int startOffset, @NotNull VisualPosition endPosition, int endOffset) { + TextRange hostRange = myDocument.injectedToHost(new ProperTextRange(startOffset, endOffset)); + myHostModel.setSelection(startPosition, hostRange.getStartOffset(), endPosition, hostRange.getEndOffset()); + } + public void removeSelection() { myHostModel.removeSelection(); } diff --git a/platform/platform-api/src/com/intellij/openapi/editor/SelectionModel.java b/platform/platform-api/src/com/intellij/openapi/editor/SelectionModel.java index 7121c6099b5e..0edb6440b245 100644 --- a/platform/platform-api/src/com/intellij/openapi/editor/SelectionModel.java +++ b/platform/platform-api/src/com/intellij/openapi/editor/SelectionModel.java @@ -39,6 +39,12 @@ public interface SelectionModel { */ int getSelectionStart(); + /** + * @return object that encapsulates information about visual position of selected text start if any + */ + @Nullable + VisualPosition getSelectionStartPosition(); + /** * Returns the end offset in the document of the selected text range, or the caret * position if there is currently no selection. @@ -47,6 +53,12 @@ public interface SelectionModel { */ int getSelectionEnd(); + /** + * @return object that encapsulates information about visual position of selected text end if any; + */ + @Nullable + VisualPosition getSelectionEndPosition(); + /** * Returns the text selected in the editor (or the concatenation of text ranges selected * in each line, if block selection mode is used). @@ -66,6 +78,12 @@ public interface SelectionModel { */ int getLeadSelectionOffset(); + /** + * @return object that encapsulates information about visual position from which the user started to extend the selection if any + */ + @Nullable + VisualPosition getLeadSelectionPosition(); + /** * Checks if a range of text is currently selected in regular (non-block) selection mode. * @@ -83,6 +101,18 @@ public interface SelectionModel { */ void setSelection(int startOffset, int endOffset); + /** + * Selects target range based on its visual boundaries. + *

+ * That is the case for soft wraps-aware processing where the whole soft wraps virtual space is matched to the same offset. + * + * @param startPosition start visual position of the text range to select + * @param endPosition end visual position of the text range to select + * @param startOffset start selection offset + * @param endOffset end selection offset + */ + void setSelection(@NotNull VisualPosition startPosition, int startOffset, @NotNull VisualPosition endPosition, int endOffset); + /** * Removes the selection in the editor. */ diff --git a/platform/platform-api/src/com/intellij/openapi/editor/VisualPosition.java b/platform/platform-api/src/com/intellij/openapi/editor/VisualPosition.java index 231d268d9083..3c8f40c23f75 100644 --- a/platform/platform-api/src/com/intellij/openapi/editor/VisualPosition.java +++ b/platform/platform-api/src/com/intellij/openapi/editor/VisualPosition.java @@ -16,6 +16,7 @@ package com.intellij.openapi.editor; import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; /** * Represents a visual position in the editor. Visual positions take folding into account - @@ -38,6 +39,27 @@ public class VisualPosition { this.column = column; } + /** + * Allows to answer if current visual position is located after the given one. + *

+ * One visual position is considered to be 'after' another only if one of the following is true: + *

+   * 
    + *
  • its visual line is greater;
  • + *
  • it has the same visual line but its column is greater;
  • + *
+ *
+ * + * @param other visual position to compare with the current one + * @return true if current position is 'after' the given one; false otherwise + */ + public boolean after(@NotNull VisualPosition other) { + if (line == other.line) { + return column > other.column; + } + return line > other.line; + } + @NonNls public String toString() { return "VisualPosition: line = " + line + " column = " + column; diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java index 90a56ca7cea2..adea3e7961fb 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java @@ -1270,7 +1270,10 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi if (endOffset > myDocument.getTextLength()) { endOffset = myDocument.getTextLength(); } - if (startOffset < endOffset) { + + // We do repaint in case of equal offsets because there is a possible case that there is a soft wrap at the same offset and + // it does occupy particular amount of visual space that may be necessary to repaint. + if (startOffset <= endOffset) { int startLine = myDocument.getLineNumber(startOffset); int endLine = myDocument.getLineNumber(endOffset); repaintLines(startLine, endLine); @@ -1711,23 +1714,6 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi int start = logicalPositionToOffset(logicalPosition); getSoftWrapModel().registerSoftWrapsIfNecessary(); - // There is a possible case that we need to draw background from the start of soft wrap-introduced visual line. Given position - // has valid 'y' coordinate then at it shouldn't be affected by soft wrap that corresponds to the visual line start offset. - // Hence, we store information about soft wrap to be skipped for further processing and adjust 'x' coordinate value if necessary. - TIntHashSet softWrapsToSkip = new TIntHashSet(); - SoftWrap softWrap = getSoftWrapModel().getSoftWrap(start); - if (softWrap != null) { - softWrapsToSkip.add(softWrap.getStart()); - if (position.y == getCaretModel().getVisualPosition().line * getLineHeight()) { - // There is a possible case that target clip points to soft wrap-introduced visual line and that it's an active - // line (caret cursor is located on it). We want to draw corresponding 'caret line' background for soft wraps-introduced - // virtual space then. - Color caretRowColor = getColorsScheme().getColor(EditorColors.CARET_ROW_COLOR); - drawBackground(g, caretRowColor, softWrap.getIndentInPixels(), position, defaultBackground, clip); - } - position.x = softWrap.getIndentInPixels(); - } - IterationState iterationState = new IterationState(this, start, paintSelection()); LineIterator lIterator = createLineIterator(); @@ -1742,6 +1728,31 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi CharSequence text = myDocument.getCharsNoThreadCheck(); int lastLineIndex = Math.max(0, myDocument.getLineCount() - 1); + // There is a possible case that we need to draw background from the start of soft wrap-introduced visual line. Given position + // has valid 'y' coordinate then at it shouldn't be affected by soft wrap that corresponds to the visual line start offset. + // Hence, we store information about soft wrap to be skipped for further processing and adjust 'x' coordinate value if necessary. + TIntHashSet softWrapsToSkip = new TIntHashSet(); + SoftWrap softWrap = getSoftWrapModel().getSoftWrap(start); + if (softWrap != null) { + softWrapsToSkip.add(softWrap.getStart()); + Color color = null; + if (!backColor.equals(defaultBackground)) { + color = backColor; + } + + // There is a possible case that target clip points to soft wrap-introduced visual line and that it's an active + // line (caret cursor is located on it). We want to draw corresponding 'caret line' background for soft wraps-introduced + // virtual space then. + if (color == null && position.y == getCaretModel().getVisualPosition().line * getLineHeight()) { + color = getColorsScheme().getColor(EditorColors.CARET_ROW_COLOR); + } + + if (color != null) { + drawBackground(g, color, softWrap.getIndentInPixels(), position, defaultBackground, clip); + } + position.x = softWrap.getIndentInPixels(); + } + // There is a possible case that caret is located at soft-wrapped line. We don't need to paint caret row background // on a last visual line of that soft-wrapped line then. Below is a holder for the flag that indicates if caret row // background is already drawn. @@ -1901,7 +1912,11 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi if (startToUse < softWrapStart) { position.x = drawBackground(g, backColor, text.subSequence(startToUse, softWrapStart), position, fontType, defaultBackground, clip); } - drawSoftWrap(g, softWrap, position, fontType, defaultBackground, clip, caretRowPainted); + boolean drawCustomBackgroundAtSoftWrapVirtualSpace = + backColor != defaultBackground && (softWrapStart > start || myLastBackgroundColor == backColor); + drawSoftWrap( + g, softWrap, position, fontType, backColor, drawCustomBackgroundAtSoftWrapVirtualSpace, defaultBackground, clip, caretRowPainted + ); startToUse = softWrapStart; } @@ -1911,65 +1926,157 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi return position.x; } - private void drawSoftWrap(Graphics g, SoftWrap softWrap, Point position, int fontType, Color defaultBackground, Rectangle clip, - boolean[] caretRowPainted) { + private void drawSoftWrap(Graphics g, SoftWrap softWrap, Point position, int fontType, Color backColor, + boolean drawCustomBackgroundAtSoftWrapVirtualSpace, Color defaultBackground, Rectangle clip, + boolean[] caretRowPainted) + { // The main idea is to to do the following: // *) update given drawing position coordinates in accordance with the current soft wrap; - // *) draw 'active line' background at soft wrap-introduced virtual space if necessary; + // *) draw background at soft wrap-introduced virtual space if necessary; CharSequence softWrapText = softWrap.getText(); int activeRowY = getCaretModel().getVisualPosition().line * getLineHeight(); - if (position.y == activeRowY) { + int afterSoftWrapWidth = clip.x + clip.width - position.x; + if (drawCustomBackgroundAtSoftWrapVirtualSpace && backColor != null) { + drawBackground(g, backColor, afterSoftWrapWidth, position, defaultBackground, clip); + } + else if (position.y == activeRowY) { // Draw 'active line' background after soft wrap. Color caretRowColor = getColorsScheme().getColor(EditorColors.CARET_ROW_COLOR); - drawBackground(g, caretRowColor, clip.x + clip.width - position.x, position, defaultBackground, clip); + drawBackground(g, caretRowColor, afterSoftWrapWidth, position, defaultBackground, clip); caretRowPainted[0] = true; } + paintSelectionOnFirstSoftWrapLineIfNecessary(g, position, clip, defaultBackground, fontType); + int i = CharArrayUtil.lastIndexOf(softWrapText, "\n", softWrapText.length()) + 1; - position.x = getTextSegmentWidth(softWrapText.subSequence(i, softWrapText.length()), 0, fontType, clip); - position.x += getSoftWrapModel().getMinDrawingWidthInPixels(SoftWrapDrawingType.AFTER_SOFT_WRAP); + int width = getTextSegmentWidth(softWrapText.subSequence(i, softWrapText.length()), 0, fontType, clip) + + getSoftWrapModel().getMinDrawingWidthInPixels(SoftWrapDrawingType.AFTER_SOFT_WRAP); + position.x = 0; position.y += getLineHeight(); - - if (position.y == activeRowY) { + + if (drawCustomBackgroundAtSoftWrapVirtualSpace && backColor != null) { + drawBackground(g, backColor, width, position, defaultBackground, clip); + } + else if (position.y == activeRowY) { // Draw 'active line' background for the soft wrap-introduced virtual space. Color caretRowColor = getColorsScheme().getColor(EditorColors.CARET_ROW_COLOR); - drawBackground(g, caretRowColor, position.x, new Point(0, activeRowY), defaultBackground, clip); + drawBackground(g, caretRowColor, width, position, defaultBackground, clip); } - - // The code below draws background for soft wrap-introduced virtual space. It's is considered that we don't want - // to do that for now. Uncomment if that decision is changed. - - //position.x = drawBackground( - // g, backColor, getSoftWrapModel().getMinDrawingWidthInPixels(SoftWrapDrawingType.BEFORE_SOFT_WRAP_LINE_FEED), position, - // defaultBackground, clip - //); - // - //CharSequence softWrapText = softWrap.getText(); - //int start = 0; - //for ( - // int end = CharArrayUtil.shiftForwardUntil(softWrapText, start, "\n"); - // start < softWrapText.length() && end < softWrapText.length(); - // end = CharArrayUtil.shiftForwardUntil(softWrapText, start, "\n")) - //{ - // drawBackground(g, backColor, softWrapText.subSequence(start, end), position, fontType, defaultBackground, clip); - // start = end + 1; - // position.x = 0; - // position.y += getLineHeight(); - //} - // - //if (start < softWrapText.length()) { - // position.x = drawBackground( - // g, backColor, softWrapText.subSequence(start, softWrapText.length()), position, fontType, defaultBackground, clip - // ); - //} - // - //position.x = drawBackground( - // g, backColor, getSoftWrapModel().getMinDrawingWidthInPixels(SoftWrapDrawingType.AFTER_SOFT_WRAP), position, - // defaultBackground, clip - //); + + position.x = 0; + paintSelectionOnSecondSoftWrapLineIfNecessary(g, position, clip, defaultBackground, fontType, softWrap); + position.x = width; } + /** + * End user is allowed to perform selection by visual coordinates (e.g. by dragging mouse with left button hold). There is a possible + * case that such a move intersects with soft wrap introduced virtual space. We want to draw corresponding selection background + * there then. + *

+ * This method encapsulates functionality of drawing selection background on the first soft wrap line (e.g. on a visual line where + * it is applied). + * + * @param g graphics to draw on + * @param position current position (assumed to be position of soft wrap appliance) + * @param clip target drawing area boundaries + * @param defaultBackground default background + * @param fontType current font type + */ + private void paintSelectionOnFirstSoftWrapLineIfNecessary(Graphics g, Point position, Rectangle clip, Color defaultBackground, + int fontType) + { + // There is a possible case that the user performed selection at soft wrap virtual space. We need to paint corresponding background + // there then. + VisualPosition selectionStartPosition = getSelectionModel().getSelectionStartPosition(); + VisualPosition selectionEndPosition = getSelectionModel().getSelectionEndPosition(); + if (selectionStartPosition == null || selectionEndPosition == null || selectionStartPosition.equals(selectionEndPosition)) { + return; + } + + int currentVisualLine = position.y / getLineHeight(); + int lastColumn = EditorUtil.getLastVisualLineColumnNumber(this, currentVisualLine); + + // Check if the first soft wrap line is within the visual selection. + if (currentVisualLine < selectionStartPosition.line || currentVisualLine > selectionEndPosition.line + || (currentVisualLine == selectionEndPosition.line && selectionEndPosition.column <= lastColumn)) { + return; + } + + // Adjust 'x' if selection starts at soft wrap virtual space. + final int columnsToSkip = selectionStartPosition.column - lastColumn; + if (columnsToSkip > 0) { + position.x += getSoftWrapModel().getMinDrawingWidthInPixels(SoftWrapDrawingType.BEFORE_SOFT_WRAP_LINE_FEED); + position.x += (columnsToSkip - 1) * EditorUtil.getSpaceWidth(Font.PLAIN, this); + } + + // Calculate selection width. + final int width; + if (selectionEndPosition.line > currentVisualLine) { + width = clip.x + clip.width - position.x; + } + else if (selectionStartPosition.line < currentVisualLine || selectionStartPosition.column <= lastColumn) { + width = getSoftWrapModel().getMinDrawingWidthInPixels(SoftWrapDrawingType.BEFORE_SOFT_WRAP_LINE_FEED) + + (selectionEndPosition.column - lastColumn - 1) * EditorUtil.getSpaceWidth(fontType, this); + } + else { + width = (selectionEndPosition.column - selectionStartPosition.column) * EditorUtil.getSpaceWidth(fontType, this); + } + + drawBackground(g, getColorsScheme().getColor(EditorColors.SELECTION_BACKGROUND_COLOR), width, position, defaultBackground, clip); + } + + /** + * End user is allowed to perform selection by visual coordinates (e.g. by dragging mouse with left button hold). There is a possible + * case that such a move intersects with soft wrap introduced virtual space. We want to draw corresponding selection background + * there then. + *

+ * This method encapsulates functionality of drawing selection background on the second soft wrap line (e.g. on a visual line after + * the one where it is applied). + * + * @param g graphics to draw on + * @param position current position (assumed to be position of soft wrap appliance) + * @param clip target drawing area boundaries + * @param defaultBackground default background + * @param fontType current font type + * @param softWrap target soft wrap which second line virtual space may contain selection + */ + private void paintSelectionOnSecondSoftWrapLineIfNecessary(Graphics g, Point position, Rectangle clip, Color defaultBackground, + int fontType, SoftWrap softWrap) + { + // There is a possible case that the user performed selection at soft wrap virtual space. We need to paint corresponding background + // there then. + VisualPosition selectionStartPosition = getSelectionModel().getSelectionStartPosition(); + VisualPosition selectionEndPosition = getSelectionModel().getSelectionEndPosition(); + if (selectionStartPosition == null || selectionEndPosition == null || selectionStartPosition.equals(selectionEndPosition)) { + return; + } + + int currentVisualLine = position.y / getLineHeight(); + + // Check if the second soft wrap line is within the visual selection. + if (currentVisualLine < selectionStartPosition.line || currentVisualLine > selectionEndPosition.line + || (currentVisualLine == selectionStartPosition.line && selectionStartPosition.column >= softWrap.getIndentInColumns())) { + return; + } + + // Adjust 'x' if selection starts at soft wrap virtual space. + if (selectionStartPosition.line == currentVisualLine && selectionStartPosition.column > 0) { + position.x += selectionStartPosition.column * EditorUtil.getSpaceWidth(fontType, this); + } + + // Calculate selection width. + final int width; + if (selectionEndPosition.line > currentVisualLine || selectionEndPosition.column >= softWrap.getIndentInColumns()) { + width = softWrap.getIndentInPixels() - position.x; + } + else { + width = selectionEndPosition.column * EditorUtil.getSpaceWidth(fontType, this) - position.x; + } + + drawBackground(g, getColorsScheme().getColor(EditorColors.SELECTION_BACKGROUND_COLOR), width, position, defaultBackground, clip); + } + private int drawBackground(Graphics g, Color backColor, CharSequence text, Point position, int fontType, Color defaultBackground, Rectangle clip) { @@ -3278,12 +3385,15 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi SelectionModel selectionModel = getSelectionModel(); int oldSelectionStart = selectionModel.getLeadSelectionOffset(); + VisualPosition oldVisLeadSelectionStart = selectionModel.getLeadSelectionPosition(); int oldCaretOffset = getCaretModel().getOffset(); LogicalPosition oldLogicalCaret = getCaretModel().getLogicalPosition(); + VisualPosition oldVisualCaret = getCaretModel().getVisualPosition(); moveCaretToScreenPos(x, y); getScrollingModel().scrollToCaret(ScrollType.RELATIVE); int newCaretOffset = getCaretModel().getOffset(); + VisualPosition newVisualCaret = getCaretModel().getVisualPosition(); int caretShift = newCaretOffset - mySavedSelectionStart; if (myMousePressedEvent != null && getMouseEventArea(myMousePressedEvent) != EditorMouseEventArea.EDITING_AREA && @@ -3331,7 +3441,12 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi } if (!myMousePressedInsideSelection) { - selectionModel.setSelection(oldSelectionStart, newCaretOffset); + if (oldVisLeadSelectionStart != null) { + selectionModel.setSelection(oldVisLeadSelectionStart, oldSelectionStart, newVisualCaret, newCaretOffset); + } + else { + selectionModel.setSelection(oldSelectionStart, newCaretOffset); + } } else { if (caretShift != 0) { diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/SelectionModelImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/SelectionModelImpl.java index c291207e1c02..b7c7ae24706e 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/SelectionModelImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/SelectionModelImpl.java @@ -50,6 +50,7 @@ import com.intellij.util.ArrayUtil; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.ui.EmptyClipboardOwner; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.awt.*; import java.awt.datatransfer.Clipboard; @@ -70,9 +71,13 @@ public class SelectionModelImpl implements SelectionModel, PrioritizedDocumentLi private DocumentEvent myIsInUpdate; private class MyRangeMarker extends RangeMarkerImpl { + + private VisualPosition myStartPosition; + private VisualPosition myEndPosition; + private boolean myEndPositionIsLead; private boolean myIsReleased; - private MyRangeMarker(DocumentEx document, int start, int end) { + MyRangeMarker(DocumentEx document, int start, int end) { super(document, start, end); myIsReleased = false; } @@ -81,6 +86,34 @@ public class SelectionModelImpl implements SelectionModel, PrioritizedDocumentLi myIsReleased = true; } + @Nullable + public VisualPosition getStartPosition() { + invalidateVisualPositions(); + return myStartPosition; + } + + public void setStartPosition(@NotNull VisualPosition startPosition) { + myStartPosition = startPosition; + } + + @Nullable + public VisualPosition getEndPosition() { + invalidateVisualPositions(); + return myEndPosition; + } + + public void setEndPosition(@NotNull VisualPosition endPosition) { + myEndPosition = endPosition; + } + + public boolean isEndPositionIsLead() { + return myEndPositionIsLead; + } + + public void setEndPositionIsLead(boolean endPositionIsLead) { + myEndPositionIsLead = endPositionIsLead; + } + @Override protected void changedUpdateImpl(DocumentEvent e) { if (myIsReleased) return; @@ -103,6 +136,16 @@ public class SelectionModelImpl implements SelectionModel, PrioritizedDocumentLi protected void registerInDocument() { } + + private void invalidateVisualPositions() { + SoftWrapModelImpl model = myEditor.getSoftWrapModel(); + if ((!myEditor.offsetToVisualPosition(myStart).equals(myStartPosition) && model.getSoftWrap(myStart) == null) + || (!myEditor.offsetToVisualPosition(myEnd).equals(myEndPosition) && model.getSoftWrap(myEnd) == null)) + { + myStartPosition = null; + myEndPosition = null; + } + } } public void beforeDocumentChange(DocumentEvent event) { @@ -138,6 +181,23 @@ public class SelectionModelImpl implements SelectionModel, PrioritizedDocumentLi return myEditor.getCaretModel().getOffset(); } + @NotNull + @Override + public VisualPosition getSelectionStartPosition() { + VisualPosition defaultPosition = myEditor.offsetToVisualPosition(getSelectionStart()); + if (!hasSelection()) { + return defaultPosition; + } + + MyRangeMarker marker = mySelectionMarker.get(); + if (marker == null) { + return defaultPosition; + } + + VisualPosition result = marker.getStartPosition(); + return result == null ? defaultPosition : result; + } + private void validateContext(boolean isWrite) { if (isWrite) { ApplicationManager.getApplication().assertIsDispatchThread(); @@ -162,6 +222,23 @@ public class SelectionModelImpl implements SelectionModel, PrioritizedDocumentLi return myEditor.getCaretModel().getOffset(); } + @NotNull + @Override + public VisualPosition getSelectionEndPosition() { + VisualPosition defaultPosition = myEditor.offsetToVisualPosition(getSelectionEnd()); + if (!hasSelection()) { + return defaultPosition; + } + + MyRangeMarker marker = mySelectionMarker.get(); + if (marker == null) { + return defaultPosition; + } + + VisualPosition result = marker.getEndPosition(); + return result == null ? defaultPosition : result; + } + public boolean hasSelection() { validateContext(false); MyRangeMarker marker = mySelectionMarker.get(); @@ -173,6 +250,17 @@ public class SelectionModelImpl implements SelectionModel, PrioritizedDocumentLi } public void setSelection(int startOffset, int endOffset) { + doSetSelection(myEditor.offsetToVisualPosition(startOffset), startOffset, myEditor.offsetToVisualPosition(endOffset), endOffset, false); + } + + @Override + public void setSelection(@NotNull VisualPosition startPosition, int startOffset, @NotNull VisualPosition endPosition, int endOffset) { + doSetSelection(startPosition, startOffset, endPosition, endOffset, true); + } + + private void doSetSelection(@NotNull VisualPosition startPosition, int startOffset, @NotNull VisualPosition endPosition, + int endOffset, boolean visualPositionAware) + { validateContext(true); removeBlockSelection(); @@ -186,7 +274,7 @@ public class SelectionModelImpl implements SelectionModel, PrioritizedDocumentLi } myLastSelectionStart = startOffset; - if (startOffset == endOffset) { + if (!visualPositionAware && startOffset == endOffset) { removeSelection(); return; } @@ -204,7 +292,7 @@ public class SelectionModelImpl implements SelectionModel, PrioritizedDocumentLi if (hasSelection()) { oldSelectionStart = getSelectionStart(); oldSelectionEnd = getSelectionEnd(); - if (oldSelectionStart == startOffset && oldSelectionEnd == endOffset) return; + if (oldSelectionStart == startOffset && oldSelectionEnd == endOffset && !visualPositionAware) return; } else { oldSelectionStart = oldSelectionEnd = myEditor.getCaretModel().getOffset(); @@ -215,7 +303,20 @@ public class SelectionModelImpl implements SelectionModel, PrioritizedDocumentLi marker.release(); } - mySelectionMarker.set(new MyRangeMarker((DocumentEx)doc, startOffset, endOffset)); + marker = new MyRangeMarker((DocumentEx)doc, startOffset, endOffset); + if (visualPositionAware) { + if (endPosition.after(startPosition)) { + marker.setStartPosition(startPosition); + marker.setEndPosition(endPosition); + marker.setEndPositionIsLead(false); + } + else { + marker.setStartPosition(endPosition); + marker.setEndPosition(startPosition); + marker.setEndPositionIsLead(true); + } + } + mySelectionMarker.set(marker); fireSelectionChanged(oldSelectionStart, oldSelectionEnd, startOffset, endOffset); @@ -432,7 +533,7 @@ public class SelectionModelImpl implements SelectionModel, PrioritizedDocumentLi int selectionEnd = getSelectionEnd(); return text.subSequence(selectionStart, selectionEnd).toString(); } - + private static void appendCharSequence(@NotNull StringBuffer buf, @NotNull CharSequence s, int srcOffset, int len) { if (srcOffset < 0 || len < 0 || srcOffset > s.length() - len) { throw new IndexOutOfBoundsException("srcOffset " + srcOffset + ", len " + len + ", s.length() " + s.length()); @@ -446,7 +547,6 @@ public class SelectionModelImpl implements SelectionModel, PrioritizedDocumentLi } } - public int getLeadSelectionOffset() { validateContext(false); int caretOffset = myEditor.getCaretModel().getOffset(); @@ -466,6 +566,24 @@ public class SelectionModelImpl implements SelectionModel, PrioritizedDocumentLi return caretOffset; } + @NotNull + @Override + public VisualPosition getLeadSelectionPosition() { + MyRangeMarker marker = mySelectionMarker.get(); + VisualPosition caretPosition = myEditor.getCaretModel().getVisualPosition(); + if (marker == null) { + return caretPosition; + } + + VisualPosition startPosition = marker.getStartPosition(); + VisualPosition endPosition = marker.getEndPosition(); + if (startPosition == null || endPosition == null) { + return caretPosition; + } + + return marker.isEndPositionIsLead() ? endPosition : startPosition; + } + public void selectLineAtCaret() { validateContext(true); int lineNumber = myEditor.getCaretModel().getLogicalPosition().line; diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/textarea/TextComponentSelectionModel.java b/platform/platform-impl/src/com/intellij/openapi/editor/textarea/TextComponentSelectionModel.java index dff4311b4789..c5bd698e5777 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/textarea/TextComponentSelectionModel.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/textarea/TextComponentSelectionModel.java @@ -20,10 +20,11 @@ import com.intellij.openapi.actionSystem.IdeActions; import com.intellij.openapi.editor.LogicalPosition; import com.intellij.openapi.editor.RangeMarker; import com.intellij.openapi.editor.SelectionModel; -import com.intellij.openapi.editor.markup.TextAttributes; +import com.intellij.openapi.editor.VisualPosition; import com.intellij.openapi.editor.actionSystem.EditorActionHandler; import com.intellij.openapi.editor.actionSystem.EditorActionManager; import com.intellij.openapi.editor.event.SelectionListener; +import com.intellij.openapi.editor.markup.TextAttributes; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -45,10 +46,22 @@ public class TextComponentSelectionModel implements SelectionModel { return myTextComponent.getSelectionStart(); } + @Nullable + @Override + public VisualPosition getSelectionStartPosition() { + return null; + } + public int getSelectionEnd() { return myTextComponent.getSelectionEnd(); } + @Nullable + @Override + public VisualPosition getSelectionEndPosition() { + return null; + } + @Nullable public String getSelectedText() { return myTextComponent.getSelectedText(); @@ -61,6 +74,12 @@ public class TextComponentSelectionModel implements SelectionModel { return caretPosition == start ? end : start; } + @Nullable + @Override + public VisualPosition getLeadSelectionPosition() { + return null; + } + public boolean hasSelection() { return myTextComponent.getSelectionStart() != myTextComponent.getSelectionEnd(); } @@ -76,6 +95,11 @@ public class TextComponentSelectionModel implements SelectionModel { } } + @Override + public void setSelection(@NotNull VisualPosition startPosition, int startOffset, @NotNull VisualPosition endPosition, int endOffset) { + setSelection(startOffset, endOffset); + } + public void removeSelection() { final int position = myTextComponent.getCaretPosition(); myTextComponent.select(position, position); From eb130ea93e4a7c59df5432c60c3c4be96319db1d Mon Sep 17 00:00:00 2001 From: Denis Zhdanov Date: Fri, 17 Dec 2010 15:44:55 +0300 Subject: [PATCH 04/16] Corrected (x; y) -> visual position mapping for the points that lay beyond soft wrap appliance point at the same visual line --- .../src/com/intellij/openapi/editor/impl/EditorImpl.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java index adea3e7961fb..db08112e8a55 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java @@ -923,6 +923,9 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi if (x >= px) { onSoftWrapDrawing = true; } + else { + column++; + } break outer; } else { From f5524341e63d1d8ab97124f5b916f0bcd43af452 Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Thu, 16 Dec 2010 20:07:43 +0300 Subject: [PATCH 05/16] IDEA-63054: HTML 5 support bug with xhtml files --- .../source/html/dtd/HtmlNSDescriptorImpl.java | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/xml/impl/src/com/intellij/psi/impl/source/html/dtd/HtmlNSDescriptorImpl.java b/xml/impl/src/com/intellij/psi/impl/source/html/dtd/HtmlNSDescriptorImpl.java index 86b561363c42..85717dc84ffe 100644 --- a/xml/impl/src/com/intellij/psi/impl/source/html/dtd/HtmlNSDescriptorImpl.java +++ b/xml/impl/src/com/intellij/psi/impl/source/html/dtd/HtmlNSDescriptorImpl.java @@ -24,6 +24,8 @@ import com.intellij.psi.xml.XmlFile; import com.intellij.psi.xml.XmlTag; import com.intellij.xml.XmlElementDescriptor; import com.intellij.xml.XmlNSDescriptor; +import com.intellij.xml.impl.schema.TypeDescriptor; +import com.intellij.xml.impl.schema.XmlNSTypeDescriptorProvider; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -33,7 +35,7 @@ import java.util.Map; /** * @author Maxim.Mossienko */ -public class HtmlNSDescriptorImpl implements XmlNSDescriptor, DumbAware { +public class HtmlNSDescriptorImpl implements XmlNSDescriptor, DumbAware, XmlNSTypeDescriptorProvider { private XmlNSDescriptor myDelegate; private boolean myRelaxed; private boolean myCaseSensitive; @@ -126,4 +128,16 @@ public class HtmlNSDescriptorImpl implements XmlNSDescriptor, DumbAware { public Object[] getDependences() { return myDelegate == null ? null : myDelegate.getDependences(); } + + @Override + public TypeDescriptor getTypeDescriptor(String name, XmlTag context) { + return myDelegate instanceof XmlNSTypeDescriptorProvider ? + ((XmlNSTypeDescriptorProvider)myDelegate).getTypeDescriptor(name, context) : null; + } + + @Override + public TypeDescriptor getTypeDescriptor(XmlTag descriptorTag) { + return myDelegate instanceof XmlNSTypeDescriptorProvider ? + ((XmlNSTypeDescriptorProvider)myDelegate).getTypeDescriptor(descriptorTag) : null; + } } From dc804bc1b67aa05ed418b51d83300367fbec8349 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Fri, 17 Dec 2010 15:37:24 +0300 Subject: [PATCH 06/16] assertion text --- .../com/intellij/psi/impl/PsiDocumentManagerImpl.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/psi/impl/PsiDocumentManagerImpl.java b/platform/lang-impl/src/com/intellij/psi/impl/PsiDocumentManagerImpl.java index 52e40566c43a..fe56c7d34a60 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/PsiDocumentManagerImpl.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/PsiDocumentManagerImpl.java @@ -34,6 +34,7 @@ import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.Computable; import com.intellij.openapi.util.Key; import com.intellij.openapi.util.Ref; @@ -487,11 +488,14 @@ public class PsiDocumentManagerImpl extends PsiDocumentManager implements Projec if (x) { myBlockSupport.reparseRange(file, startOffset, endOffset, lengthShift, chars); } + String fileText = file.getText(); + String documentText = document.getText(); throw new AssertionError("commitDocument left PSI inconsistent; file len=" + file.getTextLength() + "; doc len=" + document.getTextLength() + - "; file text=" + file.getText() + - "; doc text=" + document.getText() + - "; old file text=" + oldText); + "; doc.getText() == file.getText(): " + Comparing.equal(fileText, documentText) + + ";\n file text=" + fileText + + ";\n doc text=" + documentText + + ";\n old file text=" + oldText); } throw new AssertionError("commitDocument left PSI inconsistent: " + file); From 91a3737ae5cf64525308138f898af001cd6cfbc3 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Fri, 17 Dec 2010 15:37:51 +0300 Subject: [PATCH 07/16] javadoc --- .../lang-impl/src/com/intellij/psi/impl/PsiManagerEx.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/platform/lang-impl/src/com/intellij/psi/impl/PsiManagerEx.java b/platform/lang-impl/src/com/intellij/psi/impl/PsiManagerEx.java index c519336ac5df..d4678f1849fa 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/PsiManagerEx.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/PsiManagerEx.java @@ -41,10 +41,16 @@ public abstract class PsiManagerEx extends PsiManager { @NotNull public abstract ResolveCache getResolveCache(); + /** + * @param runnable to be run before physical PSI change + */ public abstract void registerRunnableToRunOnChange(@NotNull Runnable runnable); public abstract void registerWeakRunnableToRunOnChange(@NotNull Runnable runnable); + /** + * @param runnable to be run before physical or non-physical PSI change + */ public abstract void registerRunnableToRunOnAnyChange(@NotNull Runnable runnable); public abstract void registerRunnableToRunAfterAnyChange(@NotNull Runnable runnable); From a746f42b0398f56f2472e135c8e0001366772a57 Mon Sep 17 00:00:00 2001 From: Dmitry Trofimov Date: Fri, 17 Dec 2010 16:16:34 +0300 Subject: [PATCH 08/16] added env variable about runnerw.exe location --- .../execution/process/RunnerMediator.java | 22 ++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/execution/process/RunnerMediator.java b/platform/platform-impl/src/com/intellij/execution/process/RunnerMediator.java index 3c5b8277af29..87f8af1ca40f 100644 --- a/platform/platform-impl/src/com/intellij/execution/process/RunnerMediator.java +++ b/platform/platform-impl/src/com/intellij/execution/process/RunnerMediator.java @@ -20,6 +20,7 @@ import com.intellij.execution.configurations.GeneralCommandLine; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.SystemInfo; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.io.File; import java.io.OutputStream; @@ -33,6 +34,7 @@ public class RunnerMediator { private static final char IAC = (char)5; private static final char BRK = (char)3; + private static final String STANDARD_RUNNERW = "runnerw.exe"; /** * Creates default runner mediator @@ -84,10 +86,17 @@ public class RunnerMediator { return new CustomDestroyProcessHandler(process, commandLine); } - + @Nullable private String getRunnerPath() { - if (File.separatorChar == '\\') { - return "runnerw.exe"; + if (isWindows()) { + final String path = System.getenv("IDEA_RUNNERW"); + if (path != null && new File(path).exists()) { + return path; + } + if (new File(STANDARD_RUNNERW).exists()) { + return STANDARD_RUNNERW; + } + return null; } else { throw new IllegalStateException("There is no need of runner under unix based OS"); @@ -95,8 +104,11 @@ public class RunnerMediator { } private void injectRunnerCommand(@NotNull GeneralCommandLine commandLine) { - commandLine.getParametersList().addAt(0, commandLine.getExePath()); - commandLine.setExePath(getRunnerPath()); + final String path = getRunnerPath(); + if (path != null) { + commandLine.getParametersList().addAt(0, commandLine.getExePath()); + commandLine.setExePath(path); + } } public static boolean isUnix() { From cdf565714b7e1ab1777de8d7413e97c7ec7cbf57 Mon Sep 17 00:00:00 2001 From: Eugene Kudelevsky Date: Fri, 17 Dec 2010 16:24:09 +0300 Subject: [PATCH 09/16] IDEA-63072 do not add duplicated android-library dependency when user already added it before creating facet --- .../android/facet/AndroidFacetType.java | 51 +++++++++++++------ 1 file changed, 35 insertions(+), 16 deletions(-) diff --git a/plugins/android/src/org/jetbrains/android/facet/AndroidFacetType.java b/plugins/android/src/org/jetbrains/android/facet/AndroidFacetType.java index 0c175a193abb..fbf175d10c46 100644 --- a/plugins/android/src/org/jetbrains/android/facet/AndroidFacetType.java +++ b/plugins/android/src/org/jetbrains/android/facet/AndroidFacetType.java @@ -27,6 +27,9 @@ import com.intellij.openapi.module.JavaModuleType; import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleType; import com.intellij.openapi.project.Project; +import com.intellij.openapi.roots.LibraryOrderEntry; +import com.intellij.openapi.roots.ModuleRootManager; +import com.intellij.openapi.roots.OrderEntry; import com.intellij.openapi.roots.libraries.Library; import com.intellij.openapi.roots.libraries.LibraryTable; import com.intellij.openapi.roots.libraries.LibraryTablesRegistrar; @@ -55,22 +58,7 @@ public class AndroidFacetType extends FacetType Date: Fri, 17 Dec 2010 16:01:51 +0300 Subject: [PATCH 10/16] cleanup --- .../testFramework/fixtures/CodeInsightTestFixture.java | 1 + .../fixtures/impl/CodeInsightTestFixtureImpl.java | 6 ++---- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/platform/testFramework/src/com/intellij/testFramework/fixtures/CodeInsightTestFixture.java b/platform/testFramework/src/com/intellij/testFramework/fixtures/CodeInsightTestFixture.java index 66fa0c988012..462be22a2139 100644 --- a/platform/testFramework/src/com/intellij/testFramework/fixtures/CodeInsightTestFixture.java +++ b/platform/testFramework/src/com/intellij/testFramework/fixtures/CodeInsightTestFixture.java @@ -333,6 +333,7 @@ public interface CodeInsightTestFixture extends IdeaProjectTestFixture { PsiFile addFileToProject(@NonNls String relativePath, @NonNls String fileText); + @Nullable List getCompletionVariants(String... filesBefore); /** diff --git a/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/CodeInsightTestFixtureImpl.java b/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/CodeInsightTestFixtureImpl.java index ff5bac1e4688..658b86ff86c3 100644 --- a/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/CodeInsightTestFixtureImpl.java +++ b/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/CodeInsightTestFixtureImpl.java @@ -498,10 +498,7 @@ public class CodeInsightTestFixtureImpl extends BaseFixture implements CodeInsig public void testCompletion(final String[] filesBefore, final String fileAfter) { assertInitialized(); configureByFiles(filesBefore); - final LookupElement[] items = complete(CompletionType.BASIC); - if (items != null) { - System.out.println("items = " + Arrays.toString(items)); - } + complete(CompletionType.BASIC); checkResultByFile(fileAfter); } @@ -518,6 +515,7 @@ public class CodeInsightTestFixtureImpl extends BaseFixture implements CodeInsig public void testCompletionVariants(final String fileBefore, final String... expectedItems) { assertInitialized(); final List result = getCompletionVariants(fileBefore); + UsefulTestCase.assertNotNull(result); UsefulTestCase.assertSameElements(result, expectedItems); } From 5c817f9dd50fef5de9a51af2698602e3de804af4 Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Fri, 17 Dec 2010 16:25:55 +0300 Subject: [PATCH 11/16] IDEA-63144: Issue list in new task dialog sorts incorrectly --- .../tasks/actions/TaskSearchSupport.java | 41 ++------------ .../tasks/impl/TaskCompletionContributor.java | 53 +++++++++---------- .../intellij/tasks/TaskCompletionTest.java | 7 +++ 3 files changed, 35 insertions(+), 66 deletions(-) diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/TaskSearchSupport.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/TaskSearchSupport.java index 6004e8725dd4..4f0cdd3a998e 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/TaskSearchSupport.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/TaskSearchSupport.java @@ -17,7 +17,6 @@ package com.intellij.tasks.actions; import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.Comparing; import com.intellij.psi.codeStyle.NameUtil; import com.intellij.tasks.Task; import com.intellij.tasks.TaskManager; @@ -34,34 +33,9 @@ public class TaskSearchSupport { protected NameUtil.Matcher myMatcher; private final TaskManagerImpl myManager; - private final Project myProject; - private final Comparator myTaskComparator; - private final boolean myRemoveLocal; - public TaskSearchSupport(final Project project, boolean removeLocal) { - - myProject = project; - myRemoveLocal = removeLocal; - myManager = (TaskManagerImpl)TaskManager.getManager(myProject); - - myTaskComparator = new Comparator() { - public int compare(Task o1, Task o2) { - int i = Comparing.compare(isOpen(o2, myProject), isOpen(o1, myProject)); - if (i != 0) { - return i; - } - //i = Comparing.compare(o1.isClosed(), o2.isClosed()); - //if (i != 0) { - // return i; - //} - i = Comparing.compare(o2.getUpdated(), o1.getUpdated()); - return i == 0 ? Comparing.compare(o2.getCreated(), o1.getCreated()) : i; - } - }; - } - - private static boolean isOpen(Task task, Project project) { - return !task.isClosed() && !TaskManager.getManager(project).getOpenChangelists(task).isEmpty(); + public TaskSearchSupport(final Project project) { + myManager = (TaskManagerImpl)TaskManager.getManager(project); } public List getItems(String pattern, boolean cached) { @@ -90,15 +64,6 @@ public class TaskSearchSupport { } private List getTasks(String pattern, boolean cached) { - Set taskSet = new HashSet(myManager.getCachedIssues()); - if (!cached) { - taskSet.addAll(myManager.getIssues(pattern)); - } - if (myRemoveLocal) { - taskSet.removeAll(Arrays.asList(myManager.getLocalTasks())); - } - List issues = new ArrayList(taskSet); - Collections.sort(issues, myTaskComparator); - return issues; + return cached ? myManager.getCachedIssues() : myManager.getIssues(pattern); } } diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskCompletionContributor.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskCompletionContributor.java index 0b7b03ec36fd..5e0ef2d91178 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskCompletionContributor.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskCompletionContributor.java @@ -15,8 +15,6 @@ import com.intellij.psi.PsiFile; import com.intellij.tasks.Task; import com.intellij.tasks.actions.TaskSearchSupport; import com.intellij.util.Consumer; -import com.intellij.util.Function; -import com.intellij.util.containers.ContainerUtil; import java.util.List; import java.util.concurrent.Callable; @@ -55,9 +53,9 @@ public class TaskCompletionContributor extends CompletionContributor { } result = result.withPrefixMatcher(new PlainPrefixMatcher(prefix)); - final TaskSearchSupport searchSupport = new TaskSearchSupport(file.getProject(), false); + final TaskSearchSupport searchSupport = new TaskSearchSupport(file.getProject()); List items = searchSupport.getItems(prefix, true); - addCompletionElements(result, consumer, items); + addCompletionElements(result, consumer, items, -10000); Future> future = ApplicationManager.getApplication().executeOnPooledThread(new Callable>() { @Override @@ -70,7 +68,7 @@ public class TaskCompletionContributor extends CompletionContributor { try { List tasks = future.get(100, TimeUnit.MILLISECONDS); if (tasks != null) { - addCompletionElements(result, consumer, tasks); + addCompletionElements(result, consumer, tasks, 0); return; } } @@ -85,32 +83,31 @@ public class TaskCompletionContributor extends CompletionContributor { } } - private static void addCompletionElements(CompletionResultSet result, final Consumer consumer, List items) { + private static void addCompletionElements(CompletionResultSet result, final Consumer consumer, List items, int index) { final AutoCompletionPolicy completionPolicy = ApplicationManager.getApplication().isUnitTestMode() ? AutoCompletionPolicy.ALWAYS_AUTOCOMPLETE : AutoCompletionPolicy.NEVER_AUTOCOMPLETE; - result.addAllElements(ContainerUtil.map(items, new Function() { - @Override - public LookupElement fun(final Task task) { - LookupElementBuilder builder = LookupElementBuilder.create(task.getId()) - .setIcon(task.getIcon()) - .addLookupString(task.getSummary()) - .setTailText(" " + task.getSummary(), true) - .setInsertHandler(new InsertHandler() { - @Override - public void handleInsert(InsertionContext context, LookupElement item) { - Document document = context.getEditor().getDocument(); - String s = task.getId() + ": " + task.getSummary(); - document.replaceString(context.getStartOffset(), context.getTailOffset(), s); - context.getEditor().getCaretModel().moveToOffset(context.getStartOffset() + s.length()); - consumer.consume(task); - } - }); - if (task.isClosed()) { - builder = builder.setStrikeout(); - } - return builder.withAutoCompletionPolicy(completionPolicy); + + for (final Task task : items) { + LookupElementBuilder builder = LookupElementBuilder.create(task.getId()) + .setIcon(task.getIcon()) + .addLookupString(task.getSummary()) + .setTailText(" " + task.getSummary(), true) + .setInsertHandler(new InsertHandler() { + @Override + public void handleInsert(InsertionContext context, LookupElement item) { + Document document = context.getEditor().getDocument(); + String s = task.getId() + ": " + task.getSummary(); + document.replaceString(context.getStartOffset(), context.getTailOffset(), s); + context.getEditor().getCaretModel().moveToOffset(context.getStartOffset() + s.length()); + consumer.consume(task); + } + }); + if (task.isClosed()) { + builder = builder.setStrikeout(); } - })); + + result.addElement(PrioritizedLookupElement.withGrouping(builder.withAutoCompletionPolicy(completionPolicy), index--)); + } } } diff --git a/plugins/tasks/tasks-tests/test/com/intellij/tasks/TaskCompletionTest.java b/plugins/tasks/tasks-tests/test/com/intellij/tasks/TaskCompletionTest.java index 5a891420757f..ffad6a19a5ff 100644 --- a/plugins/tasks/tasks-tests/test/com/intellij/tasks/TaskCompletionTest.java +++ b/plugins/tasks/tasks-tests/test/com/intellij/tasks/TaskCompletionTest.java @@ -35,6 +35,13 @@ public class TaskCompletionTest extends LightCodeInsightFixtureTestCase { assertEquals(2, elements.length); } + public void testKeepOrder() throws Exception { + configureFile(""); + configureRepository(new LocalTaskImpl("TEST-002", "Test task 2"), new LocalTaskImpl("TEST-001", "Test task 1")); + myFixture.complete(CompletionType.BASIC); + assertEquals(Arrays.asList("TEST-002", "TEST-001"), myFixture.getLookupElementStrings()); + } + public void testSIOOBE() throws Exception { doTest(" my", " TEST-001: Test task my"); } From 6b439b2b2edf4417face4352db8a2de0e9a868d6 Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Fri, 17 Dec 2010 17:21:22 +0300 Subject: [PATCH 12/16] IDEA-63123 Flex component event handlers Refactoring problem --- .../rename/inplace/VariableInplaceRenamer.java | 9 ++++----- .../fixtures/CodeInsightTestUtil.java | 17 ++++++++++++----- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/VariableInplaceRenamer.java b/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/VariableInplaceRenamer.java index adb4f94525e7..cd01409972b3 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/VariableInplaceRenamer.java +++ b/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/VariableInplaceRenamer.java @@ -111,8 +111,10 @@ public class VariableInplaceRenamer { return false; } - VirtualFile vFile = myElementToRename.getContainingFile().getVirtualFile(); - SearchScope referencesSearchScope = vFile == null || ProjectRootManager.getInstance(myProject).getFileIndex().isInContent(vFile) + final FileViewProvider fileViewProvider = myElementToRename.getContainingFile().getViewProvider(); + VirtualFile file = getTopLevelVirtualFile(fileViewProvider); + + SearchScope referencesSearchScope = file == null || ProjectRootManager.getInstance(myProject).getFileIndex().isInContent(file) ? ProjectScope.getProjectScope(myElementToRename.getProject()) : new LocalSearchScope(myElementToRename.getContainingFile()); @@ -120,9 +122,6 @@ public class VariableInplaceRenamer { addReferenceAtCaret(refs); - final FileViewProvider fileViewProvider = myElementToRename.getContainingFile().getViewProvider(); - VirtualFile file = getTopLevelVirtualFile(fileViewProvider); - for (PsiReference ref : refs) { final FileViewProvider usageViewProvider = ref.getElement().getContainingFile().getViewProvider(); diff --git a/platform/testFramework/src/com/intellij/testFramework/fixtures/CodeInsightTestUtil.java b/platform/testFramework/src/com/intellij/testFramework/fixtures/CodeInsightTestUtil.java index f23786a40649..aa0b72d4710d 100644 --- a/platform/testFramework/src/com/intellij/testFramework/fixtures/CodeInsightTestUtil.java +++ b/platform/testFramework/src/com/intellij/testFramework/fixtures/CodeInsightTestUtil.java @@ -29,6 +29,7 @@ import com.intellij.codeInsight.template.impl.TemplateManagerImpl; import com.intellij.codeInsight.template.impl.TemplateState; import com.intellij.codeInsight.template.impl.actions.ListTemplatesAction; import com.intellij.ide.DataManager; +import com.intellij.injected.editor.EditorWindow; import com.intellij.lang.surroundWith.Surrounder; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.DataContext; @@ -152,27 +153,33 @@ public class CodeInsightTestUtil { } public static void doInlineRename(VariableInplaceRenameHandler handler, final String newName, CodeInsightTestFixture fixture) { - final Editor editor = fixture.getEditor(); - PsiElement element = fixture.getElementAtCaret(); + doInlineRename(handler, newName, fixture.getEditor(), fixture.getElementAtCaret()); + } + + public static void doInlineRename(VariableInplaceRenameHandler handler, final String newName, Editor editor, PsiElement elementAtCaret) { Project project = editor.getProject(); TemplateManagerImpl templateManager = (TemplateManagerImpl)TemplateManager.getInstance(project); try { templateManager.setTemplateTesting(true); - VariableInplaceRenamer renamer = handler.doRename(element, editor, null); + VariableInplaceRenamer renamer = handler.doRename(elementAtCaret, editor, null); + if (editor instanceof EditorWindow) { + editor = ((EditorWindow)editor).getDelegate(); + } TemplateState state = TemplateManagerImpl.getTemplateState(editor); final TextRange range = state.getCurrentVariableRange(); assert range != null; + final Editor finalEditor = editor; new WriteCommandAction.Simple(project) { @Override protected void run() throws Throwable { - editor.getDocument().replaceString(range.getStartOffset(), range.getEndOffset(), newName); + finalEditor.getDocument().replaceString(range.getStartOffset(), range.getEndOffset(), newName); } }.execute().throwException(); assert renamer != null; renamer.finish(); TemplateManagerImpl.getTemplateState(editor).gotoEnd(); - renamer.performAutomaticRename(newName, element); + renamer.performAutomaticRename(newName, elementAtCaret); } finally { templateManager.setTemplateTesting(false); From 2d1a82620a1e35e70320d6904baabb371a8f2fcd Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Sat, 18 Dec 2010 15:21:29 +0100 Subject: [PATCH 13/16] fix AIOOB --- .../src/com/siyeh/ig/telemetry/TableSorter.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/telemetry/TableSorter.java b/plugins/InspectionGadgets/src/com/siyeh/ig/telemetry/TableSorter.java index bf100c497d9f..07ac3cb05baa 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/telemetry/TableSorter.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/telemetry/TableSorter.java @@ -246,7 +246,8 @@ public class TableSorter extends AbstractTableModel { } private Row[] getViewToModel() { - if (viewToModel == null) { + if (viewToModel == null || + viewToModel.length != tableModel.getRowCount()) { final int tableModelRowCount = tableModel.getRowCount(); viewToModel = new Row[tableModelRowCount]; for (int row = 0; row < tableModelRowCount; row++) { From d6acce00ac70bc24ffa3dbac41c0f928b80d908b Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Tue, 14 Dec 2010 16:27:44 +0300 Subject: [PATCH 14/16] Support for one line EditorTextField via new OneLineEditorCustomization feature. Using it in the ChangeListChooser. --- .../com/intellij/ui/EditorCustomization.java | 2 +- .../intellij/ui/EditorTextFieldProvider.java | 2 +- .../ui/OneLineEditorCustomization.java | 37 +++++++++++++++++++ .../src/META-INF/LangExtensions.xml | 1 + .../changes/ui/NewEditChangelistPanel.java | 1 + 5 files changed, 41 insertions(+), 2 deletions(-) create mode 100644 platform/platform-impl/src/com/intellij/ui/OneLineEditorCustomization.java diff --git a/platform/platform-impl/src/com/intellij/ui/EditorCustomization.java b/platform/platform-impl/src/com/intellij/ui/EditorCustomization.java index fc8b21f2e0b3..24b2f3479de0 100644 --- a/platform/platform-impl/src/com/intellij/ui/EditorCustomization.java +++ b/platform/platform-impl/src/com/intellij/ui/EditorCustomization.java @@ -33,7 +33,7 @@ import java.util.Set; public interface EditorCustomization { enum Feature { - SOFT_WRAP, SPELL_CHECK, NO_HORIZONTAL_SCROLLBAR + SOFT_WRAP, SPELL_CHECK, NO_HORIZONTAL_SCROLLBAR, ONE_LINE } ExtensionPointName EP_NAME = ExtensionPointName.create("com.intellij.editorCustomization"); diff --git a/platform/platform-impl/src/com/intellij/ui/EditorTextFieldProvider.java b/platform/platform-impl/src/com/intellij/ui/EditorTextFieldProvider.java index ada8488f894d..c2df2bfaafaa 100644 --- a/platform/platform-impl/src/com/intellij/ui/EditorTextFieldProvider.java +++ b/platform/platform-impl/src/com/intellij/ui/EditorTextFieldProvider.java @@ -30,7 +30,7 @@ public interface EditorTextFieldProvider { /** * @param project target project * @param features features to use within the returned editor text field - * @return {@link EditorTextField} with spell checking support. + * @return Multiline {@link EditorTextField} with spell checking support. */ EditorTextField getEditorField(@NotNull Language language, @NotNull Project project, @NotNull EditorCustomization.Feature ... features); } diff --git a/platform/platform-impl/src/com/intellij/ui/OneLineEditorCustomization.java b/platform/platform-impl/src/com/intellij/ui/OneLineEditorCustomization.java new file mode 100644 index 000000000000..ab4d16161049 --- /dev/null +++ b/platform/platform-impl/src/com/intellij/ui/OneLineEditorCustomization.java @@ -0,0 +1,37 @@ +/* + * Copyright 2000-2010 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.ui; + +import com.intellij.openapi.editor.ex.EditorEx; +import org.jetbrains.annotations.NotNull; + +import java.util.EnumSet; +import java.util.Set; + +/** + * @author Kirill Likhodedov + */ +public class OneLineEditorCustomization implements EditorCustomization { + public Set getSupportedFeatures() { + return EnumSet.of(Feature.ONE_LINE); + } + + public void customize(@NotNull EditorEx editor, @NotNull Feature feature) { + if (Feature.ONE_LINE.equals(feature)) { + editor.setOneLineMode(true); + } + } +} diff --git a/platform/platform-resources/src/META-INF/LangExtensions.xml b/platform/platform-resources/src/META-INF/LangExtensions.xml index 108f7b5677a2..6633bae9a907 100644 --- a/platform/platform-resources/src/META-INF/LangExtensions.xml +++ b/platform/platform-resources/src/META-INF/LangExtensions.xml @@ -454,6 +454,7 @@ + diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/NewEditChangelistPanel.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/NewEditChangelistPanel.java index 701ed0e33560..d2b6a8718677 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/NewEditChangelistPanel.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/NewEditChangelistPanel.java @@ -175,6 +175,7 @@ public abstract class NewEditChangelistPanel extends JPanel { final EnumSet features = EnumSet.of(EditorCustomization.Feature.SPELL_CHECK); if (defaultLines == 1) { features.add(EditorCustomization.Feature.NO_HORIZONTAL_SCROLLBAR); + features.add(EditorCustomization.Feature.ONE_LINE); } else { features.add(EditorCustomization.Feature.SOFT_WRAP); } From b7a4d8a805c529390b974dc688b0b8b917686f2e Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Fri, 17 Dec 2010 11:45:23 +0300 Subject: [PATCH 15/16] GitPushActiveBranchesDialog: "close" button instead of "cancel". --- .../checkin/GitPushActiveBranchesDialog.java | 24 ++++--------------- .../src/git4idea/i18n/GitBundle.properties | 2 ++ 2 files changed, 7 insertions(+), 19 deletions(-) diff --git a/plugins/git4idea/src/git4idea/checkin/GitPushActiveBranchesDialog.java b/plugins/git4idea/src/git4idea/checkin/GitPushActiveBranchesDialog.java index c7c33029829c..35b1299a1bc4 100644 --- a/plugins/git4idea/src/git4idea/checkin/GitPushActiveBranchesDialog.java +++ b/plugins/git4idea/src/git4idea/checkin/GitPushActiveBranchesDialog.java @@ -43,11 +43,7 @@ import git4idea.GitUtil; import git4idea.GitVcs; import git4idea.actions.GitRepositoryAction; import git4idea.actions.GitShowAllSubmittedFilesAction; -import git4idea.commands.GitCommand; -import git4idea.commands.GitHandlerUtil; -import git4idea.commands.GitLineHandler; -import git4idea.commands.GitSimpleHandler; -import git4idea.commands.StringScanner; +import git4idea.commands.*; import git4idea.config.GitVcsSettings; import git4idea.i18n.GitBundle; import git4idea.ui.GitUIUtil; @@ -55,11 +51,7 @@ import git4idea.update.UpdatePolicyUtils; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import javax.swing.JButton; -import javax.swing.JComponent; -import javax.swing.JPanel; -import javax.swing.JRadioButton; -import javax.swing.JTree; +import javax.swing.*; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import javax.swing.event.TreeSelectionEvent; @@ -67,18 +59,11 @@ import javax.swing.event.TreeSelectionListener; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.DefaultTreeModel; import javax.swing.tree.TreePath; -import java.awt.Color; +import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Date; -import java.util.HashMap; -import java.util.HashSet; +import java.util.*; import java.util.List; -import java.util.Map; -import java.util.Set; import java.util.concurrent.atomic.AtomicReference; /** @@ -184,6 +169,7 @@ public class GitPushActiveBranchesDialog extends DialogWrapper { setTitle(GitBundle.getString("push.active.title")); setOKButtonText(GitBundle.getString("push.active.rebase.and.push")); + setCancelButtonText(GitBundle.getString("git.push.active.close")); init(); } diff --git a/plugins/git4idea/src/git4idea/i18n/GitBundle.properties b/plugins/git4idea/src/git4idea/i18n/GitBundle.properties index 0373394f9e9f..6bca1aa94b48 100644 --- a/plugins/git4idea/src/git4idea/i18n/GitBundle.properties +++ b/plugins/git4idea/src/git4idea/i18n/GitBundle.properties @@ -494,6 +494,8 @@ git.executable.dialog.error=It doesn't appear to be a valid git executable git.executable.filechooser.title=Git executable git.executable.filechooser.description=Specify the full path to git executable +git.push.active.close=Close + git.unstash.clear.confirmation.message=Remove all stashes? This cannot be undone. git.unstash.clear.confirmation.title=Remove all stashes? git.unstash.drop.confirmation.message=Do you want to remove {0}?
"{1}" From acedf0dec589fcef44fd1490a0005539e3e9fce7 Mon Sep 17 00:00:00 2001 From: irengrig Date: Sat, 18 Dec 2010 21:14:10 +0300 Subject: [PATCH 16/16] VCS: fix unversioned files counting --- .../vcs/changes/VirtualFileHolder.java | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/VirtualFileHolder.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/VirtualFileHolder.java index 11cf7f69bc83..6df9cb915dbc 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/VirtualFileHolder.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/VirtualFileHolder.java @@ -62,21 +62,21 @@ public class VirtualFileHolder implements FileHolder { for(FilePath dirtyFile: dirtyFiles) { VirtualFile f = dirtyFile.getVirtualFile(); if (f != null) { - files.remove(f); - if (f.isDirectory()) ++ result; + if (files.remove(f)) { + if (f.isDirectory()) ++ result; + } } else { cleanDroppedFiles = true; } - - if (cleanDroppedFiles) { - for (Iterator iterator = files.iterator(); iterator.hasNext();) { - final VirtualFile file = iterator.next(); - if (fileDropped(file)) { - iterator.remove(); - scope.addDirtyFile(new FilePathImpl(file)); - if (file.isDirectory()) ++ result; - } + } + if (cleanDroppedFiles) { + for (Iterator iterator = files.iterator(); iterator.hasNext();) { + final VirtualFile file = iterator.next(); + if (fileDropped(file)) { + iterator.remove(); + scope.addDirtyFile(new FilePathImpl(file)); + if (file.isDirectory()) ++ result; } } } @@ -156,6 +156,7 @@ public class VirtualFileHolder implements FileHolder { } public int getNumDirs() { + assert myNumDirs >= 0; return myNumDirs; } }