com.microsoft.alm.plugin.idea.ui.common.tabs.TabFormImpl.java Source code

Java tutorial

Introduction

Here is the source code for com.microsoft.alm.plugin.idea.ui.common.tabs.TabFormImpl.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.ui.common.tabs;

import com.google.common.annotations.VisibleForTesting;
import com.intellij.icons.AllIcons;
import com.intellij.openapi.actionSystem.ActionManager;
import com.intellij.openapi.actionSystem.ActionToolbar;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CommonShortcuts;
import com.intellij.openapi.actionSystem.DefaultActionGroup;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.ui.JBMenuItem;
import com.intellij.openapi.ui.JBPopupMenu;
import com.intellij.util.ui.JBUI;
import com.microsoft.alm.plugin.idea.resources.Icons;
import com.microsoft.alm.plugin.idea.resources.TfPluginBundle;
import com.microsoft.alm.plugin.idea.ui.common.FeedbackAction;
import com.microsoft.alm.plugin.idea.ui.common.FilteredModel;
import com.microsoft.alm.plugin.idea.ui.common.VcsTabStatus;
import com.microsoft.alm.plugin.idea.ui.controls.Hyperlink;
import com.microsoft.alm.plugin.idea.ui.controls.SearchFilter;
import org.apache.commons.lang.StringUtils;

import javax.swing.Icon;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingConstants;
import javax.swing.Timer;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Date;
import java.util.List;
import java.util.Observable;

/**
 * Common functionality for all tab views
 */
public abstract class TabFormImpl<T extends FilteredModel> extends Observable implements TabForm<T> {
    private final String tabTitle;
    private final String createDialogTitle;
    private final String refreshTooltip;
    private final String toolbarLocation;

    protected JPanel tabPanel;
    protected JScrollPane scrollPanel;
    protected JLabel statusLabel;
    protected Hyperlink statusLink;
    protected SearchFilter searchFilter;

    private boolean initialized = false;
    protected Timer timer;

    public TabFormImpl(final String tabTitle, final String createDialogTitle, final String refreshTooltip,
            final String toolbarLocation) {
        this.tabTitle = tabTitle;
        this.createDialogTitle = createDialogTitle;
        this.refreshTooltip = refreshTooltip;
        this.toolbarLocation = toolbarLocation;
    }

    /**
     * Create and return the tab panel
     *
     * @return
     */
    public JComponent getPanel() {
        ensureInitialized();
        return tabPanel;
    }

    /**
     * Create the custom view for the tab (i.e. tree, table, etc.)
     */
    protected abstract void createCustomView();

    /**
     * Sets the view model that is used for the tab
     *
     * @param modelView
     */
    public abstract void setModelForView(final T modelView);

    /**
     * Create the tab view if not already done
     */
    protected void ensureInitialized() {
        if (!initialized) {
            createCustomView();
            createFilterToolbar();

            //toolbars
            final JPanel toolBarPanel;
            if (ApplicationManager.getApplication() != null) {
                final ActionToolbar prActionsToolbar = createToolbar(createActionsGroup());
                final ActionToolbar feedbackActionsToolbar = createToolbar(createFeedbackGroup());

                // left panel of the top toolbar
                final FlowLayout flowLayout = new FlowLayout(FlowLayout.LEFT, 0, JBUI.scale(3)); // give vertical padding
                final JPanel toolBarPanelLeft = new JPanel(flowLayout);
                toolBarPanelLeft.add(prActionsToolbar.getComponent());
                toolBarPanelLeft.add(searchFilter);

                //entire top toolbar
                toolBarPanel = new JPanel(new BorderLayout());
                toolBarPanel.add(toolBarPanelLeft, BorderLayout.LINE_START);
                toolBarPanel.add(feedbackActionsToolbar.getComponent(), BorderLayout.LINE_END);
            } else {
                //skip setup when called from unit tests
                toolBarPanel = new JPanel();
            }

            //status panel with label and link
            final JPanel statusPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
            statusLabel = new JLabel();
            statusLink = new Hyperlink();
            statusLink.setActionCommand(CMD_STATUS_LINK);
            statusPanel.add(statusLabel);
            statusPanel.add(statusLink);

            //tabPanel
            tabPanel = new JPanel(new BorderLayout());
            tabPanel.add(toolBarPanel, BorderLayout.PAGE_START);
            tabPanel.add(scrollPanel, BorderLayout.CENTER);
            tabPanel.add(statusPanel, BorderLayout.PAGE_END);
            this.initialized = true;
        }
    }

