com.ritesh.idea.plugin.ui.toolswindow.reviewpanel.ReviewsPanel.java Source code

Java tutorial

Introduction

Here is the source code for com.ritesh.idea.plugin.ui.toolswindow.reviewpanel.ReviewsPanel.java

Source

/*
 * Copyright 2015 Ritesh Kapoor
 *
 * 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.ritesh.idea.plugin.ui.toolswindow.reviewpanel;

import com.intellij.icons.AllIcons;
import com.intellij.ide.BrowserUtil;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.diff.DiffRequest;
import com.intellij.openapi.options.ShowSettingsUtil;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.ComboBox;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.ui.Splitter;
import com.intellij.openapi.vcs.FilePath;
import com.intellij.openapi.vcs.changes.Change;
import com.intellij.openapi.vcs.changes.SimpleContentRevision;
import com.intellij.ui.GuiUtils;
import com.intellij.ui.components.JBLabel;
import com.intellij.ui.components.JBScrollPane;
import com.intellij.ui.table.JBTable;
import com.ritesh.idea.plugin.reviewboard.Review;
import com.ritesh.idea.plugin.reviewboard.ReviewDataProvider;
import com.ritesh.idea.plugin.state.SettingsPage;
import com.ritesh.idea.plugin.ui.Icons;
import com.ritesh.idea.plugin.ui.action.CustomComponentActionBase;
import com.ritesh.idea.plugin.ui.diff.CommentsDiffTool;
import com.ritesh.idea.plugin.ui.diff.ReviewDiffRequest;
import com.ritesh.idea.plugin.ui.panels.DraftReviewPanel;
import com.ritesh.idea.plugin.ui.toolswindow.ReviewChangesTreeList;
import com.ritesh.idea.plugin.ui.toolswindow.ReviewTableModel;
import com.ritesh.idea.plugin.ui.toolswindow.reviewpanel.ReviewPanelController.ReviewListFilter;

import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;

import static com.intellij.openapi.util.text.StringUtil.join;

/**
 * @author Ritesh
 */
public class ReviewsPanel extends JPanel {

    //    reviewListActionGroup.add(new DoNothingAction(TextFieldWithAutoCompletion.create(project, Arrays.asList("asd", "Asd"), true, null)));
    //    Messages.showWarningDialog("Svn is still in refresh. Please try again later.", "Alter");
    // TODO: Check for binary files

    private JBTable reviewsTable = new JBTable();
    private ReviewChangesTreeList changesTree;
    private ComboBox statusComboBox = new ComboBox(new String[] { "all", "discarded", "pending", "submitted" });
    private ComboBox repositoryComboBox = new ComboBox(new String[] { "Select Repository" });
    private JBLabel page = new JBLabel();
    private JComponent mainReviewToolbar;

    final Logger LOG = Logger.getInstance(ReviewsPanel.class);

    private ReviewPanelController controller;
    private final Project project;

    public ReviewsPanel(final Project project) {
        this.project = project;
        this.controller = new ReviewPanelController(project, this);
        initUI();
    }

    public void setReviewsList(final int pageNumber, final List<Review> reviews) {
        ApplicationManager.getApplication().invokeLater(new Runnable() {
            @Override
            public void run() {
                reviewsTable.setModel(new ReviewTableModel(reviews));
                reviewsTable.getColumnModel().getColumn(ReviewTableModel.Columns.SUMMARY.getIndex())
                        .setPreferredWidth(400);
                reviewsTable.getColumnModel().getColumn(ReviewTableModel.Columns.SUBMITTED_TO.getIndex())
                        .setPreferredWidth(50);
                reviewsTable.getColumnModel().getColumn(ReviewTableModel.Columns.SUBMITTER.getIndex())
                        .setPreferredWidth(50);
                reviewsTable.getColumnModel().getColumn(ReviewTableModel.Columns.LAST_MODIFIED.getIndex())
                        .setPreferredWidth(50);
                page.setText(String.valueOf(pageNumber));
                GuiUtils.enableChildren(true, ReviewsPanel.this);
            }
        });
    }

