diff options
Diffstat (limited to 'platform/platform-api/src/com')
33 files changed, 493 insertions, 250 deletions
diff --git a/platform/platform-api/src/com/intellij/execution/process/AnsiEscapeDecoder.java b/platform/platform-api/src/com/intellij/execution/process/AnsiEscapeDecoder.java index 0ecf7c8a6dd0..58a8e40db2d6 100644 --- a/platform/platform-api/src/com/intellij/execution/process/AnsiEscapeDecoder.java +++ b/platform/platform-api/src/com/intellij/execution/process/AnsiEscapeDecoder.java @@ -19,80 +19,105 @@ import com.intellij.openapi.util.Key; import com.intellij.openapi.util.Pair; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.List; +import java.util.regex.Pattern; /** + * See <a href="http://en.wikipedia.org/wiki/ANSI_escape_code">ANSI escape code</a>. + * * @author traff */ public class AnsiEscapeDecoder { - private static final char TEXT_ATTRS_PREFIX_CH = '\u001B'; - private static final String TEXT_ATTRS_PREFIX = Character.toString(TEXT_ATTRS_PREFIX_CH) + "["; - private static final String TEXT_ATTRS_PATTERN = "m" + TEXT_ATTRS_PREFIX_CH + "\\["; + private static final char ESC_CHAR = '\u001B'; // Escape sequence start character + private static final String CSI = ESC_CHAR + "["; // "Control Sequence Initiator" + private static final Pattern INNER_PATTERN = Pattern.compile(Pattern.quote("m" + CSI)); - private Key myCurrentColor; + private Key myCurrentTextAttributes; /** * Parses ansi-color codes from text and sends text fragments with color attributes to textAcceptor * - * @param text - * @param outputType - * @param textAcceptor if implements ColoredTextAcceptor then it will receive text fragments with color attributes - * if implements ColoredChunksAcceptor then it will receive list of pairs <text, attribute> + * @param text a string with ANSI escape sequences + * @param outputType stdout/stderr/system (from {@link ProcessOutputTypes}) + * @param textAcceptor receives text fragments with color attributes. + * It can implement ColoredChunksAcceptor to receive list of pairs (text, attribute). */ - public void escapeText(String text, Key outputType, ColoredTextAcceptor textAcceptor) { - final List<Pair<String, Key>> textChunks = ContainerUtil.newArrayList(); + public void escapeText(@NotNull String text, @NotNull Key outputType, @NotNull ColoredTextAcceptor textAcceptor) { + List<Pair<String, Key>> chunks = null; int pos = 0; while (true) { - int macroPos = text.indexOf(TEXT_ATTRS_PREFIX, pos); - if (macroPos < 0) break; - if (pos != macroPos) { - textChunks.add(Pair.create(text.substring(pos, macroPos), getCurrentOutputAttributes(outputType))); + int escSeqBeginInd = text.indexOf(CSI, pos); + if (escSeqBeginInd < 0) { + break; } - final int macroEndPos = getEndMacroPos(text, macroPos); - if (macroEndPos < 0) { + if (pos < escSeqBeginInd) { + chunks = processTextChunk(chunks, text.substring(pos, escSeqBeginInd), outputType, textAcceptor); + } + final int escSeqEndInd = findEscSeqEndIndex(text, escSeqBeginInd); + if (escSeqEndInd < 0) { break; } + String escSeq = text.substring(escSeqBeginInd, escSeqEndInd); // this is a simple fix for RUBY-8996: // we replace several consecutive escape sequences with one which contains all these sequences - final String colorAttribute = text.substring(macroPos, macroEndPos).replaceAll(TEXT_ATTRS_PATTERN, ";"); - myCurrentColor = ColoredOutputTypeRegistry.getInstance().getOutputKey(colorAttribute); - pos = macroEndPos; + String colorAttribute = INNER_PATTERN.matcher(escSeq).replaceAll(";"); + myCurrentTextAttributes = ColoredOutputTypeRegistry.getInstance().getOutputKey(colorAttribute); + pos = escSeqEndInd; } if (pos < text.length()) { - textChunks.add(Pair.create(text.substring(pos), getCurrentOutputAttributes(outputType))); + chunks = processTextChunk(chunks, text.substring(pos), outputType, textAcceptor); } - if (textAcceptor instanceof ColoredChunksAcceptor) { - ((ColoredChunksAcceptor)textAcceptor).coloredChunksAvailable(textChunks); - } - else { - coloredTextAvailable(textChunks, textAcceptor); + if (chunks != null && textAcceptor instanceof ColoredChunksAcceptor) { + ((ColoredChunksAcceptor)textAcceptor).coloredChunksAvailable(chunks); } } - // selects all consecutive escape sequences - private static int getEndMacroPos(final String text, int macroPos) { - int endMacroPos = text.indexOf('m', macroPos); - while (endMacroPos >= 0) { - endMacroPos += 1; - macroPos = text.indexOf(TEXT_ATTRS_PREFIX, endMacroPos); - if (macroPos != endMacroPos) { + /* + * Selects all consecutive escape sequences and returns escape sequence end index (exclusive). + * If the escape sequence isn't finished, returns -1. + */ + private static int findEscSeqEndIndex(@NotNull String text, int escSeqBeginInd) { + escSeqBeginInd = text.indexOf('m', escSeqBeginInd); + while (escSeqBeginInd >= 0) { + escSeqBeginInd++; + if (!text.regionMatches(escSeqBeginInd, CSI, 0, CSI.length())) { break; } - endMacroPos = text.indexOf('m', macroPos); + escSeqBeginInd = text.indexOf('m', escSeqBeginInd); + } + return escSeqBeginInd; + } + + @Nullable + private List<Pair<String, Key>> processTextChunk(@Nullable List<Pair<String, Key>> buffer, + @NotNull String text, + @NotNull Key outputType, + @NotNull ColoredTextAcceptor textAcceptor) { + Key attributes = getCurrentOutputAttributes(outputType); + if (textAcceptor instanceof ColoredChunksAcceptor) { + if (buffer == null) { + buffer = ContainerUtil.newArrayListWithCapacity(1); + } + buffer.add(Pair.create(text, attributes)); + } + else { + textAcceptor.coloredTextAvailable(text, attributes); } - return endMacroPos; + return buffer; } - protected Key getCurrentOutputAttributes(final Key outputType) { + @NotNull + protected Key getCurrentOutputAttributes(@NotNull Key outputType) { if (outputType == ProcessOutputTypes.STDERR || outputType == ProcessOutputTypes.SYSTEM) { return outputType; } - return myCurrentColor != null ? myCurrentColor : outputType; + return myCurrentTextAttributes != null ? myCurrentTextAttributes : outputType; } - public void coloredTextAvailable(@NotNull final List<Pair<String, Key>> textChunks, ColoredTextAcceptor textAcceptor) { - for (final Pair<String, Key> textChunk : textChunks) { + public void coloredTextAvailable(@NotNull List<Pair<String, Key>> textChunks, ColoredTextAcceptor textAcceptor) { + for (Pair<String, Key> textChunk : textChunks) { textAcceptor.coloredTextAvailable(textChunk.getFirst(), textChunk.getSecond()); } } diff --git a/platform/platform-api/src/com/intellij/execution/process/CapturingAnsiEscapesAwareProcessHandler.java b/platform/platform-api/src/com/intellij/execution/process/CapturingAnsiEscapesAwareProcessHandler.java index c76e79a0bfd6..96544b8ba83c 100644 --- a/platform/platform-api/src/com/intellij/execution/process/CapturingAnsiEscapesAwareProcessHandler.java +++ b/platform/platform-api/src/com/intellij/execution/process/CapturingAnsiEscapesAwareProcessHandler.java @@ -44,7 +44,8 @@ public class CapturingAnsiEscapesAwareProcessHandler extends CapturingProcessHan private static class AnsiEscapesAwareAdapter extends CapturingProcessAdapter implements AnsiEscapeDecoder.ColoredTextAcceptor { private final AnsiEscapeDecoder myAnsiEscapeDecoder = new AnsiEscapeDecoder() { @Override - protected Key getCurrentOutputAttributes(Key outputType) { + @NotNull + protected Key getCurrentOutputAttributes(@NotNull Key outputType) { return outputType; //we don't need color information - only stdout and stderr keys are added to output in CapturingProcessAdapter } }; diff --git a/platform/platform-api/src/com/intellij/execution/process/ColoredOutputTypeRegistry.java b/platform/platform-api/src/com/intellij/execution/process/ColoredOutputTypeRegistry.java index 7fff03827fb4..be9dccb0dbca 100644 --- a/platform/platform-api/src/com/intellij/execution/process/ColoredOutputTypeRegistry.java +++ b/platform/platform-api/src/com/intellij/execution/process/ColoredOutputTypeRegistry.java @@ -8,6 +8,7 @@ import com.intellij.openapi.editor.markup.EffectType; import com.intellij.openapi.editor.markup.TextAttributes; import com.intellij.openapi.util.Key; import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; import java.awt.*; import java.util.HashMap; @@ -73,6 +74,7 @@ public class ColoredOutputTypeRegistry { see full doc at http://en.wikipedia.org/wiki/ANSI_escape_code */ + @NotNull public Key getOutputKey(@NonNls String attribute) { final Key key = myRegisteredKeys.get(attribute); if (key != null) { diff --git a/platform/platform-api/src/com/intellij/ide/CompositeSelectInTarget.java b/platform/platform-api/src/com/intellij/ide/CompositeSelectInTarget.java index 7facb6f990f8..e493770d6605 100644 --- a/platform/platform-api/src/com/intellij/ide/CompositeSelectInTarget.java +++ b/platform/platform-api/src/com/intellij/ide/CompositeSelectInTarget.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,5 +25,5 @@ import java.util.Collection; */ public interface CompositeSelectInTarget extends SelectInTarget{ @NotNull - Collection<SelectInTarget> getSubTargets(SelectInContext context); + Collection<SelectInTarget> getSubTargets(@NotNull SelectInContext context); } diff --git a/platform/platform-api/src/com/intellij/ide/SelectInTarget.java b/platform/platform-api/src/com/intellij/ide/SelectInTarget.java index 3e5f9d0e87bd..e7d834ac2268 100644 --- a/platform/platform-api/src/com/intellij/ide/SelectInTarget.java +++ b/platform/platform-api/src/com/intellij/ide/SelectInTarget.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,6 +21,7 @@ import org.jetbrains.annotations.Nullable; public interface SelectInTarget { ExtensionPointName<SelectInTarget> EP_NAME = new ExtensionPointName<SelectInTarget>("com.intellij.selectInTarget"); + @Override String toString(); /** diff --git a/platform/platform-api/src/com/intellij/openapi/actionSystem/AbbreviationManager.java b/platform/platform-api/src/com/intellij/openapi/actionSystem/AbbreviationManager.java index 78db7cf0ed5c..1e03a3482ad4 100644 --- a/platform/platform-api/src/com/intellij/openapi/actionSystem/AbbreviationManager.java +++ b/platform/platform-api/src/com/intellij/openapi/actionSystem/AbbreviationManager.java @@ -15,7 +15,7 @@ */ package com.intellij.openapi.actionSystem; -import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.components.ServiceManager; import java.util.List; import java.util.Set; @@ -26,11 +26,16 @@ import java.util.Set; */ public abstract class AbbreviationManager { public static AbbreviationManager getInstance() { - return ApplicationManager.getApplication().getComponent(AbbreviationManager.class); + return ServiceManager.getService(AbbreviationManager.class); } + public abstract Set<String> getAbbreviations(); + public abstract Set<String> getAbbreviations(String actionId); + public abstract List<String> findActions(String abbreviation); + public abstract void register(String abbreviation, String actionId); + public abstract void remove(String abbreviation, String actionId); } diff --git a/platform/platform-api/src/com/intellij/openapi/editor/actionSystem/CaretSpecificDataContext.java b/platform/platform-api/src/com/intellij/openapi/editor/actionSystem/CaretSpecificDataContext.java new file mode 100644 index 000000000000..e53cc48e4d5a --- /dev/null +++ b/platform/platform-api/src/com/intellij/openapi/editor/actionSystem/CaretSpecificDataContext.java @@ -0,0 +1,47 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.openapi.editor.actionSystem; + +import com.intellij.openapi.actionSystem.CommonDataKeys; +import com.intellij.openapi.actionSystem.DataContext; +import com.intellij.openapi.actionSystem.DataContextWrapper; +import com.intellij.openapi.editor.Caret; +import com.intellij.openapi.fileEditor.FileEditorManager; +import com.intellij.openapi.project.Project; +import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class CaretSpecificDataContext extends DataContextWrapper { + private final Caret myCaret; + + public CaretSpecificDataContext(@NotNull DataContext delegate, @NotNull Caret caret) { + super(delegate); + myCaret = caret; + } + + @Nullable + @Override + public Object getData(@NonNls String dataId) { + Project project = (Project)super.getData(CommonDataKeys.PROJECT.getName()); + if (project == null) { + return null; + } + FileEditorManager fm = FileEditorManager.getInstance(project); + Object data = fm == null ? null : fm.getData(dataId, myCaret.getEditor(), myCaret); + return data == null ? super.getData(dataId) : data; + } +} diff --git a/platform/platform-api/src/com/intellij/openapi/editor/actionSystem/EditorAction.java b/platform/platform-api/src/com/intellij/openapi/editor/actionSystem/EditorAction.java index 945c52022984..d93a508f97bd 100644 --- a/platform/platform-api/src/com/intellij/openapi/editor/actionSystem/EditorAction.java +++ b/platform/platform-api/src/com/intellij/openapi/editor/actionSystem/EditorAction.java @@ -26,13 +26,14 @@ import org.jetbrains.annotations.Nullable; import java.awt.event.KeyEvent; +import static com.intellij.openapi.actionSystem.CommonDataKeys.EDITOR; import static com.intellij.openapi.actionSystem.CommonDataKeys.PROJECT; public abstract class EditorAction extends AnAction implements DumbAware { private EditorActionHandler myHandler; private boolean myHandlersLoaded; - public EditorActionHandler getHandler() { + public final EditorActionHandler getHandler() { ensureHandlersLoaded(); return myHandler; } @@ -46,6 +47,7 @@ public abstract class EditorAction extends AnAction implements DumbAware { ensureHandlersLoaded(); EditorActionHandler tmp = myHandler; myHandler = newHandler; + myHandler.setWorksInInjected(isInInjectedContext()); return tmp; } @@ -58,12 +60,22 @@ public abstract class EditorAction extends AnAction implements DumbAware { final EditorActionHandlerBean handlerBean = extensions[i]; if (handlerBean.action.equals(id)) { myHandler = handlerBean.getHandler(myHandler); + myHandler.setWorksInInjected(isInInjectedContext()); } } } } @Override + public void setInjectedContext(boolean worksInInjected) { + super.setInjectedContext(worksInInjected); + // we assume that this method is called in constructor at the point + // where the chain of handlers is not initialized yet + // and it's enough to pass the flag to the default handler only + myHandler.setWorksInInjected(isInInjectedContext()); + } + + @Override public final void actionPerformed(AnActionEvent e) { DataContext dataContext = e.getDataContext(); Editor editor = getEditor(dataContext); @@ -72,7 +84,7 @@ public abstract class EditorAction extends AnAction implements DumbAware { @Nullable protected Editor getEditor(@NotNull DataContext dataContext) { - return CommonDataKeys.EDITOR.getData(dataContext); + return EDITOR.getData(dataContext); } public final void actionPerformed(final Editor editor, @NotNull final DataContext dataContext) { @@ -102,7 +114,7 @@ public abstract class EditorAction extends AnAction implements DumbAware { } public void update(Editor editor, Presentation presentation, DataContext dataContext) { - presentation.setEnabled(getHandler().isEnabled(editor, dataContext)); + presentation.setEnabled(getHandler().isEnabled(editor, null, dataContext)); } public void updateForKeyboardAccess(Editor editor, Presentation presentation, DataContext dataContext) { diff --git a/platform/platform-api/src/com/intellij/openapi/editor/actionSystem/EditorActionHandler.java b/platform/platform-api/src/com/intellij/openapi/editor/actionSystem/EditorActionHandler.java index c43fd13d8bef..294622ce1916 100644 --- a/platform/platform-api/src/com/intellij/openapi/editor/actionSystem/EditorActionHandler.java +++ b/platform/platform-api/src/com/intellij/openapi/editor/actionSystem/EditorActionHandler.java @@ -15,7 +15,7 @@ */ package com.intellij.openapi.editor.actionSystem; -import com.intellij.openapi.actionSystem.DataContext; +import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.editor.Caret; import com.intellij.openapi.editor.CaretAction; import com.intellij.openapi.editor.Editor; @@ -35,7 +35,9 @@ import org.jetbrains.annotations.Nullable; */ public abstract class EditorActionHandler { private final boolean myRunForEachCaret; + private boolean myWorksInInjected; private boolean inExecution; + private boolean inCheck; protected EditorActionHandler() { this(false); @@ -46,17 +48,92 @@ public abstract class EditorActionHandler { } /** - * Checks if the action handler is currently enabled. - * - * @param editor the editor in which the action is invoked. - * @param dataContext the data context for the action. - * @return true if the action is enabled, false otherwise + * @deprecated Implementations should override + * {@link #isEnabledForCaret(com.intellij.openapi.editor.Editor, com.intellij.openapi.editor.Caret, com.intellij.openapi.actionSystem.DataContext)} + * instead, + * client code should invoke + * {@link #isEnabled(com.intellij.openapi.editor.Editor, com.intellij.openapi.editor.Caret, com.intellij.openapi.actionSystem.DataContext)} + * instead. */ - public boolean isEnabled(Editor editor, DataContext dataContext) { - return true; + public boolean isEnabled(Editor editor, final DataContext dataContext) { + if (inCheck) { + return true; + } + inCheck = true; + try { + if (editor == null) { + return false; + } + Editor hostEditor = dataContext == null ? null : CommonDataKeys.HOST_EDITOR.getData(dataContext); + if (hostEditor == null) { + hostEditor = editor; + } + final boolean[] result = new boolean[1]; + final CaretTask check = new CaretTask() { + @Override + public void perform(@NotNull Caret caret, @Nullable DataContext dataContext) { + result[0] = true; + } + }; + if (myRunForEachCaret) { + hostEditor.getCaretModel().runForEachCaret(new CaretAction() { + @Override + public void perform(Caret caret) { + doIfEnabled(caret, dataContext, check); + } + }); + } + else { + doIfEnabled(hostEditor.getCaretModel().getCurrentCaret(), dataContext, check); + } + return result[0]; + } + finally { + inCheck = false; + } + } + + private void doIfEnabled(@NotNull Caret hostCaret, @Nullable DataContext context, @NotNull CaretTask task) { + DataContext caretContext = context == null ? null : new CaretSpecificDataContext(context, hostCaret); + if (myWorksInInjected && caretContext != null) { + DataContext injectedCaretContext = AnActionEvent.getInjectedDataContext(caretContext); + Caret injectedCaret = CommonDataKeys.CARET.getData(injectedCaretContext); + if (injectedCaret != null && injectedCaret != hostCaret && isEnabledForCaret(injectedCaret.getEditor(), injectedCaret, injectedCaretContext)) { + task.perform(injectedCaret, injectedCaretContext); + return; + } + } + if (isEnabledForCaret(hostCaret.getEditor(), hostCaret, caretContext)) { + task.perform(hostCaret, caretContext); + } } /** + * Implementations can override this method to define whether handler is enabled for a specific caret in a given editor. + */ + protected boolean isEnabledForCaret(@NotNull Editor editor, @NotNull Caret caret, DataContext dataContext) { + if (inCheck) { + return true; + } + inCheck = true; + try { + //noinspection deprecation + return isEnabled(editor, dataContext); + } + finally { + inCheck = false; + } + } + + /** + * If <code>caret</code> is <code>null</code>, checks whether handler is enabled in general (i.e. enabled for at least one caret in editor), + * if <code>caret</code> is not <code>null</code>, checks whether it's enabled for specified caret. + */ + public final boolean isEnabled(@NotNull Editor editor, @Nullable Caret caret, DataContext dataContext) { + //noinspection deprecation + return caret == null ? isEnabled(editor, dataContext) : isEnabledForCaret(editor, caret, dataContext); + } + /** * @deprecated To implement action logic, override * {@link #doExecute(com.intellij.openapi.editor.Editor, com.intellij.openapi.editor.Caret, com.intellij.openapi.actionSystem.DataContext)}, * to invoke the handler, call @@ -112,22 +189,49 @@ public abstract class EditorActionHandler { * @param editor the editor in which the action is invoked. * @param dataContext the data context for the action. */ - public final void execute(@NotNull final Editor editor, @Nullable Caret contextCaret, final DataContext dataContext) { + public final void execute(@NotNull Editor editor, @Nullable final Caret contextCaret, final DataContext dataContext) { + Editor hostEditor = dataContext == null ? null : CommonDataKeys.HOST_EDITOR.getData(dataContext); + if (hostEditor == null) { + hostEditor = editor; + } if (contextCaret == null && runForAllCarets()) { - editor.getCaretModel().runForEachCaret(new CaretAction() { + hostEditor.getCaretModel().runForEachCaret(new CaretAction() { @Override public void perform(Caret caret) { - doExecute(editor, caret, dataContext); + doIfEnabled(caret, dataContext, new CaretTask() { + @Override + public void perform(@NotNull Caret caret, @Nullable DataContext dataContext) { + doExecute(caret.getEditor(), caret, dataContext); + } + }); } }, true); } else { - doExecute(editor, contextCaret, dataContext); + if (contextCaret == null) { + doIfEnabled(hostEditor.getCaretModel().getCurrentCaret(), dataContext, new CaretTask() { + @Override + public void perform(@NotNull Caret caret, @Nullable DataContext dataContext) { + doExecute(caret.getEditor(), null, dataContext); + } + }); + } + else { + doExecute(editor, contextCaret, dataContext); + } } } + void setWorksInInjected(boolean worksInInjected) { + myWorksInInjected = worksInInjected; + } + public DocCommandGroupId getCommandGroupId(Editor editor) { // by default avoid merging two consequential commands, and, in the same time, pass along the Document return DocCommandGroupId.noneGroupId(editor.getDocument()); } + + private interface CaretTask { + void perform(@NotNull Caret caret, @Nullable DataContext dataContext); + } } diff --git a/platform/platform-api/src/com/intellij/openapi/fileEditor/EditorDataProvider.java b/platform/platform-api/src/com/intellij/openapi/fileEditor/EditorDataProvider.java index 7dfec0240c1f..90d05360be0e 100644 --- a/platform/platform-api/src/com/intellij/openapi/fileEditor/EditorDataProvider.java +++ b/platform/platform-api/src/com/intellij/openapi/fileEditor/EditorDataProvider.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,14 +15,14 @@ */ package com.intellij.openapi.fileEditor; +import com.intellij.openapi.editor.Caret; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.vfs.VirtualFile; /** * @author peter */ public interface EditorDataProvider { - @Nullable Object getData(@NotNull String dataId, @NotNull Editor e, @NotNull VirtualFile file); + @Nullable Object getData(@NotNull String dataId, @NotNull Editor e, @NotNull Caret caret); } diff --git a/platform/platform-api/src/com/intellij/openapi/fileEditor/FileEditorManager.java b/platform/platform-api/src/com/intellij/openapi/fileEditor/FileEditorManager.java index b9589574059d..86e719eef48d 100644 --- a/platform/platform-api/src/com/intellij/openapi/fileEditor/FileEditorManager.java +++ b/platform/platform-api/src/com/intellij/openapi/fileEditor/FileEditorManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,6 +16,7 @@ package com.intellij.openapi.fileEditor; import com.intellij.openapi.Disposable; +import com.intellij.openapi.editor.Caret; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Key; @@ -184,6 +185,13 @@ public abstract class FileEditorManager { public abstract void registerExtraEditorDataProvider(@NotNull EditorDataProvider provider, Disposable parentDisposable); /** + * Returns data associated with given editor/caret context. Data providers are registered via + * {@link #registerExtraEditorDataProvider(EditorDataProvider, com.intellij.openapi.Disposable)} method. + */ + @Nullable + public abstract Object getData(@NotNull String dataId, @NotNull Editor editor, @NotNull Caret caret); + + /** * Selects a specified file editor tab for the specified editor. * @param file a file to switch the file editor tab for. The function does nothing if the file is not currently open in the editor. * @param fileEditorProviderId the ID of the file editor to open; matches the return value of diff --git a/platform/platform-api/src/com/intellij/openapi/ui/ComboBoxTableRenderer.java b/platform/platform-api/src/com/intellij/openapi/ui/ComboBoxTableRenderer.java index c02f27af5d4b..f35d76fff51c 100644 --- a/platform/platform-api/src/com/intellij/openapi/ui/ComboBoxTableRenderer.java +++ b/platform/platform-api/src/com/intellij/openapi/ui/ComboBoxTableRenderer.java @@ -117,7 +117,7 @@ public class ComboBoxTableRenderer<T> extends JLabel implements TableCellRendere public Component getTableCellEditorComponent(JTable table, final Object value, boolean isSelected, final int row, final int column) { @SuppressWarnings("unchecked") final T t = (T)value; myValue = t; - customizeComponent(t, table, isSelected); + customizeComponent(t, table, true); //noinspection SSBasedInspection SwingUtilities.invokeLater(new Runnable() { diff --git a/platform/platform-api/src/com/intellij/openapi/ui/ComponentWithActions.java b/platform/platform-api/src/com/intellij/openapi/ui/ComponentWithActions.java index d6310f508ed0..889fb2786188 100644 --- a/platform/platform-api/src/com/intellij/openapi/ui/ComponentWithActions.java +++ b/platform/platform-api/src/com/intellij/openapi/ui/ComponentWithActions.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -41,11 +41,11 @@ public interface ComponentWithActions { boolean isContentBuiltIn(); class Impl implements ComponentWithActions { - private ActionGroup myToolbar; - private String myToolbarPlace; - private JComponent myToolbarContext; - private JComponent mySearchComponent; - private JComponent myComponent; + private final ActionGroup myToolbar; + private final String myToolbarPlace; + private final JComponent myToolbarContext; + private final JComponent mySearchComponent; + private final JComponent myComponent; public Impl(final ActionGroup toolbar, final String toolbarPlace, final JComponent toolbarContext, final JComponent searchComponent, @@ -57,6 +57,7 @@ public interface ComponentWithActions { myComponent = component; } + @Override public boolean isContentBuiltIn() { return false; } @@ -65,22 +66,27 @@ public interface ComponentWithActions { this(null, null, null, null, component); } + @Override public ActionGroup getToolbarActions() { return myToolbar; } + @Override public JComponent getSearchComponent() { return mySearchComponent; } + @Override public String getToolbarPlace() { return myToolbarPlace; } + @Override public JComponent getToolbarContextComponent() { return myToolbarContext; } + @Override @NotNull public JComponent getComponent() { return myComponent; diff --git a/platform/platform-api/src/com/intellij/openapi/ui/MasterDetailsComponent.java b/platform/platform-api/src/com/intellij/openapi/ui/MasterDetailsComponent.java index 6c13964d5789..a262ea0a3b85 100644 --- a/platform/platform-api/src/com/intellij/openapi/ui/MasterDetailsComponent.java +++ b/platform/platform-api/src/com/intellij/openapi/ui/MasterDetailsComponent.java @@ -122,7 +122,7 @@ public abstract class MasterDetailsComponent implements Configurable, DetailsCom private boolean myHasDeletedItems; protected AutoScrollToSourceHandler myAutoScrollHandler; - private boolean myToReInitWholePanel = true; + protected boolean myToReInitWholePanel = true; protected MasterDetailsComponent() { this(new MasterDetailsState()); @@ -139,7 +139,7 @@ public abstract class MasterDetailsComponent implements Configurable, DetailsCom reInitWholePanelIfNeeded(); } - private void reInitWholePanelIfNeeded() { + protected void reInitWholePanelIfNeeded() { if (!myToReInitWholePanel) return; myWholePanel = new JPanel(new BorderLayout()) { @@ -177,7 +177,8 @@ public abstract class MasterDetailsComponent implements Configurable, DetailsCom decorator.setActionGroup(group); } //left.add(myNorthPanel, BorderLayout.NORTH); - myMaster = decorator.setPanelBorder(new EmptyBorder(0, 0, 0, 0)).createPanel(); + myMaster = decorator.setAsUsualTopToolbar().setPanelBorder(new EmptyBorder(0, 0, 0, 0)).createPanel(); + myNorthPanel.setVisible(false); } else { left.add(myNorthPanel, BorderLayout.NORTH); myMaster = ScrollPaneFactory.createScrollPane(myTree); @@ -280,6 +281,7 @@ public abstract class MasterDetailsComponent implements Configurable, DetailsCom } private void initToolbar() { + if (Registry.is("ide.new.project.settings")) return; DefaultActionGroup group = createToolbarActionGroup(); if (group != null) { final JComponent component = ActionManager.getInstance().createActionToolbar(ActionPlaces.UNKNOWN, group, true).getComponent(); diff --git a/platform/platform-api/src/com/intellij/openapi/ui/PanelWithText.java b/platform/platform-api/src/com/intellij/openapi/ui/PanelWithText.java index 172772139ccf..fc6c3c6686cd 100644 --- a/platform/platform-api/src/com/intellij/openapi/ui/PanelWithText.java +++ b/platform/platform-api/src/com/intellij/openapi/ui/PanelWithText.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -36,7 +36,7 @@ public class PanelWithText extends JPanel { public PanelWithText(String text) { super(new GridBagLayout()); - setBorder(BorderFactory.createEtchedBorder()); + //setBorder(BorderFactory.createEtchedBorder()); myLabel.setText(XmlStringUtil.wrapInHtml(text)); add(myLabel, new GridBagConstraints(0, 0, 1, 1, 1, 1, GridBagConstraints.NORTH, GridBagConstraints.HORIZONTAL, new Insets(8,8,8,8), 0, 0)); } diff --git a/platform/platform-api/src/com/intellij/openapi/ui/popup/ListItemDescriptorAdapter.java b/platform/platform-api/src/com/intellij/openapi/ui/popup/ListItemDescriptorAdapter.java new file mode 100644 index 000000000000..e11e70c74b98 --- /dev/null +++ b/platform/platform-api/src/com/intellij/openapi/ui/popup/ListItemDescriptorAdapter.java @@ -0,0 +1,44 @@ +/* + * Copyright 2000-2009 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.openapi.ui.popup; + +import org.jetbrains.annotations.Nullable; + +import javax.swing.*; + +public abstract class ListItemDescriptorAdapter<T> implements ListItemDescriptor<T> { + @Nullable + @Override + public String getCaptionAboveOf(T value) { + return null; + } + + @Nullable + @Override + public String getTooltipFor(T value) { + return null; + } + + @Override + public Icon getIconFor(T value) { + return null; + } + + @Override + public boolean hasSeparatorAboveOf(T value) { + return false; + } +}
\ No newline at end of file diff --git a/platform/platform-api/src/com/intellij/openapi/vfs/VfsUtil.java b/platform/platform-api/src/com/intellij/openapi/vfs/VfsUtil.java index 3cd467048e98..254f7749fb25 100644 --- a/platform/platform-api/src/com/intellij/openapi/vfs/VfsUtil.java +++ b/platform/platform-api/src/com/intellij/openapi/vfs/VfsUtil.java @@ -51,7 +51,9 @@ import java.util.*; public class VfsUtil extends VfsUtilCore { private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.vfs.VfsUtil"); - public static final char VFS_PATH_SEPARATOR = '/'; + + /** @deprecated incorrect name, use {@link #VFS_SEPARATOR_CHAR} (to be removed in IDEA 15) */ + public static final char VFS_PATH_SEPARATOR = VFS_SEPARATOR_CHAR; public static void saveText(@NotNull VirtualFile file, @NotNull String text) throws IOException { Charset charset = file.getCharset(); @@ -585,7 +587,7 @@ public class VfsUtil extends VfsUtilCore { if (url == null) { return null; } - final int index = url.lastIndexOf(VFS_PATH_SEPARATOR); + final int index = url.lastIndexOf(VfsUtil.VFS_SEPARATOR_CHAR); return index < 0 ? null : url.substring(0, index); } @@ -598,12 +600,12 @@ public class VfsUtil extends VfsUtilCore { if (urlOrPath == null) { return null; } - final int index = urlOrPath.lastIndexOf(VFS_PATH_SEPARATOR); + final int index = urlOrPath.lastIndexOf(VfsUtil.VFS_SEPARATOR_CHAR); return index < 0 ? null : urlOrPath.substring(index+1); } @NotNull - public static List<VirtualFile> markDirty(boolean recursive, boolean reloadChildren, VirtualFile... files) { + public static List<VirtualFile> markDirty(boolean recursive, boolean reloadChildren, @NotNull VirtualFile... files) { List<VirtualFile> list = ContainerUtil.filter(Condition.NOT_NULL, files); if (list.isEmpty()) { return Collections.emptyList(); @@ -626,7 +628,7 @@ public class VfsUtil extends VfsUtilCore { return list; } - public static void markDirtyAndRefresh(boolean async, boolean recursive, boolean reloadChildren, VirtualFile... files) { + public static void markDirtyAndRefresh(boolean async, boolean recursive, boolean reloadChildren, @NotNull VirtualFile... files) { List<VirtualFile> list = markDirty(recursive, reloadChildren, files); if (list.isEmpty()) return; LocalFileSystem.getInstance().refreshFiles(list, async, recursive, null); diff --git a/platform/platform-api/src/com/intellij/openapi/wm/FocusCommand.java b/platform/platform-api/src/com/intellij/openapi/wm/FocusCommand.java index 6c40a04f5831..38dcb877e030 100644 --- a/platform/platform-api/src/com/intellij/openapi/wm/FocusCommand.java +++ b/platform/platform-api/src/com/intellij/openapi/wm/FocusCommand.java @@ -192,7 +192,7 @@ public abstract class FocusCommand extends ActiveRunnable implements Expirable { LOG.info("We could not request focus in window on " + myToFocus.getClass().getName()); LOG.info(myAllocation); } - if (!SystemInfo.isMac || isForced() ) { + if (isForced()) { myToFocus.requestFocus(); if (shouldLogFocuses) { LOG.info("Force request focus on " + myToFocus.getClass().getName()); @@ -217,10 +217,6 @@ public abstract class FocusCommand extends ActiveRunnable implements Expirable { if (myToFocus == null) { return true; } - if (SwingUtilities.getWindowAncestor(myToFocus) == null) { - clear(); - return true; - } return false; } diff --git a/platform/platform-api/src/com/intellij/openapi/wm/IdeFocusManager.java b/platform/platform-api/src/com/intellij/openapi/wm/IdeFocusManager.java index d8f7e86d4b9e..6b4852319899 100644 --- a/platform/platform-api/src/com/intellij/openapi/wm/IdeFocusManager.java +++ b/platform/platform-api/src/com/intellij/openapi/wm/IdeFocusManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -163,9 +163,8 @@ public abstract class IdeFocusManager implements FocusRequestor { public abstract void toFront(JComponent c); public static IdeFocusManager getInstance(@Nullable Project project) { - if (project == null) return getGlobalInstance(); + if (project == null || project.isDisposed() || !project.isInitialized()) return getGlobalInstance(); - if (project.isDisposed() || !project.isInitialized()) return getGlobalInstance(); return project.getComponent(IdeFocusManager.class); } diff --git a/platform/platform-api/src/com/intellij/openapi/wm/ToolWindowFactory.java b/platform/platform-api/src/com/intellij/openapi/wm/ToolWindowFactory.java index 477ff28baef6..cc198e18a140 100644 --- a/platform/platform-api/src/com/intellij/openapi/wm/ToolWindowFactory.java +++ b/platform/platform-api/src/com/intellij/openapi/wm/ToolWindowFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,6 +17,7 @@ package com.intellij.openapi.wm; import com.intellij.openapi.project.Project; +import org.jetbrains.annotations.NotNull; /** * Performs lazy initialization of a toolwindow registered in plugin.xml. @@ -25,5 +26,5 @@ import com.intellij.openapi.project.Project; * @see ToolWindowEP */ public interface ToolWindowFactory { - void createToolWindowContent(Project project, ToolWindow toolWindow); + void createToolWindowContent(@NotNull Project project, @NotNull ToolWindow toolWindow); } diff --git a/platform/platform-api/src/com/intellij/openapi/wm/ToolWindowManager.java b/platform/platform-api/src/com/intellij/openapi/wm/ToolWindowManager.java index 0e7ddb332151..b616429a11c8 100644 --- a/platform/platform-api/src/com/intellij/openapi/wm/ToolWindowManager.java +++ b/platform/platform-api/src/com/intellij/openapi/wm/ToolWindowManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -47,16 +47,25 @@ public abstract class ToolWindowManager { * @return tool window * @deprecated {@link com.intellij.openapi.wm.ToolWindowManager#registerToolWindow(String, boolean, ToolWindowAnchor)} */ - public abstract ToolWindow registerToolWindow(@NotNull String id,@NotNull JComponent component,@NotNull ToolWindowAnchor anchor); + @Deprecated + @NotNull + public abstract ToolWindow registerToolWindow(@NotNull String id, @NotNull JComponent component, @NotNull ToolWindowAnchor anchor); /** * @deprecated {@link com.intellij.openapi.wm.ToolWindowManager#registerToolWindow(String, boolean, ToolWindowAnchor)} */ - public abstract ToolWindow registerToolWindow(@NotNull String id,@NotNull JComponent component,@NotNull ToolWindowAnchor anchor, Disposable parentDisposable); + @Deprecated + @NotNull + public abstract ToolWindow registerToolWindow(@NotNull String id, + @NotNull JComponent component, + @NotNull ToolWindowAnchor anchor, + @NotNull Disposable parentDisposable); /** * @deprecated {@link com.intellij.openapi.wm.ToolWindowManager#registerToolWindow(String, boolean, ToolWindowAnchor)} */ + @Deprecated + @NotNull public abstract ToolWindow registerToolWindow(@NotNull String id, @NotNull JComponent component, @NotNull ToolWindowAnchor anchor, @@ -65,6 +74,8 @@ public abstract class ToolWindowManager { /** * @deprecated {@link com.intellij.openapi.wm.ToolWindowManager#registerToolWindow(String, boolean, ToolWindowAnchor)} */ + @Deprecated + @NotNull public abstract ToolWindow registerToolWindow(@NotNull String id, @NotNull JComponent component, @NotNull ToolWindowAnchor anchor, @@ -72,12 +83,16 @@ public abstract class ToolWindowManager { boolean canWorkInDumbMode, boolean canCloseContents); + @NotNull public abstract ToolWindow registerToolWindow(@NotNull String id, boolean canCloseContent, @NotNull ToolWindowAnchor anchor); + @NotNull public abstract ToolWindow registerToolWindow(@NotNull String id, boolean canCloseContent, @NotNull ToolWindowAnchor anchor, boolean secondary); + @NotNull public abstract ToolWindow registerToolWindow(@NotNull String id, boolean canCloseContent, @NotNull ToolWindowAnchor anchor, Disposable parentDisposable, boolean canWorkInDumbMode); + @NotNull public ToolWindow registerToolWindow(@NotNull final String id, final boolean canCloseContent, @NotNull final ToolWindowAnchor anchor, @@ -102,6 +117,7 @@ public abstract class ToolWindowManager { /** * @return array of <code>id</code>s of all registered tool windows. */ + @NotNull public abstract String[] getToolWindowIds(); /** @@ -120,11 +136,12 @@ public abstract class ToolWindowManager { /** * Puts specified runnable to the tail of current command queue. */ - public abstract void invokeLater(Runnable runnable); + public abstract void invokeLater(@NotNull Runnable runnable); /** * Utility method for quick access to the focus manager */ + @NotNull public abstract IdeFocusManager getFocusManager(); public abstract void notifyByBalloon(@NotNull final String toolWindowId, @NotNull final MessageType type, @NotNull final String htmlBody); diff --git a/platform/platform-api/src/com/intellij/ui/components/JBScrollPane.java b/platform/platform-api/src/com/intellij/ui/components/JBScrollPane.java index 83944a51755d..97a42176a25b 100644 --- a/platform/platform-api/src/com/intellij/ui/components/JBScrollPane.java +++ b/platform/platform-api/src/com/intellij/ui/components/JBScrollPane.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,6 +18,7 @@ package com.intellij.ui.components; import com.intellij.openapi.wm.IdeGlassPane; import com.intellij.ui.IdeBorderFactory; import com.intellij.util.ArrayUtil; +import com.intellij.util.ReflectionUtil; import com.intellij.util.ui.ButtonlessScrollBarUI; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -29,7 +30,6 @@ import javax.swing.plaf.ScrollPaneUI; import javax.swing.plaf.basic.BasicScrollBarUI; import java.awt.*; import java.awt.event.MouseEvent; -import java.lang.reflect.Method; public class JBScrollPane extends JScrollPane { private int myViewportBorderWidth = -1; @@ -302,9 +302,7 @@ public class JBScrollPane extends JScrollPane { if (ui instanceof BasicScrollBarUI) { BasicScrollBarUI bui = (BasicScrollBarUI)ui; try { - Method m = BasicScrollBarUI.class.getDeclaredMethod("getThumbBounds", ArrayUtil.EMPTY_CLASS_ARRAY); - m.setAccessible(true); - Rectangle rect = (Rectangle)m.invoke(bui); + Rectangle rect = (Rectangle)ReflectionUtil.getDeclaredMethod(BasicScrollBarUI.class, "getThumbBounds", ArrayUtil.EMPTY_CLASS_ARRAY).invoke(bui); Point point = SwingUtilities.convertPoint(e.getComponent(), e.getX(), e.getY(), bar); return !rect.contains(point); } diff --git a/platform/platform-api/src/com/intellij/ui/content/ContentManagerEvent.java b/platform/platform-api/src/com/intellij/ui/content/ContentManagerEvent.java index 9aae91aaba42..31fe871d0a05 100644 --- a/platform/platform-api/src/com/intellij/ui/content/ContentManagerEvent.java +++ b/platform/platform-api/src/com/intellij/ui/content/ContentManagerEvent.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,10 +18,10 @@ package com.intellij.ui.content; import java.util.EventObject; public class ContentManagerEvent extends EventObject { - private Content myContent; - private int myIndex; + private final Content myContent; + private final int myIndex; private boolean myConsumed; - private ContentOperation myOperation; + private final ContentOperation myOperation; public ContentManagerEvent(Object source, Content content, int index, ContentOperation operation) { super(source); @@ -54,7 +54,7 @@ public class ContentManagerEvent extends EventObject { return myOperation; } - public static enum ContentOperation { + public enum ContentOperation { add, remove, undefined } -}
\ No newline at end of file +} diff --git a/platform/platform-api/src/com/intellij/ui/table/JBTable.java b/platform/platform-api/src/com/intellij/ui/table/JBTable.java index 435c4358959f..bda230eb767e 100644 --- a/platform/platform-api/src/com/intellij/ui/table/JBTable.java +++ b/platform/platform-api/src/com/intellij/ui/table/JBTable.java @@ -52,7 +52,6 @@ public class JBTable extends JTable implements ComponentWithEmptyText, Component private Integer myMinRowHeight; private boolean myStriped; - private boolean isTypeAhead = true; private AsyncProcessIcon myBusyIcon; private boolean myBusy; @@ -69,6 +68,8 @@ public class JBTable extends JTable implements ComponentWithEmptyText, Component public JBTable(final TableModel model, final TableColumnModel columnModel) { super(model, columnModel); + setSurrendersFocusOnKeystroke(true); + myEmptyText = new StatusText(this) { @Override protected boolean isStatusVisible() { @@ -421,7 +422,10 @@ public class JBTable extends JTable implements ComponentWithEmptyText, Component return false; } - if (e instanceof KeyEvent && UIUtil.isReallyTypedEvent((KeyEvent)e)) { + if (e instanceof KeyEvent) { + // do not start editing in autoStartsEdit mode on Ctrl-Z and other non-typed events + if (!UIUtil.isReallyTypedEvent((KeyEvent)e)) return false; + SpeedSearchSupply supply = SpeedSearchSupply.getSupply(this); if (supply != null && supply.isPopupActive()) { return false; @@ -449,20 +453,43 @@ public class JBTable extends JTable implements ComponentWithEmptyText, Component add(editorComp); editorComp.validate(); - IdeFocusManager.findInstanceByComponent(this).requestFocus(editorComp, false); + if (surrendersFocusOnKeyStroke()) { + // this replaces focus request in JTable.processKeyBinding + final IdeFocusManager focusManager = IdeFocusManager.findInstanceByComponent(this); + focusManager.setTypeaheadEnabled(false); + focusManager.requestFocus(editorComp, true).doWhenProcessed(new Runnable() { + @Override + public void run() { + focusManager.setTypeaheadEnabled(true); + } + }); + } setCellEditor(editor); setEditingRow(row); setEditingColumn(column); editor.addCellEditorListener(this); - if (isTypeAhead) { - JTableCellEditorHelper.typeAhead(this, e, row, column); - } + return true; } return false; } + /** + * Always returns false. + * If you're interested in value of JTable.surrendersFocusOnKeystroke property, call JBTable.surrendersFocusOnKeyStroke() + * @return false + * @see #surrendersFocusOnKeyStroke + */ + @Override + public boolean getSurrendersFocusOnKeystroke() { + return false; // prevents JTable.processKeyBinding from requesting editor component to be focused + } + + public boolean surrendersFocusOnKeyStroke() { + return super.getSurrendersFocusOnKeystroke(); + } + private static boolean isTableDecorationSupported() { return UIUtil.isUnderAlloyLookAndFeel() || UIUtil.isUnderNativeMacLookAndFeel() @@ -472,10 +499,6 @@ public class JBTable extends JTable implements ComponentWithEmptyText, Component || UIUtil.isUnderWindowsLookAndFeel(); } - public void disableTypeAheadInCellEditors() { - isTypeAhead = false; - } - @NotNull @Override public Component prepareRenderer(@NotNull TableCellRenderer renderer, int row, int column) { diff --git a/platform/platform-api/src/com/intellij/ui/tabs/impl/JBEditorTabs.java b/platform/platform-api/src/com/intellij/ui/tabs/impl/JBEditorTabs.java index a842f623ac45..43f06bff2850 100644 --- a/platform/platform-api/src/com/intellij/ui/tabs/impl/JBEditorTabs.java +++ b/platform/platform-api/src/com/intellij/ui/tabs/impl/JBEditorTabs.java @@ -49,7 +49,7 @@ public class JBEditorTabs extends JBTabsImpl { private JBEditorTabsPainter myDefaultPainter = new DefaultEditorTabsPainter(); - public JBEditorTabs(@Nullable Project project, ActionManager actionManager, IdeFocusManager focusManager, @NotNull Disposable parent) { + public JBEditorTabs(@Nullable Project project, @NotNull ActionManager actionManager, IdeFocusManager focusManager, @NotNull Disposable parent) { super(project, actionManager, focusManager, parent); } diff --git a/platform/platform-api/src/com/intellij/ui/tabs/impl/JBTabsImpl.java b/platform/platform-api/src/com/intellij/ui/tabs/impl/JBTabsImpl.java index 60898a6e9bd8..326192072c4b 100644 --- a/platform/platform-api/src/com/intellij/ui/tabs/impl/JBTabsImpl.java +++ b/platform/platform-api/src/com/intellij/ui/tabs/impl/JBTabsImpl.java @@ -28,6 +28,7 @@ import com.intellij.openapi.wm.*; import com.intellij.ui.*; import com.intellij.ui.awt.RelativePoint; import com.intellij.ui.awt.RelativeRectangle; +import com.intellij.ui.components.OrphanGuardian; import com.intellij.ui.switcher.QuickActionProvider; import com.intellij.ui.switcher.SwitchProvider; import com.intellij.ui.switcher.SwitchTarget; @@ -36,6 +37,7 @@ import com.intellij.ui.tabs.impl.singleRow.SingleRowLayout; import com.intellij.ui.tabs.impl.singleRow.SingleRowPassInfo; import com.intellij.ui.tabs.impl.table.TableLayout; import com.intellij.ui.tabs.impl.table.TablePassInfo; +import com.intellij.util.Consumer; import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.ui.Animator; @@ -69,7 +71,7 @@ public class JBTabsImpl extends JComponent public static final Color MAC_AQUA_BG_COLOR = Gray._200; - final ActionManager myActionManager; + @NotNull final ActionManager myActionManager; private final List<TabInfo> myVisibleInfos = new ArrayList<TabInfo>(); private final Map<TabInfo, Integer> myHiddenInfos = new HashMap<TabInfo, Integer>(); @@ -153,8 +155,8 @@ public class JBTabsImpl extends JComponent private JBTabsPosition myPosition = JBTabsPosition.top; private final TabsBorder myBorder = new TabsBorder(this); - private BaseNavigationAction myNextAction; - private BaseNavigationAction myPrevAction; + private final BaseNavigationAction myNextAction; + private final BaseNavigationAction myPrevAction; private boolean myTabDraggingEnabled; private DragHelper myDragHelper; @@ -172,6 +174,7 @@ public class JBTabsImpl extends JComponent private Runnable myDeferredFocusRequest; private boolean myAlwaysPaintSelectedTab; + private int myFirstTabOffset; public JBTabsImpl(@NotNull Project project) { this(project, project); @@ -185,7 +188,7 @@ public class JBTabsImpl extends JComponent this(project, ActionManager.getInstance(), focusManager, parent); } - public JBTabsImpl(@Nullable Project project, ActionManager actionManager, IdeFocusManager focusManager, @NotNull Disposable parent) { + public JBTabsImpl(@Nullable Project project, @NotNull ActionManager actionManager, IdeFocusManager focusManager, @NotNull Disposable parent) { myProject = project; myActionManager = actionManager; myFocusManager = focusManager != null ? focusManager : IdeFocusManager.getGlobalInstance(); @@ -197,13 +200,11 @@ public class JBTabsImpl extends JComponent myNavigationActions = new DefaultActionGroup(); - if (myActionManager != null) { - myNextAction = new SelectNextAction(this, myActionManager); - myPrevAction = new SelectPreviousAction(this, myActionManager); + myNextAction = new SelectNextAction(this, myActionManager); + myPrevAction = new SelectPreviousAction(this, myActionManager); - myNavigationActions.add(myNextAction); - myNavigationActions.add(myPrevAction); - } + myNavigationActions.add(myNextAction); + myNavigationActions.add(myPrevAction); setUiDecorator(null); @@ -315,6 +316,16 @@ public class JBTabsImpl extends JComponent } } }; + putClientProperty(OrphanGuardian.CLIENT_PROPERTY_KEY, new OrphanGuardian() { + + @Override + public void iterateOrphans(Consumer<JComponent> consumer) { + for (TabInfo info : getVisibleInfos()) { + if (info == mySelectedInfo) continue; + consumer.consume(info.getComponent()); + } + } + }); } protected SingleRowLayout createSingleRowLayout() { @@ -451,14 +462,14 @@ public class JBTabsImpl extends JComponent } private void addTimerUpdate() { - if (myActionManager != null && !myListenerAdded) { + if (!myListenerAdded) { myActionManager.addTimerListener(500, this); myListenerAdded = true; } } private void removeTimerUpdate() { - if (myActionManager != null && myListenerAdded) { + if (myListenerAdded) { myActionManager.removeTimerListener(this); myListenerAdded = false; } @@ -492,6 +503,14 @@ public class JBTabsImpl extends JComponent myDropInfoIndex = dropInfoIndex; } + public int getFirstTabOffset() { + return myFirstTabOffset; + } + + public void setFirstTabOffset(int firstTabOffset) { + myFirstTabOffset = firstTabOffset; + } + class TabActionsAutoHideListener extends MouseMotionAdapter implements Weighted { private TabLabel myCurrentOverLabel; @@ -1399,7 +1418,7 @@ public class JBTabsImpl extends JComponent final ActionGroup group = info.getGroup(); final JComponent side = info.getSideComponent(); - if (group != null && myTabs.myActionManager != null) { + if (group != null) { final String place = info.getPlace(); ActionToolbar toolbar = myTabs.myActionManager.createActionToolbar(place != null ? place : ActionPlaces.UNKNOWN, group, myTabs.myHorizontalSide); @@ -1604,7 +1623,7 @@ public class JBTabsImpl extends JComponent return 3; } - public static int getGhostTabLength() { + public int getGhostTabLength() { return 15; } @@ -2561,6 +2580,7 @@ public class JBTabsImpl extends JComponent } private void updateContainer(boolean forced, final boolean layoutNow) { + if (myProject != null && !myProject.isOpen()) return; for (TabInfo each : new ArrayList<TabInfo>(myVisibleInfos)) { final JComponent eachComponent = each.getComponent(); if (getSelectedInfo() == each && getSelectedInfo() != null) { @@ -2746,8 +2766,7 @@ public class JBTabsImpl extends JComponent } private static boolean isChanged(Object oldObject, Object newObject) { - if (oldObject == null && newObject == null) return false; - return oldObject != null && !oldObject.equals(newObject) || newObject != null && !newObject.equals(oldObject); + return !Comparing.equal(oldObject, newObject); } @Override @@ -2785,12 +2804,11 @@ public class JBTabsImpl extends JComponent } private abstract static class BaseNavigationAction extends AnAction { - private final ShadowAction myShadow; - private final ActionManager myActionManager; + @NotNull private final ActionManager myActionManager; private final JBTabsImpl myTabs; - protected BaseNavigationAction(final String copyFromID, JBTabsImpl tabs, ActionManager mgr) { + protected BaseNavigationAction(@NotNull String copyFromID, @NotNull JBTabsImpl tabs, @NotNull ActionManager mgr) { myActionManager = mgr; myTabs = tabs; myShadow = new ShadowAction(this, myActionManager.getAction(copyFromID), tabs); @@ -2858,7 +2876,7 @@ public class JBTabsImpl extends JComponent private static class SelectNextAction extends BaseNavigationAction { - private SelectNextAction(JBTabsImpl tabs, ActionManager mgr) { + private SelectNextAction(JBTabsImpl tabs, @NotNull ActionManager mgr) { super(IdeActions.ACTION_NEXT_TAB, tabs, mgr); } @@ -2874,7 +2892,7 @@ public class JBTabsImpl extends JComponent } private static class SelectPreviousAction extends BaseNavigationAction { - private SelectPreviousAction(JBTabsImpl tabs, ActionManager mgr) { + private SelectPreviousAction(JBTabsImpl tabs, @NotNull ActionManager mgr) { super(IdeActions.ACTION_PREVIOUS_TAB, tabs, mgr); } @@ -3351,7 +3369,7 @@ public class JBTabsImpl extends JComponent return myVisibleInfos.isEmpty(); } - public static int getInterTabSpaceLength() { + public int getInterTabSpaceLength() { return 1; } diff --git a/platform/platform-api/src/com/intellij/ui/tabs/impl/singleRow/SingleRowLayout.java b/platform/platform-api/src/com/intellij/ui/tabs/impl/singleRow/SingleRowLayout.java index 4e5925d2a2ee..6bd2e1aa52bf 100644 --- a/platform/platform-api/src/com/intellij/ui/tabs/impl/singleRow/SingleRowLayout.java +++ b/platform/platform-api/src/com/intellij/ui/tabs/impl/singleRow/SingleRowLayout.java @@ -209,6 +209,7 @@ public class SingleRowLayout extends TabLayout { protected void prepareLayoutPassInfo(SingleRowPassInfo data, TabInfo selected) { data.insets = myTabs.getLayoutInsets(); + data.insets.left += myTabs.getFirstTabOffset(); final JBTabsImpl.Toolbar selectedToolbar = myTabs.myInfo2Toolbar.get(selected); data.hToolbar = selectedToolbar != null && myTabs.myHorizontalSide && !selectedToolbar.isEmpty() ? selectedToolbar : null; @@ -216,7 +217,7 @@ public class SingleRowLayout extends TabLayout { data.toFitLength = getStrategy().getToFitLength(data); if (myTabs.isGhostsAlwaysVisible()) { - data.toFitLength -= JBTabsImpl.getGhostTabLength() * 2 + (JBTabsImpl.getInterTabSpaceLength() * 2); + data.toFitLength -= myTabs.getGhostTabLength() * 2 + (myTabs.getInterTabSpaceLength() * 2); } } @@ -236,9 +237,9 @@ public class SingleRowLayout extends TabLayout { private void layoutLabelsAndGhosts(final SingleRowPassInfo data) { if (data.firstGhostVisible || myTabs.isGhostsAlwaysVisible()) { - data.firstGhost = getStrategy().getLayoutRect(data, data.position, JBTabsImpl.getGhostTabLength()); + data.firstGhost = getStrategy().getLayoutRect(data, data.position, myTabs.getGhostTabLength()); myTabs.layout(myLeftGhost, data.firstGhost); - data.position += getStrategy().getLengthIncrement(data.firstGhost.getSize()) + JBTabsImpl.getInterTabSpaceLength(); + data.position += getStrategy().getLengthIncrement(data.firstGhost.getSize()) + myTabs.getInterTabSpaceLength(); } int deltaToFit = 0; @@ -275,9 +276,9 @@ public class SingleRowLayout extends TabLayout { boolean continueLayout = applyTabLayout(data, label, length, deltaToFit); data.position = getStrategy().getMaxPosition(label.getBounds()); - data.position += JBTabsImpl.getInterTabSpaceLength(); + data.position += myTabs.getInterTabSpaceLength(); - totalLength = getStrategy().getMaxPosition(label.getBounds()) - positionStart + JBTabsImpl.getInterTabSpaceLength(); + totalLength = getStrategy().getMaxPosition(label.getBounds()) - positionStart + myTabs.getInterTabSpaceLength(); if (!continueLayout) { layoutStopped = true; } @@ -288,7 +289,7 @@ public class SingleRowLayout extends TabLayout { } if (data.lastGhostVisible || myTabs.isGhostsAlwaysVisible()) { - data.lastGhost = getStrategy().getLayoutRect(data, data.position, JBTabsImpl.getGhostTabLength()); + data.lastGhost = getStrategy().getLayoutRect(data, data.position, myTabs.getGhostTabLength()); myTabs.layout(myRightGhost, data.lastGhost); } } @@ -366,7 +367,7 @@ public class SingleRowLayout extends TabLayout { protected int getRequiredLength(TabInfo eachInfo) { TabLabel label = myTabs.myInfo2Label.get(eachInfo); return getStrategy().getLengthIncrement(label != null ? label.getPreferredSize() : new Dimension()) - + (myTabs.isEditorTabs() ? JBTabsImpl.getInterTabSpaceLength() : 0); + + (myTabs.isEditorTabs() ? myTabs.getInterTabSpaceLength() : 0); } @@ -417,13 +418,13 @@ public class SingleRowLayout extends TabLayout { if (!data.firstGhostVisible && isFirstSide) { data.firstGhostVisible = !myTabs.isEditorTabs(); if (!myTabs.isGhostsAlwaysVisible() && !myTabs.isEditorTabs()) { - data.toFitLength -= JBTabsImpl.getGhostTabLength(); + data.toFitLength -= myTabs.getGhostTabLength(); } } else if (!data.lastGhostVisible && !isFirstSide) { data.lastGhostVisible = !myTabs.isEditorTabs(); if (!myTabs.isGhostsAlwaysVisible() && !myTabs.isEditorTabs()) { - data.toFitLength -= JBTabsImpl.getGhostTabLength(); + data.toFitLength -= myTabs.getGhostTabLength(); } } } diff --git a/platform/platform-api/src/com/intellij/ui/tabs/impl/table/TableLayout.java b/platform/platform-api/src/com/intellij/ui/tabs/impl/table/TableLayout.java index 1326531e2465..9b313783dea7 100644 --- a/platform/platform-api/src/com/intellij/ui/tabs/impl/table/TableLayout.java +++ b/platform/platform-api/src/com/intellij/ui/tabs/impl/table/TableLayout.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -56,8 +56,8 @@ public class TableLayout extends TabLayout { eachX = data.toFitRec.x; } myTabs.layout(eachLabel, eachX, 0, size.width, 1); - eachX += size.width + JBTabsImpl.getInterTabSpaceLength(); - data.requiredWidth += size.width + JBTabsImpl.getInterTabSpaceLength(); + eachX += size.width + myTabs.getInterTabSpaceLength(); + data.requiredWidth += size.width + myTabs.getInterTabSpaceLength(); } int selectedRow = -1; @@ -84,7 +84,7 @@ public class TableLayout extends TabLayout { if (myTabs.getSelectedInfo() == eachInfo) { selectedRow = eachRow; } - eachX += size.width + JBTabsImpl.getInterTabSpaceLength(); + eachX += size.width + myTabs.getInterTabSpaceLength(); } else { eachTableRow = new TableRow(data); @@ -161,9 +161,9 @@ public class TableLayout extends TabLayout { label.setAlignmentToCenter(deltaToFit > 0); boolean lastCell = i == eachRow.myColumns.size() - 1; - eachX += width + (lastCell ? 0 : JBTabsImpl.getInterTabSpaceLength()); + eachX += width + (lastCell ? 0 : myTabs.getInterTabSpaceLength()); } - eachY += myTabs.myHeaderFitSize.height - 1 + JBTabsImpl.getInterTabSpaceLength() - (row < data.table.size() - 1 ? tabUnderlineFix : 0); + eachY += myTabs.myHeaderFitSize.height - 1 + myTabs.getInterTabSpaceLength() - (row < data.table.size() - 1 ? tabUnderlineFix : 0); row++; } diff --git a/platform/platform-api/src/com/intellij/ui/treeStructure/Tree.java b/platform/platform-api/src/com/intellij/ui/treeStructure/Tree.java index 0975876055b2..c8c50bc94680 100644 --- a/platform/platform-api/src/com/intellij/ui/treeStructure/Tree.java +++ b/platform/platform-api/src/com/intellij/ui/treeStructure/Tree.java @@ -283,7 +283,7 @@ public class Tree extends JTree implements ComponentWithEmptyText, ComponentWith if (myBusyIcon != null) { if (myBusy) { - if (hasFocus()) { + if (shouldShowBusyIconIfNeeded()) { myBusyIcon.resume(); myBusyIcon.setToolTipText("Update is in progress. Click to cancel"); } @@ -305,6 +305,11 @@ public class Tree extends JTree implements ComponentWithEmptyText, ComponentWith } } + protected boolean shouldShowBusyIconIfNeeded() { + // http://youtrack.jetbrains.com/issue/IDEA-101422 "Rotating wait symbol in Project list whenever typing" + return hasFocus(); + } + protected boolean paintNodes() { return false; } @@ -429,7 +434,6 @@ public class Tree extends JTree implements ComponentWithEmptyText, ComponentWith } final Method method = ReflectionUtil.getDeclaredMethod(aClass, "isLocationInExpandControl", TreePath.class, int.class, int.class); if (method != null) { - method.setAccessible(true); return (Boolean)method.invoke(ui, path, x, y); } } diff --git a/platform/platform-api/src/com/intellij/util/net/HttpConfigurable.java b/platform/platform-api/src/com/intellij/util/net/HttpConfigurable.java index 0bcb416c7334..d51891a8ffe4 100644 --- a/platform/platform-api/src/com/intellij/util/net/HttpConfigurable.java +++ b/platform/platform-api/src/com/intellij/util/net/HttpConfigurable.java @@ -65,7 +65,7 @@ import java.util.*; ) public class HttpConfigurable implements PersistentStateComponent<HttpConfigurable>, ApplicationComponent, ExportableApplicationComponent { - public static final int CONNECTION_TIMEOUT = SystemProperties.getIntProperty("connection.timeout", 10000); + public static final int CONNECTION_TIMEOUT = SystemProperties.getIntProperty("idea.connection.timeout", 10000); private static final Logger LOG = Logger.getInstance("#com.intellij.util.net.HttpConfigurable"); public boolean PROXY_TYPE_IS_SOCKS = false; public boolean USE_HTTP_PROXY = false; @@ -350,8 +350,6 @@ public class HttpConfigurable implements PersistentStateComponent<HttpConfigurab final URLConnection connection = openConnection(url); try { - connection.setConnectTimeout(CONNECTION_TIMEOUT); - connection.setReadTimeout(CONNECTION_TIMEOUT); connection.connect(); connection.getInputStream(); } @@ -387,6 +385,10 @@ public class HttpConfigurable implements PersistentStateComponent<HttpConfigurab throw ioe; } } + if (urlConnection != null) { + urlConnection.setReadTimeout(CONNECTION_TIMEOUT); + urlConnection.setConnectTimeout(CONNECTION_TIMEOUT); + } return urlConnection; } diff --git a/platform/platform-api/src/com/intellij/util/ui/AsyncProcessIcon.java b/platform/platform-api/src/com/intellij/util/ui/AsyncProcessIcon.java index 3c3b42721b58..3d467232b3e3 100644 --- a/platform/platform-api/src/com/intellij/util/ui/AsyncProcessIcon.java +++ b/platform/platform-api/src/com/intellij/util/ui/AsyncProcessIcon.java @@ -71,7 +71,7 @@ public class AsyncProcessIcon extends AnimatedIcon { return icons; } - public void updateLocation(JComponent container) { + public void updateLocation(final JComponent container) { final Rectangle rec = container.getVisibleRect(); final Dimension iconSize = getPreferredSize(); @@ -79,7 +79,14 @@ public class AsyncProcessIcon extends AnimatedIcon { final Rectangle newBounds = new Rectangle(rec.x + rec.width - iconSize.width, rec.y, iconSize.width, iconSize.height); if (!newBounds.equals(getBounds())) { setBounds(newBounds); - container.repaint(); + // painting problems with scrollpane + // repaint shouldn't be called from paint method + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + container.repaint(); + } + }); } } diff --git a/platform/platform-api/src/com/intellij/util/ui/ButtonlessScrollBarUI.java b/platform/platform-api/src/com/intellij/util/ui/ButtonlessScrollBarUI.java index 57f9cfca8a54..d73e21e8dc3a 100644 --- a/platform/platform-api/src/com/intellij/util/ui/ButtonlessScrollBarUI.java +++ b/platform/platform-api/src/com/intellij/util/ui/ButtonlessScrollBarUI.java @@ -23,6 +23,7 @@ import com.intellij.ui.Gray; import com.intellij.ui.JBColor; import com.intellij.ui.LightColors; import com.intellij.ui.components.JBScrollPane; +import com.intellij.util.ReflectionUtil; import javax.swing.*; import javax.swing.event.ChangeEvent; @@ -316,28 +317,21 @@ public class ButtonlessScrollBarUI extends BasicScrollBarUI { resetMacScrollbarFadeout(); } + private static final Method setValueFrom = ReflectionUtil.getDeclaredMethod(TrackListener.class, "setValueFrom", MouseEvent.class); + static { + LOG.assertTrue(setValueFrom != null, "Cannot get TrackListener.setValueFrom method"); + } + @Override protected TrackListener createTrackListener() { return new TrackListener() { - private Method mySetValueFrom; - - { - try { - mySetValueFrom = TrackListener.class.getDeclaredMethod("setValueFrom", MouseEvent.class); - mySetValueFrom.setAccessible(true); - } - catch (Exception e) { - LOG.error("Cannot get TrackListener.setValueFrom method", e); - } - } - @Override public void mousePressed(MouseEvent e) { if (scrollbar.isEnabled() && SwingUtilities.isLeftMouseButton(e) && !getThumbBounds().contains(e.getPoint()) && NSScrollerHelper.getClickBehavior() == NSScrollerHelper.ClickBehavior.JumpToSpot - && mySetValueFrom != null) { + && setValueFrom != null) { switch (scrollbar.getOrientation()) { case Adjustable.VERTICAL: @@ -349,7 +343,7 @@ public class ButtonlessScrollBarUI extends BasicScrollBarUI { } isDragging = true; try { - mySetValueFrom.invoke(this, e); + setValueFrom.invoke(this, e); } catch (Exception ex) { LOG.error(ex); diff --git a/platform/platform-api/src/com/intellij/util/ui/JTableCellEditorHelper.java b/platform/platform-api/src/com/intellij/util/ui/JTableCellEditorHelper.java deleted file mode 100644 index 733fec87e0b6..000000000000 --- a/platform/platform-api/src/com/intellij/util/ui/JTableCellEditorHelper.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright 2000-2011 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.util.ui; - -import com.intellij.ide.DataManager; -import com.intellij.openapi.actionSystem.CommonDataKeys; -import com.intellij.openapi.actionSystem.PlatformDataKeys; -import com.intellij.openapi.editor.Editor; - -import javax.swing.*; -import java.awt.*; -import java.awt.event.KeyEvent; -import java.util.EventObject; - -/** - * @author Konstantin Bulenkov - */ -public class JTableCellEditorHelper { - private JTableCellEditorHelper() {} - - public static void typeAhead(final JTable table, final EventObject e, final int row, final int column) { - if (e instanceof KeyEvent) { - final Runnable r = new Runnable() { - @Override - public void run() { - if (table.getEditingColumn() != column && table.getEditingRow() != row) return; - - Component focusOwner = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner(); - if (focusOwner == null || !SwingUtilities.isDescendingFrom(focusOwner, table)) return; - - KeyEvent keyEvent = (KeyEvent)e; - if (Character.isDefined(keyEvent.getKeyChar())) { - try { - selectAll(focusOwner); - - Robot r = new Robot(); - r.keyPress(keyEvent.getKeyCode()); - r.keyRelease(keyEvent.getKeyCode()); - } - catch (AWTException e1) { - return; - } - } else { - selectAll(focusOwner); - } - } - }; - - SwingUtilities.invokeLater(r); - } - } - - private static void selectAll(Component component) { - if (component instanceof TextComponent) { - ((TextComponent)component).selectAll(); - } else { - Editor editor = CommonDataKeys.EDITOR.getData(DataManager.getInstance().getDataContext(component)); - if (editor != null) { - editor.getSelectionModel().setSelection(0, editor.getDocument().getTextLength()); - } - } - } -} |