mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
quickdoc reformat, rearrange, drop final
This commit is contained in:
+185
-164
@@ -96,15 +96,14 @@ import java.util.List;
|
||||
public class DocumentationComponent extends JPanel implements Disposable, DataProvider {
|
||||
|
||||
private static final Logger LOG = Logger.getInstance(DocumentationComponent.class);
|
||||
private static final String DOCUMENTATION_TOPIC_ID = "reference.toolWindows.Documentation";
|
||||
|
||||
private static final Color DOCUMENTATION_COLOR = new JBColor(new Color(0xf7f7f7), new Color(0x46484a));
|
||||
static final JBColor BORDER_COLOR = new JBColor(new Color(0xadadad), new Color(0x616366));
|
||||
private static final JBColor BORDER_COLOR = new JBColor(new Color(0xadadad), new Color(0x616366));
|
||||
public static final ColorKey COLOR_KEY = ColorKey.createColorKey("DOCUMENTATION_COLOR", DOCUMENTATION_COLOR);
|
||||
|
||||
public static final Color SECTION_COLOR = Gray.get(0x90);
|
||||
|
||||
private static final Highlighter.HighlightPainter LINK_HIGHLIGHTER = new LinkHighlighter();
|
||||
@NonNls private static final String DOCUMENTATION_TOPIC_ID = "reference.toolWindows.Documentation";
|
||||
|
||||
private static final int PREFERRED_HEIGHT_MAX_EM = 10;
|
||||
private static final JBDimension MAX_DEFAULT = new JBDimension(650, 500);
|
||||
@@ -132,81 +131,13 @@ public class DocumentationComponent extends JPanel implements Disposable, DataPr
|
||||
private final MyDictionary<String, Image> myImageProvider = new MyDictionary<String, Image>() {
|
||||
@Override
|
||||
public Image get(Object key) {
|
||||
if (myManager == null || key == null) return null;
|
||||
PsiElement element = getElement();
|
||||
if (element == null) return null;
|
||||
URL url = (URL)key;
|
||||
Image inMemory = myManager.getElementImage(element, url.toExternalForm());
|
||||
if (inMemory != null) {
|
||||
return inMemory;
|
||||
}
|
||||
|
||||
Url parsedUrl = Urls.parseEncoded(url.toExternalForm());
|
||||
BuiltInServerManager builtInServerManager = BuiltInServerManager.getInstance();
|
||||
if (parsedUrl != null && builtInServerManager.isOnBuiltInWebServer(parsedUrl)) {
|
||||
try {
|
||||
url = new URL(builtInServerManager.addAuthToken(parsedUrl).toExternalForm());
|
||||
}
|
||||
catch (MalformedURLException e) {
|
||||
LOG.warn(e);
|
||||
}
|
||||
}
|
||||
Image image = ImageLoader.loadFromUrl(url);
|
||||
return image != null ? ImageUtil.toBufferedImage(image) : Toolkit.getDefaultToolkit().createImage(url);
|
||||
return getImageByKeyImpl(key);
|
||||
}
|
||||
};
|
||||
|
||||
private Runnable myToolwindowCallback;
|
||||
private final ActionButton myCorner;
|
||||
|
||||
public AnAction[] getActions() {
|
||||
return myToolBar.getActions().stream().filter((action -> !(action instanceof Separator))).toArray(AnAction[]::new);
|
||||
}
|
||||
|
||||
public AnAction getFontSizeAction() {
|
||||
return new MyShowSettingsAction();
|
||||
}
|
||||
|
||||
public void removeCornerMenu() {
|
||||
myCorner.setVisible(false);
|
||||
}
|
||||
|
||||
public void setToolwindowCallback(Runnable callback) {
|
||||
myToolwindowCallback = callback;
|
||||
}
|
||||
|
||||
public void showExternalDoc() {
|
||||
final DataContext dataContext = DataManager.getInstance().getDataContext(this);
|
||||
myExternalDocAction.actionPerformed(AnActionEvent.createFromDataContext(ActionPlaces.UNKNOWN, null, dataContext));
|
||||
}
|
||||
|
||||
private static class Context {
|
||||
final SmartPsiElementPointer element;
|
||||
final String text;
|
||||
final String externalUrl;
|
||||
final DocumentationProvider provider;
|
||||
final Rectangle viewRect;
|
||||
final int highlightedLink;
|
||||
|
||||
Context(SmartPsiElementPointer element,
|
||||
String text,
|
||||
String externalUrl,
|
||||
DocumentationProvider provider,
|
||||
Rectangle viewRect,
|
||||
int highlightedLink) {
|
||||
this.element = element;
|
||||
this.text = text;
|
||||
this.externalUrl = externalUrl;
|
||||
this.provider = provider;
|
||||
this.viewRect = viewRect;
|
||||
this.highlightedLink = highlightedLink;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
Context withText(@NotNull String text) {
|
||||
return new Context(element, text, externalUrl, provider, viewRect, highlightedLink);
|
||||
}
|
||||
}
|
||||
|
||||
private final MyScrollPane myScrollPane;
|
||||
private final JEditorPane myEditorPane;
|
||||
private String myText; // myEditorPane.getText() surprisingly crashes.., let's cache the text
|
||||
@@ -219,34 +150,10 @@ public class DocumentationComponent extends JPanel implements Disposable, DataPr
|
||||
|
||||
private final Map<KeyStroke, ActionListener> myKeyboardActions = new HashMap<>();
|
||||
|
||||
@Override
|
||||
public boolean requestFocusInWindow() {
|
||||
// With a screen reader active, set the focus directly to the editor because
|
||||
// it makes it easier for users to read/navigate the documentation contents.
|
||||
if (ScreenReader.isActive()) {
|
||||
return myEditorPane.requestFocusInWindow();
|
||||
}
|
||||
else {
|
||||
return myScrollPane.requestFocusInWindow();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void requestFocus() {
|
||||
// With a screen reader active, set the focus directly to the editor because
|
||||
// it makes it easier for users to read/navigate the documentation contents.
|
||||
IdeFocusManager.getGlobalInstance().doWhenFocusSettlesDown(() -> {
|
||||
if (ScreenReader.isActive()) {
|
||||
IdeFocusManager.getGlobalInstance().requestFocus(myEditorPane, true);
|
||||
}
|
||||
else {
|
||||
IdeFocusManager.getGlobalInstance().requestFocus(myScrollPane, true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static DocumentationComponent createAndFetch(Project project, PsiElement element, Disposable disposable) {
|
||||
@NotNull
|
||||
public static DocumentationComponent createAndFetch(@NotNull Project project,
|
||||
@NotNull PsiElement element,
|
||||
@NotNull Disposable disposable) {
|
||||
DocumentationManager manager = DocumentationManager.getInstance(project);
|
||||
DocumentationComponent component = new DocumentationComponent(manager);
|
||||
Disposer.register(disposable, component);
|
||||
@@ -254,13 +161,12 @@ public class DocumentationComponent extends JPanel implements Disposable, DataPr
|
||||
return component;
|
||||
}
|
||||
|
||||
public DocumentationComponent(final DocumentationManager manager) {
|
||||
public DocumentationComponent(DocumentationManager manager) {
|
||||
myManager = manager;
|
||||
myIsEmpty = true;
|
||||
myIsShown = false;
|
||||
|
||||
myEditorPane = new JEditorPane(UIUtil.HTML_MIME, "") {
|
||||
private Point initialClick;
|
||||
{
|
||||
enableEvents(AWTEvent.KEY_EVENT_MASK);
|
||||
}
|
||||
@@ -277,6 +183,8 @@ public class DocumentationComponent extends JPanel implements Disposable, DataPr
|
||||
super.processKeyEvent(e);
|
||||
}
|
||||
|
||||
Point initialClick;
|
||||
|
||||
@Override
|
||||
protected void processMouseEvent(MouseEvent e) {
|
||||
if (e.getID() == MouseEvent.MOUSE_PRESSED && myHint != null) {
|
||||
@@ -357,10 +265,10 @@ public class DocumentationComponent extends JPanel implements Disposable, DataPr
|
||||
@Override
|
||||
public View create(Element elem) {
|
||||
if ("icon".equals(elem.getName())) {
|
||||
final Object src = elem.getAttributes().getAttribute(HTML.Attribute.SRC);
|
||||
Object src = elem.getAttributes().getAttribute(HTML.Attribute.SRC);
|
||||
Icon icon = src != null ? IconLoader.findIcon((String)src, false) : null;
|
||||
if (icon == null) {
|
||||
final ModuleType id = ModuleTypeManager.getInstance().findByID((String)src);
|
||||
ModuleType id = ModuleTypeManager.getInstance().findByID((String)src);
|
||||
if (id != null) icon = id.getIcon();
|
||||
}
|
||||
if (icon != null) {
|
||||
@@ -400,7 +308,7 @@ public class DocumentationComponent extends JPanel implements Disposable, DataPr
|
||||
|
||||
@Override
|
||||
public int viewToModel(float x, float y, Shape a, Position.Bias[] bias) {
|
||||
Rectangle alloc = (Rectangle) a;
|
||||
Rectangle alloc = (Rectangle)a;
|
||||
if (x < alloc.x + (alloc.width / 2)) {
|
||||
bias[0] = Position.Bias.Forward;
|
||||
return getStartOffset();
|
||||
@@ -422,7 +330,7 @@ public class DocumentationComponent extends JPanel implements Disposable, DataPr
|
||||
myScrollPane = new MyScrollPane();
|
||||
myScrollPane.putClientProperty(DataManager.CLIENT_PROPERTY_DATA_PROVIDER, helpDataProvider);
|
||||
|
||||
final FocusListener focusAdapter = new FocusAdapter() {
|
||||
FocusListener focusAdapter = new FocusAdapter() {
|
||||
@Override
|
||||
public void focusLost(FocusEvent e) {
|
||||
Component previouslyFocused = WindowManagerEx.getInstanceEx().getFocusedComponent(manager.getProject(getElement()));
|
||||
@@ -448,9 +356,9 @@ public class DocumentationComponent extends JPanel implements Disposable, DataPr
|
||||
setOpaque(true);
|
||||
myScrollPane.setBorder(JBUI.Borders.empty());
|
||||
|
||||
final DefaultActionGroup actions = new DefaultActionGroup();
|
||||
final BackAction back = new BackAction();
|
||||
final ForwardAction forward = new ForwardAction();
|
||||
DefaultActionGroup actions = new DefaultActionGroup();
|
||||
BackAction back = new BackAction();
|
||||
ForwardAction forward = new ForwardAction();
|
||||
EditDocumentationSourceAction edit = new EditDocumentationSourceAction();
|
||||
myExternalDocAction = new ExternalDocAction();
|
||||
actions.add(back);
|
||||
@@ -469,18 +377,18 @@ public class DocumentationComponent extends JPanel implements Disposable, DataPr
|
||||
forward.registerCustomShortcutSet(forwardShortcutSet, this);
|
||||
// mouse actions are checked only for exact component over which click was performed,
|
||||
// so we need to register shortcuts for myEditorPane as well
|
||||
back.registerCustomShortcutSet(backShortcutSet, myEditorPane);
|
||||
back.registerCustomShortcutSet(backShortcutSet, myEditorPane);
|
||||
forward.registerCustomShortcutSet(forwardShortcutSet, myEditorPane);
|
||||
}
|
||||
catch (InvalidDataException e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
|
||||
|
||||
myExternalDocAction.registerCustomShortcutSet(CustomShortcutSet.fromString("UP"), this);
|
||||
myExternalDocAction.registerCustomShortcutSet(ActionManager.getInstance().getAction(IdeActions.ACTION_EXTERNAL_JAVADOC).getShortcutSet(), myEditorPane);
|
||||
edit.registerCustomShortcutSet(CommonShortcuts.getEditSource(), this);
|
||||
ActionPopupMenu contextMenu = ((ActionManagerImpl)ActionManager.getInstance()).createActionPopupMenu(ActionPlaces.JAVADOC_TOOLBAR, actions,
|
||||
new MenuItemPresentationFactory(true));
|
||||
ActionPopupMenu contextMenu = ((ActionManagerImpl)ActionManager.getInstance()).createActionPopupMenu(
|
||||
ActionPlaces.JAVADOC_TOOLBAR, actions, new MenuItemPresentationFactory(true));
|
||||
PopupHandler popupHandler = new PopupHandler() {
|
||||
@Override
|
||||
public void invokePopup(Component comp, int x, int y) {
|
||||
@@ -499,7 +407,7 @@ public class DocumentationComponent extends JPanel implements Disposable, DataPr
|
||||
JLayeredPane layeredPane = new JBLayeredPane() {
|
||||
@Override
|
||||
public void doLayout() {
|
||||
final Rectangle r = getBounds();
|
||||
Rectangle r = getBounds();
|
||||
for (Component component : getComponents()) {
|
||||
if (component instanceof JScrollPane) {
|
||||
component.setBounds(0, 0, r.width, r.height);
|
||||
@@ -526,7 +434,7 @@ public class DocumentationComponent extends JPanel implements Disposable, DataPr
|
||||
layeredPane.add(myScrollPane);
|
||||
layeredPane.setLayer(myScrollPane, 0);
|
||||
|
||||
final DefaultActionGroup gearActions = new MyGearActionGroup();
|
||||
DefaultActionGroup gearActions = new MyGearActionGroup();
|
||||
gearActions.add(new ShowAsToolwindowAction());
|
||||
gearActions.add(new MyShowSettingsAction());
|
||||
gearActions.add(new ShowToolbarAction());
|
||||
@@ -553,7 +461,7 @@ public class DocumentationComponent extends JPanel implements Disposable, DataPr
|
||||
myControlPanel.add(new MyShowSettingsButton(), BorderLayout.EAST);
|
||||
myControlPanelVisible = false;
|
||||
|
||||
final HyperlinkListener hyperlinkListener = new HyperlinkListener() {
|
||||
HyperlinkListener hyperlinkListener = new HyperlinkListener() {
|
||||
@Override
|
||||
public void hyperlinkUpdate(HyperlinkEvent e) {
|
||||
HyperlinkEvent.EventType type = e.getEventType();
|
||||
@@ -572,7 +480,8 @@ public class DocumentationComponent extends JPanel implements Disposable, DataPr
|
||||
|
||||
if (myHint != null) {
|
||||
Disposer.register(myHint, this);
|
||||
} else if (myManager.myToolWindow != null) {
|
||||
}
|
||||
else if (myManager.myToolWindow != null) {
|
||||
Disposer.register(myManager.myToolWindow.getContentManager(), this);
|
||||
}
|
||||
|
||||
@@ -581,14 +490,62 @@ public class DocumentationComponent extends JPanel implements Disposable, DataPr
|
||||
updateControlState();
|
||||
}
|
||||
|
||||
public AnAction[] getActions() {
|
||||
return myToolBar.getActions().stream().filter((action -> !(action instanceof Separator))).toArray(AnAction[]::new);
|
||||
}
|
||||
|
||||
public AnAction getFontSizeAction() {
|
||||
return new MyShowSettingsAction();
|
||||
}
|
||||
|
||||
public void removeCornerMenu() {
|
||||
myCorner.setVisible(false);
|
||||
}
|
||||
|
||||
public void setToolwindowCallback(Runnable callback) {
|
||||
myToolwindowCallback = callback;
|
||||
}
|
||||
|
||||
public void showExternalDoc() {
|
||||
DataContext dataContext = DataManager.getInstance().getDataContext(this);
|
||||
myExternalDocAction.actionPerformed(AnActionEvent.createFromDataContext(ActionPlaces.UNKNOWN, null, dataContext));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean requestFocusInWindow() {
|
||||
// With a screen reader active, set the focus directly to the editor because
|
||||
// it makes it easier for users to read/navigate the documentation contents.
|
||||
if (ScreenReader.isActive()) {
|
||||
return myEditorPane.requestFocusInWindow();
|
||||
}
|
||||
else {
|
||||
return myScrollPane.requestFocusInWindow();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void requestFocus() {
|
||||
// With a screen reader active, set the focus directly to the editor because
|
||||
// it makes it easier for users to read/navigate the documentation contents.
|
||||
IdeFocusManager.getGlobalInstance().doWhenFocusSettlesDown(() -> {
|
||||
if (ScreenReader.isActive()) {
|
||||
IdeFocusManager.getGlobalInstance().requestFocus(myEditorPane, true);
|
||||
}
|
||||
else {
|
||||
IdeFocusManager.getGlobalInstance().requestFocus(myScrollPane, true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static void prepareCSS(HTMLEditorKit editorKit) {
|
||||
Color borderColor = ColorUtil.mix(DOCUMENTATION_COLOR, BORDER_COLOR, 0.5);
|
||||
String editorFontName = StringUtil.escapeQuotes(EditorColorsManager.getInstance().getGlobalScheme().getEditorFontName());
|
||||
editorKit.getStyleSheet().addRule("code {font-family:\"" + editorFontName + "\"}");
|
||||
editorKit.getStyleSheet().addRule("pre {font-family:\"" + editorFontName + "\"}");
|
||||
editorKit.getStyleSheet().addRule(".pre {font-family:\"" + editorFontName + "\"}");
|
||||
editorKit.getStyleSheet().addRule("html { padding-bottom: 5px; }");
|
||||
editorKit.getStyleSheet().addRule("a { color: #" + ColorUtil.toHex(getLinkColor()) + "; text-decoration: none;}");
|
||||
editorKit.getStyleSheet().addRule(".definition { padding: 3px 17px 1px 7px; border-bottom: thin solid #" + ColorUtil.toHex(ColorUtil.mix(DOCUMENTATION_COLOR, BORDER_COLOR, 0.5)) + "; }");
|
||||
editorKit.getStyleSheet().addRule(".definition { padding: 3px 17px 1px 7px; border-bottom: thin solid #" + ColorUtil.toHex(borderColor) + "; }");
|
||||
editorKit.getStyleSheet().addRule(".content { padding: 5px 16px 0 7px; max-width: 100% }");
|
||||
editorKit.getStyleSheet().addRule(".bottom { padding: 3px 16px 0 7px; }");
|
||||
editorKit.getStyleSheet().addRule(".bottom-no-content { padding: 5px 16px 0 7px; }");
|
||||
@@ -616,7 +573,7 @@ public class DocumentationComponent extends JPanel implements Disposable, DataPr
|
||||
// Javadocs often contain symbols (non-breakable white space). We don't want to copy them as is and replace
|
||||
// with raw white spaces. See IDEA-86633 for more details.
|
||||
String selectedText = myEditorPane.getSelectedText();
|
||||
return selectedText == null? null : selectedText.replace((char)160, ' ');
|
||||
return selectedText == null ? null : selectedText.replace((char)160, ' ');
|
||||
}
|
||||
|
||||
return null;
|
||||
@@ -768,7 +725,7 @@ public class DocumentationComponent extends JPanel implements Disposable, DataPr
|
||||
pointer = SmartPointerManager.getInstance(element.getProject()).createSmartPsiElementPointer(element);
|
||||
}
|
||||
setDataInternal(pointer, text, new Rectangle(0, 0), ref);
|
||||
}
|
||||
}
|
||||
|
||||
private void setDataInternal(@Nullable SmartPsiElementPointer element,
|
||||
@NotNull String text,
|
||||
@@ -779,7 +736,7 @@ public class DocumentationComponent extends JPanel implements Disposable, DataPr
|
||||
updateControlState();
|
||||
|
||||
setElement(element);
|
||||
|
||||
|
||||
highlightLink(-1);
|
||||
|
||||
myEditorPane.setText(decorate(text));
|
||||
@@ -794,10 +751,13 @@ public class DocumentationComponent extends JPanel implements Disposable, DataPr
|
||||
myEditorPane.scrollRectToVisible(viewRect); // if ref is defined but is not found in document, this provides a default location
|
||||
if (ref != null) {
|
||||
myEditorPane.scrollToReference(ref);
|
||||
} else if (ScreenReader.isActive()) {
|
||||
}
|
||||
else if (ScreenReader.isActive()) {
|
||||
myEditorPane.setCaretPosition(0);
|
||||
}});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void showHint() {
|
||||
Editor editor = myManager.getEditor();
|
||||
Component popupAnchor = getPopupAnchor(editor);
|
||||
@@ -820,7 +780,8 @@ public class DocumentationComponent extends JPanel implements Disposable, DataPr
|
||||
int height = preferredSize.height + (needsToolbar() ? myControlPanel.getPreferredSize().height : 0);
|
||||
height = Math.min(MAX_DEFAULT.height, Math.max(MIN_DEFAULT.height, height));
|
||||
hintSize = new Dimension(width, height);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
hintSize = DimensionService.getInstance().getSize(DocumentationManager.NEW_JAVADOC_LOCATION_AND_SIZE, myManager.myProject);
|
||||
if (hintSize == null) {
|
||||
hintSize = new Dimension(MIN_DEFAULT);
|
||||
@@ -836,7 +797,8 @@ public class DocumentationComponent extends JPanel implements Disposable, DataPr
|
||||
// pin upper right corner (instead of default upper left)
|
||||
location = new RelativePoint(popupAnchor, new Point(-hintSize.width - 5, 0)).getScreenPoint();
|
||||
myHint.setLocation(location);
|
||||
} else if (editor != null && editor.getComponent().isShowing()) {
|
||||
}
|
||||
else if (editor != null && editor.getComponent().isShowing()) {
|
||||
// pin lower bound (instead of default upper)
|
||||
Point preferredLocation = JBPopupFactory.getInstance().guessBestPopupLocation(editor).getScreenPoint();
|
||||
preferredLocation.y -= editor.getLineHeight();
|
||||
@@ -883,7 +845,8 @@ public class DocumentationComponent extends JPanel implements Disposable, DataPr
|
||||
// if documentation doesn't fit into screen, put it on the left hand side
|
||||
if (x + Math.max(hintSize.width, maxWidth) > screenRectangle.width) {
|
||||
point = new RelativePoint(popupAnchor, new Point(-hintSize.width - 5, 0));
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
point = new RelativePoint(popupAnchor, new Point(lookupWidthAndGap, 0));
|
||||
}
|
||||
myHint.show(point);
|
||||
@@ -892,14 +855,15 @@ public class DocumentationComponent extends JPanel implements Disposable, DataPr
|
||||
lookup.addLookupListener(new LookupAdapter() {
|
||||
@Override
|
||||
public void lookupCanceled(LookupEvent event) {
|
||||
final AbstractPopup hint = myHint;
|
||||
AbstractPopup hint = myHint;
|
||||
if (hint != null && hint.canClose() && hint.isVisible()) {
|
||||
hint.cancel();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
} else if (editor != null && editor.getComponent().isShowing()) {
|
||||
}
|
||||
else if (editor != null && editor.getComponent().isShowing()) {
|
||||
// let's try to fit at least of half of maximum size on the bottom
|
||||
Point preferredLocation = JBPopupFactory.getInstance().guessBestPopupLocation(editor).getScreenPoint();
|
||||
Rectangle preferred = new Rectangle(preferredLocation.x, preferredLocation.y, MAX_DEFAULT.width, MAX_DEFAULT.height / 2);
|
||||
@@ -935,7 +899,7 @@ public class DocumentationComponent extends JPanel implements Disposable, DataPr
|
||||
if (lookup != null && lookup.getCurrentItem() != null && lookup.getComponent().isShowing()) {
|
||||
return lookup.getComponent();
|
||||
}
|
||||
final Component focusOwner = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner();
|
||||
Component focusOwner = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner();
|
||||
JBPopup popup = PopupUtil.getPopupContainerFor(focusOwner);
|
||||
if (popup != null) {
|
||||
return popup.getContent();
|
||||
@@ -944,10 +908,10 @@ public class DocumentationComponent extends JPanel implements Disposable, DataPr
|
||||
}
|
||||
|
||||
private void registerSizeTracker() {
|
||||
final AbstractPopup hint = myHint;
|
||||
AbstractPopup hint = myHint;
|
||||
if (hint == null) return;
|
||||
final Window window = hint.getPopupWindow();
|
||||
final ComponentAdapter listener = new ComponentAdapter() {
|
||||
Window window = hint.getPopupWindow();
|
||||
ComponentAdapter listener = new ComponentAdapter() {
|
||||
@Override
|
||||
public void componentResized(ComponentEvent e) {
|
||||
if (myResizing) {
|
||||
@@ -962,9 +926,9 @@ public class DocumentationComponent extends JPanel implements Disposable, DataPr
|
||||
}
|
||||
|
||||
private int definitionPreferredWidth() {
|
||||
final TextUI ui = myEditorPane.getUI();
|
||||
final View view = ui.getRootView(myEditorPane);
|
||||
final View definition = findDefinition(view);
|
||||
TextUI ui = myEditorPane.getUI();
|
||||
View view = ui.getRootView(myEditorPane);
|
||||
View definition = findDefinition(view);
|
||||
return definition != null ? (int)definition.getPreferredSpan(View.X_AXIS) : -1;
|
||||
}
|
||||
|
||||
@@ -973,7 +937,7 @@ public class DocumentationComponent extends JPanel implements Disposable, DataPr
|
||||
return view;
|
||||
}
|
||||
for (int i = 0; i < view.getViewCount(); i++) {
|
||||
final View definition = findDefinition(view.getView(i));
|
||||
View definition = findDefinition(view.getView(i));
|
||||
if (definition != null) return definition;
|
||||
}
|
||||
return null;
|
||||
@@ -990,12 +954,13 @@ public class DocumentationComponent extends JPanel implements Disposable, DataPr
|
||||
DocumentationMarkup.CONTENT_START +
|
||||
text.substring(bodyStart) +
|
||||
DocumentationMarkup.CONTENT_END;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
text = DocumentationMarkup.CONTENT_START + text + DocumentationMarkup.CONTENT_END;
|
||||
}
|
||||
hasContent = true;
|
||||
}
|
||||
final String location = getLocationText();
|
||||
String location = getLocationText();
|
||||
if (location != null) {
|
||||
text = text + getBottom(hasContent) + location + "</div>";
|
||||
}
|
||||
@@ -1020,7 +985,7 @@ public class DocumentationComponent extends JPanel implements Disposable, DataPr
|
||||
return null;
|
||||
}
|
||||
|
||||
final String title = manager.getTitle(element);
|
||||
String title = manager.getTitle(element);
|
||||
if (externalUrl == null) {
|
||||
List<String> urls = provider.getUrlFor(element, originalElement);
|
||||
if (urls != null) {
|
||||
@@ -1086,7 +1051,7 @@ public class DocumentationComponent extends JPanel implements Disposable, DataPr
|
||||
try {
|
||||
return new URL(url).toURI().getHost();
|
||||
}
|
||||
catch (URISyntaxException|MalformedURLException ignored) {}
|
||||
catch (URISyntaxException | MalformedURLException ignored) { }
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -1113,22 +1078,22 @@ public class DocumentationComponent extends JPanel implements Disposable, DataPr
|
||||
}
|
||||
|
||||
private String getLocationText() {
|
||||
final PsiElement element = getElement();
|
||||
PsiElement element = getElement();
|
||||
if (element != null) {
|
||||
PsiFile file = element.getContainingFile();
|
||||
VirtualFile vfile = file == null ? null : file.getVirtualFile();
|
||||
|
||||
if (vfile == null) return null;
|
||||
|
||||
final ProjectFileIndex fileIndex = ProjectRootManager.getInstance(element.getProject()).getFileIndex();
|
||||
final Module module = fileIndex.getModuleForFile(vfile);
|
||||
ProjectFileIndex fileIndex = ProjectRootManager.getInstance(element.getProject()).getFileIndex();
|
||||
Module module = fileIndex.getModuleForFile(vfile);
|
||||
|
||||
if (module != null) {
|
||||
if (ModuleManager.getInstance(element.getProject()).getModules().length == 1) return null;
|
||||
return "<icon src='" + ModuleType.get(module).getId() + "'> " + module.getName().replace("<", "<");
|
||||
}
|
||||
else {
|
||||
final List<OrderEntry> entries = fileIndex.getOrderEntriesForFile(vfile);
|
||||
List<OrderEntry> entries = fileIndex.getOrderEntriesForFile(vfile);
|
||||
for (OrderEntry order : entries) {
|
||||
if (order instanceof LibraryOrderEntry || order instanceof JdkOrderEntry) {
|
||||
return "<icon src='AllIcons.Nodes.PpLibFolder" + "'> " + order.getPresentableName().replace("<", "<");
|
||||
@@ -1153,6 +1118,31 @@ public class DocumentationComponent extends JPanel implements Disposable, DataPr
|
||||
myEditorPane.setFont(UIUtil.getFontWithFallback(fontName, Font.PLAIN, JBUI.scale(getQuickDocFontSize().getSize())));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Image getImageByKeyImpl(Object key) {
|
||||
if (myManager == null || key == null) return null;
|
||||
PsiElement element = getElement();
|
||||
if (element == null) return null;
|
||||
URL url = (URL)key;
|
||||
Image inMemory = myManager.getElementImage(element, url.toExternalForm());
|
||||
if (inMemory != null) {
|
||||
return inMemory;
|
||||
}
|
||||
|
||||
Url parsedUrl = Urls.parseEncoded(url.toExternalForm());
|
||||
BuiltInServerManager builtInServerManager = BuiltInServerManager.getInstance();
|
||||
if (parsedUrl != null && builtInServerManager.isOnBuiltInWebServer(parsedUrl)) {
|
||||
try {
|
||||
url = new URL(builtInServerManager.addAuthToken(parsedUrl).toExternalForm());
|
||||
}
|
||||
catch (MalformedURLException e) {
|
||||
LOG.warn(e);
|
||||
}
|
||||
}
|
||||
Image image = ImageLoader.loadFromUrl(url);
|
||||
return image != null ? ImageUtil.toBufferedImage(image) : Toolkit.getDefaultToolkit().createImage(url);
|
||||
}
|
||||
|
||||
private void goBack() {
|
||||
if (myBackStack.isEmpty()) return;
|
||||
Context context = myBackStack.pop();
|
||||
@@ -1198,14 +1188,14 @@ public class DocumentationComponent extends JPanel implements Disposable, DataPr
|
||||
}
|
||||
|
||||
private static class MyGearActionGroup extends DefaultActionGroup implements HintManagerImpl.ActionToIgnore {
|
||||
public MyGearActionGroup(@NotNull AnAction... actions) {
|
||||
MyGearActionGroup(@NotNull AnAction... actions) {
|
||||
super(actions);
|
||||
setPopup(true);
|
||||
}
|
||||
}
|
||||
|
||||
private class BackAction extends AnAction implements HintManagerImpl.ActionToIgnore {
|
||||
public BackAction() {
|
||||
BackAction() {
|
||||
super(CodeInsightBundle.message("javadoc.action.back"), null, AllIcons.Actions.Back);
|
||||
}
|
||||
|
||||
@@ -1225,7 +1215,7 @@ public class DocumentationComponent extends JPanel implements Disposable, DataPr
|
||||
}
|
||||
|
||||
private class ForwardAction extends AnAction implements HintManagerImpl.ActionToIgnore {
|
||||
public ForwardAction() {
|
||||
ForwardAction() {
|
||||
super(CodeInsightBundle.message("javadoc.action.forward"), null, AllIcons.Actions.Forward);
|
||||
}
|
||||
|
||||
@@ -1255,7 +1245,7 @@ public class DocumentationComponent extends JPanel implements Disposable, DataPr
|
||||
@Override
|
||||
public void actionPerformed(AnActionEvent e) {
|
||||
super.actionPerformed(e);
|
||||
final JBPopup hint = myHint;
|
||||
JBPopup hint = myHint;
|
||||
if (hint != null && hint.isVisible()) {
|
||||
hint.cancel();
|
||||
}
|
||||
@@ -1267,7 +1257,7 @@ public class DocumentationComponent extends JPanel implements Disposable, DataPr
|
||||
SmartPsiElementPointer element = myElement;
|
||||
if (element != null) {
|
||||
PsiElement psiElement = element.getElement();
|
||||
return psiElement instanceof Navigatable ? new Navigatable[] {(Navigatable)psiElement} : null;
|
||||
return psiElement instanceof Navigatable ? new Navigatable[]{(Navigatable)psiElement} : null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -1290,15 +1280,15 @@ public class DocumentationComponent extends JPanel implements Disposable, DataPr
|
||||
return;
|
||||
}
|
||||
|
||||
final PsiElement element = myElement.getElement();
|
||||
final PsiElement originalElement = DocumentationManager.getOriginalElement(element);
|
||||
|
||||
PsiElement element = myElement.getElement();
|
||||
PsiElement originalElement = DocumentationManager.getOriginalElement(element);
|
||||
|
||||
ExternalJavaDocAction.showExternalJavadoc(element, originalElement, myExternalUrl, e.getDataContext());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(AnActionEvent e) {
|
||||
final Presentation presentation = e.getPresentation();
|
||||
Presentation presentation = e.getPresentation();
|
||||
presentation.setEnabled(hasExternalDoc());
|
||||
}
|
||||
}
|
||||
@@ -1445,7 +1435,7 @@ public class DocumentationComponent extends JPanel implements Disposable, DataPr
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
private void highlightLink(int n) {
|
||||
myHighlightedLink = n;
|
||||
Highlighter highlighter = myEditorPane.getHighlighter();
|
||||
@@ -1480,10 +1470,41 @@ public class DocumentationComponent extends JPanel implements Disposable, DataPr
|
||||
}
|
||||
}
|
||||
|
||||
private static class Context {
|
||||
final SmartPsiElementPointer element;
|
||||
final String text;
|
||||
final String externalUrl;
|
||||
final DocumentationProvider provider;
|
||||
final Rectangle viewRect;
|
||||
final int highlightedLink;
|
||||
|
||||
Context(SmartPsiElementPointer element,
|
||||
String text,
|
||||
String externalUrl,
|
||||
DocumentationProvider provider,
|
||||
Rectangle viewRect,
|
||||
int highlightedLink) {
|
||||
this.element = element;
|
||||
this.text = text;
|
||||
this.externalUrl = externalUrl;
|
||||
this.provider = provider;
|
||||
this.viewRect = viewRect;
|
||||
this.highlightedLink = highlightedLink;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
Context withText(@NotNull String text) {
|
||||
return new Context(element, text, externalUrl, provider, viewRect, highlightedLink);
|
||||
}
|
||||
}
|
||||
|
||||
private class MyShowSettingsButton extends ActionButton {
|
||||
|
||||
public MyShowSettingsButton() {
|
||||
this(new MyGearActionGroup(new ShowAsToolwindowAction(), new MyShowSettingsAction(), new ShowToolbarAction(), new RestoreDefaultSizeAction()),
|
||||
MyShowSettingsButton() {
|
||||
this(new MyGearActionGroup(new ShowAsToolwindowAction(),
|
||||
new MyShowSettingsAction(),
|
||||
new ShowToolbarAction(),
|
||||
new RestoreDefaultSizeAction()),
|
||||
new Presentation(), ActionPlaces.JAVADOC_INPLACE_SETTINGS, ActionToolbar.DEFAULT_MINIMUM_BUTTON_SIZE);
|
||||
}
|
||||
|
||||
@@ -1494,7 +1515,7 @@ public class DocumentationComponent extends JPanel implements Disposable, DataPr
|
||||
}
|
||||
|
||||
private class MyShowSettingsAction extends AnAction implements HintManagerImpl.ActionToIgnore {
|
||||
public MyShowSettingsAction() {
|
||||
MyShowSettingsAction() {
|
||||
super("Adjust font size...");
|
||||
}
|
||||
|
||||
@@ -1565,10 +1586,10 @@ public class DocumentationComponent extends JPanel implements Disposable, DataPr
|
||||
activateLink(myHighlightedLink);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static class LinkHighlighter implements Highlighter.HighlightPainter {
|
||||
private static final Stroke STROKE = new BasicStroke(1, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 1, new float[]{1}, 0);
|
||||
|
||||
|
||||
@Override
|
||||
public void paint(Graphics g, int p0, int p1, Shape bounds, JTextComponent c) {
|
||||
try {
|
||||
@@ -1590,7 +1611,7 @@ public class DocumentationComponent extends JPanel implements Disposable, DataPr
|
||||
}
|
||||
|
||||
private class ShowToolbarAction extends ToggleAction implements HintManagerImpl.ActionToIgnore {
|
||||
public ShowToolbarAction() {
|
||||
ShowToolbarAction() {
|
||||
super("Show Toolbar");
|
||||
}
|
||||
|
||||
@@ -1608,7 +1629,7 @@ public class DocumentationComponent extends JPanel implements Disposable, DataPr
|
||||
}
|
||||
|
||||
private class MyScrollPane extends JBScrollPane {
|
||||
public MyScrollPane() {
|
||||
MyScrollPane() {
|
||||
super(myEditorPane, VERTICAL_SCROLLBAR_AS_NEEDED, HORIZONTAL_SCROLLBAR_AS_NEEDED);
|
||||
setLayout(new Layout() {
|
||||
@Override
|
||||
@@ -1665,7 +1686,7 @@ public class DocumentationComponent extends JPanel implements Disposable, DataPr
|
||||
}
|
||||
|
||||
private class ShowAsToolwindowAction extends AnAction implements HintManagerImpl.ActionToIgnore {
|
||||
public ShowAsToolwindowAction() {
|
||||
ShowAsToolwindowAction() {
|
||||
super("Open as Tool Window");
|
||||
}
|
||||
|
||||
@@ -1681,7 +1702,7 @@ public class DocumentationComponent extends JPanel implements Disposable, DataPr
|
||||
}
|
||||
|
||||
private class RestoreDefaultSizeAction extends AnAction implements HintManagerImpl.ActionToIgnore {
|
||||
public RestoreDefaultSizeAction() {
|
||||
RestoreDefaultSizeAction() {
|
||||
super("Restore Size");
|
||||
}
|
||||
|
||||
|
||||
+107
-100
@@ -89,7 +89,7 @@ public class DocumentationManager extends DockablePopupManager<DocumentationComp
|
||||
private static final Logger LOG = Logger.getInstance(DocumentationManager.class);
|
||||
private static final String SHOW_DOCUMENTATION_IN_TOOL_WINDOW = "ShowDocumentationInToolWindow";
|
||||
private static final String DOCUMENTATION_AUTO_UPDATE_ENABLED = "DocumentationAutoUpdateEnabled";
|
||||
|
||||
|
||||
private static final long DOC_GENERATION_TIMEOUT_MILLISECONDS = 60000;
|
||||
private static final long DOC_GENERATION_PAUSE_MILLISECONDS = 100;
|
||||
|
||||
@@ -105,10 +105,10 @@ public class DocumentationManager extends DockablePopupManager<DocumentationComp
|
||||
|
||||
private boolean myCloseOnSneeze;
|
||||
private String myPrecalculatedDocumentation;
|
||||
|
||||
|
||||
private ActionCallback myLastAction;
|
||||
private DocumentationComponent myTestDocumentationComponent;
|
||||
|
||||
|
||||
private AnAction myRestorePopupAction;
|
||||
|
||||
@Override
|
||||
@@ -173,9 +173,9 @@ public class DocumentationManager extends DockablePopupManager<DocumentationComp
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@code true} if quick doc control is configured to not prevent user-IDE interaction (e.g. should be closed if
|
||||
* the user presses a key);
|
||||
* {@code false} otherwise
|
||||
* @return {@code true} if quick doc control is configured to not prevent user-IDE interaction (e.g. should be closed if
|
||||
* the user presses a key);
|
||||
* {@code false} otherwise
|
||||
*/
|
||||
public boolean isCloseOnSneeze() {
|
||||
return myCloseOnSneeze;
|
||||
@@ -203,13 +203,13 @@ public class DocumentationManager extends DockablePopupManager<DocumentationComp
|
||||
return ServiceManager.getService(project, DocumentationManager.class);
|
||||
}
|
||||
|
||||
public DocumentationManager(final Project project, ActionManager manager, TargetElementUtil targetElementUtil) {
|
||||
public DocumentationManager(Project project, ActionManager manager, TargetElementUtil targetElementUtil) {
|
||||
super(project);
|
||||
myActionManager = manager;
|
||||
final AnActionListener actionListener = new AnActionListener() {
|
||||
AnActionListener actionListener = new AnActionListener() {
|
||||
@Override
|
||||
public void beforeActionPerformed(AnAction action, DataContext dataContext, AnActionEvent event) {
|
||||
final JBPopup hint = getDocInfoHint();
|
||||
JBPopup hint = getDocInfoHint();
|
||||
if (hint != null) {
|
||||
if (action instanceof ShowQuickDocInfoAction) {
|
||||
((AbstractPopup)hint).focusPreferredComponent();
|
||||
@@ -230,14 +230,14 @@ public class DocumentationManager extends DockablePopupManager<DocumentationComp
|
||||
|
||||
@Override
|
||||
public void beforeEditorTyping(char c, DataContext dataContext) {
|
||||
final JBPopup hint = getDocInfoHint();
|
||||
JBPopup hint = getDocInfoHint();
|
||||
if (hint != null && LookupManager.getActiveLookup(myEditor) == null) {
|
||||
hint.cancel();
|
||||
}
|
||||
}
|
||||
};
|
||||
myActionManager.addAnActionListener(actionListener, project);
|
||||
myUpdateDocAlarm = new Alarm(Alarm.ThreadToUse.POOLED_THREAD,myProject);
|
||||
myUpdateDocAlarm = new Alarm(Alarm.ThreadToUse.POOLED_THREAD, myProject);
|
||||
myTargetElementUtil = targetElementUtil;
|
||||
}
|
||||
|
||||
@@ -276,53 +276,52 @@ public class DocumentationManager extends DockablePopupManager<DocumentationComp
|
||||
.doWhenDone(() -> component.clearHistory());
|
||||
}
|
||||
|
||||
public void showJavaDocInfo(@NotNull final PsiElement element, final PsiElement original) {
|
||||
public void showJavaDocInfo(@NotNull PsiElement element, PsiElement original) {
|
||||
showJavaDocInfo(element, original, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Asks to show quick doc for the target element.
|
||||
*
|
||||
* @param editor editor with an element for which quick do should be shown
|
||||
* @param element target element which documentation should be shown
|
||||
* @param original element that was used as a quick doc anchor. Example: consider a code like {@code Runnable task;}.
|
||||
* A user wants to see javadoc for the {@code Runnable}, so, original element is a class name from the variable
|
||||
* declaration but {@code 'element'} argument is a {@code Runnable} descriptor
|
||||
* @param closeCallback callback to be notified on target hint close (if any)
|
||||
* @param documentation precalculated documentation
|
||||
* @param closeOnSneeze flag that defines whether quick doc control should be as non-obtrusive as possible. E.g. there are at least
|
||||
* two possible situations - the quick doc is shown automatically on mouse over element; the quick doc is shown
|
||||
* on explicit action call (Ctrl+Q). We want to close the doc on, say, editor viewport position change
|
||||
* at the first situation but don't want to do that at the second
|
||||
* @param editor editor with an element for which quick do should be shown
|
||||
* @param element target element which documentation should be shown
|
||||
* @param original element that was used as a quick doc anchor. Example: consider a code like {@code Runnable task;}.
|
||||
* A user wants to see javadoc for the {@code Runnable}, so, original element is a class name from the variable
|
||||
* declaration but {@code 'element'} argument is a {@code Runnable} descriptor
|
||||
* @param closeCallback callback to be notified on target hint close (if any)
|
||||
* @param documentation precalculated documentation
|
||||
* @param closeOnSneeze flag that defines whether quick doc control should be as non-obtrusive as possible. E.g. there are at least
|
||||
* two possible situations - the quick doc is shown automatically on mouse over element; the quick doc is shown
|
||||
* on explicit action call (Ctrl+Q). We want to close the doc on, say, editor viewport position change
|
||||
* at the first situation but don't want to do that at the second
|
||||
*/
|
||||
public void showJavaDocInfo(@NotNull Editor editor,
|
||||
@NotNull final PsiElement element,
|
||||
@NotNull final PsiElement original,
|
||||
@NotNull PsiElement element,
|
||||
@NotNull PsiElement original,
|
||||
@Nullable Runnable closeCallback,
|
||||
@Nullable String documentation,
|
||||
boolean closeOnSneeze)
|
||||
{
|
||||
boolean closeOnSneeze) {
|
||||
myEditor = editor;
|
||||
myCloseOnSneeze = closeOnSneeze;
|
||||
showJavaDocInfo(element, original, false, closeCallback, documentation);
|
||||
}
|
||||
|
||||
public void showJavaDocInfo(@NotNull final PsiElement element,
|
||||
final PsiElement original,
|
||||
public void showJavaDocInfo(@NotNull PsiElement element,
|
||||
PsiElement original,
|
||||
@Nullable Runnable closeCallback) {
|
||||
showJavaDocInfo(element, original, false, closeCallback);
|
||||
}
|
||||
|
||||
public void showJavaDocInfo(@NotNull final PsiElement element,
|
||||
final PsiElement original,
|
||||
final boolean requestFocus,
|
||||
public void showJavaDocInfo(@NotNull PsiElement element,
|
||||
PsiElement original,
|
||||
boolean requestFocus,
|
||||
@Nullable Runnable closeCallback) {
|
||||
showJavaDocInfo(element, original, requestFocus, closeCallback, null);
|
||||
}
|
||||
|
||||
public void showJavaDocInfo(@NotNull final PsiElement element,
|
||||
final PsiElement original,
|
||||
final boolean requestFocus,
|
||||
public void showJavaDocInfo(@NotNull PsiElement element,
|
||||
PsiElement original,
|
||||
boolean requestFocus,
|
||||
@Nullable Runnable closeCallback,
|
||||
@Nullable String documentation) {
|
||||
if (!element.isValid()) {
|
||||
@@ -341,31 +340,31 @@ public class DocumentationManager extends DockablePopupManager<DocumentationComp
|
||||
doShowJavaDocInfo(element, requestFocus, updateProcessor, original, closeCallback, documentation);
|
||||
}
|
||||
|
||||
public void showJavaDocInfo(final Editor editor, @Nullable final PsiFile file, boolean requestFocus) {
|
||||
public void showJavaDocInfo(Editor editor, @Nullable PsiFile file, boolean requestFocus) {
|
||||
showJavaDocInfo(editor, file, requestFocus, null);
|
||||
}
|
||||
|
||||
public void showJavaDocInfo(final Editor editor,
|
||||
@Nullable final PsiFile file,
|
||||
public void showJavaDocInfo(Editor editor,
|
||||
@Nullable PsiFile file,
|
||||
boolean requestFocus,
|
||||
@Nullable final Runnable closeCallback) {
|
||||
@Nullable Runnable closeCallback) {
|
||||
myEditor = editor;
|
||||
final Project project = getProject(file);
|
||||
Project project = getProject(file);
|
||||
PsiDocumentManager.getInstance(project).commitAllDocuments();
|
||||
|
||||
final PsiElement list =
|
||||
ParameterInfoController.findArgumentList(file, editor.getCaretModel().getOffset(), -1);
|
||||
PsiElement list = ParameterInfoController.findArgumentList(file, editor.getCaretModel().getOffset(), -1);
|
||||
PsiElement expressionList = null;
|
||||
if (list != null) {
|
||||
LookupEx lookup = LookupManager.getInstance(myProject).getActiveLookup();
|
||||
if (lookup != null) {
|
||||
expressionList = null; // take completion variants for documentation then
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
expressionList = list;
|
||||
}
|
||||
}
|
||||
|
||||
final PsiElement originalElement = getContextElement(editor, file);
|
||||
PsiElement originalElement = getContextElement(editor, file);
|
||||
PsiElement element = assertSameProject(findTargetElement(editor, file));
|
||||
|
||||
if (element == null && expressionList != null) {
|
||||
@@ -387,7 +386,7 @@ public class DocumentationManager extends DockablePopupManager<DocumentationComp
|
||||
}
|
||||
|
||||
PsiElement finalElement = element;
|
||||
final PopupUpdateProcessor updateProcessor = new PopupUpdateProcessor(project) {
|
||||
PopupUpdateProcessor updateProcessor = new PopupUpdateProcessor(project) {
|
||||
@Override
|
||||
public void updatePopup(Object lookupIteObject) {
|
||||
if (lookupIteObject == null) {
|
||||
@@ -413,7 +412,7 @@ public class DocumentationManager extends DockablePopupManager<DocumentationComp
|
||||
}
|
||||
|
||||
if (myEditor != null) {
|
||||
final PsiFile file = element.getContainingFile();
|
||||
PsiFile file = element.getContainingFile();
|
||||
if (file != null) {
|
||||
Editor editor = myEditor;
|
||||
showJavaDocInfo(myEditor, file, false);
|
||||
@@ -437,11 +436,11 @@ public class DocumentationManager extends DockablePopupManager<DocumentationComp
|
||||
return file != null ? file.findElementAt(editor.getCaretModel().getOffset()) : null;
|
||||
}
|
||||
|
||||
private void doShowJavaDocInfo(@NotNull final PsiElement element,
|
||||
private void doShowJavaDocInfo(@NotNull PsiElement element,
|
||||
boolean requestFocus,
|
||||
PopupUpdateProcessor updateProcessor,
|
||||
final PsiElement originalElement,
|
||||
@Nullable final Runnable closeCallback,
|
||||
PsiElement originalElement,
|
||||
@Nullable Runnable closeCallback,
|
||||
@Nullable String documentation) {
|
||||
Project project = getProject(element);
|
||||
if (!project.isOpen()) return;
|
||||
@@ -493,18 +492,18 @@ public class DocumentationManager extends DockablePopupManager<DocumentationComp
|
||||
}
|
||||
}
|
||||
|
||||
private void showInPopup(@NotNull final PsiElement element,
|
||||
private void showInPopup(@NotNull PsiElement element,
|
||||
boolean requestFocus,
|
||||
PopupUpdateProcessor updateProcessor,
|
||||
final PsiElement originalElement,
|
||||
@Nullable final Runnable closeCallback) {
|
||||
final DocumentationComponent component = myTestDocumentationComponent == null ? new DocumentationComponent(this) :
|
||||
myTestDocumentationComponent;
|
||||
PsiElement originalElement,
|
||||
@Nullable Runnable closeCallback) {
|
||||
DocumentationComponent component = myTestDocumentationComponent == null ? new DocumentationComponent(this) :
|
||||
myTestDocumentationComponent;
|
||||
ActionListener actionListener = new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
createToolWindow(element, originalElement);
|
||||
final JBPopup hint = getDocInfoHint();
|
||||
JBPopup hint = getDocInfoHint();
|
||||
if (hint != null && hint.isVisible()) hint.cancel();
|
||||
}
|
||||
};
|
||||
@@ -516,7 +515,8 @@ public class DocumentationManager extends DockablePopupManager<DocumentationComp
|
||||
}
|
||||
|
||||
boolean hasLookup = LookupManager.getActiveLookup(myEditor) != null;
|
||||
AbstractPopup hint = (AbstractPopup)JBPopupFactory.getInstance().createComponentPopupBuilder(component, component)
|
||||
AbstractPopup hint = (AbstractPopup)JBPopupFactory
|
||||
.getInstance().createComponentPopupBuilder(component, component)
|
||||
.setProject(element.getProject())
|
||||
.addListener(updateProcessor)
|
||||
.addUserData(updateProcessor)
|
||||
@@ -579,30 +579,32 @@ public class DocumentationManager extends DockablePopupManager<DocumentationComp
|
||||
findQuickSearchComponent(myPreviouslyFocused).ifPresent(quickSearch -> quickSearch.registerHint(hint));
|
||||
}
|
||||
|
||||
static String getTitle(@NotNull final PsiElement element, final boolean _short) {
|
||||
final String title = SymbolPresentationUtil.getSymbolPresentableText(element);
|
||||
return _short ? title != null ? title : element.getText() : CodeInsightBundle.message("javadoc.info.title", title != null ? title : element.getText());
|
||||
static String getTitle(@NotNull PsiElement element, boolean isShort) {
|
||||
String title = SymbolPresentationUtil.getSymbolPresentableText(element);
|
||||
return isShort ? title != null ? title : element.getText()
|
||||
: CodeInsightBundle.message("javadoc.info.title", title != null ? title : element.getText());
|
||||
}
|
||||
|
||||
public static void storeOriginalElement(final Project project, final PsiElement originalElement, final PsiElement element) {
|
||||
public static void storeOriginalElement(Project project, PsiElement originalElement, PsiElement element) {
|
||||
if (element == null) return;
|
||||
try {
|
||||
element.putUserData(
|
||||
ORIGINAL_ELEMENT_KEY,
|
||||
SmartPointerManager.getInstance(project).createSmartPsiElementPointer(originalElement)
|
||||
);
|
||||
} catch (RuntimeException ex) {
|
||||
}
|
||||
catch (RuntimeException ex) {
|
||||
// PsiPackage does not allow putUserData
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public PsiElement findTargetElement(@NotNull final Editor editor, @Nullable final PsiFile file, PsiElement contextElement) {
|
||||
public PsiElement findTargetElement(@NotNull Editor editor, @Nullable PsiFile file, PsiElement contextElement) {
|
||||
return findTargetElement(editor, editor.getCaretModel().getOffset(), file, contextElement);
|
||||
}
|
||||
|
||||
|
||||
@Nullable
|
||||
public PsiElement findTargetElement(final Editor editor, int offset, @Nullable final PsiFile file, PsiElement contextElement) {
|
||||
public PsiElement findTargetElement(Editor editor, int offset, @Nullable PsiFile file, PsiElement contextElement) {
|
||||
try {
|
||||
return findTargetElementUnsafe(editor, offset, file, contextElement);
|
||||
}
|
||||
@@ -617,7 +619,7 @@ public class DocumentationManager extends DockablePopupManager<DocumentationComp
|
||||
* in case index is not ready will throw IndexNotReadyException
|
||||
*/
|
||||
@Nullable
|
||||
private PsiElement findTargetElementUnsafe(final Editor editor, int offset, @Nullable final PsiFile file, PsiElement contextElement) {
|
||||
private PsiElement findTargetElementUnsafe(Editor editor, int offset, @Nullable PsiFile file, PsiElement contextElement) {
|
||||
if (LookupManager.getInstance(myProject).getActiveLookup() != null) {
|
||||
return assertSameProject(getElementFromLookup(editor, file));
|
||||
}
|
||||
@@ -625,7 +627,7 @@ public class DocumentationManager extends DockablePopupManager<DocumentationComp
|
||||
TargetElementUtil util = TargetElementUtil.getInstance();
|
||||
PsiElement element = null;
|
||||
if (file != null) {
|
||||
final DocumentationProvider documentationProvider = getProviderFromElement(file);
|
||||
DocumentationProvider documentationProvider = getProviderFromElement(file);
|
||||
if (documentationProvider instanceof DocumentationProviderEx) {
|
||||
element = assertSameProject(((DocumentationProviderEx)documentationProvider).getCustomDocumentationElement(editor, file, contextElement));
|
||||
}
|
||||
@@ -636,7 +638,7 @@ public class DocumentationManager extends DockablePopupManager<DocumentationComp
|
||||
|
||||
// Allow context doc over xml tag content
|
||||
if (element != null || contextElement != null) {
|
||||
final PsiElement adjusted = assertSameProject(util.adjustElement(editor, myTargetElementUtil.getAllAccepted(), element, contextElement));
|
||||
PsiElement adjusted = assertSameProject(util.adjustElement(editor, myTargetElementUtil.getAllAccepted(), element, contextElement));
|
||||
if (adjusted != null) {
|
||||
element = adjusted;
|
||||
}
|
||||
@@ -644,7 +646,7 @@ public class DocumentationManager extends DockablePopupManager<DocumentationComp
|
||||
}
|
||||
|
||||
if (element == null) {
|
||||
final PsiReference ref = TargetElementUtil.findReference(editor, offset);
|
||||
PsiReference ref = TargetElementUtil.findReference(editor, offset);
|
||||
if (ref != null) {
|
||||
element = assertSameProject(util.adjustReference(ref));
|
||||
if (ref instanceof PsiPolyVariantReference) {
|
||||
@@ -668,7 +670,7 @@ public class DocumentationManager extends DockablePopupManager<DocumentationComp
|
||||
int offset = editor.getCaretModel().getOffset();
|
||||
if (offset > 0 && offset == editor.getDocument().getTextLength()) offset--;
|
||||
PsiReference ref = TargetElementUtil.findReference(editor, offset);
|
||||
PsiElement contextElement = file == null? null : file.findElementAt(offset);
|
||||
PsiElement contextElement = file == null ? null : file.findElementAt(offset);
|
||||
PsiElement targetElement = ref != null ? ref.getElement() : contextElement;
|
||||
if (targetElement != null) {
|
||||
PsiUtilCore.ensureValid(targetElement);
|
||||
@@ -698,15 +700,15 @@ public class DocumentationManager extends DockablePopupManager<DocumentationComp
|
||||
return hint;
|
||||
}
|
||||
|
||||
public void fetchDocInfo(PsiElement element, DocumentationComponent component) {
|
||||
public void fetchDocInfo(@NotNull PsiElement element, @NotNull DocumentationComponent component) {
|
||||
cancelAndFetchDocInfo(component, new MyCollector(myProject, element, null, null));
|
||||
}
|
||||
|
||||
public ActionCallback queueFetchDocInfo(PsiElement element, DocumentationComponent component) {
|
||||
public ActionCallback queueFetchDocInfo(@NotNull PsiElement element, @NotNull DocumentationComponent component) {
|
||||
return doFetchDocInfo(component, new MyCollector(myProject, element, null, null));
|
||||
}
|
||||
|
||||
private void cancelAndFetchDocInfo(DocumentationComponent component, DocumentationCollector provider) {
|
||||
private void cancelAndFetchDocInfo(@NotNull DocumentationComponent component, @NotNull DocumentationCollector provider) {
|
||||
myUpdateDocAlarm.cancelAllRequests();
|
||||
doFetchDocInfo(component, provider);
|
||||
}
|
||||
@@ -728,7 +730,7 @@ public class DocumentationManager extends DockablePopupManager<DocumentationComp
|
||||
component.startWait();
|
||||
if (wasEmpty) {
|
||||
component.setText(CodeInsightBundle.message("javadoc.fetching.progress"), collector.element, collector.provider);
|
||||
final AbstractPopup jbPopup = (AbstractPopup)getDocInfoHint();
|
||||
AbstractPopup jbPopup = (AbstractPopup)getDocInfoHint();
|
||||
if (jbPopup != null) {
|
||||
jbPopup.setDimensionServiceKey(null);
|
||||
}
|
||||
@@ -760,8 +762,8 @@ public class DocumentationManager extends DockablePopupManager<DocumentationComp
|
||||
Throwable finalFail = fail;
|
||||
GuiUtils.invokeLaterIfNeeded(() -> {
|
||||
String message = finalFail instanceof IndexNotReadyException
|
||||
? "Documentation is not available until indices are built."
|
||||
: CodeInsightBundle.message("javadoc.external.fetch.error.message");
|
||||
? "Documentation is not available until indices are built."
|
||||
: CodeInsightBundle.message("javadoc.external.fetch.error.message");
|
||||
component.setText(message, null, collector.provider);
|
||||
component.clearHistory();
|
||||
callback.setDone();
|
||||
@@ -771,7 +773,7 @@ public class DocumentationManager extends DockablePopupManager<DocumentationComp
|
||||
|
||||
LOG.debug("Documentation fetched successfully:\n", text);
|
||||
|
||||
final String finalText = text;
|
||||
String finalText = text;
|
||||
PsiDocumentManager.getInstance(myProject).performLaterWhenAllCommitted(() -> {
|
||||
if (!element.isValid()) {
|
||||
LOG.debug("Element for which documentation was requested is not valid");
|
||||
@@ -809,8 +811,8 @@ public class DocumentationManager extends DockablePopupManager<DocumentationComp
|
||||
return callback;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static DocumentationProvider getProviderFromElement(final PsiElement element) {
|
||||
@NotNull
|
||||
public static DocumentationProvider getProviderFromElement(PsiElement element) {
|
||||
return getProviderFromElement(element, null);
|
||||
}
|
||||
|
||||
@@ -863,33 +865,33 @@ public class DocumentationManager extends DockablePopupManager<DocumentationComp
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PsiElement getOriginalElement(final PsiElement element) {
|
||||
SmartPsiElementPointer originalElementPointer = element!=null ? element.getUserData(ORIGINAL_ELEMENT_KEY):null;
|
||||
public static PsiElement getOriginalElement(PsiElement element) {
|
||||
SmartPsiElementPointer originalElementPointer = element != null ? element.getUserData(ORIGINAL_ELEMENT_KEY) : null;
|
||||
return originalElementPointer != null ? originalElementPointer.getElement() : null;
|
||||
}
|
||||
|
||||
void navigateByLink(final DocumentationComponent component, final String url) {
|
||||
void navigateByLink(DocumentationComponent component, String url) {
|
||||
component.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
|
||||
final PsiElement psiElement = component.getElement();
|
||||
PsiElement psiElement = component.getElement();
|
||||
if (psiElement == null) {
|
||||
return;
|
||||
}
|
||||
final PsiManager manager = PsiManager.getInstance(getProject(psiElement));
|
||||
PsiManager manager = PsiManager.getInstance(getProject(psiElement));
|
||||
if (url.equals("external_doc")) {
|
||||
component.showExternalDoc();
|
||||
return;
|
||||
}
|
||||
if (url.startsWith("open")) {
|
||||
final PsiFile containingFile = psiElement.getContainingFile();
|
||||
PsiFile containingFile = psiElement.getContainingFile();
|
||||
OrderEntry libraryEntry = null;
|
||||
if (containingFile != null) {
|
||||
final VirtualFile virtualFile = containingFile.getVirtualFile();
|
||||
VirtualFile virtualFile = containingFile.getVirtualFile();
|
||||
libraryEntry = LibraryUtil.findLibraryEntry(virtualFile, myProject);
|
||||
}
|
||||
else if (psiElement instanceof PsiDirectoryContainer) {
|
||||
PsiDirectory[] directories = ((PsiDirectoryContainer)psiElement).getDirectories();
|
||||
for (PsiDirectory directory : directories) {
|
||||
final VirtualFile virtualFile = directory.getVirtualFile();
|
||||
VirtualFile virtualFile = directory.getVirtualFile();
|
||||
libraryEntry = LibraryUtil.findLibraryEntry(virtualFile, myProject);
|
||||
if (libraryEntry != null) {
|
||||
break;
|
||||
@@ -977,12 +979,14 @@ public class DocumentationManager extends DockablePopupManager<DocumentationComp
|
||||
}
|
||||
|
||||
public void requestFocus() {
|
||||
findQuickSearchComponent(myPreviouslyFocused).ifPresent(quickSearch ->
|
||||
getGlobalInstance().doWhenFocusSettlesDown(() -> getGlobalInstance().requestFocus(quickSearch.asComponent(), true))
|
||||
findQuickSearchComponent(myPreviouslyFocused).ifPresent(
|
||||
quickSearch ->
|
||||
getGlobalInstance().doWhenFocusSettlesDown(
|
||||
() -> getGlobalInstance().requestFocus(quickSearch.asComponent(), true))
|
||||
);
|
||||
}
|
||||
|
||||
public Project getProject(@Nullable final PsiElement element) {
|
||||
public Project getProject(@Nullable PsiElement element) {
|
||||
assertSameProject(element);
|
||||
return myProject;
|
||||
}
|
||||
@@ -994,7 +998,7 @@ public class DocumentationManager extends DockablePopupManager<DocumentationComp
|
||||
return element;
|
||||
}
|
||||
|
||||
public static void createHyperlink(StringBuilder buffer, String refText,String label,boolean plainLink) {
|
||||
public static void createHyperlink(StringBuilder buffer, String refText, String label, boolean plainLink) {
|
||||
DocumentationManagerUtil.createHyperlink(buffer, refText, label, plainLink);
|
||||
}
|
||||
|
||||
@@ -1012,7 +1016,7 @@ public class DocumentationManager extends DockablePopupManager<DocumentationComp
|
||||
protected void doUpdateComponent(PsiElement element, PsiElement originalElement, DocumentationComponent component) {
|
||||
cancelAndFetchDocInfo(component, new MyCollector(myProject, element, originalElement, null));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void doUpdateComponent(Editor editor, PsiFile psiFile, boolean requestFocus) {
|
||||
showJavaDocInfo(editor, psiFile, requestFocus, null);
|
||||
@@ -1055,7 +1059,7 @@ public class DocumentationManager extends DockablePopupManager<DocumentationComp
|
||||
public ActionCallback getLastAction() {
|
||||
return myLastAction;
|
||||
}
|
||||
|
||||
|
||||
@TestOnly
|
||||
public void setDocumentationComponent(DocumentationComponent documentationComponent) {
|
||||
myTestDocumentationComponent = documentationComponent;
|
||||
@@ -1107,7 +1111,8 @@ public class DocumentationManager extends DockablePopupManager<DocumentationComp
|
||||
LOG.debug("External documentation URLs: ", urls);
|
||||
if (urls != null) {
|
||||
for (String url : urls) {
|
||||
String doc = ((ExternalDocumentationProvider)provider).fetchExternalDocumentation(project, element, Collections.singletonList(url));
|
||||
String doc = ((ExternalDocumentationProvider)provider).fetchExternalDocumentation(
|
||||
project, element, Collections.singletonList(url));
|
||||
if (doc != null) {
|
||||
LOG.debug("Fetched documentation from ", url);
|
||||
effectiveUrl = url;
|
||||
@@ -1151,18 +1156,20 @@ public class DocumentationManager extends DockablePopupManager<DocumentationComp
|
||||
type == ArchiveFileType.INSTANCE ? "Archive" :
|
||||
type.getName();
|
||||
String languageName = type.isBinary() ? "" : psiFile.getLanguage().getDisplayName();
|
||||
return (withUrl ? DocumentationMarkup.DEFINITION_START + file.getPresentableUrl() + DocumentationMarkup.DEFINITION_END + DocumentationMarkup.CONTENT_START : "") +
|
||||
"<p><span class='grayed'>Size:</span> " + StringUtil.formatFileSize(attr.size()) +
|
||||
"<p><span class='grayed'>Type:</span> " + typeName + (type.isBinary() || typeName.equals(languageName) ? "" : " (" + languageName + ")") +
|
||||
"<p><span class='grayed'>Modified:</span> " + DateFormatUtil.formatDateTime(attr.lastModifiedTime().toMillis()) +
|
||||
"<p><span class='grayed'>Created:</span> " + DateFormatUtil.formatDateTime(attr.creationTime().toMillis()) +
|
||||
(withUrl ? DocumentationMarkup.CONTENT_END : "");
|
||||
return (withUrl ? DocumentationMarkup.DEFINITION_START +
|
||||
file.getPresentableUrl() +
|
||||
DocumentationMarkup.DEFINITION_END +
|
||||
DocumentationMarkup.CONTENT_START : "") +
|
||||
"<p><span class='grayed'>Size:</span> " + StringUtil.formatFileSize(attr.size()) +
|
||||
"<p><span class='grayed'>Type:</span> " + typeName + (type.isBinary() || typeName.equals(languageName) ? "" : " (" + languageName + ")") +
|
||||
"<p><span class='grayed'>Modified:</span> " + DateFormatUtil.formatDateTime(attr.lastModifiedTime().toMillis()) +
|
||||
"<p><span class='grayed'>Created:</span> " + DateFormatUtil.formatDateTime(attr.creationTime().toMillis()) + (withUrl ? DocumentationMarkup.CONTENT_END : "");
|
||||
}
|
||||
|
||||
private static Optional<QuickSearchComponent> findQuickSearchComponent(Component c) {
|
||||
while (c != null) {
|
||||
if (c instanceof QuickSearchComponent) {
|
||||
return Optional.of((QuickSearchComponent) c);
|
||||
return Optional.of((QuickSearchComponent)c);
|
||||
}
|
||||
c = c.getParent();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user