/* * Copyright 2014-2015 CyberVision, Inc. * * 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 org.kaaproject.avro.ui.gwt.client.widget; import java.util.Comparator; import java.util.LinkedHashMap; import java.util.Map; import java.util.TreeMap; import org.kaaproject.avro.ui.gwt.client.util.Utils; import org.kaaproject.avro.ui.gwt.client.widget.choosen.AvroChoosenListBox; import org.kaaproject.avro.ui.shared.FqnKey; import org.kaaproject.avro.ui.shared.Fqn; import com.google.gwt.event.logical.shared.ValueChangeEvent; import com.google.gwt.event.logical.shared.ValueChangeHandler; import com.google.gwt.event.shared.HandlerRegistration; import com.google.gwt.user.client.ui.HasValue; import com.google.gwt.user.client.ui.SimplePanel; import com.watopi.chosen.client.event.ChosenChangeEvent; import com.watopi.chosen.client.event.ChosenChangeEvent.ChosenChangeHandler; import com.watopi.chosen.client.gwt.ChosenListBox; public class FqnReferenceBox extends SimplePanel implements HasValue<FqnKey>, ChosenChangeHandler, ShowableWidget { private ChosenListBox fqnListBox; private FqnKey value; private Map<String, FqnKey> hashToKeyMap = new LinkedHashMap<>(); private TreeMap<FqnKey, Fqn> fqnsMap = new TreeMap<>(); private int lastRenderedWidth = 0; public FqnReferenceBox(String displayPrompt) { fqnListBox = AvroChoosenListBox.createChoosenListBox(true); fqnListBox.setMaxSelectedOptions(1); fqnListBox.setPlaceholderText(displayPrompt); fqnListBox.setAllowSingleDeselect(true); fqnListBox.addChosenChangeHandler(this); fqnListBox.setWidth("100%"); AvroChoosenListBox.setChoosenListBoxWidth(fqnListBox, "100%"); add(fqnListBox); } @Override public void onChange(ChosenChangeEvent event) { FqnKey newValue = null; if (fqnListBox.getValues().length == 1) { String hashValue = fqnListBox.getValues()[0]; if (hashValue != null) { newValue = hashToKeyMap.get(hashValue); } } setValue(newValue, true); } @Override public FqnKey getValue() { return value; } @Override public void setValue(FqnKey value) { setValue(value, false); } @Override public void setValue(FqnKey value, boolean fireEvents) { if (value != null && !fqnsMap.containsKey(value)) { value = null; } if (value == this.value || (this.value != null && this.value.equals(value))) { return; } FqnKey before = this.value; this.value = value; updateListBox(); if (fireEvents) { ValueChangeEvent.fireIfNotEqual(this, before, value); } } @Override public HandlerRegistration addValueChangeHandler( ValueChangeHandler<FqnKey> handler) { return addHandler(handler, ValueChangeEvent.getType()); } public void updateDeclaredFqns(Map<FqnKey, Fqn> declaredFqns) { FqnComparator fc = new FqnComparator(declaredFqns); fqnsMap = new TreeMap<>(fc); fqnsMap.putAll(declaredFqns); hashToKeyMap.clear(); for (FqnKey key : this.fqnsMap.keySet()) { hashToKeyMap.put(key.hashCode() + "", key); } clearListBox(); setValue(this.value, true); } public void reset() { this.value = null; hashToKeyMap.clear(); fqnsMap.clear(); clearListBox(); AvroChoosenListBox.setChoosenSearchFieldVisible(fqnListBox, true); } private void updateListBox() { if (value != null) { fqnListBox.setSelectedValue(value.hashCode() + ""); } else { clearListBox(); } if (fqnListBox.getValues().length == 0) { AvroChoosenListBox.setChoosenSearchFieldVisible(fqnListBox, true); fqnListBox.forceRedraw(); } else { AvroChoosenListBox.setChoosenSearchFieldVisible(fqnListBox, false); } } private void clearListBox() { fqnListBox.clear(); for (String hash : hashToKeyMap.keySet()) { FqnKey key = hashToKeyMap.get(hash); fqnListBox.addItem(fqnValueText(fqnsMap.get(key)), hash); } fqnListBox.update(); } private String fqnValueText(Fqn fqn) { if (fqn != null) { return updateFqnTextWidth(fqn.getFqnString(), lastRenderedWidth); } else { return Utils.constants.invalidFqn(); } } private String updateFqnTextWidth(String stringFqn, int width) { stringFqn = stringFqn.replaceAll("\\s+",""); if (width == 0) { return stringFqn; } int maxRowChars = (int) ((float)width / 7.5f); if (stringFqn.length() > maxRowChars) { String parts[] = stringFqn.split("\\."); stringFqn = ""; int rowLength = 0; for (int i = 0; i < parts.length; i++) { if (i > 0) { stringFqn += "."; rowLength++; } if (rowLength + parts[i].length() > maxRowChars) { stringFqn += "\n"; rowLength = 0; } stringFqn += parts[i]; rowLength += parts[i].length(); } } return stringFqn; } @Override protected void onAttach() { super.onAttach(); fqnListBox.setWidth("100%"); AvroChoosenListBox.setChoosenListBoxWidth(fqnListBox, "100%"); AvroChoosenListBox.setChoosenSearchFieldVisible(fqnListBox, fqnListBox.getValues().length == 0); updateTextWidth(); fqnListBox.update(); } @Override public void onShown() { updateTextWidth(); } private void updateTextWidth() { int width = AvroChoosenListBox.getChoosenListBoxWidth(fqnListBox); if (lastRenderedWidth != width) { AvroChoosenListBox.updateChoosenListBoxMaxTextWidth(fqnListBox, width, new AvroChoosenListBox.TextWidthFunction() { @Override public String updateTextWidth(String text, int width) { return updateFqnTextWidth(text, width); } }); lastRenderedWidth = width; } } class FqnComparator implements Comparator<FqnKey> { Map<FqnKey, Fqn> map; public FqnComparator(Map<FqnKey, Fqn> base) { this.map = base; } public int compare(FqnKey a, FqnKey b) { Fqn af = map.get(a); Fqn bf = map.get(b); if (af == null) { if (a.equals(b)) { return 0; } else { return -1; } } else { return af.compareTo(bf); } } } }