Java tutorial
/* * Copyright 2012 Corpuslinguistic working group Humboldt University Berlin. * * 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 annis.gui.flatquerybuilder; import com.vaadin.data.Property.ValueChangeEvent; import com.vaadin.data.Property.ValueChangeListener; import com.vaadin.event.FieldEvents; import com.vaadin.event.FieldEvents.TextChangeEvent; import com.vaadin.ui.AbstractSelect.Filtering; import com.vaadin.ui.Button; import com.vaadin.ui.CheckBox; import com.vaadin.ui.HorizontalLayout; import com.vaadin.ui.Panel; import com.vaadin.ui.VerticalLayout; import com.vaadin.ui.themes.ChameleonTheme; import java.text.Normalizer; import java.text.Normalizer.Form; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Set; import java.util.SortedSet; import java.util.TreeSet; import java.util.concurrent.ConcurrentSkipListSet; import org.apache.commons.lang3.StringUtils; /** * * @author tom */ public class SearchBox extends Panel implements Button.ClickListener, FieldEvents.TextChangeListener { private Button btClose; private VerticalNode vn; private String ebene; private SensitiveComboBox cb; private CheckBox reBox; private Collection<String> annonames; private FlatQueryBuilder sq; public static final String BUTTON_CLOSE_LABEL = "Close"; private static final String SB_CB_WIDTH = "145px"; public SearchBox(final String ebene, final FlatQueryBuilder sq, final VerticalNode vn) { this.vn = vn; this.ebene = ebene; this.sq = sq; VerticalLayout sb = new VerticalLayout(); sb.setImmediate(true); sb.setSpacing(true); ConcurrentSkipListSet<String> annos = new ConcurrentSkipListSet<String>(); for (String a : sq.getAvailableAnnotationLevels(ebene)) { annos.add(a); } this.annonames = annos;//by Martin this.cb = new SensitiveComboBox(); cb.setCaption(ebene); cb.setInputPrompt(ebene); cb.setWidth(SB_CB_WIDTH); // configure & load content cb.setImmediate(true); for (String annoname : this.annonames) { cb.addItem(annoname); } cb.setFilteringMode(Filtering.FILTERINGMODE_OFF);//necessary? cb.addListener((FieldEvents.TextChangeListener) this); sb.addComponent(cb); HorizontalLayout sbtoolbar = new HorizontalLayout(); sbtoolbar.setSpacing(true); // searchbox tickbox for regex CheckBox tb = new CheckBox("Regex"); tb.setImmediate(true); sbtoolbar.addComponent(tb); tb.addListener(new ValueChangeListener() { // TODO make this into a nice subroutine @Override public void valueChange(ValueChangeEvent event) { boolean r = reBox.booleanValue(); cb.setNewItemsAllowed(r); if (!r) { SpanBox.buildBoxValues(cb, ebene, sq); } else if (cb.getValue() != null) { String escapedItem = sq.escapeRegexCharacters(cb.getValue().toString()); cb.addItem(escapedItem); cb.setValue(escapedItem); } } }); reBox = tb; // close the searchbox btClose = new Button(BUTTON_CLOSE_LABEL, (Button.ClickListener) this); btClose.setStyleName(ChameleonTheme.BUTTON_SMALL); sbtoolbar.addComponent(btClose); sb.addComponent(sbtoolbar); sb.setSpacing(true); setContent(sb); } @Override public void buttonClick(Button.ClickEvent event) { if (event.getButton() == btClose) { vn.removeSearchBox(this); } else if (event.getComponent() == reBox) { boolean r = reBox.booleanValue(); cb.setNewItemsAllowed(r); if (!r) { SpanBox.buildBoxValues(cb, ebene, sq); } else if (cb.getValue() != null) { String escapedItem = sq.escapeRegexCharacters(cb.getValue().toString()); cb.addItem(escapedItem); cb.setValue(escapedItem); } } } @Override public void textChange(TextChangeEvent event) { if ("specific".equals(sq.getFilterMechanism())) { ConcurrentSkipListSet<String> notInYet = new ConcurrentSkipListSet<String>(); reducingStringComparator esc = new reducingStringComparator(); String txt = event.getText(); if (!txt.equals("")) { cb.removeAllItems(); for (Iterator<String> it = annonames.iterator(); it.hasNext();) { String s = it.next(); if (esc.compare(s, txt) == 0) { cb.addItem(s); } else { notInYet.add(s); } } //startsWith for (String s : notInYet) { if (esc.startsWith(s, txt)) { cb.addItem(s); notInYet.remove(s); } } //contains for (String s : notInYet) { if (esc.contains(s, txt)) { cb.addItem(s); } } } else { //have a look and speed it up SpanBox.buildBoxValues(cb, ebene, sq); } } if ("levenshtein".equals(sq.getFilterMechanism())) { String txt = event.getText(); HashMap<Integer, Collection> levdistvals = new HashMap<Integer, Collection>(); if (txt.length() > 1) { cb.removeAllItems(); for (String s : annonames) { Integer d = StringUtils.getLevenshteinDistance(removeAccents(txt), removeAccents(s)); if (levdistvals.containsKey(d)) { levdistvals.get(d).add(s); } if (!levdistvals.containsKey(d)) { Set<String> newc = new TreeSet<String>(); newc.add(s); levdistvals.put(d, newc); } } SortedSet<Integer> keys = new TreeSet<Integer>(levdistvals.keySet()); for (Integer k : keys.subSet(0, 5)) { List<String> values = new ArrayList(levdistvals.get(k)); Collections.sort(values, String.CASE_INSENSITIVE_ORDER); for (String v : values) { cb.addItem(v); } } } } } public String getAttribute() { return ebene; } public String getValue() { return cb.toString(); } public boolean isRegEx() { return reBox.booleanValue(); } public static String removeAccents(String text) { return text == null ? null : Normalizer.normalize(text, Form.NFD).replaceAll("\\p{InCombiningDiacriticalMarks}+", ""); } }