    public void setCurrentReview(List<Review.File> files) {
        final List<Change> changes = new ArrayList<>();
        for (Review.File file : files) {
            FilePath srcFilePath;
            FilePath patchFilePath;
            try {
                Class<?> aClass = Class.forName("com.intellij.openapi.vcs.LocalFilePath");
                srcFilePath = (FilePath) aClass.getDeclaredConstructor(String.class, boolean.class)
                        .newInstance(file.srcFileName, false);
                patchFilePath = (FilePath) aClass.getDeclaredConstructor(String.class, boolean.class)
                        .newInstance(file.dstFileName, false);
            } catch (Exception e) {
                try {
                    srcFilePath = (FilePath) Class.forName("com.intellij.openapi.vcs.FilePathImpl")
                            .getDeclaredMethod("createNonLocal", String.class, boolean.class)
                            .invoke(null, file.srcFileName, false);
                    patchFilePath = (FilePath) Class.forName("com.intellij.openapi.vcs.FilePathImpl")
                            .getDeclaredMethod("createNonLocal", String.class, boolean.class)
                            .invoke(null, file.dstFileName, false);
                } catch (Exception e1) {
                    throw new RuntimeException(e1);
                }
            }
            SimpleContentRevision original = new SimpleContentRevision(file.srcFileContents, srcFilePath,
                    file.sourceRevision);
            SimpleContentRevision patched = new SimpleContentRevision(file.dstFileContents, patchFilePath,
                    "New Change");
            changes.add(new Change(original, patched));
        }
        ApplicationManager.getApplication().invokeLater(new Runnable() {
            public void run() {
                changesTree.setChangesToDisplay(changes);
                GuiUtils.enableChildren(true, ReviewsPanel.this);
            }
        });
    }

    public void updateRepositories(final List<String> repositories, final String defaultRepository) {
        ApplicationManager.getApplication().invokeLater(new Runnable() {
            @Override
            public void run() {
                repositoryComboBox.removeAllItems();
                repositoryComboBox.addItem("Select Repository");
                repositoryComboBox.setSelectedIndex(0);
                for (String repository : repositories) {
                    repositoryComboBox.addItem(repository);
                }
                if (defaultRepository == null) {
                    repositoryComboBox.setSelectedIndex(0);
                } else {
                    repositoryComboBox.setSelectedItem(defaultRepository);
                }
                repositoryComboBox.setEnabled(true);
            }
        });
    }

    //TODO remove join
    private void draftReview() {
        Review selectedReview = controller.selectedReview();
        if (selectedReview != null) {
            final DraftReviewPanel reviewPanel = new DraftReviewPanel(project, "Update Review Request",
                    selectedReview.summary, selectedReview.description, join(selectedReview.targetPeople, ","),
                    join(selectedReview.targetGroups, ","), selectedReview.respository);

            if (reviewPanel.showAndGet()) {
                controller.updateReviewRequest(selectedReview, reviewPanel.getSummary(),
                        reviewPanel.getDescription(), reviewPanel.getTargetPeople(), reviewPanel.getTargetGroup());
            }
        }
    }

    public void enablePanel(final boolean enable) {
        ApplicationManager.getApplication().invokeLater(new Runnable() {
            public void run() {
                GuiUtils.enableChildren(ReviewsPanel.this, enable, mainReviewToolbar);
            }
        });
    }

    private void loadFileComments() {
        final Change selectedChange = changesTree.getSelectedChanges().get(0);
        List<Review.File> selectedFiles = controller.selectedFiles();
        for (Review.File file : selectedFiles) {
            if (file.srcFileName.equals(selectedChange.getBeforeRevision().getFile().getPath())) {
                controller.loadComments(file);
                break;
            }
        }
    }

