// 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.AwesomeBox.Resources; import com.google.collide.client.util.CssUtils; import com.google.collide.json.shared.JsonArray; import com.google.collide.shared.util.StringUtils; /** * Renders actions which are filtered via query. Meant to allow easy * implementation of a large list of actions which can quickly be filtered. * * NOTE: This section adds all items to the DOM and hides/shows them, it will * not handle dynamic lists nor is it particularly DOM efficient. * */ public abstract class AbstractActionSection<T extends AbstractActionSection.FilteredActionItem> extends AbstractAwesomeBoxSection<T> { protected final int maxResults; private final JsonArray<T> allActions; public static abstract class FilteredActionItem extends ActionItem { private final String text; public FilteredActionItem(Resources res, String text) { super(res, text); this.text = text.toLowerCase(); } public FilteredActionItem(Resources res, String text, int modifiers, String shortcutKey) { super(res, text); this.text = text.toLowerCase(); getElement().insertBefore(AwesomeBoxUtils.createSectionShortcut(res, modifiers, shortcutKey), getElement().getFirstChild()); } /** * @return true to show as soon as the AwesomeBox is focused. */ public abstract boolean onShowing(); /** * Return true for this item to be visible. */ public boolean onQueryChanged(String query) { return !StringUtils.isNullOrWhitespace(query) && text.contains(query.toLowerCase()); } } public AbstractActionSection(AwesomeBox.Resources res, int maxResults) { super(res); this.maxResults = maxResults; sectionElement = AwesomeBoxUtils.createSectionContainer(res); allActions = getAllActions(); initializeDom(); } /** * Returns the header title for this section. */ protected abstract String getTitle(); /** * Creates all DOM for all items in getAllActions hiding them by default. */ protected void initializeDom() { for (int i = 0; i < allActions.size(); i++) { CssUtils.setDisplayVisibility2(allActions.get(i).getElement(), false); sectionElement.appendChild(allActions.get(i).getElement()); } } @Override public boolean onQueryChanged(final String query) { listItems.clear(); updateItemVisibility(new ItemConditionCallback<T>() { @Override public boolean isCondition(T item) { return item.onQueryChanged(query); } }); return listItems.size() > 0; } @Override public boolean onShowing(AwesomeBox awesomeBox) { listItems.clear(); updateItemVisibility(new ItemConditionCallback<T>() { @Override public boolean isCondition(T item) { return item.onShowing(); } }); return listItems.size() > 0; } /** * Override to provide a list of actions to be added to the DOM. This will be * cached at construction time within the AbstractActionSection. */ protected abstract JsonArray<T> getAllActions(); private interface ItemConditionCallback<T extends FilteredActionItem> { public boolean isCondition(T item); } private void updateItemVisibility(ItemConditionCallback<T> callback) { for (int i = 0, r = 0; i < allActions.size(); i++) { if (r < maxResults && callback.isCondition(allActions.get(i))) { CssUtils.setDisplayVisibility2(allActions.get(i).getElement(), true); listItems.add(allActions.get(i)); r++; } else { CssUtils.setDisplayVisibility2(allActions.get(i).getElement(), false); } } } }