/*******************************************************************************
* Copyright (c) 2012-2017 Codenvy, S.A.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Codenvy, S.A. - initial API and implementation
*******************************************************************************/
package org.eclipse.che.ide.hotkeys.dialog;
import com.google.gwt.dom.client.DivElement;
import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.Node;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import org.eclipse.che.ide.Resources;
import org.eclipse.che.ide.api.action.ActionManager;
import org.eclipse.che.ide.api.editor.EditorAgent;
import org.eclipse.che.ide.api.editor.EditorPartPresenter;
import org.eclipse.che.ide.api.hotkeys.HasHotKeyItems;
import org.eclipse.che.ide.api.hotkeys.HotKeyItem;
import org.eclipse.che.ide.api.keybinding.KeyBindingAgent;
import org.eclipse.che.ide.api.keybinding.KeyBuilder;
import org.eclipse.che.ide.api.keybinding.Scheme;
import org.eclipse.che.ide.collections.js.JsoArray;
import org.eclipse.che.ide.util.StringUtils;
import org.eclipse.che.ide.util.input.CharCodeWithModifiers;
import org.eclipse.che.ide.util.input.KeyMapUtil;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* The class provides displaying list hotKeys for IDE and editor
*
* @author Alexander Andrienko
* @author Artem Zatsarynnyi
* @author <a href="mailto:ak@nuxeo.com">Arnaud Kervern</a>
*/
@Singleton
public class HotKeysDialogPresenter implements HotKeysDialogView.ActionDelegate {
private static final String EDITOR_KEYBINDINGS = "Editor";
private static final String IDE_KEYBINDINGS = "IDE";
private final HotKeysDialogView view;
private final KeyBindingAgent keyBindingAgent;
private final ActionManager actionManager;
private final EditorAgent editorAgent;
private final Resources resources;
private List<HotKeyItem> ideHotKey;
private List<HotKeyItem> editorHotKeys;
private String selectedSchemeId;
private Map<String, List<HotKeyItem>> categories;
@Inject
public HotKeysDialogPresenter(HotKeysDialogView view,
KeyBindingAgent keyBindingAgent,
ActionManager actionManager,
EditorAgent editorAgent,
Resources resources) {
this.view = view;
this.keyBindingAgent = keyBindingAgent;
this.actionManager = actionManager;
this.editorAgent = editorAgent;
this.resources = resources;
categories = new HashMap<>();
view.setDelegate(this);
}
@Override
public void showHotKeys() {
showHotKeys(keyBindingAgent.getActive().getSchemeId());
}
public void showHotKeys(String scheme) {
selectedSchemeId = keyBindingAgent.getScheme(scheme).getSchemeId();
ideHotKey = getIDEHotKey();
editorHotKeys = getEditorHotKey();
categories.clear();
if (!ideHotKey.isEmpty()) {
categories.put(IDE_KEYBINDINGS, ideHotKey);
}
if (!editorHotKeys.isEmpty()) {
categories.put(EDITOR_KEYBINDINGS, editorHotKeys);
}
view.setData(categories);
view.setSchemes(selectedSchemeId, keyBindingAgent.getSchemes());
view.renderKeybindings();
view.show();
}
private List<HotKeyItem> getIDEHotKey() {
List<HotKeyItem> ideHotKeys = new ArrayList<>();
Scheme scheme = keyBindingAgent.getScheme(selectedSchemeId);
for (String actionId : actionManager.getActionIds("")) {
boolean isGlobal = false;
CharCodeWithModifiers activeCharCodeWithModifiers = scheme.getKeyBinding(actionId);
if (activeCharCodeWithModifiers == null) {
activeCharCodeWithModifiers = keyBindingAgent.getKeyBinding(actionId);
isGlobal = true;
}
if (activeCharCodeWithModifiers != null) {
String hotKey = KeyMapUtil.getShortcutText(activeCharCodeWithModifiers);
String description = actionManager.getAction(actionId).getTemplatePresentation().getDescription();
if (description != null && !description.isEmpty()) {
ideHotKeys.add(new HotKeyItem(description, hotKey, isGlobal));
}
}
}
return ideHotKeys;
}
private List<HotKeyItem> getEditorHotKey() {
EditorPartPresenter activeEditor = editorAgent.getActiveEditor();
if (activeEditor instanceof HasHotKeyItems) {
return ((HasHotKeyItems)activeEditor).getHotKeys();
}
return Collections.emptyList();
}
@Override
public void onSaveClicked() {
keyBindingAgent.setActive(selectedSchemeId);
view.hide();
}
@Override
public void onCloseClicked() {
view.hide();
}
@Override
public void onPrintClicked() {
final JsoArray<Node> nodesArray = JsoArray.create();
for (Map.Entry<String, List<HotKeyItem>> entry : categories.entrySet()) {
nodesArray.add(wrapCategory(entry.getKey()));
for (HotKeyItem hotKeyItem : entry.getValue()) {
if (hotKeyItem.getActionDescription() != null) {
nodesArray.add(wrapHotKey(hotKeyItem.getHotKey(), hotKeyItem.getActionDescription(), hotKeyItem.isGlobal()));
}
}
}
openWindowForPrinting(resources.printTemplate().getText(), nodesArray);
}
private static Element wrapCategory(String text) {
final DivElement div = Document.get().createDivElement();
div.setClassName("divCategory");
div.setInnerText(text);
return div;
}
private static Element wrapHotKey(String hotKey, String description, boolean global) {
final DivElement containerDiv = Document.get().createDivElement();
final DivElement hotKeyDiv = Document.get().createDivElement();
final DivElement descriptionDiv = Document.get().createDivElement();
hotKeyDiv.setInnerText(hotKey);
descriptionDiv.setInnerText(description);
containerDiv.setClassName("divRow");
hotKeyDiv.setClassName("divCell");
hotKeyDiv.addClassName("hotKey");
descriptionDiv.setClassName("divCell");
descriptionDiv.addClassName("description");
containerDiv.appendChild(hotKeyDiv);
containerDiv.appendChild(descriptionDiv);
return containerDiv;
}
private static native void openWindowForPrinting(String htmlTemplate, JsoArray<Node> nodes) /*-{
var printWindow = $wnd.open("about:blank", "", "width=650,height=800");
printWindow.document.write(htmlTemplate);
var container = printWindow.document.getElementById("key-bindings-container");
for (var node in nodes) {
container.appendChild(nodes[node]);
}
printWindow.document.close(); // necessary for IE >= 10
printWindow.focus(); // necessary for IE >= 10
printWindow.print();
printWindow.close();
}-*/;
@Override
public void onFilterValueChanged(String filteredText) {
categories.clear();
List<HotKeyItem> ideFilteredHotKey = filterCategory(ideHotKey, filteredText);
if (!ideFilteredHotKey.isEmpty()) {
categories.put(IDE_KEYBINDINGS, ideFilteredHotKey);
}
List<HotKeyItem> editorFilteredHotKeys = filterCategory(editorHotKeys, filteredText);
if (!editorFilteredHotKeys.isEmpty()) {
categories.put(EDITOR_KEYBINDINGS, editorFilteredHotKeys);
}
view.setData(categories);
view.renderKeybindings();
}
@Override
public void onSchemeSelectionChanged() {
showHotKeys(view.getSelectedScheme());
}
private List<HotKeyItem> filterCategory(List<HotKeyItem> hotKeyItems, String expectedText) {
List<HotKeyItem> result = new ArrayList<>();
for (HotKeyItem hotKeyItem : hotKeyItems) {
String description = hotKeyItem.getActionDescription();
String keyBindings = hotKeyItem.getHotKey();
boolean isFound = description != null && (StringUtils.containsIgnoreCase(description, expectedText)
|| StringUtils.containsIgnoreCase(keyBindings, expectedText));
if (isFound) {
result.add(hotKeyItem);
}
}
return result;
}
}