package org.activityinfo.ui.client.component.form.field.hierarchy; import com.google.common.base.Supplier; import com.google.gwt.core.client.GWT; import com.google.gwt.core.client.Scheduler; import com.google.gwt.dom.client.Element; import com.google.gwt.event.dom.client.ChangeEvent; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.logical.shared.*; import com.google.gwt.event.shared.GwtEvent; import com.google.gwt.event.shared.HandlerRegistration; import com.google.gwt.event.shared.SimpleEventBus; 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.rpc.AsyncCallback; import com.google.gwt.user.client.ui.*; import org.activityinfo.model.resource.ResourceId; import org.activityinfo.core.shared.Projection; import org.activityinfo.promise.Promise; import org.activityinfo.i18n.shared.I18N; import org.activityinfo.legacy.shared.Log; import java.util.List; import static org.activityinfo.core.shared.application.ApplicationProperties.LABEL_PROPERTY; /** * A single level within the label */ public class LevelWidget implements IsWidget, LevelView { private final HTMLPanel panel; private boolean enabled = true; private boolean readOnly; private ResourceId parentId; private Level level; private Supplier<Promise<List<Projection>>> choiceSupplier; private List<Projection> choices; private Projection selection; private SimpleEventBus eventBus = new SimpleEventBus(); interface LevelWidgetUiBinder extends UiBinder<HTMLPanel, LevelWidget> { } private static LevelWidgetUiBinder ourUiBinder = GWT.create(LevelWidgetUiBinder.class); @UiField Element levelLabel; @UiField ListBox listBox; @UiField Button clearButton; public LevelWidget(String label) { panel = ourUiBinder.createAndBindUi(this); levelLabel.setInnerText(label); } @Override public Widget asWidget() { return panel; } public void setEnabled(boolean enabled) { listBox.setEnabled(enabled); } @Override public void setSelection(Projection selection) { this.selection = selection; listBox.clear(); listBox.addItem(selection.getStringValue(LABEL_PROPERTY)); listBox.addItem(I18N.CONSTANTS.loading()); listBox.setSelectedIndex(0); } @Override public void setChoices(Supplier<Promise<List<Projection>>> choices) { choiceSupplier = choices; } @Override public void clearSelection() { this.selection = null; this.choices = null; listBox.clear(); listBox.addItem(I18N.CONSTANTS.loading()); listBox.setSelectedIndex(-1); } @UiHandler("listBox") public void onDropDown(ClickEvent event) { if(choices == null) { Scheduler.get().scheduleDeferred(new Command() { @Override public void execute() { populateListBox(); } }); } else { // sometimes this gets confused with a selection maybeFireChange(); } } @UiHandler("clearButton") public void onClear(ClickEvent event) { if(selection != null) { selection = null; clearSelection(); SelectionEvent.fire(this, null); } } @UiHandler("listBox") public void onChange(ChangeEvent event) { if(choices != null) { maybeFireChange(); } } private void maybeFireChange() { int selectedIndex = listBox.getSelectedIndex(); if(selectedIndex != -1) { Projection newSelection = choices.get(selectedIndex); if(this.selection == null || !this.selection.getRootInstanceId().equals(newSelection.getRootInstanceId())) { this.selection = newSelection; SelectionEvent.fire(this, newSelection); } } } private void populateListBox() { choiceSupplier.get().then(new AsyncCallback<List<Projection>>() { @Override public void onFailure(Throwable caught) { listBox.addItem(I18N.CONSTANTS.connectionProblem()); } @Override public void onSuccess(List<Projection> result) { choices = result; Log.info("Received " + result.size()); listBox.clear(); for(Projection projection : choices) { String label = projection.getStringValue(LABEL_PROPERTY); Log.info("Label = " + label); listBox.addItem(label); } if(selection != null) { applySelection(); } } }); } private void applySelection() { for(int i=0;i!=choices.size();++i) { if(choices.get(i).getRootInstanceId().equals(selection.getRootInstanceId())) { listBox.setSelectedIndex(i); break; } } } public void setReadOnly(boolean readOnly) { this.readOnly = readOnly; } public boolean isReadOnly() { return readOnly; } @Override public HandlerRegistration addSelectionHandler(SelectionHandler<Projection> handler) { return eventBus.addHandler(SelectionEvent.getType(), handler); } @Override public void fireEvent(GwtEvent<?> event) { eventBus.fireEvent(event); } }