    public void showCommentsDiff(final Review.File file, final List<Review.File.Comment> comments) {
        ApplicationManager.getApplication().invokeLater(new Runnable() {
            @Override
            public void run() {
                final Change selectedChange = changesTree.getSelectedChanges().get(0);
                DiffRequest request = new ReviewDiffRequest(project, selectedChange);
                final CommentsDiffTool commentsDiffTool = new CommentsDiffTool(file, comments);
                commentsDiffTool.setActionListener(new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        controller.updateNewComments(file, commentsDiffTool.getNewComments());
                    }
                });
                commentsDiffTool.show(request);
            }
        });
    }

    private int getSelectedReviewIndex() {
        return reviewsTable.getSelectedRow();
    }

    @SuppressWarnings("unchecked")
    private void initUI() {
        setLayout(new BorderLayout());

        changesTree = new ReviewChangesTreeList(project, new ArrayList());

        mainReviewToolbar = createMainReviewToolbar();

        JPanel reviewsListPanel = new JPanel(new BorderLayout());
        JPanel toolbarGroup = new JPanel(new BorderLayout());
        toolbarGroup.add(mainReviewToolbar, BorderLayout.WEST);
        toolbarGroup.add(createReviewListToolbar(), BorderLayout.CENTER);

        reviewsListPanel.add(toolbarGroup, BorderLayout.PAGE_START);
        reviewsListPanel.add(new JBScrollPane(reviewsTable), BorderLayout.CENTER);

        JPanel diffPanel = new JPanel(new BorderLayout());
        diffPanel.add(createDiffPanelToolbar(), BorderLayout.PAGE_START);
        diffPanel.add(changesTree, BorderLayout.CENTER);

        Splitter splitter = new Splitter(false, 0.7f);
        splitter.setFirstComponent(reviewsListPanel);
        splitter.setSecondComponent(diffPanel);

        add(splitter);

        reviewsTable.setRowHeight(20);
        reviewsTable.setShowGrid(false);
        reviewsTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
            @Override
            public void valueChanged(ListSelectionEvent e) {
                if (e.getValueIsAdjusting() || getSelectedReviewIndex() < 0)
                    return;
                controller.selectedReviewChanged(getSelectedReviewIndex());
            }
        });

        statusComboBox.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                controller.statusChanged((String) statusComboBox.getSelectedItem());
            }
        });
        repositoryComboBox.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                controller.repositoryChanged((String) repositoryComboBox.getSelectedItem());
            }
        });
        changesTree.setDoubleClickHandler(new Runnable() {
            @Override
            public void run() {
                loadFileComments();
            }
        });
        new AnAction() {
            @Override
            public void actionPerformed(AnActionEvent anActionEvent) {
                loadFileComments();
            }
        }.registerCustomShortcutSet(new CustomShortcutSet(CommonShortcuts.getDiff().getShortcuts()), changesTree);

        // Trigger to load reviews
        statusComboBox.setSelectedIndex(0);
        repositoryComboBox.setEnabled(false);
        controller.loadRepositories(null);

    }

    private void refreshPanel() {
        repositoryComboBox.setEnabled(false);
        controller.loadRepositories((String) repositoryComboBox.getSelectedItem());
        controller.refreshReviews();
    }

    private JComponent createMainReviewToolbar() {

        DefaultActionGroup actionGroup = new DefaultActionGroup("ReviewBoardMainActionsGroup", false);
        actionGroup.add(new AnAction("Refresh reviews", "Refresh reviews", AllIcons.Actions.Refresh) {
            @Override
            public void actionPerformed(AnActionEvent anActionEvent) {
                refreshPanel();
            }
        });
        actionGroup.add(new AnAction("Browse", "Open the selected review in browser", AllIcons.General.Web) {
            @Override
            public void actionPerformed(AnActionEvent anActionEvent) {
                if (controller.selectedReview() == null)
                    BrowserUtil.browse(ReviewDataProvider.getInstance(project).reviewBoardUrl(project));
                else
                    BrowserUtil.browse(ReviewDataProvider.getInstance(project).reviewUrl(project,
                            controller.selectedReview()));
            }
        });
        actionGroup.add(new AnAction("Settings", "Open review board settings", AllIcons.General.Settings) {
            @Override
            public void actionPerformed(AnActionEvent anActionEvent) {
                ShowSettingsUtil.getInstance().showSettingsDialog(project, SettingsPage.SETTINGS_DISPLAY_NAME);
            }
        });

        return ActionManager.getInstance().createActionToolbar("ReviewBoardMainActionsGroup", actionGroup, true)
                .getComponent();

    }

    private JComponent createDiffPanelToolbar() {
        DefaultActionGroup actionGroup = new DefaultActionGroup("ReviewBoardDiffActionsGroup", false);
        actionGroup.add(new AnAction("Refresh", "Refresh", AllIcons.Actions.Refresh) {
            @Override
            public void actionPerformed(AnActionEvent anActionEvent) {
                controller.loadSelectedReview();
            }
        });
        actionGroup.addAction(
                new AnAction("Publish Review", "Publish comments and changes to server", AllIcons.Actions.Export) {
                    @Override
                    public void actionPerformed(AnActionEvent anActionEvent) {
                        if (controller.commentsAvailableForPublish()) {
                            final String reviewComment = Messages.showInputDialog(project, "Review Comment",
                                    "Review Comment", null);
                            if (reviewComment != null) {
                                controller.publishReview(reviewComment);
                            }
                        }
                    }

                    @Override
                    public void update(AnActionEvent e) {
                        e.getPresentation().setEnabled(controller.commentsAvailableForPublish());
                    }
                });
        actionGroup.add(new Separator());
        actionGroup.addAll(changesTree.getTreeActions());
        return ActionManager.getInstance().createActionToolbar("ReviewBoardDiffActionGroup", actionGroup, true)
                .getComponent();
    }

    private JComponent createReviewListToolbar() {
        DefaultActionGroup actionGroup = new DefaultActionGroup("ReviewBoardListActionGroup", false);

        actionGroup.add(new Separator());
        actionGroup.add(new CustomComponentActionBase(new JBLabel("Status : ")));
        actionGroup.add(new CustomComponentActionBase(statusComboBox));
        actionGroup.add(new Separator());
        actionGroup.add(new CustomComponentActionBase(repositoryComboBox));
        actionGroup.add(new Separator());
        actionGroup.add(new ToggleAction("Incoming", "Show incoming reviews", AllIcons.Ide.IncomingChangesOn) {
            @Override
            public boolean isSelected(AnActionEvent anActionEvent) {
                return controller.reviewListFilter() == ReviewListFilter.INCOMING;
            }

            @Override
            public void setSelected(AnActionEvent anActionEvent, boolean b) {
                controller.filterChanged(ReviewListFilter.INCOMING);
            }
        });
        actionGroup.add(new ToggleAction("Outgoing", "Show outgoing reviews", AllIcons.Ide.OutgoingChangesOn) {
            @Override
            public boolean isSelected(AnActionEvent anActionEvent) {
                return controller.reviewListFilter() == ReviewListFilter.OUTGOING;
            }

            @Override
            public void setSelected(AnActionEvent anActionEvent, boolean b) {
                controller.filterChanged(ReviewListFilter.OUTGOING);
            }
        });

        actionGroup.add(new ToggleAction("All", "Show all Reviews", AllIcons.General.ProjectStructure) {
            @Override
            public boolean isSelected(AnActionEvent anActionEvent) {
                return controller.reviewListFilter() == ReviewListFilter.ALL;
            }

            @Override
            public void setSelected(AnActionEvent anActionEvent, boolean b) {
                controller.filterChanged(ReviewListFilter.ALL);
            }
        });

        actionGroup.add(new Separator());
        actionGroup.add(new AnAction("First", "Go to first page", Icons.First) {
            @Override
            public void actionPerformed(AnActionEvent anActionEvent) {
                controller.loadFirst();
            }

            @Override
            public void update(AnActionEvent e) {
                e.getPresentation().setEnabled(controller.isFirstEnabled());
            }
        });

        actionGroup.add(new AnAction("Back", "Move page backward", Icons.Back) {
            @Override
            public void actionPerformed(AnActionEvent anActionEvent) {
                controller.loadPrevious();
            }

            @Override
            public void update(AnActionEvent e) {
                e.getPresentation().setEnabled(controller.hasPrevious());
            }
        });

        actionGroup.add(new CustomComponentActionBase(page));
        actionGroup.add(new AnAction("Forward", "Move page forward", Icons.Forward) {
            @Override
            public void actionPerformed(AnActionEvent anActionEvent) {
                controller.loadNext();
            }

            @Override
            public void update(AnActionEvent e) {
                e.getPresentation().setEnabled(controller.hasNext());
            }
        });

        actionGroup.add(new AnAction("Last", "Go to last page", Icons.Last) {
            @Override
            public void actionPerformed(AnActionEvent anActionEvent) {
                controller.loadLast();
            }

            @Override
            public void update(AnActionEvent e) {
                e.getPresentation().setEnabled(controller.isLastEnabled());
            }
        });

        actionGroup.add(new Separator());
        actionGroup.add(new AnAction("Edit Review", "Edit selected review", AllIcons.Actions.EditSource) {
            @Override
            public void actionPerformed(AnActionEvent anActionEvent) {
                draftReview();
            }

            @Override
            public void update(AnActionEvent e) {
                e.getPresentation().setEnabled(controller.selectedReview() != null);
            }
        });

        actionGroup.add(new AnAction("Ship It", "Ship It", AllIcons.Graph.NodeSelectionMode) {
            @Override
            public void actionPerformed(AnActionEvent anActionEvent) {
                controller.shipReview(controller.selectedReview());
            }

            @Override
            public void update(AnActionEvent e) {
                e.getPresentation().setEnabled(controller.selectedReview() != null);
            }
        });
        actionGroup.add(new AnAction("Submit Review", "Submit the selected review",
                AllIcons.Actions.MoveToAnotherChangelist) {
            @Override
            public void actionPerformed(AnActionEvent anActionEvent) {
                controller.submitReview(controller.selectedReview());
            }

            @Override
            public void update(AnActionEvent e) {
                e.getPresentation().setEnabled(controller.selectedReview() != null);
            }
        });

        actionGroup.add(new AnAction("Discard Review", "Discard the selected review", AllIcons.Actions.Cancel) {
            @Override
            public void actionPerformed(AnActionEvent anActionEvent) {
                controller.discardReview(controller.selectedReview());
            }

            @Override
            public void update(AnActionEvent e) {
                e.getPresentation().setEnabled(controller.selectedReview() != null);
            }
        });

        return ActionManager.getInstance().createActionToolbar("ReviewBoardActions", actionGroup, true)
                .getComponent();
    }

}