/******************************************************************************* * 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.actions.find; import elemental.dom.Element; import elemental.dom.Node; import elemental.html.TableCellElement; import elemental.html.TableElement; import com.google.gwt.core.client.Scheduler; import com.google.gwt.dom.client.Style; import com.google.gwt.event.dom.client.KeyCodes; import com.google.gwt.event.dom.client.KeyDownEvent; 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.Command; import com.google.gwt.user.client.ui.CheckBox; import com.google.gwt.user.client.ui.DockLayoutPanel; import com.google.gwt.user.client.ui.FlowPanel; import com.google.gwt.user.client.ui.HTML; import com.google.gwt.user.client.ui.Image; import com.google.gwt.user.client.ui.PopupPanel; import com.google.gwt.user.client.ui.TextBox; import com.google.inject.Inject; import com.google.inject.Provider; import org.eclipse.che.ide.Resources; import org.eclipse.che.ide.api.action.Action; import org.eclipse.che.ide.api.action.ActionEvent; import org.eclipse.che.ide.api.action.ActionManager; import org.eclipse.che.ide.api.action.Presentation; import org.eclipse.che.ide.api.autocomplete.AutoCompleteResources; import org.eclipse.che.ide.api.keybinding.KeyBindingAgent; import org.eclipse.che.ide.api.parts.PerspectiveManager; import org.eclipse.che.ide.ui.list.SimpleList; import org.eclipse.che.ide.ui.toolbar.PresentationFactory; import org.eclipse.che.ide.ui.toolbar.ToolbarResources; import org.eclipse.che.ide.util.dom.Elements; import org.eclipse.che.ide.util.input.KeyMapUtil; import org.vectomatic.dom.svg.ui.SVGImage; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; /** * @author Evgen Vidolob * @author Dmitry Shnurenko */ public class FindActionViewImpl extends PopupPanel implements FindActionView { interface FindActionViewImplUiBinder extends UiBinder<DockLayoutPanel, FindActionViewImpl> { } private final AutoCompleteResources.Css css; private final PresentationFactory presentationFactory; private final SimpleList.ListEventDelegate<Action> eventDelegate = new SimpleList.ListEventDelegate<Action>() { @Override public void onListItemClicked(Element listItemBase, Action itemData) { list.getSelectionModel().setSelectedItem(itemData); } @Override public void onListItemDoubleClicked(Element listItemBase, Action itemData) { delegate.onActionSelected(itemData); } }; private final SimpleList.ListItemRenderer<Action> listItemRenderer = new SimpleList.ListItemRenderer<Action>() { @Override public void render(Element itemElement, Action itemData) { TableCellElement icon = Elements.createTDElement(css.proposalIcon()); TableCellElement label = Elements.createTDElement(css.proposalLabel()); TableCellElement group = Elements.createTDElement(css.proposalGroup()); Presentation presentation = presentationFactory.getPresentation(itemData); itemData.update(new ActionEvent(presentation, actionManager, perspectiveManager.get())); if (presentation.getImageResource() != null) { Image image = new Image(presentation.getImageResource()); icon.appendChild((Node)image.getElement()); } else if (presentation.getSVGResource() != null) { SVGImage image = new SVGImage(presentation.getSVGResource()); image.getElement().setAttribute("class", toolbarResources.toolbar().iconButtonIcon()); image.getElement().getStyle().setMargin(0, Style.Unit.PX); icon.appendChild((Node)image.getElement()); } else if (presentation.getHTMLResource() != null) { icon.setInnerHTML(presentation.getHTMLResource()); } String hotKey = KeyMapUtil.getShortcutText(keyBindingAgent.getKeyBinding(actionManager.getId(itemData))); if (hotKey == null) { hotKey = " "; } else { hotKey = "<nobr> [" + hotKey + "] </nobr>"; } label.setInnerHTML(presentation.getText() + hotKey); if (!presentation.isEnabled() || !presentation.isVisible()) { itemElement.getStyle().setProperty("opacity", "0.6"); } String groupName = actions.get(itemData); if (groupName != null) { group.setInnerHTML(groupName); } itemElement.appendChild(icon); itemElement.appendChild(label); itemElement.appendChild(group); } @Override public Element createElement() { return Elements.createTRElement(); } }; @UiField TextBox nameField; @UiField CheckBox includeNonMenu; private ActionDelegate delegate; private Resources resources; private KeyBindingAgent keyBindingAgent; private ActionManager actionManager; @UiField DockLayoutPanel layoutPanel; @UiField FlowPanel actionsPanel; @UiField HTML actionsContainer; private SimpleList<Action> list; private Map<Action, String> actions; private Provider<PerspectiveManager> perspectiveManager; private ToolbarResources toolbarResources; @Inject public FindActionViewImpl(Resources resources, KeyBindingAgent keyBindingAgent, ActionManager actionManager, AutoCompleteResources autoCompleteResources, Provider<PerspectiveManager> perspectiveManager, ToolbarResources toolbarResources, FindActionViewImplUiBinder uiBinder) { this.resources = resources; this.keyBindingAgent = keyBindingAgent; this.actionManager = actionManager; this.perspectiveManager = perspectiveManager; this.toolbarResources = toolbarResources; this.presentationFactory = new PresentationFactory(); css = autoCompleteResources.autocompleteComponentCss(); css.ensureInjected(); DockLayoutPanel rootElement = uiBinder.createAndBindUi(this); setWidget(rootElement); setAutoHideEnabled(true); setAnimationEnabled(true); layoutPanel.setWidgetHidden(actionsPanel, true); layoutPanel.setHeight("60px"); addCloseHandler(event -> delegate.onClose()); includeNonMenu.addValueChangeHandler(event -> { includeNonMenu.getElement().setAttribute("checked", Boolean.toString(event.getValue())); delegate.nameChanged(nameField.getText(), event.getValue()); }); } @Override public void setDelegate(ActionDelegate delegate) { this.delegate = delegate; } @Override public void focusOnInput() { nameField.setFocus(true); } @Override public void show() { super.show(); if (nameField.getValue() != null && nameField.getValue().trim().isEmpty()) { hideActions(); } Scheduler.get().scheduleDeferred(() -> center()); } @Override public String getName() { return nameField.getText(); } @Override public void showActions(Map<Action, String> actions) { this.actions = actions; actionsContainer.getElement().setInnerHTML(""); TableElement itemHolder = Elements.createTableElement(); itemHolder.setClassName(css.items()); actionsContainer.getElement().appendChild(((com.google.gwt.dom.client.Element) itemHolder)); list = SimpleList.create((SimpleList.View)actionsContainer.getElement().cast(), (Element)actionsContainer.getElement(), itemHolder, resources.defaultSimpleListCss(), listItemRenderer, eventDelegate); list.render(new ArrayList<>(actions.keySet())); if (!actions.isEmpty()) { list.getSelectionModel().setSelectedItem(0); } layoutPanel.setWidgetHidden(actionsPanel, false); layoutPanel.setHeight("250px"); if (isVisible()) { Scheduler.get().scheduleDeferred(() -> center()); } } @Override public void hideActions() { actions = new HashMap<>(); actionsContainer.getElement().setInnerHTML(""); layoutPanel.setWidgetHidden(actionsPanel, true); layoutPanel.setHeight("60px"); if (isVisible()) { Scheduler.get().scheduleDeferred(() -> center()); } } @Override public boolean getCheckBoxState() { return includeNonMenu.getValue(); } @UiHandler("nameField") void handleKeyDown(KeyDownEvent event) { switch (event.getNativeKeyCode()) { case KeyCodes.KEY_UP: event.stopPropagation(); event.preventDefault(); list.getSelectionModel().selectPrevious(); return; case KeyCodes.KEY_DOWN: event.stopPropagation(); event.preventDefault(); list.getSelectionModel().selectNext(); return; case KeyCodes.KEY_PAGEUP: event.stopPropagation(); event.preventDefault(); list.getSelectionModel().selectPreviousPage(); return; case KeyCodes.KEY_PAGEDOWN: event.stopPropagation(); event.preventDefault(); list.getSelectionModel().selectNextPage(); return; case KeyCodes.KEY_ENTER: event.stopPropagation(); event.preventDefault(); delegate.onActionSelected(list.getSelectionModel().getSelectedItem()); return; case KeyCodes.KEY_ESCAPE: event.stopPropagation(); event.preventDefault(); hide(); return; } Scheduler.get().scheduleDeferred((Command)() -> delegate.nameChanged(nameField.getText(), includeNonMenu.getValue())); } }