mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-18 09:34:34 +07:00
IDEA-153874 apply changes from AndroidStudio
This commit is contained in:
@@ -185,7 +185,7 @@ public class AutoPopupController implements Disposable {
|
||||
if (editor.isDisposed() || !editor.getComponent().isShowing()) return;
|
||||
int lbraceOffset = editor.getCaretModel().getOffset() - 1;
|
||||
try {
|
||||
ShowParameterInfoHandler.invoke(myProject, editor, file1, lbraceOffset, highlightedMethod);
|
||||
ShowParameterInfoHandler.invoke(myProject, editor, file1, lbraceOffset, highlightedMethod, false);
|
||||
}
|
||||
catch (IndexNotReadyException ignored) { //anything can happen on alarm
|
||||
}
|
||||
|
||||
@@ -40,6 +40,10 @@ public class DaemonTooltipUtil {
|
||||
}
|
||||
|
||||
public static void showInfoTooltip(@NotNull final HighlightInfo info, @NotNull Editor editor, final int defaultOffset, final int currentWidth) {
|
||||
showInfoTooltip(info, editor, defaultOffset, currentWidth, false);
|
||||
}
|
||||
|
||||
public static void showInfoTooltip(@NotNull final HighlightInfo info, @NotNull Editor editor, final int defaultOffset, final int currentWidth, final boolean requestFocus) {
|
||||
if (info.getToolTip() == null) return;
|
||||
Rectangle visibleArea = editor.getScrollingModel().getVisibleArea();
|
||||
|
||||
@@ -56,7 +60,11 @@ public class DaemonTooltipUtil {
|
||||
editor.getComponent().getRootPane().getLayeredPane()
|
||||
);
|
||||
|
||||
TooltipController.getInstance().showTooltip(editor, p, info.getToolTip(), currentWidth, false, DAEMON_INFO_GROUP, new HintHint(editor, bestPoint).setAwtTooltip(true).setHighlighterType(true).setCalloutShift(
|
||||
editor.getLineHeight() / 2 - 1));
|
||||
HintHint hintHint = new HintHint(editor, bestPoint)
|
||||
.setAwtTooltip(true)
|
||||
.setHighlighterType(true)
|
||||
.setRequestFocus(requestFocus)
|
||||
.setCalloutShift(editor.getLineHeight() / 2 - 1);
|
||||
TooltipController.getInstance().showTooltip(editor, p, info.getToolTip(), currentWidth, false, DAEMON_INFO_GROUP, hintHint);
|
||||
}
|
||||
}
|
||||
|
||||
+4
-2
@@ -25,9 +25,11 @@ import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class ShowErrorDescriptionHandler implements CodeInsightActionHandler {
|
||||
private final int myWidth;
|
||||
private final boolean myRequestFocus;
|
||||
|
||||
public ShowErrorDescriptionHandler(final int width) {
|
||||
public ShowErrorDescriptionHandler(final int width, final boolean requestFocus) {
|
||||
myWidth = width;
|
||||
myRequestFocus = requestFocus;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -36,7 +38,7 @@ public class ShowErrorDescriptionHandler implements CodeInsightActionHandler {
|
||||
DaemonCodeAnalyzer codeAnalyzer = DaemonCodeAnalyzer.getInstance(project);
|
||||
HighlightInfo info = ((DaemonCodeAnalyzerImpl)codeAnalyzer).findHighlightByOffset(editor.getDocument(), offset, false);
|
||||
if (info != null) {
|
||||
DaemonTooltipUtil.showInfoTooltip(info, editor, editor.getCaretModel().getOffset(), myWidth);
|
||||
DaemonTooltipUtil.showInfoTooltip(info, editor, editor.getCaretModel().getOffset(), myWidth, myRequestFocus);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+7
-1
@@ -30,12 +30,16 @@ import com.intellij.openapi.project.DumbAware;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.util.ui.accessibility.ScreenReader;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.awt.event.KeyEvent;
|
||||
|
||||
public class ShowErrorDescriptionAction extends BaseCodeInsightAction implements DumbAware {
|
||||
private static int width;
|
||||
private static boolean shouldShowDescription = false;
|
||||
private static boolean descriptionShown = true;
|
||||
private boolean myRequestFocus = false;
|
||||
|
||||
public ShowErrorDescriptionAction() {
|
||||
setEnabledInModalContext(true);
|
||||
@@ -44,7 +48,7 @@ public class ShowErrorDescriptionAction extends BaseCodeInsightAction implements
|
||||
@NotNull
|
||||
@Override
|
||||
protected CodeInsightActionHandler getHandler() {
|
||||
return new ShowErrorDescriptionHandler(shouldShowDescription ? width : 0);
|
||||
return new ShowErrorDescriptionHandler(shouldShowDescription ? width : 0, myRequestFocus);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -62,6 +66,8 @@ public class ShowErrorDescriptionAction extends BaseCodeInsightAction implements
|
||||
@Override
|
||||
public void beforeActionPerformedUpdate(@NotNull final AnActionEvent e) {
|
||||
super.beforeActionPerformedUpdate(e);
|
||||
// The tooltip gets the focus if using a screen reader and invocation through a keyboard shortcut.
|
||||
myRequestFocus = ScreenReader.isActive() && (e.getInputEvent() instanceof KeyEvent);
|
||||
changeState();
|
||||
}
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@ import com.intellij.ui.ScrollPaneFactory;
|
||||
import com.intellij.ui.SideBorder;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import com.intellij.util.ui.accessibility.AccessibleContextUtil;
|
||||
import com.intellij.xml.util.XmlStringUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -73,6 +74,7 @@ public class ParameterInfoComponent extends JPanel {
|
||||
return -1;
|
||||
}
|
||||
};
|
||||
private boolean myRequestFocus;
|
||||
|
||||
@TestOnly
|
||||
public static ParameterInfoUIContextEx createContext(Object[] objects, Editor editor, @NotNull ParameterInfoHandler handler, int currentParameterIndex) {
|
||||
@@ -112,6 +114,9 @@ public class ParameterInfoComponent extends JPanel {
|
||||
GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL,
|
||||
new Insets(0, 0, 0, 0), 0, 0));
|
||||
}
|
||||
if (myRequestFocus) {
|
||||
AccessibleContextUtil.setName(this, "Parameter Info. Press TAB to navigate through each element. Press ESC to close.");
|
||||
}
|
||||
|
||||
final JScrollPane pane = ScrollPaneFactory.createScrollPane(panel);
|
||||
pane.setBorder(null);
|
||||
@@ -137,6 +142,14 @@ public class ParameterInfoComponent extends JPanel {
|
||||
return myHighlighted;
|
||||
}
|
||||
|
||||
public void setRequestFocus(boolean requestFocus) {
|
||||
myRequestFocus = requestFocus;
|
||||
}
|
||||
|
||||
public boolean isRequestFocus() {
|
||||
return myRequestFocus;
|
||||
}
|
||||
|
||||
class MyParameterContext implements ParameterInfoUIContextEx {
|
||||
private int i;
|
||||
private Function<String, String> myEscapeFunction;
|
||||
@@ -370,6 +383,8 @@ public class ParameterInfoComponent extends JPanel {
|
||||
|
||||
myLabel.setOpaque(true);
|
||||
myLabel.setFont(NORMAL_FONT);
|
||||
if (myRequestFocus)
|
||||
myLabel.setFocusable(true);
|
||||
|
||||
add(myLabel, new GridBagConstraints(0, 0, 1, 1, 1, 1, GridBagConstraints.WEST, GridBagConstraints.NONE,
|
||||
new Insets(0, 0, 0, 0), 0, 0));
|
||||
@@ -468,4 +483,4 @@ public class ParameterInfoComponent extends JPanel {
|
||||
isDisabledBeforeHighlight = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,6 +48,7 @@ public class ShowParameterInfoContext implements CreateParameterInfoContext {
|
||||
private final int myParameterListStart;
|
||||
private PsiElement myHighlightedElement;
|
||||
private Object[] myItems;
|
||||
private boolean myRequestFocus;
|
||||
|
||||
public ShowParameterInfoContext(final Editor editor, final Project project,
|
||||
final PsiFile file, int offset, int parameterListStart) {
|
||||
@@ -108,7 +109,7 @@ public class ShowParameterInfoContext implements CreateParameterInfoContext {
|
||||
public void showHint(PsiElement element, int offset, ParameterInfoHandler handler) {
|
||||
final Object[] itemsToShow = getItemsToShow();
|
||||
if (itemsToShow == null || itemsToShow.length == 0) return;
|
||||
showMethodInfo(getProject(), getEditor(), element, getHighlightedElement(), itemsToShow, offset, handler);
|
||||
showMethodInfo(getProject(), getEditor(), element, getHighlightedElement(), itemsToShow, offset, handler, myRequestFocus);
|
||||
}
|
||||
|
||||
private static void showParameterHint(final PsiElement element,
|
||||
@@ -117,12 +118,14 @@ public class ShowParameterInfoContext implements CreateParameterInfoContext {
|
||||
final Project project,
|
||||
@Nullable PsiElement highlighted,
|
||||
final int elementStart,
|
||||
final ParameterInfoHandler handler) {
|
||||
final ParameterInfoHandler handler,
|
||||
final boolean requestFocus) {
|
||||
if (ParameterInfoController.isAlreadyShown(editor, elementStart)) return;
|
||||
|
||||
if (editor.isDisposed() || !editor.getComponent().isVisible()) return;
|
||||
final ParameterInfoComponent component = new ParameterInfoComponent(descriptors, editor,handler);
|
||||
component.setParameterOwner(element);
|
||||
component.setRequestFocus(requestFocus);
|
||||
if (highlighted != null) {
|
||||
component.setHighlightedParameter(highlighted);
|
||||
}
|
||||
@@ -143,6 +146,7 @@ public class ShowParameterInfoContext implements CreateParameterInfoContext {
|
||||
|
||||
HintHint hintHint = HintManagerImpl.createHintHint(editor, pos.getFirst(), hint, pos.getSecond());
|
||||
hintHint.setExplicitClose(true);
|
||||
hintHint.setRequestFocus(requestFocus);
|
||||
|
||||
Editor editorToShow = editor instanceof EditorWindow ? ((EditorWindow)editor).getDelegate() : editor;
|
||||
// is case of injection we need to calculate position for EditorWindow
|
||||
@@ -157,9 +161,10 @@ public class ShowParameterInfoContext implements CreateParameterInfoContext {
|
||||
PsiElement highlighted,
|
||||
Object[] candidates,
|
||||
int offset,
|
||||
ParameterInfoHandler handler
|
||||
ParameterInfoHandler handler,
|
||||
boolean requestFocus
|
||||
) {
|
||||
showParameterHint(list, editor, candidates, project, candidates.length > 1 ? highlighted : null, offset, handler);
|
||||
showParameterHint(list, editor, candidates, project, candidates.length > 1 ? highlighted : null, offset, handler, requestFocus);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -222,6 +227,14 @@ public class ShowParameterInfoContext implements CreateParameterInfoContext {
|
||||
HintManager.ABOVE);
|
||||
}
|
||||
|
||||
public void setRequestFocus(boolean requestFocus) {
|
||||
myRequestFocus = requestFocus;
|
||||
}
|
||||
|
||||
public boolean isRequestFocus() {
|
||||
return myRequestFocus;
|
||||
}
|
||||
|
||||
static class MyBestLocationPointProvider implements ShowParameterInfoHandler.BestLocationPointProvider {
|
||||
private final Editor myEditor;
|
||||
private int previousOffset = -1;
|
||||
|
||||
@@ -40,9 +40,19 @@ import java.awt.*;
|
||||
import java.util.Set;
|
||||
|
||||
public class ShowParameterInfoHandler implements CodeInsightActionHandler {
|
||||
private boolean myRequestFocus;
|
||||
|
||||
public ShowParameterInfoHandler() {
|
||||
this(false);
|
||||
}
|
||||
|
||||
public ShowParameterInfoHandler(boolean requestFocus) {
|
||||
myRequestFocus = requestFocus;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invoke(@NotNull Project project, @NotNull Editor editor, @NotNull PsiFile file) {
|
||||
invoke(project, editor, file, -1, null);
|
||||
invoke(project, editor, file, -1, null, myRequestFocus);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -57,7 +67,7 @@ public class ShowParameterInfoHandler implements CodeInsightActionHandler {
|
||||
return element;
|
||||
}
|
||||
|
||||
public static void invoke(final Project project, final Editor editor, PsiFile file, int lbraceOffset, PsiElement highlightedElement) {
|
||||
public static void invoke(final Project project, final Editor editor, PsiFile file, int lbraceOffset, PsiElement highlightedElement, boolean requestFocus) {
|
||||
ApplicationManager.getApplication().assertIsDispatchThread();
|
||||
PsiDocumentManager.getInstance(project).commitAllDocuments();
|
||||
|
||||
@@ -74,6 +84,7 @@ public class ShowParameterInfoHandler implements CodeInsightActionHandler {
|
||||
);
|
||||
|
||||
context.setHighlightedElement(highlightedElement);
|
||||
context.setRequestFocus(requestFocus);
|
||||
|
||||
final Language language = psiElement.getLanguage();
|
||||
ParameterInfoHandler[] handlers = getHandlers(project, language, file.getViewProvider().getBaseLanguage());
|
||||
|
||||
+15
-2
@@ -20,22 +20,35 @@ import com.intellij.codeInsight.CodeInsightActionHandler;
|
||||
import com.intellij.codeInsight.actions.BaseCodeInsightAction;
|
||||
import com.intellij.codeInsight.hint.ShowParameterInfoHandler;
|
||||
import com.intellij.lang.Language;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.project.DumbAware;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.util.PsiUtilCore;
|
||||
import com.intellij.util.ui.accessibility.ScreenReader;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.awt.event.KeyEvent;
|
||||
|
||||
public class ShowParameterInfoAction extends BaseCodeInsightAction implements DumbAware {
|
||||
private boolean myRequestFocus = false;
|
||||
|
||||
public ShowParameterInfoAction() {
|
||||
setEnabledInModalContext(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beforeActionPerformedUpdate(@NotNull AnActionEvent e) {
|
||||
super.beforeActionPerformedUpdate(e);
|
||||
// The tooltip gets the focus if using a screen reader and invocation through a keyboard shortcut.
|
||||
myRequestFocus = ScreenReader.isActive() && (e.getInputEvent() instanceof KeyEvent);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected CodeInsightActionHandler getHandler() {
|
||||
return new ShowParameterInfoHandler();
|
||||
return new ShowParameterInfoHandler(myRequestFocus);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -48,4 +61,4 @@ public class ShowParameterInfoAction extends BaseCodeInsightAction implements Du
|
||||
protected boolean isValidForLookup() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@ import com.intellij.ui.GuiUtils;
|
||||
import com.intellij.ui.UIBundle;
|
||||
import com.intellij.util.Consumer;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import com.intellij.util.ui.accessibility.ScreenReader;
|
||||
import com.intellij.util.ui.update.LazyUiDisposable;
|
||||
import org.jetbrains.annotations.Nls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -71,11 +72,14 @@ public class ComponentWithBrowseButton<Comp extends JComponent> extends JPanel i
|
||||
add(wrapWithoutResize(myBrowseButton), BorderLayout.EAST);
|
||||
|
||||
myBrowseButton.setToolTipText(UIBundle.message("component.with.browse.button.browse.button.tooltip.text"));
|
||||
|
||||
// FixedSizeButton isn't focusable but it should be selectable via keyboard.
|
||||
if (ApplicationManager.getApplication() != null) { // avoid crash at design time
|
||||
new MyDoClickAction(myBrowseButton).registerShortcut(myComponent);
|
||||
}
|
||||
if (ScreenReader.isActive()) {
|
||||
myBrowseButton.setFocusable(true);
|
||||
myBrowseButton.getAccessibleContext().setAccessibleName("Browse");
|
||||
}
|
||||
}
|
||||
|
||||
private static JPanel wrapWithoutResize(JComponent component) {
|
||||
|
||||
@@ -95,6 +95,9 @@ public interface BalloonBuilder {
|
||||
@NotNull
|
||||
BalloonBuilder setBlockClicksThroughBalloon(boolean block);
|
||||
|
||||
@NotNull
|
||||
BalloonBuilder setRequestFocus(boolean requestFocus);
|
||||
|
||||
/**
|
||||
* Links target balloon life cycle to the given object. I.e. current balloon will be auto-hide and collected as soon
|
||||
* as given anchor is disposed.
|
||||
@@ -109,4 +112,4 @@ public interface BalloonBuilder {
|
||||
|
||||
@NotNull
|
||||
Balloon createBalloon();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,23 +17,27 @@ package com.intellij.ui;
|
||||
|
||||
import com.intellij.openapi.ui.popup.IconButton;
|
||||
import com.intellij.openapi.util.Pass;
|
||||
import com.intellij.ui.awt.RelativePoint;
|
||||
import com.intellij.util.ui.BaseButtonBehavior;
|
||||
import com.intellij.util.ui.CenteredIcon;
|
||||
import com.intellij.util.ui.TimedDeadzone;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
|
||||
import javax.accessibility.*;
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class InplaceButton extends JComponent implements ActiveComponent {
|
||||
public class InplaceButton extends JComponent implements ActiveComponent, Accessible {
|
||||
|
||||
private boolean myPainting = true;
|
||||
private boolean myActive = true;
|
||||
|
||||
private BaseButtonBehavior myBehavior;
|
||||
private ActionListener myListener;
|
||||
|
||||
private CenteredIcon myRegular;
|
||||
private CenteredIcon myHovered;
|
||||
@@ -62,9 +66,11 @@ public class InplaceButton extends JComponent implements ActiveComponent {
|
||||
}
|
||||
|
||||
public InplaceButton(IconButton source, final ActionListener listener, final Pass<MouseEvent> me, TimedDeadzone.Length mouseDeadzone) {
|
||||
myListener = listener;
|
||||
myBehavior = new BaseButtonBehavior(this, mouseDeadzone) {
|
||||
@Override
|
||||
protected void execute(final MouseEvent e) {
|
||||
listener.actionPerformed(new ActionEvent(e, ActionEvent.ACTION_PERFORMED, "execute", e.getModifiers()));
|
||||
doClick(e);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -91,12 +97,22 @@ public class InplaceButton extends JComponent implements ActiveComponent {
|
||||
protected void doRepaintComponent(Component c) {
|
||||
c.repaint();
|
||||
}
|
||||
|
||||
|
||||
public void doClick() {
|
||||
RelativePoint point = new RelativePoint(this, new Point(this.getWidth() / 2, this.getHeight() / 2));
|
||||
doClick(point.toMouseEvent());
|
||||
}
|
||||
|
||||
public void doClick(final MouseEvent e) {
|
||||
if (myListener != null) {
|
||||
myListener.actionPerformed(new ActionEvent(e, ActionEvent.ACTION_PERFORMED, "execute", e.getModifiers()));
|
||||
}
|
||||
}
|
||||
|
||||
public void setMouseDeadzone(final TimedDeadzone.Length deadZone) {
|
||||
myBehavior.setMouseDeadzone(deadZone);
|
||||
}
|
||||
|
||||
|
||||
public void setIcons(IconButton source) {
|
||||
setIcons(source.getRegular(), source.getInactive(), source.getHovered());
|
||||
}
|
||||
@@ -132,6 +148,7 @@ public class InplaceButton extends JComponent implements ActiveComponent {
|
||||
repaint();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setActive(final boolean active) {
|
||||
myActive = active;
|
||||
repaint();
|
||||
@@ -141,10 +158,12 @@ public class InplaceButton extends JComponent implements ActiveComponent {
|
||||
setIcons(icon, icon, icon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JComponent getComponent() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void paintComponent(Graphics g) {
|
||||
super.paintComponent(g);
|
||||
|
||||
@@ -188,8 +207,120 @@ public class InplaceButton extends JComponent implements ActiveComponent {
|
||||
}
|
||||
|
||||
public boolean isActive() {
|
||||
|
||||
|
||||
return myActive;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AccessibleContext getAccessibleContext() {
|
||||
if (accessibleContext == null) {
|
||||
accessibleContext = new AccessibleInplaceButton();
|
||||
}
|
||||
return accessibleContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* The Accessible implementation of InplaceButton is a subset of AccessibleAbstractButton.
|
||||
*/
|
||||
protected class AccessibleInplaceButton extends AccessibleJComponent implements AccessibleAction, AccessibleExtendedComponent {
|
||||
|
||||
@Override
|
||||
public String getAccessibleName() {
|
||||
String name = accessibleName;
|
||||
|
||||
if (name == null) {
|
||||
name = (String)getClientProperty(AccessibleContext.ACCESSIBLE_NAME_PROPERTY);
|
||||
}
|
||||
if (name == null) {
|
||||
name = InplaceButton.this.getToolTipText();
|
||||
}
|
||||
if (name == null) {
|
||||
name = super.getAccessibleName();
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AccessibleRole getAccessibleRole() {
|
||||
return AccessibleRole.PUSH_BUTTON;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAccessibleActionCount() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAccessibleActionDescription(int i) {
|
||||
if (i == 0) {
|
||||
return "Click";
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean doAccessibleAction(int i) {
|
||||
if (i == 0) {
|
||||
doClick();
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public AccessibleAction getAccessibleAction() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AccessibleIcon[] getAccessibleIcon() {
|
||||
Icon[] icons = {myRegular, myInactive, myHovered};
|
||||
ArrayList<AccessibleIcon> accessibleIconList = new ArrayList<AccessibleIcon>();
|
||||
for (Icon icon : icons) {
|
||||
if (icon instanceof Accessible) {
|
||||
AccessibleContext ac = ((Accessible)icon).getAccessibleContext();
|
||||
if (ac != null && ac instanceof AccessibleIcon) {
|
||||
accessibleIconList.add((AccessibleIcon)ac);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (accessibleIconList.size() == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return accessibleIconList.toArray(new AccessibleIcon[accessibleIconList.size()]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AccessibleStateSet getAccessibleStateSet() {
|
||||
AccessibleStateSet states = super.getAccessibleStateSet();
|
||||
if (isFocusOwner()) {
|
||||
states.add(AccessibleState.FOCUSED);
|
||||
}
|
||||
return states;
|
||||
}
|
||||
|
||||
// ----- AccessibleExtendedComponent
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
AccessibleExtendedComponent getAccessibleExtendedComponent() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getToolTipText() {
|
||||
return InplaceButton.this.getToolTipText();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTitledBorderText() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AccessibleKeyBinding getAccessibleKeyBinding() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ import com.intellij.ui.LightweightHint;
|
||||
import com.intellij.ui.ScrollPaneFactory;
|
||||
import com.intellij.util.ui.Html;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import com.intellij.util.ui.accessibility.ScreenReader;
|
||||
import com.intellij.util.ui.update.ComparableObject;
|
||||
import com.intellij.xml.util.XmlStringUtil;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
@@ -38,6 +39,7 @@ import javax.swing.*;
|
||||
import javax.swing.event.HyperlinkEvent;
|
||||
import javax.swing.event.HyperlinkListener;
|
||||
import java.awt.*;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.net.URL;
|
||||
@@ -101,6 +103,10 @@ public class LineTooltipRenderer extends ComparableObject.Impl implements Toolti
|
||||
|
||||
scrollPane.setViewportBorder(null);
|
||||
|
||||
if (hintHint.isRequestFocus()) {
|
||||
pane.setFocusable(true);
|
||||
}
|
||||
|
||||
final Ref<AnAction> actionRef = new Ref<AnAction>();
|
||||
final LightweightHint hint = new LightweightHint(scrollPane) {
|
||||
@Override
|
||||
@@ -123,6 +129,8 @@ public class LineTooltipRenderer extends ComparableObject.Impl implements Toolti
|
||||
|
||||
@Override
|
||||
public void actionPerformed(final AnActionEvent e) {
|
||||
// The tooltip gets the focus if using a screen reader and invocation through a keyboard shortcut.
|
||||
hintHint.setRequestFocus(ScreenReader.isActive() && (e.getInputEvent() instanceof KeyEvent));
|
||||
expand(hint, editor, p, pane, alignToRight, group, hintHint);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -36,6 +36,7 @@ public class IdeTooltip extends ComparableObject.Impl {
|
||||
private boolean myToCenter = false;
|
||||
private boolean myToCenterIfSmall = true;
|
||||
private boolean myHighlighter;
|
||||
private boolean myRequestFocus;
|
||||
|
||||
private Color myTextBackground;
|
||||
private Color myTextForeground;
|
||||
@@ -263,6 +264,15 @@ public class IdeTooltip extends ComparableObject.Impl {
|
||||
return myUi != null && myUi.isInside(target);
|
||||
}
|
||||
|
||||
public boolean isRequestFocus() {
|
||||
return myRequestFocus;
|
||||
}
|
||||
|
||||
public IdeTooltip setRequestFocus(boolean requestFocus) {
|
||||
myRequestFocus = requestFocus;
|
||||
return this;
|
||||
}
|
||||
|
||||
public interface Ui {
|
||||
boolean isInside(RelativePoint target);
|
||||
|
||||
|
||||
@@ -311,6 +311,7 @@ public class IdeTooltipManager implements ApplicationComponent, AWTEventListener
|
||||
.setPositionChangeYShift(tooltip.getPositionChangeY())
|
||||
.setHideOnKeyOutside(!tooltip.isExplicitClose())
|
||||
.setHideOnAction(!tooltip.isExplicitClose())
|
||||
.setRequestFocus(tooltip.isRequestFocus())
|
||||
.setLayer(tooltip.getLayer());
|
||||
tooltip.getTipComponent().setForeground(fg);
|
||||
tooltip.getTipComponent().setBorder(new EmptyBorder(1, 3, 2, 3));
|
||||
|
||||
@@ -55,10 +55,12 @@ import com.intellij.ui.mac.MacMainFrameDecorator;
|
||||
import com.intellij.util.Alarm;
|
||||
import com.intellij.util.io.storage.HeavyProcessLatch;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import com.intellij.util.ui.accessibility.AccessibleContextAccessor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.io.PowerSupplyKit;
|
||||
|
||||
import javax.accessibility.AccessibleContext;
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.WindowAdapter;
|
||||
@@ -72,7 +74,7 @@ import java.io.File;
|
||||
* @author Anton Katilin
|
||||
* @author Vladimir Kondratyev
|
||||
*/
|
||||
public class IdeFrameImpl extends JFrame implements IdeFrameEx, DataProvider {
|
||||
public class IdeFrameImpl extends JFrame implements IdeFrameEx, AccessibleContextAccessor, DataProvider {
|
||||
public static final Key<Boolean> SHOULD_OPEN_IN_FULL_SCREEN = Key.create("should.open.in.full.screen");
|
||||
|
||||
private static final String FULL_SCREEN = "FullScreen";
|
||||
@@ -354,6 +356,11 @@ public class IdeFrameImpl extends JFrame implements IdeFrameEx, DataProvider {
|
||||
((IdeRootPane)getRootPane()).updateNorthComponents();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AccessibleContext getCurrentAccessibleContext() {
|
||||
return accessibleContext;
|
||||
}
|
||||
|
||||
private static final class Builder {
|
||||
public StringBuilder sb = new StringBuilder();
|
||||
|
||||
@@ -601,4 +608,29 @@ public class IdeFrameImpl extends JFrame implements IdeFrameEx, DataProvider {
|
||||
|
||||
return ActionCallback.DONE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AccessibleContext getAccessibleContext() {
|
||||
if (accessibleContext == null) {
|
||||
accessibleContext = new AccessibleIdeFrameImpl();
|
||||
}
|
||||
return accessibleContext;
|
||||
}
|
||||
|
||||
protected class AccessibleIdeFrameImpl extends AccessibleJFrame {
|
||||
@Override
|
||||
public String getAccessibleName() {
|
||||
final StringBuilder builder = new StringBuilder();
|
||||
|
||||
if (myProject != null) {
|
||||
builder.append(myProject.getName());
|
||||
builder.append(" - ");
|
||||
}
|
||||
|
||||
final String applicationName = ((ApplicationInfoEx)ApplicationInfo.getInstance()).getFullApplicationName();
|
||||
builder.append(applicationName);
|
||||
|
||||
return builder.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+19
-1
@@ -42,6 +42,9 @@ import com.intellij.util.ui.UIUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.accessibility.Accessible;
|
||||
import javax.accessibility.AccessibleContext;
|
||||
import javax.accessibility.AccessibleRole;
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.HyperlinkListener;
|
||||
import java.awt.*;
|
||||
@@ -53,7 +56,7 @@ import java.util.List;
|
||||
/**
|
||||
* User: spLeaner
|
||||
*/
|
||||
public class IdeStatusBarImpl extends JComponent implements StatusBarEx {
|
||||
public class IdeStatusBarImpl extends JComponent implements Accessible, StatusBarEx {
|
||||
private static final int MIN_ICON_HEIGHT = 18 + 1 + 1;
|
||||
private final InfoAndProgressPanel myInfoAndProgressPanel;
|
||||
private IdeFrame myFrame;
|
||||
@@ -883,4 +886,19 @@ public class IdeStatusBarImpl extends JComponent implements StatusBarEx {
|
||||
public IdeFrame getFrame() {
|
||||
return myFrame;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AccessibleContext getAccessibleContext() {
|
||||
if (accessibleContext == null) {
|
||||
accessibleContext = new AccessibleIdeStatusBarImpl();
|
||||
}
|
||||
return accessibleContext;
|
||||
}
|
||||
|
||||
protected class AccessibleIdeStatusBarImpl extends AccessibleJComponent {
|
||||
@Override
|
||||
public AccessibleRole getAccessibleRole() {
|
||||
return AccessibleRole.PANEL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,6 +39,8 @@ import com.intellij.util.ui.JBUI;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.accessibility.AccessibleContext;
|
||||
import javax.accessibility.AccessibleRole;
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.datatransfer.StringSelection;
|
||||
@@ -243,4 +245,18 @@ class StatusPanel extends JPanel {
|
||||
return myTextPanel.getText();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AccessibleContext getAccessibleContext() {
|
||||
if (accessibleContext == null) {
|
||||
accessibleContext = new AccessibleStatusPanel();
|
||||
}
|
||||
return accessibleContext;
|
||||
}
|
||||
|
||||
protected class AccessibleStatusPanel extends AccessibleJPanel {
|
||||
@Override
|
||||
public AccessibleRole getAccessibleRole() {
|
||||
return AccessibleRole.STATUS_BAR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,10 +24,13 @@ import com.intellij.util.ui.UIUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.accessibility.Accessible;
|
||||
import javax.accessibility.AccessibleContext;
|
||||
import javax.accessibility.AccessibleRole;
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
|
||||
public class TextPanel extends JComponent {
|
||||
public class TextPanel extends JComponent implements Accessible {
|
||||
@Nullable private String myText;
|
||||
@Nullable private Color myCustomColor;
|
||||
|
||||
@@ -135,7 +138,20 @@ public class TextPanel extends JComponent {
|
||||
return;
|
||||
}
|
||||
|
||||
String oldAccessibleName = null;
|
||||
if (accessibleContext != null) {
|
||||
oldAccessibleName = accessibleContext.getAccessibleName();
|
||||
}
|
||||
|
||||
myText = text;
|
||||
|
||||
if ((accessibleContext != null) && !StringUtil.equals(accessibleContext.getAccessibleName(), oldAccessibleName)) {
|
||||
accessibleContext.firePropertyChange(
|
||||
AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY,
|
||||
oldAccessibleName,
|
||||
accessibleContext.getAccessibleName());
|
||||
}
|
||||
|
||||
setPreferredSize(getPanelDimensionFromFontMetrics(myText));
|
||||
revalidate();
|
||||
repaint();
|
||||
@@ -227,4 +243,24 @@ public class TextPanel extends JComponent {
|
||||
return new Dimension(size.width + 3, size.height);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public AccessibleContext getAccessibleContext() {
|
||||
if (accessibleContext == null) {
|
||||
accessibleContext = new AccessibleTextPanel();
|
||||
}
|
||||
return accessibleContext;
|
||||
}
|
||||
|
||||
protected class AccessibleTextPanel extends AccessibleJComponent {
|
||||
@Override
|
||||
public AccessibleRole getAccessibleRole() {
|
||||
return AccessibleRole.LABEL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAccessibleName() {
|
||||
return myText;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+8
-1
@@ -53,10 +53,12 @@ import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.ui.JBUI;
|
||||
import com.intellij.util.ui.MouseEventAdapter;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import com.intellij.util.ui.accessibility.AccessibleContextAccessor;
|
||||
import com.intellij.util.ui.accessibility.AccessibleContextUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.accessibility.AccessibleContext;
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.ListDataEvent;
|
||||
import javax.swing.event.ListDataListener;
|
||||
@@ -73,7 +75,7 @@ import java.util.List;
|
||||
/**
|
||||
* @author Konstantin Bulenkov
|
||||
*/
|
||||
public class FlatWelcomeFrame extends JFrame implements IdeFrame {
|
||||
public class FlatWelcomeFrame extends JFrame implements IdeFrame, AccessibleContextAccessor {
|
||||
private static final String ACTION_GROUP_KEY = "ACTION_GROUP_KEY";
|
||||
private static final String WELCOME_TITLE = "Welcome to " + ApplicationNamesInfo.getInstance().getFullProductName();
|
||||
private final BalloonLayout myBalloonLayout;
|
||||
@@ -176,6 +178,11 @@ public class FlatWelcomeFrame extends JFrame implements IdeFrame {
|
||||
return new JBColor(Gray.xEC, new Color(72, 75, 78));
|
||||
}
|
||||
|
||||
@Override
|
||||
public AccessibleContext getCurrentAccessibleContext() {
|
||||
return accessibleContext;
|
||||
}
|
||||
|
||||
private class FlatWelcomeScreen extends JPanel implements WelcomeScreen {
|
||||
private JBSlidingPanel mySlidingPanel = new JBSlidingPanel();
|
||||
|
||||
|
||||
+8
-1
@@ -43,15 +43,17 @@ import com.intellij.ui.AppUIUtil;
|
||||
import com.intellij.ui.BalloonLayout;
|
||||
import com.intellij.ui.BalloonLayoutImpl;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import com.intellij.util.ui.accessibility.AccessibleContextAccessor;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.accessibility.AccessibleContext;
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.WindowAdapter;
|
||||
import java.awt.event.WindowEvent;
|
||||
import java.io.File;
|
||||
|
||||
public class WelcomeFrame extends JFrame implements IdeFrame {
|
||||
public class WelcomeFrame extends JFrame implements IdeFrame, AccessibleContextAccessor {
|
||||
public static final ExtensionPointName<WelcomeFrameProvider> EP = ExtensionPointName.create("com.intellij.welcomeFrameProvider");
|
||||
static final String DIMENSION_KEY = "WELCOME_SCREEN";
|
||||
private static IdeFrame ourInstance;
|
||||
@@ -234,4 +236,9 @@ public class WelcomeFrame extends JFrame implements IdeFrame {
|
||||
public JComponent getComponent() {
|
||||
return getRootPane();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AccessibleContext getCurrentAccessibleContext() {
|
||||
return accessibleContext;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -268,6 +268,8 @@ public class BalloonImpl implements Balloon, IdeTooltip.Ui {
|
||||
private boolean myHideOnMouse;
|
||||
private final boolean myHideOnKey;
|
||||
private final boolean myHideOnAction;
|
||||
private final boolean myRequestFocus;
|
||||
private Component myOriginalFocusOwner;
|
||||
private final boolean myEnableButtons;
|
||||
|
||||
public BalloonImpl(@NotNull JComponent content,
|
||||
@@ -294,7 +296,8 @@ public class BalloonImpl implements Balloon, IdeTooltip.Ui {
|
||||
boolean shadow,
|
||||
boolean smallVariant,
|
||||
boolean blockClicks,
|
||||
Layer layer) {
|
||||
Layer layer,
|
||||
boolean requestFocus) {
|
||||
myBorderColor = borderColor;
|
||||
myBorderInsets = borderInsets != null ? borderInsets : new Insets(3, 3, 3, 3);
|
||||
myFillColor = fillColor;
|
||||
@@ -315,6 +318,7 @@ public class BalloonImpl implements Balloon, IdeTooltip.Ui {
|
||||
myTitle = title;
|
||||
myLayer = layer != null ? layer : Layer.normal;
|
||||
myBlockClicks = blockClicks;
|
||||
myRequestFocus = requestFocus;
|
||||
MnemonicHelper.init(content);
|
||||
|
||||
if (!myDialogMode) {
|
||||
@@ -468,6 +472,22 @@ public class BalloonImpl implements Balloon, IdeTooltip.Ui {
|
||||
}
|
||||
});
|
||||
}
|
||||
if (myRequestFocus) {
|
||||
myFocusManager.doWhenFocusSettlesDown(new ExpirableRunnable() {
|
||||
@Override
|
||||
public boolean isExpired() {
|
||||
return isDisposed();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
myOriginalFocusOwner = myFocusManager.getFocusOwner();
|
||||
|
||||
// Set the focus to "myContent"
|
||||
myFocusManager.requestFocus(getContentToFocus(), true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
myLayeredPane.addComponentListener(myComponentListener);
|
||||
|
||||
@@ -588,6 +608,32 @@ public class BalloonImpl implements Balloon, IdeTooltip.Ui {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Figure out the component to focus inside the {@link myContent} field.
|
||||
*/
|
||||
@NotNull
|
||||
private Component getContentToFocus() {
|
||||
Component focusComponent = myContent;
|
||||
while (true) {
|
||||
// Setting focus to a JScrollPane is not very useful. Better setting focus to the
|
||||
// contained view. This is useful for Tooltip popups, for example.
|
||||
if (focusComponent instanceof JScrollPane) {
|
||||
JViewport viewport = ((JScrollPane)focusComponent).getViewport();
|
||||
if (viewport == null)
|
||||
break;
|
||||
Component child = viewport.getView();
|
||||
if (child == null)
|
||||
break;
|
||||
focusComponent = child;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Done if we can't find anything to dive into
|
||||
break;
|
||||
}
|
||||
return focusComponent;
|
||||
}
|
||||
|
||||
private Rectangle getRecForPosition(AbstractPosition position, boolean adjust) {
|
||||
Dimension size = getContentSizeFor(position);
|
||||
Rectangle rec = new Rectangle(new Point(0, 0), size);
|
||||
@@ -888,6 +934,11 @@ public class BalloonImpl implements Balloon, IdeTooltip.Ui {
|
||||
@Override
|
||||
public void run() {
|
||||
myFadedOut = true;
|
||||
if (myRequestFocus) {
|
||||
if (myOriginalFocusOwner != null) {
|
||||
myFocusManager.requestFocus(myOriginalFocusOwner, false);
|
||||
}
|
||||
}
|
||||
|
||||
for (JBPopupListener each : myListeners) {
|
||||
each.onClosed(new LightweightWindowEvent(BalloonImpl.this, ok));
|
||||
|
||||
@@ -50,6 +50,7 @@ public class HintHint {
|
||||
private int myPositionChangeY;
|
||||
private boolean myShowImmediately = false;
|
||||
private boolean myAnimationEnabled;
|
||||
private boolean myRequestFocus;
|
||||
|
||||
public HintHint() {
|
||||
}
|
||||
@@ -282,4 +283,13 @@ public class HintHint {
|
||||
myAnimationEnabled = enabled;
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean isRequestFocus() {
|
||||
return myRequestFocus;
|
||||
}
|
||||
|
||||
public HintHint setRequestFocus(boolean requestFocus) {
|
||||
myRequestFocus = requestFocus;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -183,6 +183,7 @@ public class LightweightHint extends UserDataHolderBase implements Hint {
|
||||
.setCalloutShift(hintHint.getCalloutShift())
|
||||
.setPositionChangeShift(hintHint.getPositionChangeX(), hintHint.getPositionChangeY())
|
||||
.setExplicitClose(hintHint.isExplicitClose())
|
||||
.setRequestFocus(hintHint.isRequestFocus())
|
||||
.setHint(true);
|
||||
myComponent.validate();
|
||||
myCurrentIdeTooltip = IdeTooltipManager.getInstance().show(tooltip, hintHint.isShowImmediately(), hintHint.isAnimationEnabled());
|
||||
|
||||
@@ -19,10 +19,14 @@ import com.intellij.ide.ui.UISettings;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.ui.components.JBScrollPane;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.SystemProperties;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import com.intellij.util.ui.tree.WideSelectionTreeUI;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
|
||||
import javax.accessibility.Accessible;
|
||||
import javax.accessibility.AccessibleContext;
|
||||
import javax.accessibility.AccessibleRole;
|
||||
import javax.swing.*;
|
||||
import javax.swing.plaf.TreeUI;
|
||||
import javax.swing.tree.DefaultMutableTreeNode;
|
||||
@@ -34,7 +38,7 @@ import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.util.ArrayList;
|
||||
|
||||
public abstract class MultilineTreeCellRenderer extends JComponent implements TreeCellRenderer {
|
||||
public abstract class MultilineTreeCellRenderer extends JComponent implements Accessible, TreeCellRenderer {
|
||||
|
||||
private boolean myWrapsCalculated = false;
|
||||
private boolean myTooSmall = false;
|
||||
@@ -473,5 +477,42 @@ public abstract class MultilineTreeCellRenderer extends JComponent implements Tr
|
||||
// return myDelegatee.getScrollableTracksViewportHeight();
|
||||
// }
|
||||
// }
|
||||
|
||||
@Override
|
||||
public AccessibleContext getAccessibleContext() {
|
||||
if (accessibleContext == null) {
|
||||
accessibleContext = new AccessibleMultilineTreeCellRenderer();
|
||||
}
|
||||
return accessibleContext;
|
||||
}
|
||||
|
||||
protected class AccessibleMultilineTreeCellRenderer extends AccessibleJComponent {
|
||||
@Override
|
||||
public String getAccessibleName() {
|
||||
String name = accessibleName;
|
||||
if (name == null) {
|
||||
name = (String)getClientProperty(AccessibleContext.ACCESSIBLE_NAME_PROPERTY);
|
||||
}
|
||||
|
||||
if (name == null) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (String aLine : myLines) {
|
||||
sb.append(aLine);
|
||||
sb.append(SystemProperties.getLineSeparator());
|
||||
}
|
||||
if (sb.length() > 0) name = sb.toString();
|
||||
}
|
||||
|
||||
if (name == null) {
|
||||
name = super.getAccessibleName();
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AccessibleRole getAccessibleRole() {
|
||||
return AccessibleRole.LABEL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -68,6 +68,7 @@ public class BalloonPopupBuilderImpl implements BalloonBuilder {
|
||||
|
||||
private Balloon.Layer myLayer;
|
||||
private boolean myBlockClicks = false;
|
||||
private boolean myRequestFocus = false;
|
||||
|
||||
public BalloonPopupBuilderImpl(@Nullable Map<Disposable, List<Balloon>> storage, @NotNull final JComponent content) {
|
||||
myStorage = storage;
|
||||
@@ -144,6 +145,13 @@ public class BalloonPopupBuilderImpl implements BalloonBuilder {
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public BalloonBuilder setRequestFocus(boolean requestFocus) {
|
||||
myRequestFocus = requestFocus;
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public BalloonBuilder setAnimationCycle(int time) {
|
||||
@@ -250,7 +258,7 @@ public class BalloonPopupBuilderImpl implements BalloonBuilder {
|
||||
myContent, myBorder, myBorderInsets, myFill, myHideOnMouseOutside, myHideOnKeyOutside, myHideOnAction, myShowCallout, myCloseButtonEnabled,
|
||||
myFadeoutTime, myHideOnFrameResize, myHideOnLinkClick, myClickHandler, myCloseOnClick, myAnimationCycle, myCalloutShift,
|
||||
myPositionChangeXShift, myPositionChangeYShift, myDialogMode, myTitle, myContentInsets, myShadow, mySmallVariant, myBlockClicks,
|
||||
myLayer);
|
||||
myLayer, myRequestFocus);
|
||||
|
||||
if (myStorage != null && myAnchor != null) {
|
||||
List<Balloon> balloons = myStorage.get(myAnchor);
|
||||
|
||||
@@ -134,7 +134,7 @@ public interface PopupComponent {
|
||||
@Override
|
||||
public void windowClosed(WindowEvent e) {
|
||||
super.windowClosed(e);
|
||||
A11YFix.invokeFocusGained(myDialog);
|
||||
//A11YFix.invokeFocusGained(myDialog);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@ public class BalloonTest {
|
||||
|
||||
balloon.set(new BalloonImpl(
|
||||
new JLabel("Content"), Color.black, null , MessageType.ERROR.getPopupBackground(), true, true, true, true, true, 0, true, false, null,
|
||||
false, 500, 25, 0, 0, false, "This is the title", new Insets(2, 2, 2, 2), true, false, false, Balloon.Layer.normal));
|
||||
false, 500, 25, 0, 0, false, "This is the title", new Insets(2, 2, 2, 2), true, false, false, Balloon.Layer.normal, false));
|
||||
balloon.get().setShowPointer(true);
|
||||
|
||||
if (e.isShiftDown()) {
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
*
|
||||
* 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.accessibility;
|
||||
|
||||
import javax.accessibility.AccessibleContext;
|
||||
|
||||
/**
|
||||
* Interface allowing direct access to the {@link AccessibleContext} instance
|
||||
* of a component.
|
||||
*/
|
||||
public interface AccessibleContextAccessor {
|
||||
/**
|
||||
* Same as {@link javax.accessibility.Accessible#getAccessibleContext}, except that the returned
|
||||
* {@link AccessibleContext} is null if it has not been created yet.
|
||||
*/
|
||||
AccessibleContext getCurrentAccessibleContext();
|
||||
}
|
||||
@@ -22,6 +22,10 @@ import org.jetbrains.annotations.Nullable;
|
||||
import javax.swing.*;
|
||||
|
||||
public class AccessibleContextUtil {
|
||||
public static void setName(@NotNull JComponent component, @NotNull String name) {
|
||||
component.getAccessibleContext().setAccessibleName(name);
|
||||
}
|
||||
|
||||
public static void setName(@NotNull JComponent component, @NotNull JComponent source) {
|
||||
String name = source.getAccessibleContext().getAccessibleName();
|
||||
if (name != null) {
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
*
|
||||
* 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.accessibility;
|
||||
|
||||
import com.intellij.util.SystemProperties;
|
||||
|
||||
import javax.accessibility.AccessibleContext;
|
||||
import java.awt.*;
|
||||
|
||||
/**
|
||||
* Expose system-wide screen reader status for accessibility features.
|
||||
*/
|
||||
public class ScreenReader {
|
||||
public static String SYSTEM_PROPERTY_KEY = "screenreader";
|
||||
|
||||
/**
|
||||
* Components that need to customize their behavior in the presence of a external screen reader
|
||||
* application should call this method to determine the presence of such screen reader.
|
||||
*
|
||||
* For example, this can be used to determine if components should to be focusable via keyboard
|
||||
* as opposed to accessible only via the mouse pointer.
|
||||
*
|
||||
* @return <code>true</code> if a screen reader is currently active, or has been active
|
||||
* since the start of the application.
|
||||
*/
|
||||
public static boolean isActive() {
|
||||
// Return system property value if it is set
|
||||
if (SystemProperties.has(SYSTEM_PROPERTY_KEY)) {
|
||||
return SystemProperties.is(SYSTEM_PROPERTY_KEY);
|
||||
}
|
||||
|
||||
// Auto-detect if system property not set.
|
||||
for (Frame frame: Frame.getFrames()) {
|
||||
if (frame instanceof AccessibleContextAccessor) {
|
||||
AccessibleContext frameContext = ((AccessibleContextAccessor)frame).getCurrentAccessibleContext();
|
||||
if (frameContext != null)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user