    /**
     * Creates the toolbar for top of the tab
     *
     * @param actions
     * @return
     */
    protected ActionToolbar createToolbar(DefaultActionGroup actions) {
        final ActionToolbar toolbar = ActionManager.getInstance().createActionToolbar(toolbarLocation, actions,
                false);
        toolbar.setOrientation(SwingConstants.HORIZONTAL);
        toolbar.setTargetComponent(scrollPanel);
        return toolbar;
    }

    /**
     * Create the action buttons for the toolbar
     *
     * @return action toolbar
     */
    protected DefaultActionGroup createActionsGroup() {
        final AnAction createAction = new AnAction(TfPluginBundle.message(createDialogTitle),
                TfPluginBundle.message(createDialogTitle), AllIcons.ToolbarDecorator.Add) {
            @Override
            public void actionPerformed(AnActionEvent anActionEvent) {
                setChangedAndNotify(CMD_CREATE_NEW_ITEM);
            }
        };
        createAction.registerCustomShortcutSet(CommonShortcuts.getNew(), scrollPanel); //Ctrl+N on windows or Cmd+M on Mac

        final AnAction refreshAction = new AnAction(TfPluginBundle.message(refreshTooltip),
                TfPluginBundle.message(refreshTooltip), AllIcons.Actions.Refresh) {
            @Override
            public void actionPerformed(AnActionEvent anActionEvent) {
                setChangedAndNotify(CMD_REFRESH);
            }
        };
        refreshAction.registerCustomShortcutSet(CommonShortcuts.getRerun(), scrollPanel); //Ctrl+R on windows or Cmd+R on Mac

        return new DefaultActionGroup(createAction, refreshAction);
    }

    /**
     * Create the feedback portion of the toolbar
     *
     * @return feedback toolbar
     */
    protected DefaultActionGroup createFeedbackGroup() {
        final AnAction sendFeedback = new AnAction(TfPluginBundle.message(TfPluginBundle.KEY_FEEDBACK_DIALOG_TITLE),
                TfPluginBundle.message(TfPluginBundle.KEY_FEEDBACK_DIALOG_TITLE), Icons.Smile) {
            @Override
            public void actionPerformed(AnActionEvent anActionEvent) {
                final FeedbackAction action = new FeedbackAction(anActionEvent.getProject(),
                        TfPluginBundle.message(tabTitle));
                action.actionPerformed(new ActionEvent(anActionEvent.getInputEvent().getSource(),
                        anActionEvent.getInputEvent().getID(), CMD_SEND_FEEDBACK));
            }
        };

        return new DefaultActionGroup(sendFeedback);
    }

    /**
     * Create the search filter for the toolbar
     */
    protected void createFilterToolbar() {
        // Create timer for filtering the list
        timer = new Timer(400, null);
        timer.setInitialDelay(400);
        timer.setActionCommand(CMD_FILTER_CHANGED);
        timer.setRepeats(false);

        searchFilter = new SearchFilter();
        //initialize to empty string
        searchFilter.setFilterText(StringUtils.EMPTY);
    }

