mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Calculating dialog location to prevent selected text hiding. We take first place from: on the right of the text, over selected text, under selected text, if dialog fits there.
This commit is contained in:
+142
-4
@@ -18,11 +18,14 @@ package com.intellij.formatting.contextConfiguration;
|
||||
import com.intellij.codeInsight.intention.IntentionAction;
|
||||
import com.intellij.lang.Language;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.SelectionModel;
|
||||
import com.intellij.openapi.editor.VisualPosition;
|
||||
import com.intellij.openapi.options.ConfigurationException;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.DialogWrapper;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.psi.PsiFile;
|
||||
@@ -36,6 +39,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
|
||||
import static com.intellij.psi.codeStyle.CodeStyleSettingsCodeFragmentFilter.CodeStyleSettingsToShow;
|
||||
|
||||
@@ -67,7 +71,7 @@ public class ConfigureCodeStyleOnSelectedFragment implements IntentionAction {
|
||||
SelectedTextFormatter textFormatter = new SelectedTextFormatter(project, editor, file);
|
||||
CodeStyleSettingsToShow settingsToShow = calculateAffectingSettings(editor, file);
|
||||
CodeStyleSettings settings = CodeStyleSettingsManager.getSettings(project);
|
||||
new FragmentCodeStyleSettingsDialog(project, textFormatter, file.getLanguage(), settings, settingsToShow).show();
|
||||
new FragmentCodeStyleSettingsDialog(editor, textFormatter, file.getLanguage(), settings, settingsToShow).show();
|
||||
}
|
||||
|
||||
private static CodeStyleSettingsToShow calculateAffectingSettings(@NotNull Editor editor, @NotNull PsiFile file) {
|
||||
@@ -85,21 +89,35 @@ public class ConfigureCodeStyleOnSelectedFragment implements IntentionAction {
|
||||
|
||||
static class FragmentCodeStyleSettingsDialog extends DialogWrapper {
|
||||
private final CodeFragmentCodeStyleSettingsPanel myTabbedLanguagePanel;
|
||||
private final Editor myEditor;
|
||||
private final Document myDocument;
|
||||
private SelectedTextFormatter mySelectedTextFormatter;
|
||||
private final CodeStyleSettings mySettings;
|
||||
|
||||
public FragmentCodeStyleSettingsDialog(@NotNull Project project,
|
||||
|
||||
public FragmentCodeStyleSettingsDialog(@NotNull final Editor editor,
|
||||
@NotNull SelectedTextFormatter selectedTextFormatter,
|
||||
@NotNull Language language,
|
||||
CodeStyleSettings settings,
|
||||
CodeStyleSettingsToShow settingsToShow) {
|
||||
super(project, true);
|
||||
super(editor.getContentComponent(), true);
|
||||
mySettings = settings;
|
||||
mySelectedTextFormatter = selectedTextFormatter;
|
||||
myTabbedLanguagePanel = new CodeFragmentCodeStyleSettingsPanel(settings, settingsToShow, language, selectedTextFormatter);
|
||||
|
||||
|
||||
myEditor = editor;
|
||||
myDocument = editor.getDocument();
|
||||
|
||||
setTitle("Configure Code Style Settings: " + language.getDisplayName());
|
||||
setOKButtonText("Save");
|
||||
|
||||
setInitialLocationCallback(new Computable<Point>() {
|
||||
@Override
|
||||
public Point compute() {
|
||||
return new DialogPositionProvider().calculateLocation();
|
||||
}
|
||||
});
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
@@ -131,5 +149,125 @@ public class ConfigureCodeStyleOnSelectedFragment implements IntentionAction {
|
||||
mySelectedTextFormatter.restoreSelectedText();
|
||||
super.doCancelAction();
|
||||
}
|
||||
|
||||
private class DialogPositionProvider {
|
||||
private static final int PREFERRED_PADDING = 100;
|
||||
|
||||
private JComponent myEditorComponent;
|
||||
private JComponent myContentComponent;
|
||||
|
||||
private int mySelectionStartY;
|
||||
private int mySelectionEndY;
|
||||
private int myTextRangeMaxColumnX;
|
||||
private int myEditorComponentWidth;
|
||||
private int myEditorComponentHeight;
|
||||
|
||||
public DialogPositionProvider() {
|
||||
myContentComponent = myEditor.getContentComponent();
|
||||
myEditorComponent = myEditor.getComponent();
|
||||
|
||||
myEditorComponentWidth = myEditorComponent.getWidth();
|
||||
myEditorComponentHeight = myEditorComponent.getHeight();
|
||||
}
|
||||
|
||||
public Point calculateLocation() {
|
||||
calculateSelectedTextRectangle();
|
||||
|
||||
int dialogWidth = getSize().width;
|
||||
int dialogHeight = getSize().height;
|
||||
|
||||
int spaceIfPlacedOnTheRight = myEditorComponentWidth - (myTextRangeMaxColumnX + dialogWidth);
|
||||
|
||||
Integer dialogX = null;
|
||||
Integer dialogY = null;
|
||||
|
||||
if (spaceIfPlacedOnTheRight > 0) {
|
||||
int paddingFromText = spaceIfPlacedOnTheRight > PREFERRED_PADDING ? PREFERRED_PADDING : (spaceIfPlacedOnTheRight / 2);
|
||||
dialogX = myTextRangeMaxColumnX + paddingFromText;
|
||||
|
||||
if (mySelectionEndY - mySelectionStartY > dialogHeight) {
|
||||
dialogY = (myEditorComponentHeight - dialogHeight) / 2;
|
||||
}
|
||||
else {
|
||||
dialogY = getYMatchingDialogAndSelectionCenter(dialogHeight);
|
||||
}
|
||||
}
|
||||
else if (mySelectionStartY > dialogHeight) {
|
||||
dialogX = (myEditorComponentWidth - dialogWidth) / 2;
|
||||
dialogY = mySelectionStartY - dialogHeight;
|
||||
}
|
||||
else if (mySelectionEndY + dialogHeight < myEditorComponentHeight) {
|
||||
dialogX = (myEditorComponentWidth - dialogWidth) / 2;
|
||||
dialogY = mySelectionEndY;
|
||||
}
|
||||
|
||||
if (dialogX != null && dialogY != null) {
|
||||
Point location = new Point(dialogX, dialogY);
|
||||
SwingUtilities.convertPointToScreen(location, myEditor.getComponent());
|
||||
return location;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private Integer getYMatchingDialogAndSelectionCenter(int dialogHeight) {
|
||||
int selectionCenter = (mySelectionStartY + mySelectionEndY) / 2;
|
||||
int dialogTop = selectionCenter - dialogHeight / 2;
|
||||
int dialogBottom = selectionCenter + dialogHeight / 2;
|
||||
|
||||
if (dialogTop >= 0 && dialogBottom <= myEditorComponentHeight) {
|
||||
return dialogTop;
|
||||
}
|
||||
else if (dialogTop < 0) {
|
||||
int extraTopSpace = -dialogTop;
|
||||
if (dialogBottom + extraTopSpace <= myEditorComponentHeight) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else if (dialogBottom > myEditorComponentHeight) {
|
||||
int extraBottomSpace = dialogBottom - myEditorComponentHeight;
|
||||
if (dialogTop - extraBottomSpace >= 0) {
|
||||
return dialogTop - extraBottomSpace;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private void calculateSelectedTextRectangle() {
|
||||
SelectionModel selectionModel = myEditor.getSelectionModel();
|
||||
int selectionStartOffset = selectionModel.getSelectionStart();
|
||||
int selectionEndOffset = selectionModel.getSelectionEnd();
|
||||
|
||||
VisualPosition maxColumnVp = getMaxColumnInsideRange(selectionStartOffset, selectionEndOffset);
|
||||
|
||||
Point maxColumnsPoint = myEditor.visualPositionToXY(maxColumnVp);
|
||||
Point selectionStart = myEditor.visualPositionToXY(myEditor.offsetToVisualPosition(selectionStartOffset));
|
||||
Point selectionEnd = myEditor.visualPositionToXY(myEditor.offsetToVisualPosition(selectionEndOffset));
|
||||
|
||||
selectionStart = SwingUtilities.convertPoint(myContentComponent, selectionStart, myEditorComponent);
|
||||
selectionEnd = SwingUtilities.convertPoint(myContentComponent, selectionEnd, myEditorComponent);
|
||||
maxColumnsPoint = SwingUtilities.convertPoint(myContentComponent, maxColumnsPoint, myEditorComponent);
|
||||
|
||||
mySelectionStartY = selectionStart.y;
|
||||
mySelectionEndY = selectionEnd.y;
|
||||
myTextRangeMaxColumnX = maxColumnsPoint.x;
|
||||
}
|
||||
|
||||
private VisualPosition getMaxColumnInsideRange(int startOffset, int endOffset) {
|
||||
int firstLine = myDocument.getLineNumber(startOffset);
|
||||
int lastLine = myDocument.getLineNumber(endOffset);
|
||||
|
||||
VisualPosition positionWithMaxColumn = new VisualPosition(0, 0);
|
||||
for (int currentLine = firstLine; currentLine <= lastLine; currentLine++) {
|
||||
int offset = myDocument.getLineEndOffset(currentLine);
|
||||
VisualPosition position = myEditor.offsetToVisualPosition(offset);
|
||||
if (position.getColumn() > positionWithMaxColumn.getColumn()) {
|
||||
positionWithMaxColumn = position;
|
||||
}
|
||||
}
|
||||
return positionWithMaxColumn;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user