com.microsoft.alm.plugin.idea.common.ui.controls.HelpPanel.java Source code

Java tutorial

Introduction

Here is the source code for com.microsoft.alm.plugin.idea.common.ui.controls.HelpPanel.java

Source

// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See License.txt in the project root.

package com.microsoft.alm.plugin.idea.common.ui.controls;

import com.intellij.ide.IdeTooltip;
import com.intellij.ide.IdeTooltipManager;
import com.intellij.openapi.ui.popup.Balloon;
import com.intellij.util.ui.JBUI;
import com.microsoft.alm.plugin.idea.common.resources.Icons;
import com.microsoft.alm.plugin.idea.common.ui.common.SwingHelper;
import com.microsoft.alm.plugin.idea.common.utils.IdeaHelper;
import org.apache.commons.lang.StringUtils;

import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.Timer;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.FontMetrics;
import java.awt.GridBagLayout;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import java.util.List;

public class HelpPanel extends JPanel {
    private static final int INITIAL_DELAY = 1000; // 1 second delay before opening the popup
    private static final int DISMISS_DELAY = 5000; // 5 second delay before closing the popup (once mouse leaves panel)

    private final JLabel helpLabel;
    private final List<HelpPopupCommand> popupCommands = new ArrayList<HelpPopupCommand>();
    private final List<ActionListener> listeners = new ArrayList<ActionListener>();
    private final Timer showTooltipTimer;
    private final Timer hideTooltipTimer;
    private String popupText;
    private HelpIdeTooltip tip;

    public HelpPanel() {
        // Create controls
        helpLabel = new JLabel();
        final IconPanel helpIcon = new IconPanel(Icons.Help);

        // Layout controls
        setLayout(new GridBagLayout());
        SwingHelper.addToGridBag(this, helpLabel, 0, 0, 1, 1, 0, JBUI.scale(4));
        SwingHelper.addToGridBag(this, helpIcon, 1, 0);

        this.addMouseListener(new MouseEventListener());

        showTooltipTimer = new Timer(INITIAL_DELAY, new ActionListener() {
            @Override
            public void actionPerformed(final ActionEvent e) {
                IdeaHelper.runOnUIThread(new Runnable() {
                    @Override
                    public void run() {
                        showToolTip(true);
                    }
                });
            }
        });
        showTooltipTimer.setInitialDelay(INITIAL_DELAY);
        showTooltipTimer.setRepeats(false);

        hideTooltipTimer = new Timer(DISMISS_DELAY, new ActionListener() {
            @Override
            public void actionPerformed(final ActionEvent e) {
                IdeaHelper.runOnUIThread(new Runnable() {
                    @Override
                    public void run() {
                        hideToolTip(true);
                    }
                });
            }
        });
        hideTooltipTimer.setInitialDelay(DISMISS_DELAY);
        hideTooltipTimer.setRepeats(false);
    }

    public void addActionListener(final ActionListener listener) {
        // Hook up all controls that add listeners
        listeners.add(listener);
    }

    public void clearListeners() {
        listeners.clear();
    }

    public String getHelpText() {
        return helpLabel.getText();
    }

    public void setHelpText(final String text) {
        helpLabel.setText(text);
    }

    public String getPopupText() {
        return popupText;
    }

    public void setPopupText(final String popupText) {
        this.popupText = popupText;
    }

    public void addPopupCommand(final String text, final String command) {
        popupCommands.add(new HelpPopupCommand(text, command));
    }

    public void clearPopupCommands() {
        popupCommands.clear();
    }

    private void onPopupCommandEvent(final String command) {
        hideToolTip(true);
        for (final ActionListener listener : listeners) {
            listener.actionPerformed(new ActionEvent(this, 0, command));
        }
    }

    private void toggleToolTip() {
        if (tip == null || !tip.isShowing()) {
            showToolTip(true);
        } else {
            hideToolTip(true);
        }
    }