    /**
     * Set the tab's status in the toolbar
     *
     * @param status
     */
    public void setStatus(final VcsTabStatus status) {
        switch (status) {
        case NOT_TF_GIT_REPO:
            statusLabel.setText(TfPluginBundle.message(TfPluginBundle.KEY_ERRORS_NOT_TFS_REPO,
                    TfPluginBundle.message(tabTitle).toLowerCase()));
            statusLabel.setIcon(AllIcons.General.Error);
            statusLink.setText(TfPluginBundle.message(TfPluginBundle.KEY_IMPORT_DIALOG_TITLE));
            statusLink.setVisible(true);
            break;
        case NO_AUTH_INFO:
            statusLabel.setText(TfPluginBundle.message(TfPluginBundle.KEY_VCS_NOT_AUTHENTICATED));
            statusLabel.setIcon(AllIcons.General.Error);
            statusLink.setText(TfPluginBundle.message(TfPluginBundle.KEY_VCS_SIGN_IN));
            statusLink.setVisible(true);
            break;
        case LOADING_IN_PROGRESS:
            //Loading in progress
            statusLabel.setText(TfPluginBundle.message(TfPluginBundle.KEY_VCS_LOADING));
            statusLabel.setIcon(AllIcons.General.Information);
            statusLink.setText("");
            statusLink.setVisible(false);
            break;
        case LOADING_COMPLETED_ERRORS:
            statusLabel.setText(TfPluginBundle.message(TfPluginBundle.KEY_VCS_LOADING_ERRORS,
                    TfPluginBundle.message(tabTitle).toLowerCase()));
            statusLabel.setIcon(AllIcons.General.Warning);
            statusLink.setText(TfPluginBundle.message(TfPluginBundle.KEY_VCS_OPEN_IN_BROWSER));
            statusLink.setVisible(true);
            break;
        case LOADING_COMPLETED:
            //loading complete
            statusLabel.setText(
                    TfPluginBundle.message(TfPluginBundle.KEY_VCS_LAST_REFRESHED_AT, new Date().toString()));
            statusLabel.setIcon(AllIcons.General.Information);
            statusLink.setText(TfPluginBundle.message(TfPluginBundle.KEY_VCS_OPEN_IN_BROWSER));
            statusLink.setVisible(true);

            break;
        default:
            //we shouldn't get here, nothing to do
            break;
        }
    }

    public void addActionListener(final ActionListener listener) {
        timer.addActionListener(listener);
        statusLink.addActionListener(listener);
    }

    /**
     * Display popup menu on the view
     *
     * @param component
     * @param x
     * @param y
     * @param listener
     */
    protected void showPopupMenu(final Component component, final int x, final int y,
            final ActionListener listener) {
        final JBPopupMenu menu = new JBPopupMenu();
        final List<JBMenuItem> openMenuItems = getMenuItems(listener);
        for (JBMenuItem menuItem : openMenuItems) {
            menu.add(menuItem);
        }
        menu.show(component, x, y);
    }

    /**
     * Creates and returns the menu items to be shown in the popup menu
     *
     * @param listener
     * @return list of menu items
     */
    protected abstract List<JBMenuItem> getMenuItems(final ActionListener listener);

    /**
     * Creates a menu item to use in the popup menu
     *
     * @param resourceKey
     * @param icon
     * @param actionCommand
     * @param listener
     * @return menu item
     */
    protected JBMenuItem createMenuItem(final String resourceKey, final Icon icon, final String actionCommand,
            final ActionListener listener) {
        final String text = TfPluginBundle.message(resourceKey);
        final JBMenuItem menuItem = new JBMenuItem(text, icon);
        menuItem.setActionCommand(actionCommand);
        menuItem.addActionListener(listener);
        return menuItem;
    }

    protected void setChangedAndNotify(final String propertyName) {
        super.setChanged();
        super.notifyObservers(propertyName);
    }

    public void setFilter(final String filterString) {
        searchFilter.setFilterText(filterString);
    }

    public String getFilter() {
        return searchFilter.getFilterText();
    }

    @VisibleForTesting
    String getStatusText() {
        return statusLabel.getText();
    }

    @VisibleForTesting
    String getStatusLinkText() {
        return statusLink.getText();
    }
}