Java tutorial
/* * Copyright 2013 by Maxim Kalina * * 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 net.javaforge.netty.vaadin; import com.vaadin.annotations.Title; import com.vaadin.data.Container.Filter; import com.vaadin.data.Item; import com.vaadin.data.Property; import com.vaadin.data.Property.ValueChangeEvent; import com.vaadin.data.fieldgroup.FieldGroup; import com.vaadin.data.util.IndexedContainer; import com.vaadin.event.FieldEvents; import com.vaadin.event.FieldEvents.BlurEvent; import com.vaadin.event.FieldEvents.TextChangeEvent; import com.vaadin.event.FieldEvents.TextChangeListener; import com.vaadin.server.VaadinRequest; import com.vaadin.ui.AbstractTextField.TextChangeEventMode; import com.vaadin.ui.*; import com.vaadin.ui.Button.ClickEvent; import com.vaadin.ui.Button.ClickListener; /* * UI class is the starting point for your app. You may deploy it with VaadinServlet * or VaadinPortlet by giving your UI class name a parameter. When you browse to your * app a web page showing your UI is automatically generated. Or you may choose to * embed your UI to an existing web page. */ @Title("Addressbook") public class AddressbookUI extends UI { private static final long serialVersionUID = 1L; /* User interface components are stored in session. */ private Table contactList = new Table(); private TextField searchField = new TextField(); private Button addNewContactButton = new Button("New"); private Button removeContactButton = new Button("Remove this contact"); private FormLayout editorLayout = new FormLayout(); private FieldGroup editorFields = new FieldGroup(); private static final String FNAME = "First Name"; private static final String LNAME = "Last Name"; private static final String COMPANY = "Company"; private static final String[] fieldNames = new String[] { FNAME, LNAME, COMPANY, "Mobile Phone", "Work Phone", "Home Phone", "Work Email", "Home Email", "Street", "City", "Zip", "State", "Country" }; /* * Any component can be bound to an external data source. This example uses * just a dummy in-memory list, but there are many more practical * implementations. */ IndexedContainer contactContainer = createDummyDatasource(); /* * After UI class is created, init() is executed. You should build and wire * up your user interface here. */ protected void init(VaadinRequest request) { initLayout(); initContactList(); initEditor(); initSearch(); initAddRemoveButtons(); } /* * In this example layouts are programmed in Java. You may choose use a * visual editor, CSS or HTML templates for layout instead. */ private void initLayout() { /* Root of the user interface component tree is set */ HorizontalSplitPanel splitPanel = new HorizontalSplitPanel(); setContent(splitPanel); /* Build the component tree */ VerticalLayout leftLayout = new VerticalLayout(); splitPanel.addComponent(leftLayout); splitPanel.addComponent(editorLayout); leftLayout.addComponent(contactList); HorizontalLayout bottomLeftLayout = new HorizontalLayout(); leftLayout.addComponent(bottomLeftLayout); bottomLeftLayout.addComponent(searchField); bottomLeftLayout.addComponent(addNewContactButton); /* Set the contents in the left of the split panel to use all the space */ leftLayout.setSizeFull(); /* * On the left side, expand the size of the contactList so that it uses * all the space left after from bottomLeftLayout */ leftLayout.setExpandRatio(contactList, 1); contactList.setSizeFull(); /* * In the bottomLeftLayout, searchField takes all the width there is * after adding addNewContactButton. The height of the layout is defined * by the tallest component. */ bottomLeftLayout.setWidth("100%"); searchField.setWidth("100%"); bottomLeftLayout.setExpandRatio(searchField, 1); /* Put a little margin around the fields in the right side editor */ editorLayout.setMargin(true); editorLayout.setVisible(false); } private void initEditor() { editorLayout.addComponent(removeContactButton); /* User interface can be created dynamically to reflect underlying data. */ for (String fieldName : fieldNames) { final TextField field = new TextField(fieldName); editorLayout.addComponent(field); field.setWidth("100%"); /* * We use a FieldGroup to connect multiple components to a data * source at once. */ editorFields.bind(field, fieldName); field.addBlurListener(new FieldEvents.BlurListener() { private static final long serialVersionUID = 1L; @Override public void blur(BlurEvent event) { field.commit(); } }); } /* * Data can be buffered in the user interface. When doing so, commit() * writes the changes to the data source. Here we choose to write the * changes automatically without calling commit(). */ // editorFields.setBuffered(false); } private void initSearch() { /* * We want to show a subtle prompt in the search field. We could also * set a caption that would be shown above the field or description to * be shown in a tooltip. */ searchField.setInputPrompt("Search contacts"); /* * Granularity for sending events over the wire can be controlled. By * default simple changes like writing a text in TextField are sent to * server with the next Ajax call. You can set your component to be * immediate to send the changes to server immediately after focus * leaves the field. Here we choose to send the text over the wire as * soon as user stops writing for a moment. */ searchField.setTextChangeEventMode(TextChangeEventMode.LAZY); /* * When the event happens, we handle it in the anonymous inner class. * You may choose to use separate controllers (in MVC) or presenters (in * MVP) instead. In the end, the preferred application architecture is * up to you. */ searchField.addTextChangeListener(new TextChangeListener() { private static final long serialVersionUID = 1L; public void textChange(final TextChangeEvent event) { /* Reset the filter for the contactContainer. */ contactContainer.removeAllContainerFilters(); contactContainer.addContainerFilter(new ContactFilter(event.getText())); } }); } /* * A custom filter for searching names and companies in the * contactContainer. */ private class ContactFilter implements Filter { private static final long serialVersionUID = 1L; private String needle; public ContactFilter(String needle) { this.needle = needle.toLowerCase(); } public boolean passesFilter(Object itemId, Item item) { String haystack = ("" + item.getItemProperty(FNAME).getValue() + item.getItemProperty(LNAME).getValue() + item.getItemProperty(COMPANY).getValue()).toLowerCase(); return haystack.contains(needle); } public boolean appliesToProperty(Object id) { return true; } } private void initAddRemoveButtons() { addNewContactButton.addClickListener(new ClickListener() { private static final long serialVersionUID = 1L; @SuppressWarnings("unchecked") public void buttonClick(ClickEvent event) { /* * Rows in the Container data model are called Item. Here we add * a new row in the beginning of the list. */ contactContainer.removeAllContainerFilters(); Object contactId = contactContainer.addItemAt(0); /* * Each Item has a set of Properties that hold values. Here we * set a couple of those. */ contactList.getContainerProperty(contactId, FNAME).setValue("New"); contactList.getContainerProperty(contactId, LNAME).setValue("Contact"); /* Lets choose the newly created contact to edit it. */ contactList.select(contactId); } }); removeContactButton.addClickListener(new ClickListener() { private static final long serialVersionUID = 1L; public void buttonClick(ClickEvent event) { Object contactId = contactList.getValue(); contactList.removeItem(contactId); } }); } private void initContactList() { contactList.setContainerDataSource(contactContainer); contactList.setVisibleColumns(new String[] { FNAME, LNAME, COMPANY }); contactList.setSelectable(true); contactList.setImmediate(true); contactList.addValueChangeListener(new Property.ValueChangeListener() { private static final long serialVersionUID = 1L; public void valueChange(ValueChangeEvent event) { Object contactId = contactList.getValue(); /* * When a contact is selected from the list, we want to show * that in our editor on the right. This is nicely done by the * FieldGroup that binds all the fields to the corresponding * Properties in our contact at once. */ if (contactId != null) editorFields.setItemDataSource(contactList.getItem(contactId)); editorLayout.setVisible(contactId != null); } }); } /* * Generate some in-memory example data to play with. In a real application * we could be using SQLContainer, JPAContainer or some other to persist the * data. */ @SuppressWarnings("unchecked") private static IndexedContainer createDummyDatasource() { IndexedContainer ic = new IndexedContainer(); for (String p : fieldNames) { ic.addContainerProperty(p, String.class, ""); } /* Create dummy data by randomly combining first and last names */ String[] fnames = { "Peter", "Alice", "Joshua", "Mike", "Olivia", "Nina", "Alex", "Rita", "Dan", "Umberto", "Henrik", "Rene", "Lisa", "Marge" }; String[] lnames = { "Smith", "Gordon", "Simpson", "Brown", "Clavel", "Simons", "Verne", "Scott", "Allison", "Gates", "Rowling", "Barks", "Ross", "Schneider", "Tate" }; for (int i = 0; i < 1000; i++) { Object id = ic.addItem(); ic.getContainerProperty(id, FNAME).setValue(fnames[(int) (fnames.length * Math.random())]); ic.getContainerProperty(id, LNAME).setValue(lnames[(int) (lnames.length * Math.random())]); } return ic; } }