/*
* Copyright 2003-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 jetbrains.mps.nodeEditor.cells.contextAssistant;
import com.intellij.openapi.ui.popup.PopupStep;
import com.intellij.openapi.ui.popup.util.BaseListPopupStep;
import com.intellij.ui.popup.ClosableByLeftArrow;
import jetbrains.mps.openapi.editor.menus.transformation.ActionItem;
import jetbrains.mps.openapi.editor.menus.transformation.TransformationMenuItem;
import jetbrains.mps.openapi.editor.menus.transformation.TransformationMenuItemVisitor;
import jetbrains.mps.openapi.editor.menus.transformation.SubMenu;
import jetbrains.mps.util.StringUtil;
import org.apache.log4j.Logger;
import org.jetbrains.annotations.NotNull;
import java.util.Collections;
import java.util.IdentityHashMap;
import java.util.List;
class MenuItemListStep extends BaseListPopupStep<TransformationMenuItem> implements ClosableByLeftArrow {
private static final Logger LOG = Logger.getLogger(MenuItemListStep.class);
public static final MenuItemListStep EMPTY = new MenuItemListStep(null, Collections.emptyList());
private final ActionItemExecutor myActionItemExecutor;
private final IdentityHashMap<TransformationMenuItem, String> myItemTexts;
MenuItemListStep(ActionItemExecutor actionItemExecutor, List<TransformationMenuItem> items) {
super(null, items);
myActionItemExecutor = actionItemExecutor;
// Retrieve and cache texts of all items during construction so that calls to getTextFor do not require model read.
myItemTexts = getItemTexts(items);
}
@NotNull
private static IdentityHashMap<TransformationMenuItem, String> getItemTexts(List<TransformationMenuItem> items) {
IdentityHashMap<TransformationMenuItem, String> texts = new IdentityHashMap<>();
for (TransformationMenuItem item : items) {
texts.put(item, getLabelTextWithEmptyPattern(item));
}
return texts;
}
private static String getLabelTextWithEmptyPattern(TransformationMenuItem item) {
try {
return item.accept(new TransformationMenuItemVisitor<String>() {
@Override
public String visit(ActionItem actionItem) {
String labelText = actionItem.getLabelText("");
if (labelText == null) return "";
return labelText;
}
@Override
public String visit(SubMenu subMenu) {
return subMenu.getText();
}
});
} catch (RuntimeException e) {
// Hoping here that item.toString() doesn't throw exception
LOG.error("Exception retrieving text for item " + item, e);
String message = e.getMessage();
if (StringUtil.isEmpty(message)) {
return "Exception occurred, see log";
}
return message;
}
}
@NotNull
@Override
public String getTextFor(TransformationMenuItem value) {
String text = myItemTexts.get(value);
if (text == null) return "";
return text;
}
@Override
public boolean hasSubstep(TransformationMenuItem selectedValue) {
return selectedValue instanceof SubMenu;
}
@Override
public PopupStep onChosen(TransformationMenuItem selectedValue, boolean finalChoice) {
return selectedValue.accept(new TransformationMenuItemVisitor<PopupStep>() {
@Override
public PopupStep visit(ActionItem actionItem) {
return doFinalStep(getRunnableFor(actionItem));
}
@Override
public PopupStep visit(SubMenu subMenu) {
return new MenuItemListStep(myActionItemExecutor, subMenu.getItems());
}
});
}
private Runnable getRunnableFor(final ActionItem item) {
return () -> myActionItemExecutor.executeActionItem(item);
}
public MenuItemListStep subList(int fromIndex) {
if (fromIndex == 0) return this;
return new MenuItemListStep(myActionItemExecutor, getValues().subList(fromIndex, getValues().size()));
}
}