    private void showToolTip(final boolean immediately) {
        // stop the hiding timer
        hideTooltipTimer.stop();

        if (tip != null && tip.isShowing()) {
            // It is already showing
            return;
        }

        if (tip == null) {
            final HelpToolTip toolTipPanel = new HelpToolTip(popupText, popupCommands, this.getWidth());
            tip = new HelpIdeTooltip(this, new Point(getWidth() / 2, 0), toolTipPanel);
        }
        if (immediately) {
            IdeTooltipManager.getInstance().show(tip, true);
        } else {
            // Start the showTooltipTimer to show the tooltip
            showTooltipTimer.start();
        }
    }

    private void hideToolTip(final boolean immediately) {
        // stop the showing timer
        showTooltipTimer.stop();

        if (tip != null) {
            if (immediately) {
                IdeTooltipManager.getInstance().hide(tip);
            } else {
                // Start the hideTooltipTimer to hide the tooltip
                hideTooltipTimer.start();
            }
        }
    }

    private class HelpPopupCommand {
        private final String text;
        private final String command;

        public HelpPopupCommand(final String text, final String command) {
            this.text = text;
            this.command = command;
        }
    }

    private class HelpIdeTooltip extends IdeTooltip {
        private boolean showing = false;

        public HelpIdeTooltip(final Component component, final Point point, final JComponent tipComponent) {
            super(component, point, tipComponent);
            setCalloutShift(JBUI.scale(5));
            setExplicitClose(true);
            //setOpaque(true);
            setPreferredPosition(Balloon.Position.below);
        }

        @Override
        public boolean canBeDismissedOnTimeout() {
            return false;
        }

        @Override
        protected void onHidden() {
            showing = false;
            super.onHidden();
        }

        @Override
        protected boolean beforeShow() {
            showing = true;
            return super.beforeShow();
        }

        public boolean isShowing() {
            return showing;
        }
    }

    private class HelpToolTip extends JPanel {
        public HelpToolTip(final String wrappingText, final List<HelpPopupCommand> popupCommands,
                final int preferredWidth) {
            IdeTooltipManager.setColors(this);
            this.setLayout(new GridBagLayout());

            // Unfortunately, we have to calculate the preferredHeight of the wrapping text
            // I am roughly estimating it by getting the font metrics and dividing the full
            // width of the label string by the preferred width passed in.
            // I subtract 20 from the preferred width to help with word wrapping.
            // I add one to the number of lines it gets to provide a blank line before the links
            final JLabel label = new JLabel();
            // We use the HTML tags to get the label to word wrap
            label.setText("<HTML>" + wrappingText + "</HTML>");
            final FontMetrics fm = this.getFontMetrics(label.getFont());
            final int preferredHeight = (int) (fm.getHeight()
                    * (fm.stringWidth(wrappingText) / (double) (preferredWidth - JBUI.scale(20)) + 1));
            label.setPreferredSize(new Dimension(preferredWidth, preferredHeight));
            label.setVerticalAlignment(JLabel.TOP);
            SwingHelper.addToGridBag(this, label, 0, 0);

            int row = 1;
            for (final HelpPopupCommand popupCommand : popupCommands) {
                if (!StringUtils.isEmpty(popupCommand.text)) {
                    final Hyperlink hyperlink = new Hyperlink();
                    hyperlink.setText(popupCommand.text);
                    hyperlink.addActionListener(new ActionListener() {
                        @Override
                        public void actionPerformed(final ActionEvent e) {
                            onPopupCommandEvent(popupCommand.command);
                        }
                    });
                    SwingHelper.addToGridBag(this, hyperlink, 0, row++, 1, 1, JBUI.scale(4), 0);
                }
            }
        }
    }

    private class MouseEventListener implements MouseListener {
        private boolean ignoreNextClick = false;

        @Override
        public void mouseClicked(final MouseEvent e) {
            if (!ignoreNextClick) {
                e.consume();
                toggleToolTip();
                ignoreNextClick = true;
            } else {
                ignoreNextClick = false;
            }
        }

        @Override
        public void mousePressed(final MouseEvent e) {
        }

        @Override
        public void mouseReleased(final MouseEvent e) {
        }

        @Override
        public void mouseEntered(final MouseEvent e) {
            showToolTip(false);
        }

        @Override
        public void mouseExited(final MouseEvent e) {
            hideToolTip(false);
        }
    }
}