/******************************************************************************* * 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.command.palette; import elemental.html.DivElement; import elemental.html.SpanElement; import com.google.gwt.core.client.GWT; import com.google.gwt.dom.client.Element; import com.google.gwt.event.dom.client.KeyUpEvent; import com.google.gwt.uibinder.client.UiBinder; import com.google.gwt.uibinder.client.UiField; import com.google.gwt.uibinder.client.UiHandler; import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.TextBox; import com.google.gwt.user.client.ui.Widget; import com.google.inject.Inject; import com.google.inject.Singleton; import org.eclipse.che.ide.FontAwesome; import org.eclipse.che.ide.api.command.CommandGoal; import org.eclipse.che.ide.api.command.CommandImpl; import org.eclipse.che.ide.api.data.tree.Node; import org.eclipse.che.ide.command.node.CommandGoalNode; import org.eclipse.che.ide.command.node.ExecutableCommandNode; import org.eclipse.che.ide.command.node.NodeFactory; import org.eclipse.che.ide.ui.smartTree.NodeLoader; import org.eclipse.che.ide.ui.smartTree.NodeStorage; import org.eclipse.che.ide.ui.smartTree.Tree; import org.eclipse.che.ide.ui.window.Window; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Map.Entry; import static com.google.gwt.event.dom.client.KeyCodes.KEY_DOWN; import static com.google.gwt.event.dom.client.KeyCodes.KEY_ENTER; import static com.google.gwt.event.dom.client.KeyCodes.KEY_UP; import static org.eclipse.che.ide.ui.smartTree.SelectionModel.Mode.SINGLE; import static org.eclipse.che.ide.util.dom.Elements.createDivElement; import static org.eclipse.che.ide.util.dom.Elements.createSpanElement; import static org.eclipse.che.ide.util.dom.Elements.createTextNode; /** Implementation of {@link CommandsPaletteView}. */ @Singleton public class CommandsPaletteViewImpl extends Window implements CommandsPaletteView { private static final CommandsPaletteViewImplUiBinder UI_BINDER = GWT.create(CommandsPaletteViewImplUiBinder.class); private final NodeFactory nodeFactory; @UiField TextBox filterField; @UiField(provided = true) Tree tree; @UiField Label hintLabel; private ActionDelegate delegate; @Inject public CommandsPaletteViewImpl(NodeFactory nodeFactory, PaletteMessages messages) { this.nodeFactory = nodeFactory; tree = new Tree(new NodeStorage(), new NodeLoader()); tree.getSelectionModel().setSelectionMode(SINGLE); setWidget(UI_BINDER.createAndBindUi(this)); setTitle(messages.viewTitle()); filterField.getElement().setAttribute("placeholder", messages.filterPlaceholder()); initHintLabel(); getFooter().removeFromParent(); } private void initHintLabel() { final SpanElement upKeyLabel = createKeyLabel(); upKeyLabel.setInnerHTML(FontAwesome.ARROW_UP); final SpanElement downKeyLabel = createKeyLabel(); downKeyLabel.setInnerHTML(FontAwesome.ARROW_DOWN); final SpanElement enterKeyLabel = createKeyLabel(); enterKeyLabel.getStyle().setPadding("0px 1px 1px 4px"); enterKeyLabel.setInnerText(" Enter "); final DivElement hintElement = createDivElement(); hintElement.appendChild(upKeyLabel); hintElement.appendChild(downKeyLabel); hintElement.appendChild(createTextNode(" to select and ")); hintElement.appendChild(enterKeyLabel); hintElement.appendChild(createTextNode(" to execute")); hintLabel.getElement().appendChild((Element)hintElement); } /** Creates an html element for displaying keyboard key. */ private SpanElement createKeyLabel() { SpanElement element = createSpanElement(); element.getStyle().setFontWeight("bold"); element.getStyle().setPadding("0 4px 1px 4px"); element.getStyle().setMargin("0 3px"); element.getStyle().setBorderWidth("1px"); element.getStyle().setBorderStyle("solid"); element.getStyle().setProperty("border-radius", "3px"); return element; } @Override public void show() { super.show(); filterField.setValue(""); filterField.setFocus(true); } @Override public void close() { hide(); } @Override public void setCommands(Map<CommandGoal, List<CommandImpl>> commands) { renderCommands(commands); } /** Render commands grouped by goals. */ private void renderCommands(Map<CommandGoal, List<CommandImpl>> commands) { tree.getNodeStorage().clear(); for (Entry<CommandGoal, List<CommandImpl>> entry : commands.entrySet()) { List<ExecutableCommandNode> commandNodes = new ArrayList<>(entry.getValue().size()); for (final CommandImpl command : entry.getValue()) { commandNodes.add(nodeFactory.newExecutableCommandNode(command, () -> delegate.onCommandExecute(command))); } final CommandGoalNode commandGoalNode = nodeFactory.newCommandGoalNode(entry.getKey(), commandNodes); tree.getNodeStorage().add(commandGoalNode); } tree.expandAll(); } @Override public void setDelegate(ActionDelegate delegate) { this.delegate = delegate; } @UiHandler({"filterField"}) void onFilterChanged(KeyUpEvent event) { switch (event.getNativeKeyCode()) { case KEY_UP: tree.getSelectionModel().selectPrevious(); break; case KEY_DOWN: tree.getSelectionModel().selectNext(); break; case KEY_ENTER: final List<Node> selectedNodes = tree.getSelectionModel().getSelectedNodes(); if (!selectedNodes.isEmpty()) { final Node node = selectedNodes.get(0); if (node instanceof ExecutableCommandNode) { delegate.onCommandExecute(((ExecutableCommandNode)node).getData()); } else if (node instanceof CommandGoalNode) { tree.setExpanded(node, !tree.isExpanded(node)); } } break; default: delegate.onFilterChanged(filterField.getValue()); } } interface CommandsPaletteViewImplUiBinder extends UiBinder<Widget, CommandsPaletteViewImpl> { } }