Java tutorial
/* * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.intellij.codeInsight.documentation; import com.intellij.codeInsight.CodeInsightBundle; import com.intellij.codeInsight.hint.ElementLocationUtil; import com.intellij.codeInsight.hint.HintManagerImpl; import com.intellij.codeInsight.hint.HintUtil; import com.intellij.icons.AllIcons; import com.intellij.ide.DataManager; import com.intellij.ide.actions.BaseNavigateToSourceAction; import com.intellij.ide.actions.ExternalJavaDocAction; import com.intellij.lang.documentation.CompositeDocumentationProvider; import com.intellij.lang.documentation.DocumentationProvider; import com.intellij.lang.documentation.ExternalDocumentationHandler; import com.intellij.lang.documentation.ExternalDocumentationProvider; import com.intellij.openapi.Disposable; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.actionSystem.impl.ActionButton; import com.intellij.openapi.application.ApplicationBundle; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.editor.colors.EditorColorsManager; import com.intellij.openapi.editor.colors.EditorColorsScheme; import com.intellij.openapi.editor.ex.EditorSettingsExternalizable; import com.intellij.openapi.editor.ex.util.EditorUtil; import com.intellij.openapi.options.FontSize; import com.intellij.openapi.ui.popup.JBPopup; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.registry.Registry; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.wm.ex.WindowManagerEx; import com.intellij.pom.Navigatable; import com.intellij.psi.PsiElement; import com.intellij.psi.SmartPointerManager; import com.intellij.psi.SmartPsiElementPointer; import com.intellij.ui.IdeBorderFactory; import com.intellij.ui.JBColor; import com.intellij.ui.SideBorder; import com.intellij.ui.components.JBLayeredPane; import com.intellij.ui.components.JBScrollPane; import com.intellij.util.Consumer; import com.intellij.util.containers.HashMap; import com.intellij.util.io.URLUtil; import com.intellij.util.ui.GraphicsUtil; import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import javax.swing.event.HyperlinkEvent; import javax.swing.event.HyperlinkListener; import javax.swing.text.*; import javax.swing.text.html.HTMLDocument; import javax.swing.text.html.HTMLEditorKit; import java.awt.*; import java.awt.event.*; import java.net.MalformedURLException; import java.net.URL; import java.util.*; import java.util.List; public class DocumentationComponent extends JPanel implements Disposable, DataProvider { @NonNls private static final String DOCUMENTATION_TOPIC_ID = "reference.toolWindows.Documentation"; private static final DataContext EMPTY_DATA_CONTEXT = new DataContext() { @Override public Object getData(@NonNls String dataId) { return null; } }; private static final int PREFERRED_WIDTH_EM = 37; private static final int PREFERRED_HEIGHT_MIN_EM = 7; private static final int PREFERRED_HEIGHT_MAX_EM = 20; private DocumentationManager myManager; private SmartPsiElementPointer myElement; private final Stack<Context> myBackStack = new Stack<Context>(); private final Stack<Context> myForwardStack = new Stack<Context>(); private final ActionToolbar myToolBar; private volatile boolean myIsEmpty; private boolean myIsShown; private final JLabel myElementLabel; private Style myFontSizeStyle; private JSlider myFontSizeSlider; private final JComponent mySettingsPanel; private final MyShowSettingsButton myShowSettingsButton; private boolean myIgnoreFontSizeSliderChange; private String myEffectiveExternalUrl; 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()); return inMemory != null ? inMemory : Toolkit.getDefaultToolkit().createImage(url); } }; private static class Context { final SmartPsiElementPointer element; final String text; final Rectangle viewRect; public Context(SmartPsiElementPointer element, String text, Rectangle viewRect) { this.element = element; this.text = text; this.viewRect = viewRect; } } private final JScrollPane myScrollPane; private final JEditorPane myEditorPane; private String myText; // myEditorPane.getText() surprisingly crashes.., let's cache the text private final JPanel myControlPanel; private boolean myControlPanelVisible; private final ExternalDocAction myExternalDocAction; private Consumer<PsiElement> myNavigateCallback; private JBPopup myHint; private final Map<KeyStroke, ActionListener> myKeyboardActions = new HashMap<KeyStroke, ActionListener>(); @Override public boolean requestFocusInWindow() { return myScrollPane.requestFocusInWindow(); } @Override public void requestFocus() { myScrollPane.requestFocus(); } public DocumentationComponent(final DocumentationManager manager, final AnAction[] additionalActions) { myManager = manager; myIsEmpty = true; myIsShown = false; myEditorPane = new JEditorPane(UIUtil.HTML_MIME, "") { @Override public EditorKit getEditorKit() { return new HTMLEditorKit(); } @Override public Dimension getPreferredScrollableViewportSize() { int em = myEditorPane.getFont().getSize(); int prefWidth = PREFERRED_WIDTH_EM * em; int prefHeightMin = PREFERRED_HEIGHT_MIN_EM * em; int prefHeightMax = PREFERRED_HEIGHT_MAX_EM * em; if (getWidth() == 0 || getHeight() == 0) { setSize(prefWidth, prefHeightMax); } Insets ins = myEditorPane.getInsets(); View rootView = myEditorPane.getUI().getRootView(myEditorPane); rootView.setSize(prefWidth, prefHeightMax); // Necessary! Without this line, the size won't increase when the content does int prefHeight = (int) rootView.getPreferredSpan(View.Y_AXIS) + ins.bottom + ins.top + myScrollPane.getHorizontalScrollBar().getMaximumSize().height; prefHeight = Math.max(prefHeightMin, Math.min(prefHeightMax, prefHeight)); return new Dimension(prefWidth, prefHeight); } { enableEvents(AWTEvent.KEY_EVENT_MASK); } @Override protected void processKeyEvent(KeyEvent e) { KeyStroke keyStroke = KeyStroke.getKeyStrokeForEvent(e); ActionListener listener = myKeyboardActions.get(keyStroke); if (listener != null) { listener.actionPerformed(new ActionEvent(DocumentationComponent.this, 0, "")); e.consume(); return; } super.processKeyEvent(e); } @Override protected void paintComponent(Graphics g) { GraphicsUtil.setupAntialiasing(g); super.paintComponent(g); } @Override public void setDocument(Document doc) { super.setDocument(doc); if (doc instanceof StyledDocument) { doc.putProperty("imageCache", myImageProvider); } } }; DataProvider helpDataProvider = new DataProvider() { @Override public Object getData(@NonNls String dataId) { return PlatformDataKeys.HELP_ID.is(dataId) ? DOCUMENTATION_TOPIC_ID : null; } }; myEditorPane.putClientProperty(DataManager.CLIENT_PROPERTY_DATA_PROVIDER, helpDataProvider); myText = ""; myEditorPane.setEditable(false); myEditorPane.setBackground(HintUtil.INFORMATION_COLOR); myEditorPane.setEditorKit(UIUtil.getHTMLEditorKit()); myScrollPane = new JBScrollPane(myEditorPane) { @Override protected void processMouseWheelEvent(MouseWheelEvent e) { if (!EditorSettingsExternalizable.getInstance().isWheelFontChangeEnabled() || !EditorUtil.isChangeFontSize(e)) { super.processMouseWheelEvent(e); return; } int change = Math.abs(e.getWheelRotation()); boolean increase = e.getWheelRotation() <= 0; EditorColorsManager colorsManager = EditorColorsManager.getInstance(); EditorColorsScheme scheme = colorsManager.getGlobalScheme(); FontSize newFontSize = scheme.getQuickDocFontSize(); for (; change > 0; change--) { if (increase) { newFontSize = newFontSize.larger(); } else { newFontSize = newFontSize.smaller(); } } if (newFontSize == scheme.getQuickDocFontSize()) { return; } scheme.setQuickDocFontSize(newFontSize); applyFontSize(); setFontSizeSliderSize(newFontSize); } }; myScrollPane.setBorder(null); myScrollPane.putClientProperty(DataManager.CLIENT_PROPERTY_DATA_PROVIDER, helpDataProvider); final MouseAdapter mouseAdapter = new MouseAdapter() { @Override public void mousePressed(MouseEvent e) { myManager.requestFocus(); myShowSettingsButton.hideSettings(); } }; myEditorPane.addMouseListener(mouseAdapter); Disposer.register(this, new Disposable() { @Override public void dispose() { myEditorPane.removeMouseListener(mouseAdapter); } }); final FocusAdapter focusAdapter = new FocusAdapter() { @Override public void focusLost(FocusEvent e) { Component previouslyFocused = WindowManagerEx.getInstanceEx() .getFocusedComponent(manager.getProject(getElement())); if (!(previouslyFocused == myEditorPane)) { if (myHint != null && !myHint.isDisposed()) myHint.cancel(); } } }; myEditorPane.addFocusListener(focusAdapter); Disposer.register(this, new Disposable() { @Override public void dispose() { myEditorPane.removeFocusListener(focusAdapter); } }); setLayout(new BorderLayout()); JLayeredPane layeredPane = new JBLayeredPane() { @Override public void doLayout() { final Rectangle r = getBounds(); for (Component component : getComponents()) { if (component instanceof JScrollPane) { component.setBounds(0, 0, r.width, r.height); } else { int insets = 2; Dimension d = component.getPreferredSize(); component.setBounds(r.width - d.width - insets, insets, d.width, d.height); } } } @Override public Dimension getPreferredSize() { Dimension editorPaneSize = myEditorPane.getPreferredScrollableViewportSize(); Dimension controlPanelSize = myControlPanel.getPreferredSize(); return new Dimension(Math.max(editorPaneSize.width, controlPanelSize.width), editorPaneSize.height + controlPanelSize.height); } }; layeredPane.add(myScrollPane); layeredPane.setLayer(myScrollPane, 0); mySettingsPanel = createSettingsPanel(); layeredPane.add(mySettingsPanel); layeredPane.setLayer(mySettingsPanel, JLayeredPane.POPUP_LAYER); add(layeredPane, BorderLayout.CENTER); setOpaque(true); myScrollPane.setViewportBorder(JBScrollPane.createIndentBorder()); final DefaultActionGroup actions = new DefaultActionGroup(); final BackAction back = new BackAction(); final ForwardAction forward = new ForwardAction(); EditDocumentationSourceAction edit = new EditDocumentationSourceAction(); actions.add(back); actions.add(forward); actions.add(myExternalDocAction = new ExternalDocAction()); actions.add(edit); back.registerCustomShortcutSet(CustomShortcutSet.fromString("LEFT"), this); forward.registerCustomShortcutSet(CustomShortcutSet.fromString("RIGHT"), this); myExternalDocAction.registerCustomShortcutSet(CustomShortcutSet.fromString("UP"), this); edit.registerCustomShortcutSet(CommonShortcuts.getEditSource(), this); if (additionalActions != null) { for (final AnAction action : additionalActions) { actions.add(action); ShortcutSet shortcutSet = action.getShortcutSet(); if (shortcutSet != null) { action.registerCustomShortcutSet(shortcutSet, this); } } } myToolBar = ActionManager.getInstance().createActionToolbar(ActionPlaces.JAVADOC_TOOLBAR, actions, true); myControlPanel = new JPanel(new BorderLayout(5, 5)); myControlPanel.setBorder(IdeBorderFactory.createBorder(SideBorder.BOTTOM)); myElementLabel = new JLabel(); myElementLabel.setMinimumSize(new Dimension(100, 0)); // do not recalculate size according to the text myControlPanel.add(myToolBar.getComponent(), BorderLayout.WEST); myControlPanel.add(myElementLabel, BorderLayout.CENTER); myControlPanel.add(myShowSettingsButton = new MyShowSettingsButton(), BorderLayout.EAST); myControlPanelVisible = false; final HyperlinkListener hyperlinkListener = new HyperlinkListener() { @Override public void hyperlinkUpdate(HyperlinkEvent e) { HyperlinkEvent.EventType type = e.getEventType(); if (type == HyperlinkEvent.EventType.ACTIVATED) { manager.navigateByLink(DocumentationComponent.this, e.getDescription()); } } }; myEditorPane.addHyperlinkListener(hyperlinkListener); Disposer.register(this, new Disposable() { @Override public void dispose() { myEditorPane.removeHyperlinkListener(hyperlinkListener); } }); registerActions(); updateControlState(); } public DocumentationComponent(final DocumentationManager manager) { this(manager, null); } @Override public Object getData(@NonNls String dataId) { if (DocumentationManager.SELECTED_QUICK_DOC_TEXT.getName().equals(dataId)) { // 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 null; } private JComponent createSettingsPanel() { JPanel result = new JPanel(new FlowLayout(FlowLayout.RIGHT, 3, 0)); result.add(new JLabel(ApplicationBundle.message("label.font.size"))); myFontSizeSlider = new JSlider(SwingConstants.HORIZONTAL, 0, FontSize.values().length - 1, 3); myFontSizeSlider.setMinorTickSpacing(1); myFontSizeSlider.setPaintTicks(true); myFontSizeSlider.setPaintTrack(true); myFontSizeSlider.setSnapToTicks(true); UIUtil.setSliderIsFilled(myFontSizeSlider, true); result.add(myFontSizeSlider); result.setBorder(BorderFactory.createLineBorder(JBColor.border(), 1)); myFontSizeSlider.addChangeListener(new ChangeListener() { @Override public void stateChanged(ChangeEvent e) { if (myIgnoreFontSizeSliderChange) { return; } EditorColorsManager colorsManager = EditorColorsManager.getInstance(); EditorColorsScheme scheme = colorsManager.getGlobalScheme(); scheme.setQuickDocFontSize(FontSize.values()[myFontSizeSlider.getValue()]); applyFontSize(); } }); String tooltipText = ApplicationBundle.message("quickdoc.tooltip.font.size.by.wheel"); result.setToolTipText(tooltipText); myFontSizeSlider.setToolTipText(tooltipText); result.setVisible(false); result.setOpaque(true); myFontSizeSlider.setOpaque(true); return result; } private void setFontSizeSliderSize(FontSize fontSize) { myIgnoreFontSizeSliderChange = true; try { FontSize[] sizes = FontSize.values(); for (int i = 0; i < sizes.length; i++) { if (fontSize == sizes[i]) { myFontSizeSlider.setValue(i); break; } } } finally { myIgnoreFontSizeSliderChange = false; } } public boolean isEmpty() { return myIsEmpty; } public void startWait() { myIsEmpty = true; } private void setControlPanelVisible(boolean visible) { if (visible == myControlPanelVisible) return; if (visible) { add(myControlPanel, BorderLayout.NORTH); } else { remove(myControlPanel); } myControlPanelVisible = visible; } public void setHint(JBPopup hint) { myHint = hint; } public JComponent getComponent() { return myEditorPane; } @Nullable public PsiElement getElement() { return myElement != null ? myElement.getElement() : null; } public void setNavigateCallback(Consumer<PsiElement> navigateCallback) { myNavigateCallback = navigateCallback; } public void setText(String text, @Nullable PsiElement element, boolean clearHistory) { setText(text, element, false, clearHistory); } public void setText(String text, PsiElement element, boolean clean, boolean clearHistory) { if (clean && myElement != null) { myBackStack.push(saveContext()); myForwardStack.clear(); } updateControlState(); setData(element, text, clearHistory, null); if (clean) { myIsEmpty = false; } if (clearHistory) clearHistory(); } public void replaceText(String text, PsiElement element) { PsiElement current = getElement(); if (current == null || !current.getManager().areElementsEquivalent(current, element)) return; setText(text, element, false); if (!myBackStack.empty()) myBackStack.pop(); } private void clearHistory() { myForwardStack.clear(); myBackStack.clear(); } public void setData(PsiElement _element, String text, final boolean clearHistory, String effectiveExternalUrl) { myEffectiveExternalUrl = effectiveExternalUrl; if (myElement != null) { myBackStack.push(saveContext()); myForwardStack.clear(); } final SmartPsiElementPointer element = _element != null && _element.isValid() ? SmartPointerManager.getInstance(_element.getProject()).createSmartPsiElementPointer(_element) : null; if (element != null) { myElement = element; } myIsEmpty = false; updateControlState(); setDataInternal(element, text, new Rectangle(0, 0)); if (clearHistory) clearHistory(); } private void setDataInternal(SmartPsiElementPointer element, String text, final Rectangle viewRect) { setDataInternal(element, text, viewRect, false); } private void setDataInternal(SmartPsiElementPointer element, String text, final Rectangle viewRect, boolean skip) { myElement = element; boolean justShown = false; if (!myIsShown && myHint != null) { myEditorPane.setText(text); applyFontSize(); myManager.showHint(myHint); myIsShown = justShown = true; } if (!justShown) { myEditorPane.setText(text); applyFontSize(); } if (!skip) { myText = text; } Document document = myEditorPane.getDocument(); if (document instanceof HTMLDocument && element != null) { // set base URL for this javadoc to resolve relative images correctly VirtualFile virtualFile = element.getVirtualFile(); VirtualFile directory = virtualFile == null ? null : virtualFile.getParent(); String path = directory == null ? "" : directory.getPath() + "/"; try { URL url = new URL(URLUtil.FILE_PROTOCOL, null, path); ((HTMLDocument) document).setBase(url); } catch (MalformedURLException ignored) { } } //noinspection SSBasedInspection SwingUtilities.invokeLater(new Runnable() { @Override public void run() { myEditorPane.scrollRectToVisible(viewRect); } }); } private void applyFontSize() { Document document = myEditorPane.getDocument(); if (!(document instanceof StyledDocument)) { return; } final StyledDocument styledDocument = (StyledDocument) document; if (myFontSizeStyle == null) { myFontSizeStyle = styledDocument.addStyle("active", null); } EditorColorsManager colorsManager = EditorColorsManager.getInstance(); EditorColorsScheme scheme = colorsManager.getGlobalScheme(); StyleConstants.setFontSize(myFontSizeStyle, scheme.getQuickDocFontSize().getSize()); if (Registry.is("documentation.component.editor.font")) { StyleConstants.setFontFamily(myFontSizeStyle, scheme.getEditorFontName()); } final Style sizeStyle = myFontSizeStyle; ApplicationManager.getApplication().executeOnPooledThread(new Runnable() { @Override public void run() { styledDocument.setCharacterAttributes(0, styledDocument.getLength(), sizeStyle, false); } }); } private void goBack() { if (myBackStack.isEmpty()) return; Context context = myBackStack.pop(); myForwardStack.push(saveContext()); restoreContext(context); updateControlState(); } private void goForward() { if (myForwardStack.isEmpty()) return; Context context = myForwardStack.pop(); myBackStack.push(saveContext()); restoreContext(context); updateControlState(); } private Context saveContext() { Rectangle rect = myScrollPane.getViewport().getViewRect(); return new Context(myElement, myText, rect); } private void restoreContext(Context context) { setDataInternal(context.element, context.text, context.viewRect); if (myNavigateCallback != null) { final PsiElement element = context.element.getElement(); if (element != null) { myNavigateCallback.consume(element); } } } private void updateControlState() { ElementLocationUtil.customizeElementLabel(myElement != null ? myElement.getElement() : null, myElementLabel); myToolBar.updateActionsImmediately(); // update faster setControlPanelVisible(true);//(!myBackStack.isEmpty() || !myForwardStack.isEmpty()); } private class BackAction extends AnAction implements HintManagerImpl.ActionToIgnore { public BackAction() { super(CodeInsightBundle.message("javadoc.action.back"), null, AllIcons.Actions.Back); } @Override public void actionPerformed(AnActionEvent e) { goBack(); } @Override public void update(AnActionEvent e) { Presentation presentation = e.getPresentation(); presentation.setEnabled(!myBackStack.isEmpty()); } } private class ForwardAction extends AnAction implements HintManagerImpl.ActionToIgnore { public ForwardAction() { super(CodeInsightBundle.message("javadoc.action.forward"), null, AllIcons.Actions.Forward); } @Override public void actionPerformed(AnActionEvent e) { goForward(); } @Override public void update(AnActionEvent e) { Presentation presentation = e.getPresentation(); presentation.setEnabled(!myForwardStack.isEmpty()); } } private class EditDocumentationSourceAction extends BaseNavigateToSourceAction { EditDocumentationSourceAction() { super(true); getTemplatePresentation().setIcon(AllIcons.Actions.EditSource); getTemplatePresentation().setText("Edit Source"); } @Override public void actionPerformed(AnActionEvent e) { super.actionPerformed(e); final JBPopup hint = myHint; if (hint != null && hint.isVisible()) { hint.cancel(); } } @Nullable @Override protected Navigatable[] getNavigatables(DataContext dataContext) { SmartPsiElementPointer element = myElement; if (element != null) { PsiElement psiElement = element.getElement(); return psiElement instanceof Navigatable ? new Navigatable[] { (Navigatable) psiElement } : null; } return null; } } private class ExternalDocAction extends AnAction implements HintManagerImpl.ActionToIgnore { public ExternalDocAction() { super(CodeInsightBundle.message("javadoc.action.view.external"), null, AllIcons.Actions.Browser_externalJavaDoc); registerCustomShortcutSet( ActionManager.getInstance().getAction(IdeActions.ACTION_EXTERNAL_JAVADOC).getShortcutSet(), null); } @Override public void actionPerformed(AnActionEvent e) { if (myElement != null) { final PsiElement element = myElement.getElement(); final DocumentationProvider provider = DocumentationManager.getProviderFromElement(element); final PsiElement originalElement = DocumentationManager.getOriginalElement(element); boolean processed = false; if (provider instanceof CompositeDocumentationProvider) { for (DocumentationProvider p : ((CompositeDocumentationProvider) provider).getAllProviders()) { if (p instanceof ExternalDocumentationHandler && ((ExternalDocumentationHandler) p).handleExternal(element, originalElement)) { processed = true; break; } } } if (!processed) { final Component component = PlatformDataKeys.CONTEXT_COMPONENT.getData(e.getDataContext()); final List<String> urls; if (!StringUtil.isEmptyOrSpaces(myEffectiveExternalUrl)) { urls = Collections.singletonList(myEffectiveExternalUrl); } else { urls = provider.getUrlFor(element, originalElement); assert urls != null : provider; assert !urls.isEmpty() : provider; } ExternalJavaDocAction.showExternalJavadoc(urls, component); } } } @Override public void update(AnActionEvent e) { final Presentation presentation = e.getPresentation(); presentation.setEnabled(false); if (myElement != null) { final PsiElement element = myElement.getElement(); final DocumentationProvider provider = DocumentationManager.getProviderFromElement(element); final PsiElement originalElement = DocumentationManager.getOriginalElement(element); if (provider instanceof ExternalDocumentationProvider) { presentation.setEnabled(element != null && ((ExternalDocumentationProvider) provider) .hasDocumentationFor(element, originalElement)); } else { final List<String> urls = provider.getUrlFor(element, originalElement); presentation.setEnabled(element != null && urls != null && !urls.isEmpty()); } } } } private void registerActions() { myExternalDocAction.registerCustomShortcutSet( ActionManager.getInstance().getAction(IdeActions.ACTION_EXTERNAL_JAVADOC).getShortcutSet(), myEditorPane); myKeyboardActions.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0), new ActionListener() { @Override public void actionPerformed(ActionEvent e) { JScrollBar scrollBar = myScrollPane.getVerticalScrollBar(); int value = scrollBar.getValue() - scrollBar.getUnitIncrement(-1); value = Math.max(value, 0); scrollBar.setValue(value); } }); myKeyboardActions.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0), new ActionListener() { @Override public void actionPerformed(ActionEvent e) { JScrollBar scrollBar = myScrollPane.getVerticalScrollBar(); int value = scrollBar.getValue() + scrollBar.getUnitIncrement(+1); value = Math.min(value, scrollBar.getMaximum()); scrollBar.setValue(value); } }); myKeyboardActions.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0), new ActionListener() { @Override public void actionPerformed(ActionEvent e) { JScrollBar scrollBar = myScrollPane.getHorizontalScrollBar(); int value = scrollBar.getValue() - scrollBar.getUnitIncrement(-1); value = Math.max(value, 0); scrollBar.setValue(value); } }); myKeyboardActions.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0), new ActionListener() { @Override public void actionPerformed(ActionEvent e) { JScrollBar scrollBar = myScrollPane.getHorizontalScrollBar(); int value = scrollBar.getValue() + scrollBar.getUnitIncrement(+1); value = Math.min(value, scrollBar.getMaximum()); scrollBar.setValue(value); } }); myKeyboardActions.put(KeyStroke.getKeyStroke(KeyEvent.VK_PAGE_UP, 0), new ActionListener() { @Override public void actionPerformed(ActionEvent e) { JScrollBar scrollBar = myScrollPane.getVerticalScrollBar(); int value = scrollBar.getValue() - scrollBar.getBlockIncrement(-1); value = Math.max(value, 0); scrollBar.setValue(value); } }); myKeyboardActions.put(KeyStroke.getKeyStroke(KeyEvent.VK_PAGE_DOWN, 0), new ActionListener() { @Override public void actionPerformed(ActionEvent e) { JScrollBar scrollBar = myScrollPane.getVerticalScrollBar(); int value = scrollBar.getValue() + scrollBar.getBlockIncrement(+1); value = Math.min(value, scrollBar.getMaximum()); scrollBar.setValue(value); } }); myKeyboardActions.put(KeyStroke.getKeyStroke(KeyEvent.VK_HOME, 0), new ActionListener() { @Override public void actionPerformed(ActionEvent e) { JScrollBar scrollBar = myScrollPane.getHorizontalScrollBar(); scrollBar.setValue(0); } }); myKeyboardActions.put(KeyStroke.getKeyStroke(KeyEvent.VK_END, 0), new ActionListener() { @Override public void actionPerformed(ActionEvent e) { JScrollBar scrollBar = myScrollPane.getHorizontalScrollBar(); scrollBar.setValue(scrollBar.getMaximum()); } }); myKeyboardActions.put(KeyStroke.getKeyStroke(KeyEvent.VK_HOME, InputEvent.CTRL_MASK), new ActionListener() { @Override public void actionPerformed(ActionEvent e) { JScrollBar scrollBar = myScrollPane.getVerticalScrollBar(); scrollBar.setValue(0); } }); myKeyboardActions.put(KeyStroke.getKeyStroke(KeyEvent.VK_END, InputEvent.CTRL_MASK), new ActionListener() { @Override public void actionPerformed(ActionEvent e) { JScrollBar scrollBar = myScrollPane.getVerticalScrollBar(); scrollBar.setValue(scrollBar.getMaximum()); } }); } public String getText() { return myText; } @Override public void dispose() { myBackStack.clear(); myForwardStack.clear(); myKeyboardActions.clear(); myElement = null; myManager = null; myHint = null; myNavigateCallback = null; } private class MyShowSettingsButton extends ActionButton { MyShowSettingsButton() { this(new MyShowSettingsAction(), new Presentation(), ActionPlaces.JAVADOC_INPLACE_SETTINGS, ActionToolbar.DEFAULT_MINIMUM_BUTTON_SIZE); } MyShowSettingsButton(AnAction action, Presentation presentation, String place, @NotNull Dimension minimumSize) { super(action, presentation, place, minimumSize); myPresentation.setIcon(AllIcons.General.SecondaryGroup); } public void hideSettings() { if (!mySettingsPanel.isVisible()) { return; } AnActionEvent event = new AnActionEvent(null, EMPTY_DATA_CONTEXT, ActionPlaces.JAVADOC_INPLACE_SETTINGS, myPresentation, ActionManager.getInstance(), 0); myAction.actionPerformed(event); } } private class MyShowSettingsAction extends ToggleAction { @Override public boolean isSelected(AnActionEvent e) { return mySettingsPanel.isVisible(); } @Override public void setSelected(AnActionEvent e, boolean state) { if (!state) { mySettingsPanel.setVisible(false); return; } EditorColorsManager colorsManager = EditorColorsManager.getInstance(); EditorColorsScheme scheme = colorsManager.getGlobalScheme(); setFontSizeSliderSize(scheme.getQuickDocFontSize()); mySettingsPanel.setVisible(true); } } private static abstract class MyDictionary<K, V> extends Dictionary<K, V> { @Override public int size() { throw new UnsupportedOperationException(); } @Override public boolean isEmpty() { throw new UnsupportedOperationException(); } @Override public Enumeration<K> keys() { throw new UnsupportedOperationException(); } @Override public Enumeration<V> elements() { throw new UnsupportedOperationException(); } @Override public V put(K key, V value) { throw new UnsupportedOperationException(); } @Override public V remove(Object key) { throw new UnsupportedOperationException(); } } }