/* * Copyright 2000-2016 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.openapi.vcs.changes; import com.intellij.icons.AllIcons; import com.intellij.ide.CommonActionsManager; import com.intellij.ide.DataManager; import com.intellij.ide.TreeExpander; import com.intellij.ide.util.treeView.TreeState; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.vcs.VcsBundle; import com.intellij.openapi.vcs.changes.ui.ChangesBrowserBase; import com.intellij.openapi.vcs.changes.ui.ChangesBrowserNode; import com.intellij.openapi.vcs.changes.ui.ChangesListView; import com.intellij.openapi.vcs.changes.ui.TreeModelBuilder; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.ui.ScrollPaneFactory; import com.intellij.util.EditSourceOnDoubleClickHandler; import com.intellij.util.EditSourceOnEnterKeyHandler; import com.intellij.util.ui.tree.TreeUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; import javax.swing.tree.DefaultTreeModel; import javax.swing.tree.TreePath; import java.awt.*; import java.util.List; import java.util.stream.Stream; abstract class SpecificFilesViewDialog extends DialogWrapper { protected JPanel myPanel; protected final ChangesListView myView; protected final ChangeListManager myChangeListManager; protected boolean myInRefresh; protected final Project myProject; protected SpecificFilesViewDialog(@NotNull Project project, @NotNull String title, @NotNull DataKey<Stream<VirtualFile>> shownDataKey, @NotNull List<VirtualFile> initDataFiles) { super(project, true); setTitle(title); myProject = project; final Runnable closer = () -> this.close(0); myView = new ChangesListView(project) { @Override public void calcData(DataKey key, DataSink sink) { super.calcData(key, sink); if (shownDataKey.is(key.getName())) { sink.put(shownDataKey, getSelectedFiles()); } } @Override protected void editSourceRegistration() { EditSourceOnDoubleClickHandler.install(this, closer); EditSourceOnEnterKeyHandler.install(this, closer); } }; myChangeListManager = ChangeListManager.getInstance(project); createPanel(); setOKButtonText("Close"); init(); initData(initDataFiles); myView.setMinimumSize(new Dimension(100, 100)); } @NotNull @Override protected Action[] createActions() { return new Action[]{getOKAction()}; } private void initData(@NotNull final List<VirtualFile> files) { final TreeState state = TreeState.createOn(myView, (ChangesBrowserNode)myView.getModel().getRoot()); final DefaultTreeModel model = TreeModelBuilder.buildFromVirtualFiles(myProject, myView.isShowFlatten(), files); myView.setModel(model); myView.expandPath(new TreePath(((ChangesBrowserNode)model.getRoot()).getPath())); state.applyTo(myView); } private void createPanel() { myPanel = new JPanel(new BorderLayout()); final DefaultActionGroup group = new DefaultActionGroup(); final ActionToolbar actionToolbar = ActionManager.getInstance().createActionToolbar("SPECIFIC_FILES_DIALOG", group, true); addCustomActions(group, actionToolbar); final CommonActionsManager cam = CommonActionsManager.getInstance(); final Expander expander = new Expander(); group.addSeparator(); group.add(new ToggleShowFlattenAction()); group.add(cam.createExpandAllAction(expander, myView)); group.add(cam.createCollapseAllAction(expander, myView)); myPanel.add(actionToolbar.getComponent(), BorderLayout.NORTH); myPanel.add(ScrollPaneFactory.createScrollPane(myView), BorderLayout.CENTER); myView.setShowFlatten(false); } protected void addCustomActions(@NotNull DefaultActionGroup group, @NotNull ActionToolbar actionToolbar) { } @Override protected String getDimensionServiceKey() { return "com.intellij.openapi.vcs.changes.SpecificFilesViewDialog"; } @Override public JComponent getPreferredFocusedComponent() { return myView; } @Override protected JComponent createCenterPanel() { return myPanel; } private class Expander implements TreeExpander { public void expandAll() { TreeUtil.expandAll(myView); } public boolean canExpand() { return !myView.isShowFlatten(); } public void collapseAll() { TreeUtil.collapseAll(myView, 1); TreeUtil.expand(myView, 0); } public boolean canCollapse() { return !myView.isShowFlatten(); } } protected void refreshView() { ApplicationManager.getApplication().assertIsDispatchThread(); if (myInRefresh) return; myInRefresh = true; myChangeListManager.invokeAfterUpdate(() -> { try { initData(getFiles()); } finally { myInRefresh = false; } }, InvokeAfterUpdateMode.BACKGROUND_NOT_CANCELLABLE, "", ModalityState.current()); } @NotNull protected abstract List<VirtualFile> getFiles(); protected static ChangesBrowserBase getBrowserBase(@NotNull ChangesListView view) { return ChangesBrowserBase.DATA_KEY.getData(DataManager.getInstance().getDataContext(view)); } public static void refreshChanges(@NotNull Project project, @Nullable ChangesBrowserBase browser) { if (browser != null) { ChangeListManager.getInstance(project) .invokeAfterUpdate(browser::rebuildList, InvokeAfterUpdateMode.SYNCHRONOUS_CANCELLABLE, "Delete files", null); } } public class ToggleShowFlattenAction extends ToggleAction implements DumbAware { public ToggleShowFlattenAction() { super(VcsBundle.message("changes.action.show.directories.text"), VcsBundle.message("changes.action.show.directories.description"), AllIcons.Actions.GroupByPackage); } public boolean isSelected(AnActionEvent e) { return !myView.isShowFlatten(); } public void setSelected(AnActionEvent e, boolean state) { myView.setShowFlatten(!state); refreshView(); } } }