From 48aa8017fba20e5716122bbfd46b1bb3dcae8a4f Mon Sep 17 00:00:00 2001 From: "dmitriy.tseyler" Date: Fri, 10 Mar 2017 21:11:36 +0300 Subject: [PATCH] DBE: Grid position widget (cherry picked from commit 295d2ba) --- .../intellij/ide/actions/GotoLineAction.java | 5 +- .../ide/util/EditorGotoLineNumberDialog.java | 79 +++++++++++++++++ .../ide/util/GotoLineNumberDialog.java | 86 +++++++++---------- .../wm/impl/status/IdeStatusBarImpl.java | 2 +- .../openapi/wm/impl/status/PositionPanel.java | 53 +++++++++--- 5 files changed, 166 insertions(+), 59 deletions(-) create mode 100644 platform/platform-impl/src/com/intellij/ide/util/EditorGotoLineNumberDialog.java diff --git a/platform/platform-impl/src/com/intellij/ide/actions/GotoLineAction.java b/platform/platform-impl/src/com/intellij/ide/actions/GotoLineAction.java index d5b8af78bf94..a343296da916 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/GotoLineAction.java +++ b/platform/platform-impl/src/com/intellij/ide/actions/GotoLineAction.java @@ -16,6 +16,7 @@ package com.intellij.ide.actions; import com.intellij.ide.IdeBundle; +import com.intellij.ide.util.EditorGotoLineNumberDialog; import com.intellij.ide.util.GotoLineNumberDialog; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.command.CommandProcessor; @@ -33,14 +34,14 @@ public class GotoLineAction extends AnAction implements DumbAware { final Project project = e.getData(CommonDataKeys.PROJECT); final Editor editor = e.getData(CommonDataKeys.EDITOR_EVEN_IF_INACTIVE); if (Boolean.TRUE.equals(e.getData(PlatformDataKeys.IS_MODAL_CONTEXT))) { - GotoLineNumberDialog dialog = new GotoLineNumberDialog(project, editor); + GotoLineNumberDialog dialog = new EditorGotoLineNumberDialog(project, editor); dialog.show(); } else { CommandProcessor processor = CommandProcessor.getInstance(); processor.executeCommand( project, () -> { - GotoLineNumberDialog dialog = new GotoLineNumberDialog(project, editor); + GotoLineNumberDialog dialog = new EditorGotoLineNumberDialog(project, editor); dialog.show(); IdeDocumentHistory.getInstance(project).includeCurrentCommandAsNavigation(); }, diff --git a/platform/platform-impl/src/com/intellij/ide/util/EditorGotoLineNumberDialog.java b/platform/platform-impl/src/com/intellij/ide/util/EditorGotoLineNumberDialog.java new file mode 100644 index 000000000000..11b5093129ba --- /dev/null +++ b/platform/platform-impl/src/com/intellij/ide/util/EditorGotoLineNumberDialog.java @@ -0,0 +1,79 @@ +/* + * Copyright 2000-2016 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.ide.util; + +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.editor.LogicalPosition; +import com.intellij.openapi.editor.ScrollType; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.wm.IdeFocusManager; +import org.jetbrains.annotations.NotNull; + +public class EditorGotoLineNumberDialog extends GotoLineNumberDialog { + private final Editor myEditor; + + public EditorGotoLineNumberDialog(Project project, Editor editor) { + super(project); + myEditor = editor; + init(); + } + + protected void doOKAction() { + Coordinates coordinates = getCoordinates(); + if (coordinates == null) return; + + LogicalPosition position = new LogicalPosition(coordinates.row, coordinates.column); + myEditor.getCaretModel().removeSecondaryCarets(); + myEditor.getCaretModel().moveToLogicalPosition(position); + myEditor.getScrollingModel().scrollToCaret(ScrollType.CENTER); + myEditor.getSelectionModel().removeSelection(); + IdeFocusManager.getGlobalInstance().requestFocus(myEditor.getContentComponent(), true); + super.doOKAction(); + } + + @Override + protected int getLine() { + return myEditor.getCaretModel().getLogicalPosition().line; + } + + @Override + protected int getColumn() { + return myEditor.getCaretModel().getLogicalPosition().column; + } + + @Override + protected int getOffset() { + return myEditor.getCaretModel().getOffset(); + } + + @Override + protected int getMaxOffset() { + return myEditor.getDocument().getTextLength(); + } + + @Override + protected int coordinatesToOffset(@NotNull Coordinates coordinates) { + LogicalPosition position = new LogicalPosition(coordinates.row, coordinates.column); + return myEditor.logicalPositionToOffset(position); + } + + @NotNull + @Override + protected Coordinates offsetToCoordinates(int offset) { + LogicalPosition position = myEditor.offsetToLogicalPosition(offset); + return new Coordinates(position.line, position.column); + } +} diff --git a/platform/platform-impl/src/com/intellij/ide/util/GotoLineNumberDialog.java b/platform/platform-impl/src/com/intellij/ide/util/GotoLineNumberDialog.java index 9dcea708cba8..6b322715a20d 100644 --- a/platform/platform-impl/src/com/intellij/ide/util/GotoLineNumberDialog.java +++ b/platform/platform-impl/src/com/intellij/ide/util/GotoLineNumberDialog.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2016 JetBrains s.r.o. + * Copyright 2000-2017 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. @@ -16,15 +16,13 @@ package com.intellij.ide.util; import com.intellij.openapi.application.ex.ApplicationManagerEx; -import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.editor.LogicalPosition; -import com.intellij.openapi.editor.ScrollType; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.util.text.StringUtil; -import com.intellij.openapi.wm.IdeFocusManager; import com.intellij.ui.DocumentAdapter; import com.intellij.util.PatternUtil; +import com.intellij.util.ui.JBUI; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; @@ -33,39 +31,15 @@ import java.awt.*; import java.util.regex.Matcher; import java.util.regex.Pattern; -public class GotoLineNumberDialog extends DialogWrapper { - private JTextField myField; - private JTextField myOffsetField; - private final Editor myEditor; +public abstract class GotoLineNumberDialog extends DialogWrapper { private final Pattern myPattern = PatternUtil.compileSafe("\\s*(\\d+)?\\s*(?:[,:]?\\s*(\\d+)?)?\\s*", null); - public GotoLineNumberDialog(Project project, Editor editor) { + private JTextField myField; + private JTextField myOffsetField; + + public GotoLineNumberDialog(Project project) { super(project, true); - myEditor = editor; setTitle("Go to Line/Column"); - init(); - } - - protected void doOKAction() { - LogicalPosition position = getLogicalPosition(); - if (position == null) return; - - myEditor.getCaretModel().removeSecondaryCarets(); - myEditor.getCaretModel().moveToLogicalPosition(position); - myEditor.getScrollingModel().scrollToCaret(ScrollType.CENTER); - myEditor.getSelectionModel().removeSelection(); - IdeFocusManager.getGlobalInstance().requestFocus(myEditor.getContentComponent(), true); - super.doOKAction(); - } - - @Nullable - private LogicalPosition getLogicalPosition() { - Matcher m = myPattern.matcher(getText()); - if (!m.matches()) return null; - - int l = StringUtil.parseInt(m.group(1), myEditor.getCaretModel().getLogicalPosition().line + 1); - int c = StringUtil.parseInt(m.group(2), -1); - return l > 0 ? new LogicalPosition(l - 1, Math.max(0, c - 1)) : null; } private static boolean isInternal() { @@ -84,6 +58,24 @@ public class GotoLineNumberDialog extends DialogWrapper { return myField.getText(); } + @Nullable + protected final Coordinates getCoordinates() { + Matcher m = myPattern.matcher(getText()); + if (!m.matches()) return null; + + int l = StringUtil.parseInt(m.group(1), getLine() + 1); + int c = StringUtil.parseInt(m.group(2), -1); + return l > 0 ? new Coordinates(l - 1, Math.max(0, c - 1)) : null; + } + + protected abstract int getLine(); + protected abstract int getColumn(); + protected abstract int getOffset(); + protected abstract int getMaxOffset(); + protected abstract int coordinatesToOffset(@NotNull Coordinates coordinates); + @NotNull + protected abstract Coordinates offsetToCoordinates(int offset); + protected JComponent createNorthPanel() { class MyTextField extends JTextField { public MyTextField() { @@ -99,7 +91,7 @@ public class GotoLineNumberDialog extends DialogWrapper { JPanel panel = new JPanel(new GridBagLayout()); GridBagConstraints gbConstraints = new GridBagConstraints(); - gbConstraints.insets = new Insets(4, 0, 8, 8); + gbConstraints.insets = JBUI.insets(4, 0, 8, 8); gbConstraints.fill = GridBagConstraints.VERTICAL; gbConstraints.weightx = 0; gbConstraints.weighty = 1; @@ -111,8 +103,7 @@ public class GotoLineNumberDialog extends DialogWrapper { gbConstraints.weightx = 1; myField = new MyTextField(); panel.add(myField, gbConstraints); - LogicalPosition position = myEditor.getCaretModel().getLogicalPosition(); - myField.setText(String.format("%d:%d", position.line + 1, position.column + 1)); + myField.setText(String.format("%d:%d", getLine() + 1, getColumn() + 1)); if (isInternal()) { gbConstraints.gridy = 1; @@ -126,7 +117,7 @@ public class GotoLineNumberDialog extends DialogWrapper { gbConstraints.weightx = 1; myOffsetField = new MyTextField(); panel.add(myOffsetField, gbConstraints); - myOffsetField.setText(String.valueOf(myEditor.getCaretModel().getOffset())); + myOffsetField.setText(String.valueOf(getOffset())); DocumentAdapter valueSync = new DocumentAdapter() { boolean inSync; @@ -140,15 +131,14 @@ public class GotoLineNumberDialog extends DialogWrapper { try { if (e.getDocument() == myField.getDocument()) { f = myOffsetField; - LogicalPosition p = getLogicalPosition(); - s = p == null ? s : String.valueOf(myEditor.logicalPositionToOffset(p)); + Coordinates p = getCoordinates(); + s = p == null ? s : String.valueOf(coordinatesToOffset(p)); } else { f = myField; int offset = StringUtil.parseInt(myOffsetField.getText(), -1); - LogicalPosition p = offset >= 0 ? myEditor.offsetToLogicalPosition( - Math.min(myEditor.getDocument().getTextLength() - 1, offset)) : null; - s = p == null ? s : String.format("%d:%d", p.line + 1, p.column + 1); + Coordinates p = offset >= 0 ? offsetToCoordinates(Math.min(getMaxOffset() - 1, offset)) : null; + s = p == null ? s : String.format("%d:%d", p.row + 1, p.column + 1); } f.setText(s); } @@ -166,4 +156,14 @@ public class GotoLineNumberDialog extends DialogWrapper { return panel; } + + protected static class Coordinates { + public final int row; + public final int column; + + public Coordinates(int row, int column) { + this.row = row; + this.column = column; + } + } } diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/IdeStatusBarImpl.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/IdeStatusBarImpl.java index ddec012ab442..9bc59b895f7d 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/IdeStatusBarImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/IdeStatusBarImpl.java @@ -144,7 +144,7 @@ public class IdeStatusBarImpl extends JComponent implements Accessible, StatusBa WidgetBean eachBean = myWidgetMap.get(eachId); if (eachBean.widget instanceof StatusBarWidget.Multiframe) { StatusBarWidget copy = ((StatusBarWidget.Multiframe)eachBean.widget).copy(); - bar.addWidget(copy, eachBean.position); + UIUtil.invokeLaterIfNeeded(() -> bar.addWidget(copy, eachBean.position, eachBean.anchor)); } } diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/PositionPanel.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/PositionPanel.java index fdaacb9ac186..5ff18f690bc0 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/PositionPanel.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/PositionPanel.java @@ -15,6 +15,7 @@ */ package com.intellij.openapi.wm.impl.status; +import com.intellij.ide.util.EditorGotoLineNumberDialog; import com.intellij.ide.util.GotoLineNumberDialog; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.command.CommandProcessor; @@ -22,6 +23,8 @@ import com.intellij.openapi.editor.*; import com.intellij.openapi.editor.event.*; import com.intellij.openapi.editor.ex.DocumentBulkUpdateListener; import com.intellij.openapi.editor.ex.DocumentEx; +import com.intellij.openapi.editor.ex.EditorEventMulticasterEx; +import com.intellij.openapi.editor.ex.FocusChangeListener; import com.intellij.openapi.fileEditor.FileEditorManagerEvent; import com.intellij.openapi.fileEditor.ex.IdeDocumentHistory; import com.intellij.openapi.project.Project; @@ -30,6 +33,7 @@ import com.intellij.openapi.wm.StatusBarWidget; import com.intellij.ui.UIBundle; import com.intellij.util.Alarm; import com.intellij.util.Consumer; +import com.intellij.util.ObjectUtils; import com.intellij.util.messages.MessageBusConnection; import org.jetbrains.annotations.NotNull; @@ -39,7 +43,14 @@ import java.awt.event.MouseEvent; public class PositionPanel extends EditorBasedWidget implements StatusBarWidget.Multiframe, StatusBarWidget.TextPresentation, - CaretListener, SelectionListener, DocumentListener, DocumentBulkUpdateListener { + CaretListener, SelectionListener, DocumentListener, DocumentBulkUpdateListener, + FocusChangeListener { + + public static final String SPACE = " "; + public static final String SEPARATOR = ":"; + public static final String MAX_POSSIBLE_TEXT = "0000000000000"; + public static final String ID = "Position"; + private static final int CHAR_COUNT_SYNC_LIMIT = 500_000; private static final String CHAR_COUNT_UNKNOWN = "..."; @@ -60,7 +71,7 @@ public class PositionPanel extends EditorBasedWidget @NotNull public String ID() { - return "Position"; + return ID; } @Override @@ -79,7 +90,7 @@ public class PositionPanel extends EditorBasedWidget @NotNull public String getMaxPossibleText() { - return "0000000000000"; + return MAX_POSSIBLE_TEXT; } @Override @@ -93,14 +104,15 @@ public class PositionPanel extends EditorBasedWidget public Consumer getClickConsumer() { return mouseEvent -> { - final Project project = getProject(); - if (project == null) return; - final Editor editor = getEditor(); - if (editor == null) return; - final CommandProcessor processor = CommandProcessor.getInstance(); + Project project = getProject(); + Editor editor = getEditor(); + if (project == null || editor == null) return; + + CommandProcessor processor = CommandProcessor.getInstance(); processor.executeCommand( - project, () -> { - final GotoLineNumberDialog dialog = new GotoLineNumberDialog(project, editor); + project, + () -> { + GotoLineNumberDialog dialog = new EditorGotoLineNumberDialog(project, editor); dialog.show(); IdeDocumentHistory.getInstance(project).includeCurrentCommandAsNavigation(); }, @@ -112,12 +124,17 @@ public class PositionPanel extends EditorBasedWidget public void install(@NotNull StatusBar statusBar) { super.install(statusBar); - final EditorEventMulticaster multicaster = EditorFactory.getInstance().getEventMulticaster(); + EditorEventMulticaster multicaster = EditorFactory.getInstance().getEventMulticaster(); multicaster.addCaretListener(this, this); multicaster.addSelectionListener(this, this); multicaster.addDocumentListener(this, this); MessageBusConnection connection = ApplicationManager.getApplication().getMessageBus().connect(this); connection.subscribe(DocumentBulkUpdateListener.TOPIC, this); + ObjectUtils.consumeIfCast( + multicaster, + EditorEventMulticasterEx.class, + multicasterEx -> multicasterEx.addFocusChangeListner(this, this) + ); } @Override @@ -159,6 +176,16 @@ public class PositionPanel extends EditorBasedWidget onDocumentUpdate(doc); } + @Override + public void focusGained(Editor editor) { + updatePosition(editor); + } + + @Override + public void focusLost(Editor editor) { + updatePosition(getEditor()); + } + private void onDocumentUpdate(Document document) { Editor[] editors = EditorFactory.getInstance().getEditors(document); Component focusOwner = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner(); @@ -225,11 +252,11 @@ public class PositionPanel extends EditorBasedWidget message.append(", "); message.append(UIBundle.message("position.panel.selected.line.breaks.count", selectionEndLine - selectionStartLine)); } - message.append(" "); + message.append(SPACE); } } LogicalPosition caret = editor.getCaretModel().getLogicalPosition(); - message.append(caret.line + 1).append(":").append(caret.column + 1); + message.append(caret.line + 1).append(SEPARATOR).append(caret.column + 1); } return message.toString();