/*
* 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.openapi.actionSystem.ActionManager;
import com.intellij.openapi.actionSystem.ActionPlaces;
import com.intellij.openapi.actionSystem.ActionPopupMenu;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CustomShortcutSet;
import com.intellij.openapi.actionSystem.DefaultActionGroup;
import com.intellij.openapi.actionSystem.KeyboardShortcut;
import com.intellij.openapi.actionSystem.ToggleAction;
import jetbrains.mps.ide.ModelReadAction;
import jetbrains.mps.ide.editorTabs.TabColorProvider;
import jetbrains.mps.ide.editorTabs.tabfactory.NodeChangeCallback;
import jetbrains.mps.ide.icons.IconManager;
import jetbrains.mps.project.Project;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.mps.openapi.model.SNode;
import org.jetbrains.mps.openapi.model.SNodeReference;
import javax.swing.JComponent;
import javax.swing.JPopupMenu;
import javax.swing.KeyStroke;
import java.awt.Color;
import java.awt.Component;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
class SelectTabAction extends ToggleAction {
private final Project myProject;
private final ButtonEditorTab myTab;
private final NodeChangeCallback myCallback;
public SelectTabAction(@NotNull Project mpsProject, ButtonEditorTab tab, NodeChangeCallback callback) {
super(tab.getDescriptor().getTitle(), "", tab.getDescriptor().getIcon());
myProject = mpsProject;
myTab = tab;
myCallback = callback;
}
/*package*/ void registerShortcut(JComponent editor) {
if (myTab.getDescriptor().getShortcutChar() != null) {
KeyStroke keystroke = KeyStroke.getKeyStroke("alt shift " + myTab.getDescriptor().getShortcutChar());
KeyboardShortcut shortcut = new KeyboardShortcut(keystroke, null);
registerCustomShortcutSet(new CustomShortcutSet(shortcut), editor);
}
}
@Override
public boolean displayTextInToolbar() {
return true;
}
@Override
public boolean isSelected(AnActionEvent e) {
return myTab.isSelected();
}
@Override
public void setSelected(AnActionEvent e, boolean state) {
myProject.getModelAccess().runReadAction(new Runnable() {
@Override
public void run() {
List<SNodeReference> nodeRefs = myTab.getEditorNodes();
ArrayList<SNode> nodes = new ArrayList<>();
for (SNodeReference r : nodeRefs) {
SNode n = r.resolve(myProject.getRepository());
if (n != null) {
nodes.add(n);
}
}
if (nodes.size() == 1) {
myCallback.changeNode(nodes.get(0).getReference());
return;
}
Component component = myTab.getComponentForPopup();
DefaultActionGroup group = getGotoGroup(nodes);
ActionPopupMenu popup = ActionManager.getInstance().createActionPopupMenu(ActionPlaces.UNKNOWN, group);
JPopupMenu popupMenu = popup.getComponent();
popupMenu.show(component, 0, 0);
TabColorProvider tabColorProvider = myTab.getColorProvider();
if (tabColorProvider != null && popupMenu.getComponents().length == nodes.size()) {
for (int i = 0; i < nodes.size(); i++) {
SNode node = nodes.get(i);
Component menuItem = popupMenu.getComponents()[i];
Color color = tabColorProvider.getNodeColor(node);// WTF - TCP.getAspectColor takes SNodeReference, while TCP.getNodeColor - SNode
if (color != null) {
menuItem.setForeground(color);
}
}
}
}
});
}
@NotNull
private DefaultActionGroup getGotoGroup(List<SNode> nodes) {
DefaultActionGroup result = new DefaultActionGroup();
if (nodes.isEmpty()) {
//this is normal since now we can't guarantee button deletion (e.g. remove reduction rule from mapping configuration when it's the last usage of a concept in generator)
return result;
}
Set<SNode> added = new HashSet<>();
for (final SNode node : nodes) {
SNode root = node.getContainingRoot();
if (added.contains(root)) {
continue;
}
added.add(root);
final NodeChangeRunnable delegate = new NodeChangeRunnable(node.getReference(), myCallback);
result.add(new ModelReadAction(getActionName(node), "", IconManager.getIconFor(root), delegate));
}
return result;
}
private static String getActionName(SNode node) {
String rootName = node.getContainingRoot().getPresentation();
if (rootName != null) {
return rootName.replaceAll("_", "__");
}
return "<no name>";
}
}