// Copyright 2012 Google Inc. All Rights Reserved. // // 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 com.google.collide.client.search.awesomebox; import com.google.collide.client.search.awesomebox.AbstractAwesomeBoxSection.ActionItem; import com.google.collide.client.search.awesomebox.AwesomeBox.Resources; import com.google.collide.client.search.awesomebox.ManagedSelectionList.SelectableElement; import com.google.collide.client.util.CssUtils; import elemental.dom.Node; import elemental.events.MouseEvent; import elemental.html.DivElement; import elemental.html.Element; /** * Represents a generic AwesomeBoxSection which contains a selectable item list. */ public abstract class AbstractAwesomeBoxSection<T extends ActionItem> implements AwesomeBox.AwesomeBoxSection { /** * Generic wrapper around an element so it can be selected in our selection * list. */ public static abstract class ActionItem implements SelectableElement { public enum ActionSource { CLICK, SELECTION } protected final Element element; protected final Resources res; protected ActionItem(Resources res, Element element) { this.element = element; this.res = res; initialize(); } public ActionItem(Resources res, String text) { this(res, AwesomeBoxUtils.createSectionItem(res)); element.setTextContent(text); } /** * Initialize's the element after element creation. */ public void initialize() { } /** * Perform this elements action. */ public abstract ActionResult doAction(ActionSource source); public void remove() { getElement().removeFromParent(); } /** * Called to complete a query using tab completion. By default null is * returned indicating this item does not support completion. */ public String completeQuery() { return null; } @Override public Element getElement() { return element; } @Override public boolean onSelected() { element.addClassName(res.awesomeBoxCss().selected()); return true; } @Override public void onSelectionCleared() { element.removeClassName(res.awesomeBoxCss().selected()); } } protected final Resources res; protected final ManagedSelectionList<T> listItems; protected DivElement sectionElement; protected AbstractAwesomeBoxSection(Resources res) { this.res = res; listItems = ManagedSelectionList.create(); } @Override public DivElement getElement() { return sectionElement; } @Override public ActionResult onActionRequested() { if (listItems.hasSelection()) { return listItems.getSelectedElement().doAction(ActionItem.ActionSource.SELECTION); } return ActionResult.DO_NOTHING; } @Override public void onClearSelection() { listItems.clearSelection(); } @Override public String onCompleteSelection() { return listItems.hasSelection() ? listItems.getSelectedElement().completeQuery() : null; } @Override public void onAddedToContext(AwesomeBoxContext context) { // no-op by default } @Override public void onContextChanged(AwesomeBoxContext context) { // no-op by default } @Override public void onHiding(AwesomeBox awesomeBox) { // no-op by default } @Override public boolean onMoveSelection(boolean moveDown) { if (!CssUtils.isVisible(getElement())) { return false; } return listItems.moveSelection(moveDown); } @Override public ActionResult onSectionClicked(MouseEvent mouseEvent) { mouseEvent.preventDefault(); for (int i = 0; i < listItems.size(); i++) { if (listItems.get(i).getElement().contains((Node) mouseEvent.getTarget())) { return listItems.get(i).doAction(ActionItem.ActionSource.CLICK); } } return ActionResult.DO_NOTHING; } /** * Shows the section by default. */ @Override public boolean onShowing(AwesomeBox awesomeBox) { return true; } }