package org.ovirt.engine.ui.webadmin.widget.autocomplete; import java.util.Collection; import java.util.List; import org.ovirt.engine.ui.webadmin.widget.autocomplete.SearchSuggestBox.SearchSuggestionColumn; import org.ovirt.engine.ui.webadmin.widget.autocomplete.SearchSuggestBox.SuggestCellTable; import org.ovirt.engine.ui.webadmin.widget.autocomplete.SearchSuggestBox.SuggestionsTableResources; import com.google.gwt.core.client.GWT; import com.google.gwt.core.client.Scheduler; import com.google.gwt.dom.client.Style.Unit; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.KeyCodes; import com.google.gwt.event.dom.client.KeyDownEvent; import com.google.gwt.user.cellview.client.CellTable.Resources; import com.google.gwt.user.cellview.client.HasKeyboardSelectionPolicy.KeyboardSelectionPolicy; import com.google.gwt.user.client.Element; import com.google.gwt.user.client.ui.PopupPanel; import com.google.gwt.user.client.ui.SuggestBox; import com.google.gwt.user.client.ui.SuggestBox.DefaultSuggestionDisplay; import com.google.gwt.user.client.ui.SuggestBox.SuggestionCallback; import com.google.gwt.user.client.ui.SuggestOracle.Suggestion; import com.google.gwt.user.client.ui.VerticalPanel; import com.google.gwt.view.client.ListDataProvider; import com.google.gwt.view.client.SingleSelectionModel; public final class SearchSuggestionDisplay extends DefaultSuggestionDisplay { private SuggestBox suggestBox; private VerticalPanel searchBoxPanel; private PopupPanel suggestionPopup; private SuggestCellTable<SearchSuggestion> suggestionsTable; private ListDataProvider<SearchSuggestion> suggestionDataProvider; public SearchSuggestionDisplay() { super(); } private SuggestCellTable<SearchSuggestion> getSuggestionCellList(final Collection<SearchSuggestion> suggestions, final SuggestBox suggestBox, final PopupPanel suggestionPopup) { this.suggestBox = suggestBox; this.suggestionPopup = suggestionPopup; // Create suggestions table final SuggestCellTable<SearchSuggestion> suggestionsTable = new SuggestCellTable<>(suggestions.size(), (Resources) GWT.create(SuggestionsTableResources.class)); // Create table's column and add it to the table SearchSuggestionColumn<SearchSuggestion> suggestColumn = new SearchSuggestionColumn<SearchSuggestion>() { @Override public SearchSuggestion getValue(SearchSuggestion suggestion) { return suggestion; } }; suggestionsTable.addColumn(suggestColumn); // Create a data provider and bind it to the table suggestionDataProvider = new ListDataProvider<>(); suggestionDataProvider.addDataDisplay(suggestionsTable); // Add suggestions to data provider List<SearchSuggestion> list = suggestionDataProvider.getList(); for (SearchSuggestion suggestion : suggestions) { list.add(suggestion); } // Bind a selection model it to the table suggestionsTable.setSelectionModel(new SingleSelectionModel<SearchSuggestion>()); // Set table's properties suggestionsTable.setWidth("100%"); //$NON-NLS-1$ suggestionsTable.setRowCount(suggestions.size()); suggestionsTable.setKeyboardSelectionPolicy(KeyboardSelectionPolicy.BOUND_TO_SELECTION); // Add enter key press event handler suggestionsTable.addDomHandler(event -> { if (event.getNativeKeyCode() == KeyCodes.KEY_ENTER) { onSelect(); } if (event.getNativeKeyCode() == KeyCodes.KEY_ESCAPE) { hideSuggestions(); } }, KeyDownEvent.getType()); // Add click event handler suggestionsTable.addDomHandler(event -> onSelect(), ClickEvent.getType()); return suggestionsTable; } private void onSelect() { Scheduler.get().scheduleDeferred(() -> { int selectedItemIndex = suggestionsTable.getSelectedItemIndex(); SearchSuggestion selectedSuggetion = suggestionDataProvider.getList().get(selectedItemIndex); if (selectedSuggetion != null) { suggestBox.setText(selectedSuggetion.getReplacementString()); } suggestionPopup.hide(); suggestBox.setFocus(true); }); } @Override protected void moveSelectionDown() { // Make sure that the menu is actually showing and focus the selected item if (suggestionPopup != null && suggestionPopup.isShowing()) { suggestionsTable.focusItemByIndex(suggestionsTable.getSelectedItemIndex()); if (suggestionsTable.getSelectedItemIndex() == 0) { Scheduler.get().scheduleDeferred(() -> suggestionsTable.getElement().getParentElement().setScrollTop(0)); } } } @SuppressWarnings("unchecked") @Override protected void showSuggestions(final SuggestBox suggestBox, Collection<? extends Suggestion> suggestions, boolean isDisplayStringHTML, boolean isAutoSelectEnabled, final SuggestionCallback callback) { // Hide popup if not needed boolean anySuggestions = suggestions != null && suggestions.size() > 0; if (!anySuggestions) { hideSuggestions(); return; } // Create suggestion popup and suggestions table widget if (suggestionPopup == null) { suggestionPopup = createPopup(); } // Hide the popup before we manipulate the menu within it. if (suggestionPopup.isAttached()) { suggestionPopup.hide(); } // Link the popup autoHide to the TextBox. // If the suggest box has changed, free the old one first. if (suggestBox != null) { suggestionPopup.removeAutoHidePartner(suggestBox.getElement()); suggestionPopup.addAutoHidePartner(suggestBox.getElement()); } // Create suggestions table widget suggestionsTable = getSuggestionCellList((Collection<SearchSuggestion>) suggestions, suggestBox, suggestionPopup); // Add table to popup suggestionPopup.setWidget(suggestionsTable); // Show the popup under the TextBox. suggestionPopup.showRelativeTo(searchBoxPanel); int searchBoxWidth = searchBoxPanel.getElement().getClientWidth(); Element table = (Element) suggestionPopup.getElement().getElementsByTagName("table").getItem(0); //$NON-NLS-1$ suggestionPopup.getElement().getStyle().setWidth(searchBoxWidth, Unit.PX); table.getStyle().setWidth(searchBoxWidth, Unit.PX); } @Override public void hideSuggestions() { if (suggestionPopup != null) { suggestionPopup.hide(false); } } public void setSearchBoxPanel(VerticalPanel searchBoxPanel) { this.searchBoxPanel = searchBoxPanel; } }