/* * Copyright 2003-2015 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 jetbrains.mps.ide.editorTabs.tabfactory.tabs.buttontabs; import com.intellij.ide.DataManager; import com.intellij.openapi.actionSystem.ActionManager; import com.intellij.openapi.actionSystem.ActionPlaces; import com.intellij.openapi.actionSystem.ActionToolbar; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.DataContext; import com.intellij.openapi.actionSystem.DefaultActionGroup; import com.intellij.openapi.project.Project; import jetbrains.mps.ide.editorTabs.tabfactory.NodeChangeCallback; import jetbrains.mps.ide.editorTabs.tabfactory.tabs.BaseTabsComponent; import jetbrains.mps.ide.editorTabs.tabfactory.tabs.TabEditorLayout; import jetbrains.mps.plugins.relations.RelationDescriptor; import jetbrains.mps.workbench.action.ActionUtils; import org.jetbrains.annotations.NotNull; import org.jetbrains.mps.openapi.model.SNodeReference; import javax.swing.JComponent; import java.awt.Component; import java.awt.event.HierarchyEvent; import java.awt.event.HierarchyListener; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Set; public class ButtonTabsComponent extends BaseTabsComponent { private List<ButtonEditorTab> myRealTabs = new ArrayList<>(); private ActionToolbar myToolbar = null; public ButtonTabsComponent(SNodeReference baseNode, Set<RelationDescriptor> possibleTabs, JComponent editor, NodeChangeCallback callback, boolean showGrayed, Project project) { super(baseNode, possibleTabs, editor, callback, showGrayed, null, project); getComponent().addHierarchyListener(new HierarchyListener() { @Override public void hierarchyChanged(HierarchyEvent e) { getProject().getModelAccess().runReadAction(new Runnable() { @Override public void run() { if (isDisposed() || !getComponent().isDisplayable()) { return; } updateTabs(); } }); } }); } public Component getComponentForTabIndex(int index) { return myToolbar.getComponent().getComponent(index); } @NotNull @Override public Collection<SNodeReference> getSelectionFor(RelationDescriptor tabDescriptor, SNodeReference editedNode) { for (ButtonEditorTab bet : myRealTabs) { if (bet.isEditingTabFor(editedNode)) { return bet.getSelectionNodes(editedNode); } } return Collections.emptyList(); } @Override public RelationDescriptor getCurrentTabAspect() { SNodeReference currentAspect = getEditedNode(); assert currentAspect != null; for (ButtonEditorTab bet : myRealTabs) { if (bet.isEditingTabFor(getEditedNode())) { return bet.getDescriptor(); } } return null; } @Override public void updateTabs() { if (isDisposed()) { return; } if (getEditedNode() != null && getEditedNode().resolve(getProject().getRepository()) == null) { editNode(myBaseNode); } myRealTabs.clear(); final NodeChangeCallback callback = new NodeChangeCallback() { @Override public void changeNode(SNodeReference newNode) { editNode(newNode); } }; TabEditorLayout newContent = updateDocumentsAndNodes(); for (RelationDescriptor tabDescriptor : myPossibleTabs) { if (newContent.covers(tabDescriptor)) { final ButtonEditorTab tab = new ButtonEditorTab(this, myRealTabs.size(), tabDescriptor, newContent.get(tabDescriptor)); final SelectTabAction action = new SelectTabAction(getProject(), tab, callback); tab.setSelectTabAction(action); action.registerShortcut(myEditor); myRealTabs.add(tab); } } DefaultActionGroup group = new DefaultActionGroup(); for (ButtonEditorTab tab : myRealTabs) { group.add(tab.getSelectTabAction()); } if (myToolbar != null) { removeContent(myToolbar.getComponent()); } ActionToolbar actionToolbar = ActionManager.getInstance().createActionToolbar(ActionPlaces.EDITOR_TOOLBAR, group, true); actionToolbar.setLayoutPolicy(ActionToolbar.WRAP_LAYOUT_POLICY); myToolbar = actionToolbar; setContent(myToolbar.getComponent()); if (getEditedNode() != null) { // MPS-22337: getEditedNode() exists even if node was deleted. // So we need to check if tab created for such node as tabs was created only for non deleted aspects. boolean isTabExists = false; for (ButtonEditorTab tab : myRealTabs) { if(tab.isEditingTabFor(getEditedNode())) { isTabExists = true; break; } } editNode(isTabExists ? getEditedNode() : myBaseNode); } } @Override public void nextTab() { for (ButtonEditorTab tab : myRealTabs) { if (!isCurrent(tab)) { continue; } int index = myRealTabs.indexOf(tab) + 1; performTabAction(myRealTabs.get(index % myRealTabs.size()).getSelectTabAction()); return; } } public boolean isCurrent(ButtonEditorTab tab) { return getEditedNode() != null && tab.isEditingTabFor(getEditedNode()); } @Override public void prevTab() { for (ButtonEditorTab tab : myRealTabs) { if (isCurrent(tab)) { int index = myRealTabs.indexOf(tab); index += myRealTabs.size() - 1; performTabAction(myRealTabs.get(index % myRealTabs.size()).getSelectTabAction()); return; } } } private void performTabAction(AnAction tabAction) { final DataContext context = DataManager.getInstance().getDataContext(getComponent()); AnActionEvent event = ActionUtils.createEvent(ActionPlaces.UNKNOWN, context); tabAction.actionPerformed(event); } @Override public void updateTabColors() { } }