Java tutorial
/* * CATMA Computer Aided Text Markup and Analysis * * Copyright (C) 2009-2013 University Of Hamburg * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package de.catma.ui.tagger; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import com.vaadin.data.Property.ValueChangeEvent; import com.vaadin.data.Property.ValueChangeListener; import com.vaadin.event.FieldEvents.BlurEvent; import com.vaadin.event.FieldEvents.BlurListener; import com.vaadin.event.ShortcutAction.KeyCode; import com.vaadin.event.ShortcutAction.ModifierKey; import com.vaadin.server.ClassResource; import com.vaadin.server.Resource; import com.vaadin.ui.AbstractField; import com.vaadin.ui.Alignment; import com.vaadin.ui.Button; import com.vaadin.ui.Button.ClickEvent; import com.vaadin.ui.Button.ClickListener; import com.vaadin.ui.CheckBox; import com.vaadin.ui.ComboBox; import com.vaadin.ui.HorizontalLayout; import com.vaadin.ui.Label; import com.vaadin.ui.Notification; import com.vaadin.ui.Notification.Type; import com.vaadin.ui.TreeTable; import com.vaadin.ui.UI; import com.vaadin.ui.VerticalLayout; import com.vaadin.ui.Window; import de.catma.tag.Property; import de.catma.tag.PropertyDefinition; import de.catma.tag.PropertyValueList; import de.catma.tag.TagInstance; import de.catma.ui.dialog.SaveCancelListener; public class PropertyEditDialog extends Window { private static enum TreePropertyName { property, icon, value, assigned,; } // this is a hack to get hold of the filter string and make it available to // this edit dialog. Background: the filterstring can be added as a new value // in the ComboBox but the addition/ValueChangeEvent is triggered by enter key // only, we need to react on new values also on BlurEvents when the filterstring is // still only a filterstring and not a full new value yet private static class FilterExposingComboBox extends ComboBox { private String currentFilterString; public FilterExposingComboBox(String caption) { super(caption); } @Override public void changeVariables(Object source, Map<String, Object> variables) { String newFilter; if ((newFilter = (String) variables.get("filter")) != null) { currentFilterString = newFilter; } super.changeVariables(source, variables); } public String getCurrentFilterString() { return currentFilterString; } } private TreeTable propertyTree; private AdhocPropertyValuesBuffer propertyValuesBuffer; private ComboBox newValueInput; private Button btAdd; private Button btSave; private Button btCancel; private TagInstance tagInstance; private Set<Property> changedProperties; private Label hintText; private HashMap<Property, List<String>> changeBuffer = new HashMap<>(); public PropertyEditDialog(TagInstance tagInstance, SaveCancelListener<Set<Property>> saveCancelListener, AdhocPropertyValuesBuffer propertyValuesBuffer) { super("Edit Properties for Tag Type " + tagInstance.getTagDefinition().getName()); this.tagInstance = tagInstance; this.propertyValuesBuffer = propertyValuesBuffer; changedProperties = new HashSet<Property>(); initComponents(); initActions(saveCancelListener); initData(); } @SuppressWarnings("unchecked") private void initData() { for (Property p : tagInstance.getUserDefinedProperties()) { PropertyDefinition propertyDefinition = p.getPropertyDefinition(); ClassResource pIcon = new ClassResource("tagmanager/resources/ylwdiamd.gif"); propertyTree.addItem(new Object[] { propertyDefinition.getName(), null, null }, p); propertyTree.getContainerProperty(p, TreePropertyName.icon).setValue(pIcon); propertyTree.setChildrenAllowed(p, true); Set<String> values = new HashSet<String>(); values.addAll(propertyDefinition.getPossibleValueList().getPropertyValueList().getValues()); values.addAll(p.getPropertyValueList().getValues()); for (String pValue : values) { String pValueItemId = propertyDefinition.getUuid() + "_" + pValue; CheckBox cb = createCheckBox(p, pValue); propertyTree.addItem(new Object[] { null, pValue, cb }, pValueItemId); propertyTree.setParent(pValueItemId, p); propertyTree.setChildrenAllowed(pValueItemId, false); } propertyTree.setCollapsed(p, false); } if (tagInstance.getUserDefinedProperties().size() == 1) { propertyTree.setValue(tagInstance.getUserDefinedProperties().iterator().next()); } for (String value : propertyValuesBuffer.getValues()) { newValueInput.addItem(value); } } private CheckBox createCheckBox(final Property p, final String pValue) { final CheckBox cb = new CheckBox(null, p.getPropertyValueList().getValues().contains(pValue)); cb.addValueChangeListener(new ValueChangeListener() { @Override public void valueChange(ValueChangeEvent event) { propertyValueChanged(p, pValue, cb.getValue()); } }); return cb; } private List<String> getValueListBuffer(Property p) { List<String> valueList = changeBuffer.get(p); if (valueList == null) { valueList = new ArrayList<String>(); changeBuffer.put(p, valueList); valueList.addAll(p.getPropertyValueList().getValues()); } return valueList; } private void propertyValueChanged(Property p, String pValue, boolean add) { List<String> valueList = getValueListBuffer(p); if (add) { valueList.add(pValue); } else { valueList.remove(pValue); } changedProperties.add(tagInstance.getProperty(p.getPropertyDefinition().getUuid())); } private void initActions(final SaveCancelListener<Set<Property>> saveCancelListener) { newValueInput.addValueChangeListener(new ValueChangeListener() { @Override public void valueChange(ValueChangeEvent event) { btSave.setEnabled(newValueInput.getValue() == null); if (newValueInput.getValue() == null) { btSave.setDescription(""); } else { btSave.setDescription("Please use either the + button to add your adhoc value<br>" + "or empty the input field first!"); } } }); // we assume that having an input text on blur was intended // as a new value that one can set with the btAdd Button // therefore we need to set the input string as a value of the ComboBox newValueInput.addBlurListener(new BlurListener() { @Override public void blur(BlurEvent event) { String currentInputText = ((FilterExposingComboBox) newValueInput).getCurrentFilterString(); if ((currentInputText != null) && !currentInputText.trim().isEmpty()) { if (!newValueInput.getItemIds().contains(currentInputText)) { newValueInput.addItem(currentInputText); } newValueInput.setValue(currentInputText); } else { newValueInput.clear(); } } }); btCancel.addClickListener(new ClickListener() { public void buttonClick(ClickEvent event) { UI.getCurrent().removeWindow(PropertyEditDialog.this); saveCancelListener.cancelPressed(); } }); btSave.addClickListener(new ClickListener() { public void buttonClick(ClickEvent event) { for (Property p : changedProperties) { p.setPropertyValueList(new PropertyValueList(changeBuffer.get(p))); } UI.getCurrent().removeWindow(PropertyEditDialog.this); saveCancelListener.savePressed(changedProperties); } }); btAdd.addClickListener(new ClickListener() { public void buttonClick(ClickEvent event) { Object selection = propertyTree.getValue(); final Property property = getProperty(selection); final String pValue = (String) newValueInput.getValue(); if ((pValue == null) || (pValue.isEmpty())) { Notification.show("Info", "The value can not be empty!", Type.TRAY_NOTIFICATION); return; } if (property == null) { Notification.show("Info", "Please select exactly one Property from the list first!", Type.TRAY_NOTIFICATION); return; } List<String> valueBuffer = getValueListBuffer(property); if (valueBuffer.contains(pValue) || property.getPropertyDefinition().getPossibleValueList() .getPropertyValueList().getValues().contains(pValue)) { Notification.show("Info", "This value already exists. Please choose another name!", Type.TRAY_NOTIFICATION); return; } propertyValuesBuffer.addValue(pValue); String pValueItemId = property.getPropertyDefinition().getUuid() + "_" + pValue; CheckBox cb = createCheckBox(property, pValue); propertyTree.addItem(new Object[] { null, pValue, cb }, pValueItemId); cb.setValue(true); propertyTree.setParent(pValueItemId, property); propertyTree.setChildrenAllowed(pValueItemId, false); newValueInput.setValue(null); btSave.setEnabled(true); } }); } private void initComponents() { VerticalLayout mainLayout = new VerticalLayout(); mainLayout.setMargin(true); mainLayout.setSpacing(true); mainLayout.setSizeFull(); hintText = new Label("Please use the check boxes to set or unset values."); mainLayout.addComponent(hintText); propertyTree = new TreeTable(); propertyTree.setSelectable(true); propertyTree.setSizeFull(); propertyTree.setPageLength(10); propertyTree.setImmediate(true); propertyTree.focus(); propertyTree.addShortcutListener( new AbstractField.FocusShortcut(propertyTree, KeyCode.ARROW_UP, ModifierKey.CTRL)); propertyTree.addContainerProperty(TreePropertyName.property, String.class, ""); propertyTree.setColumnHeader(TreePropertyName.property, "Property"); propertyTree.addContainerProperty(TreePropertyName.icon, Resource.class, ""); propertyTree.addContainerProperty(TreePropertyName.value, String.class, ""); propertyTree.setColumnHeader(TreePropertyName.value, "Value"); propertyTree.addContainerProperty(TreePropertyName.assigned, CheckBox.class, ""); propertyTree.setColumnHeader(TreePropertyName.assigned, "Assigned"); propertyTree.setItemCaptionPropertyId(TreePropertyName.property); propertyTree.setItemIconPropertyId(TreePropertyName.icon); propertyTree.setVisibleColumns( new Object[] { TreePropertyName.property, TreePropertyName.value, TreePropertyName.assigned }); mainLayout.addComponent(propertyTree); mainLayout.setExpandRatio(propertyTree, 1.0f); HorizontalLayout comboBox = new HorizontalLayout(); comboBox.setSpacing(true); newValueInput = new FilterExposingComboBox("Add ad hoc value"); newValueInput.setTextInputAllowed(true); newValueInput.setNewItemsAllowed(true); newValueInput.setImmediate(true); newValueInput.addShortcutListener( new AbstractField.FocusShortcut(newValueInput, KeyCode.ARROW_DOWN, ModifierKey.CTRL)); comboBox.addComponent(newValueInput); btAdd = new Button("+"); btAdd.setClickShortcut(KeyCode.INSERT); comboBox.addComponent(btAdd); comboBox.setComponentAlignment(btAdd, Alignment.BOTTOM_RIGHT); mainLayout.addComponent(comboBox); hintText = new Label("New property values, that are created ad hoc, exist only for this tag instance! " + "For the creation of new systematic values use the Tag Type Manager."); mainLayout.addComponent(hintText); HorizontalLayout buttonPanel = new HorizontalLayout(); buttonPanel.setSpacing(true); btSave = new Button("Save"); btSave.setClickShortcut(KeyCode.ENTER, ModifierKey.ALT); buttonPanel.addComponent(btSave); buttonPanel.setComponentAlignment(btSave, Alignment.MIDDLE_RIGHT); btCancel = new Button("Cancel"); btCancel.setClickShortcut(KeyCode.ESCAPE); buttonPanel.addComponent(btCancel); buttonPanel.setComponentAlignment(btCancel, Alignment.MIDDLE_RIGHT); mainLayout.addComponent(buttonPanel); mainLayout.setComponentAlignment(buttonPanel, Alignment.MIDDLE_RIGHT); setContent(mainLayout); setWidth("40%"); setHeight("80%"); setModal(true); center(); } private Property getProperty(Object selection) { while ((selection != null) && !(selection instanceof Property)) { selection = propertyTree.getParent(selection); } return (Property) selection; } public void show() { UI.getCurrent().addWindow(this); } }