/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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.apache.usergrid.chop.webapp.view.user; import com.vaadin.data.Container; import com.vaadin.data.Item; import com.vaadin.data.Property; import com.vaadin.data.fieldgroup.FieldGroup; import com.vaadin.data.util.IndexedContainer; import com.vaadin.event.FieldEvents; import com.vaadin.ui.*; @SuppressWarnings("unchecked") class GroupSubwindow extends Window { /* User interface components are stored in session. */ private Table groupList = new Table(); private TextField searchField = new TextField(); private Button addNewGroupButton = new Button("New"); private Button removeGroupButton = new Button("Remove this group"); private Button saveButton = new Button("Save"); private Button cancelButton = new Button("Cancel"); private FormLayout editorLayout = new FormLayout(); private FieldGroup editorFields = new FieldGroup(); private static final String GROUP = "Group"; private static final String[] fieldNames = new String[]{GROUP}; IndexedContainer groupContainer; String username; public GroupSubwindow(String username) { super(String.format("Edit %s's groups", username)); // Set window caption center(); setClosable(false); setModal(true); // Set window size. setHeight("100%"); setWidth("100%"); this.username = username; groupContainer = createGroupDatasource(); initLayout(); initContactList(); initEditor(); initSearch(); initButtons(); } 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(groupList); HorizontalLayout bottomLeftLayout = new HorizontalLayout(); leftLayout.addComponent(bottomLeftLayout); bottomLeftLayout.addComponent(searchField); bottomLeftLayout.addComponent(addNewGroupButton); bottomLeftLayout.addComponent(saveButton); bottomLeftLayout.addComponent(cancelButton); /* 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 userList so that it uses * all the space left after from bottomLeftLayout */ leftLayout.setExpandRatio(groupList, 1); groupList.setSizeFull(); /* * In the bottomLeftLayout, searchField takes all the width there is * after adding addNewUserButton. 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(removeGroupButton); /* User interface can be created dynamically to reflect underlying data. */ for (String fieldName : fieldNames) { 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); } /* * 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 group"); /* * 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(AbstractTextField.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 FieldEvents.TextChangeListener() { public void textChange(final FieldEvents.TextChangeEvent event) { /* Reset the filter for the userContainer. */ groupContainer.removeAllContainerFilters(); groupContainer.addContainerFilter(new ContactFilter(event .getText())); } }); } /* * A custom filter for searching names and companies in the * userContainer. */ private class ContactFilter implements Container.Filter { private String needle; public ContactFilter(String needle) { this.needle = needle.toLowerCase(); } public boolean passesFilter(Object itemId, Item item) { String haystack = ("" + item.getItemProperty(GROUP).getValue()).toLowerCase(); return haystack.contains(needle); } public boolean appliesToProperty(Object id) { return true; } } private void initButtons() { addNewGroupButton.addClickListener(new Button.ClickListener() { public void buttonClick(Button.ClickEvent event) { /* * Rows in the Container data model are called Item. Here we add * a new row in the beginning of the list. */ groupContainer.removeAllContainerFilters(); Object contactId = groupContainer.addItemAt(0); /* * Each Item has a set of Properties that hold values. Here we * set a couple of those. */ groupContainer.getContainerProperty(contactId, GROUP).setValue( "New Group"); /* Lets choose the newly created contact to edit it. */ groupList.select(contactId); } }); removeGroupButton.addClickListener(new Button.ClickListener() { public void buttonClick(Button.ClickEvent event) { Object contactId = groupList.getValue(); groupList.removeItem(contactId); } }); cancelButton.addClickListener(new Button.ClickListener() { public void buttonClick(Button.ClickEvent event) { close(); // Close the sub-window } }); saveButton.addClickListener(new Button.ClickListener() { public void buttonClick(Button.ClickEvent event) { /*Set<String> groups = MyShiroRealm.getUserRoles(username); groups.clear(); for(Object itemId : groupList.getItemIds()){ String gname = (String) groupList.getItem(itemId).getItemProperty(GROUP).getValue(); groups.add(gname); } close(); // Close the sub-window MyShiroRealm.saveRealm();*/ } }); } private void initContactList() { groupList.setContainerDataSource(groupContainer); groupList.setVisibleColumns(new String[]{GROUP}); groupList.setSelectable(true); groupList.setImmediate(true); groupList.addValueChangeListener(new Property.ValueChangeListener() { public void valueChange(Property.ValueChangeEvent event) { Object contactId = groupList.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(groupList .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. */ private IndexedContainer createGroupDatasource() { IndexedContainer ic = new IndexedContainer(); for (String p : fieldNames) { ic.addContainerProperty(p, String.class, ""); } /*Set<String> groups = MyShiroRealm.getUserRoles(this.username); if (groups != null && !groups.isEmpty()) { for (String gname : groups) { if(!Strings.isNullOrEmpty(gname.trim())){ Object id = ic.addItem(); ic.getContainerProperty(id, GROUP).setValue( gname.trim()); } } }*/ return ic; } }